summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2015-05-21 14:50:39 +0200
committerChristophe Simonis <chs@odoo.com>2015-05-21 14:50:39 +0200
commit14a7d52307fe30443e8f08a262d46f6d2f804bc1 (patch)
treeb8183ae7549206f27bac51d9f2eaaa5ce3e4a818 /addons
parent5cff8fbb7c70a372cb5116c2fb98fd622c4d4358 (diff)
parent327e471c9b5d30317b69396b0f0932ff445e3694 (diff)
[MERGE] forward port of branch 8.0 up to 327e471
Diffstat (limited to 'addons')
-rw-r--r--addons/account/account_move_line.py2
-rw-r--r--addons/base_import/models.py11
-rw-r--r--addons/calendar/calendar.py6
-rw-r--r--addons/google_calendar/google_calendar.py4
-rw-r--r--addons/mail/wizard/mail_compose_message.py2
-rw-r--r--addons/mrp/mrp.py4
-rw-r--r--addons/mrp/procurement.py2
-rw-r--r--addons/mrp/stock.py17
-rw-r--r--addons/mrp_operations/mrp_operations.py2
-rw-r--r--addons/payment_adyen/models/adyen.py2
-rw-r--r--addons/point_of_sale/point_of_sale.py4
-rw-r--r--addons/point_of_sale/static/src/js/models.js24
-rw-r--r--addons/point_of_sale/static/src/js/screens.js10
-rw-r--r--addons/point_of_sale/static/src/js/widget_base.js1
-rw-r--r--addons/point_of_sale/static/src/xml/pos.xml5
-rw-r--r--addons/pos_restaurant/static/src/js/splitbill.js2
-rw-r--r--addons/purchase/purchase.py6
-rw-r--r--addons/report/models/report.py2
-rw-r--r--addons/report/views/layouts.xml2
-rw-r--r--addons/sale_stock/sale_stock.py12
-rw-r--r--addons/stock/stock.py2
-rw-r--r--addons/stock/wizard/stock_transfer_details.py5
-rw-r--r--addons/web/controllers/main.py1
-rw-r--r--addons/web/static/src/js/views.js2
-rw-r--r--addons/web/static/src/xml/base.xml4
-rw-r--r--addons/website/static/src/js/website.translator.js6
-rw-r--r--addons/website/views/website_templates.xml4
27 files changed, 97 insertions, 47 deletions
diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py
index 520b3ddad80..1caddec7f37 100644
--- a/addons/account/account_move_line.py
+++ b/addons/account/account_move_line.py
@@ -1272,7 +1272,7 @@ class account_move_line(osv.osv):
period = period_obj.browse(cr, uid, period_id, context=context)
for (state,) in result:
if state == 'done':
- raise UserError(_('You can not add/modify entries in a closed period %s of journal %s.') % (period.name,journal.name))
+ raise UserError(_('You can not add/modify entries in a closed period %s of journal %s.') % (period.name, journal.name))
if not result:
jour_period_obj.create(cr, uid, {
'name': (journal.code or journal.name)+':'+(period.name or ''),
diff --git a/addons/base_import/models.py b/addons/base_import/models.py
index 9778391521a..784ae7f49f1 100644
--- a/addons/base_import/models.py
+++ b/addons/base_import/models.py
@@ -158,12 +158,19 @@ class ir_import(orm.TransientModel):
all the fields to traverse
:rtype: list(Field)
"""
+ string_match = None
for field in fields:
# FIXME: should match all translations & original
# TODO: use string distance (levenshtein? hamming?)
- if header.lower() == field['name'].lower() \
- or header.lower() == field['string'].lower():
+ if header.lower() == field['name'].lower():
return [field]
+ if header.lower() == field['string'].lower():
+ # matching string are not reliable way because
+ # strings have no unique constraint
+ string_match = field
+ if string_match:
+ # this behavior is only applied if there is no matching field['name']
+ return [string_match]
if '/' not in header:
return []
diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py
index ea0eef6535d..4bcd2e58905 100644
--- a/addons/calendar/calendar.py
+++ b/addons/calendar/calendar.py
@@ -480,13 +480,13 @@ class calendar_alarm_manager(osv.AbstractModel):
def get_next_notif(self, cr, uid, context=None):
ajax_check_every_seconds = 300
- partner = self.pool['res.users'].read(cr, SUPERUSER_ID, uid, ['calendar_last_notif_ack'], context=context)
+ partner = self.pool['res.users'].read(cr, SUPERUSER_ID, uid, ['partner_id', 'calendar_last_notif_ack'], context=context)
all_notif = []
if not partner:
return []
- all_events = self.get_next_potential_limit_alarm(cr, uid, ajax_check_every_seconds, partner_id=partner['id'], mail=False, context=context)
+ all_events = self.get_next_potential_limit_alarm(cr, uid, ajax_check_every_seconds, partner_id=partner['partner_id'][0], mail=False, context=context)
for event in all_events: # .values()
max_delta = all_events[event]['max_duration']
@@ -586,7 +586,7 @@ class calendar_alarm(osv.Model):
def _update_cron(self, cr, uid, context=None):
try:
cron = self.pool['ir.model.data'].get_object(
- cr, uid, 'calendar', 'ir_cron_scheduler_alarm', context=context)
+ cr, SUPERUSER_ID, 'calendar', 'ir_cron_scheduler_alarm', context=context)
except ValueError:
return False
return cron.toggle(model=self._name, domain=[('type', '=', 'email')])
diff --git a/addons/google_calendar/google_calendar.py b/addons/google_calendar/google_calendar.py
index 1eb3f918d3e..df90f78f5d1 100644
--- a/addons/google_calendar/google_calendar.py
+++ b/addons/google_calendar/google_calendar.py
@@ -976,7 +976,9 @@ class calendar_event(osv.Model):
_inherit = "calendar.event"
def get_fields_need_update_google(self, cr, uid, context=None):
- return ['name', 'description', 'allday', 'date', 'date_end', 'stop', 'attendee_ids', 'alarm_ids', 'location', 'class', 'active']
+ return ['name', 'description', 'allday', 'start', 'date_end', 'stop',
+ 'attendee_ids', 'alarm_ids', 'location', 'class', 'active',
+ 'start_date', 'start_datetime', 'stop_date', 'stop_datetime']
def write(self, cr, uid, ids, vals, context=None):
if context is None:
diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index 2e0823add68..ac4154e80d0 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -319,7 +319,7 @@ class mail_compose_message(osv.TransientModel):
# static wizard (mail.message) values
mail_values = {
'subject': wizard.subject,
- 'body': wizard.body,
+ 'body': wizard.body or '',
'parent_id': wizard.parent_id and wizard.parent_id.id,
'partner_ids': [partner.id for partner in wizard.partner_ids],
'attachment_ids': [attach.id for attach in wizard.attachment_ids],
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py
index fbcee18d3e4..851f7368497 100644
--- a/addons/mrp/mrp.py
+++ b/addons/mrp/mrp.py
@@ -214,6 +214,8 @@ class mrp_bom(osv.osv):
@param properties: List of related properties.
@return: False or BoM id.
"""
+ if not context:
+ context = {}
if properties is None:
properties = []
if product_id:
@@ -231,6 +233,8 @@ class mrp_bom(osv.osv):
else:
# neither product nor template, makes no sense to search
return False
+ if context.get('company_id'):
+ domain = domain + [('company_id', '=', context['company_id'])]
domain = domain + [ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATE_FORMAT)),
'|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATE_FORMAT))]
# order to prioritize bom with product_id over the one without
diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py
index 8eb61d6c5cc..a0a9863491e 100644
--- a/addons/mrp/procurement.py
+++ b/addons/mrp/procurement.py
@@ -87,7 +87,7 @@ class procurement_order(osv.osv):
else:
properties = [x.id for x in procurement.property_ids]
bom_id = bom_obj._bom_find(cr, uid, product_id=procurement.product_id.id,
- properties=properties, context=context)
+ properties=properties, context=dict(context, company_id=procurement.company_id.id))
bom = bom_obj.browse(cr, uid, bom_id, context=context)
routing_id = bom.routing_id.id
return {
diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py
index fa73c994a38..77e3b0d27b6 100644
--- a/addons/mrp/stock.py
+++ b/addons/mrp/stock.py
@@ -44,6 +44,23 @@ class StockMove(osv.osv):
if move.raw_material_production_id and move.location_dest_id.usage == 'production' and move.raw_material_production_id.product_id.track_production and not move.consumed_for:
raise UserError(_("Because the product %s requires it, you must assign a serial number to your raw material %s to proceed further in your production. Please use the 'Produce' button to do so.") % (move.raw_material_production_id.product_id.name, move.product_id.name))
+ # TODO master: remove me, no longer used
+ def _check_phantom_bom(self, cr, uid, move, context=None):
+ """check if product associated to move has a phantom bom
+ return list of ids of mrp.bom for that product """
+ user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id
+ #doing the search as SUPERUSER because a user with the permission to write on a stock move should be able to explode it
+ #without giving him the right to read the boms.
+ domain = [
+ '|', ('product_id', '=', move.product_id.id),
+ '&', ('product_id', '=', False), ('product_tmpl_id.product_variant_ids', '=', move.product_id.id),
+ ('type', '=', 'phantom'),
+ '|', ('date_start', '=', False), ('date_start', '<=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
+ '|', ('date_stop', '=', False), ('date_stop', '>=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)),
+ ('company_id', '=', user_company)]
+ return self.pool.get('mrp.bom').search(cr, SUPERUSER_ID, domain, context=context)
+
+
def _action_explode(self, cr, uid, move, context=None):
""" Explodes pickings.
@param move: Stock moves
diff --git a/addons/mrp_operations/mrp_operations.py b/addons/mrp_operations/mrp_operations.py
index 86a50626558..d86c8e6cd63 100644
--- a/addons/mrp_operations/mrp_operations.py
+++ b/addons/mrp_operations/mrp_operations.py
@@ -337,7 +337,7 @@ class mrp_production(osv.osv):
for po in self.browse(cr, uid, ids, context=context):
direction[po.id] = cmp(po.date_start, vals.get('date_start', False))
result = super(mrp_production, self).write(cr, uid, ids, vals, context=context)
- if (vals.get('workcenter_lines', False) or vals.get('date_start', False)) and update:
+ if (vals.get('workcenter_lines', False) or vals.get('date_start', False) or vals.get('date_planned', False)) and update:
self._compute_planned_workcenter(cr, uid, ids, context=context, mini=mini)
for d in direction:
if direction[d] == 1:
diff --git a/addons/payment_adyen/models/adyen.py b/addons/payment_adyen/models/adyen.py
index 52336cb48d9..6539ebb5ae0 100644
--- a/addons/payment_adyen/models/adyen.py
+++ b/addons/payment_adyen/models/adyen.py
@@ -172,7 +172,7 @@ class TxAdyen(osv.Model):
})
return True
else:
- error = _('Paypal: feedback error')
+ error = _('Adyen: feedback error')
_logger.info(error)
tx.write({
'state': 'error',
diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py
index d1c4dff4cec..c8b07da4cc6 100644
--- a/addons/point_of_sale/point_of_sale.py
+++ b/addons/point_of_sale/point_of_sale.py
@@ -1362,9 +1362,9 @@ class pos_order_line(osv.osv):
'name': fields.char('Line No', required=True, copy=False),
'notice': fields.char('Discount Notice'),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True, change_default=True),
- 'price_unit': fields.float(string='Unit Price', digits_compute=dp.get_precision('Account')),
+ 'price_unit': fields.float(string='Unit Price', digits_compute=dp.get_precision('Product Price')),
'qty': fields.float('Quantity', digits_compute=dp.get_precision('Product UoS')),
- 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Account'), string='Subtotal w/o Tax', store=True),
+ 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Product Price'), string='Subtotal w/o Tax', store=True),
'price_subtotal_incl': fields.function(_amount_line_all, multi='pos_order_line_amount', digits_compute=dp.get_precision('Account'), string='Subtotal', store=True),
'discount': fields.float('Discount (%)', digits_compute=dp.get_precision('Account')),
'order_id': fields.many2one('pos.order', 'Order Ref', ondelete='cascade'),
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index ba751839ab1..4976d8da07e 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -1646,34 +1646,34 @@ openerp.point_of_sale.load_models = function load_models(instance, module){ //mo
},
/* ---- Payment Status --- */
get_subtotal : function(){
- return this.orderlines.reduce((function(sum, orderLine){
+ return round_pr(this.orderlines.reduce((function(sum, orderLine){
return sum + orderLine.get_display_price();
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_total_with_tax: function() {
- return this.orderlines.reduce((function(sum, orderLine) {
+ return round_pr(this.orderlines.reduce((function(sum, orderLine) {
return sum + orderLine.get_price_with_tax();
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_total_without_tax: function() {
- return this.orderlines.reduce((function(sum, orderLine) {
+ return round_pr(this.orderlines.reduce((function(sum, orderLine) {
return sum + orderLine.get_price_without_tax();
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_total_discount: function() {
- return this.orderlines.reduce((function(sum, orderLine) {
+ return round_pr(this.orderlines.reduce((function(sum, orderLine) {
return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity());
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_total_tax: function() {
- return this.orderlines.reduce((function(sum, orderLine) {
+ return round_pr(this.orderlines.reduce((function(sum, orderLine) {
return sum + orderLine.get_tax();
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_total_paid: function() {
- return this.paymentlines.reduce((function(sum, paymentLine) {
+ return round_pr(this.paymentlines.reduce((function(sum, paymentLine) {
return sum + paymentLine.get_amount();
- }), 0);
+ }), 0), this.pos.currency.rounding);
},
get_tax_details: function(){
var details = {};
diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js
index b31472cb63e..0e817695a6d 100644
--- a/addons/point_of_sale/static/src/js/screens.js
+++ b/addons/point_of_sale/static/src/js/screens.js
@@ -1453,6 +1453,7 @@ openerp.point_of_sale.load_screens = function load_screens(instance, module){ //
this.inputbuffer = "";
this.firstinput = true;
+ this.decimal_point = instance.web._t.database.parameters.decimal_point;
// This is a keydown handler that prevents backspace from
// doing a back navigation
@@ -1515,7 +1516,14 @@ openerp.point_of_sale.load_screens = function load_screens(instance, module){ //
this.inputbuffer = newbuf;
var order = this.pos.get_order();
if (order.selected_paymentline) {
- order.selected_paymentline.set_amount(parseFloat(this.inputbuffer));
+ var amount;
+ try{
+ amount = instance.web.parse_value(this.inputbuffer, {type: "float"});
+ }
+ catch(e){
+ amount = 0;
+ }
+ order.selected_paymentline.set_amount(amount);
this.order_changes();
this.render_paymentlines();
this.$('.paymentline.selected .edit').text(this.inputbuffer);
diff --git a/addons/point_of_sale/static/src/js/widget_base.js b/addons/point_of_sale/static/src/js/widget_base.js
index a391b3d19d3..a4006723fe8 100644
--- a/addons/point_of_sale/static/src/js/widget_base.js
+++ b/addons/point_of_sale/static/src/js/widget_base.js
@@ -48,6 +48,7 @@ openerp.point_of_sale.load_basewidget = function load_basewidget(instance, modul
if (typeof amount === 'number') {
amount = round_di(amount,decimals).toFixed(decimals);
+ amount = openerp.instances[this.session.name].web.format_value(parseFloat(amount), { type : 'float' });
}
return amount;
diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml
index 449e5511dc9..9e5ce7e5008 100644
--- a/addons/point_of_sale/static/src/xml/pos.xml
+++ b/addons/point_of_sale/static/src/xml/pos.xml
@@ -1174,7 +1174,10 @@
<div class='paymentline-name'>
<t t-esc="line.name"/>
</div>
- <input class='paymentline-input' type="number" step="0.01" t-att-value="line.get_amount_str()" />
+ <input class='paymentline-input'
+ t-att-type="widget.decimal_point === '.' ? 'number' : 'text'"
+ t-attf-pattern="[0-9]+([\\#{widget.decimal_point || '.' }][0-9]+)?"
+ step="0.01" t-att-value="line.get_amount_str()" />
<span class='paymentline-delete'>
<img src="/point_of_sale/static/src/img/search_reset.gif" />
</span>
diff --git a/addons/pos_restaurant/static/src/js/splitbill.js b/addons/pos_restaurant/static/src/js/splitbill.js
index f3d672ca7ac..519bc7104c0 100644
--- a/addons/pos_restaurant/static/src/js/splitbill.js
+++ b/addons/pos_restaurant/static/src/js/splitbill.js
@@ -43,7 +43,7 @@ openerp.pos_restaurant.load_splitbill = function(instance, module){
}
}else{
if( split.quantity < line.get_quantity()){
- split.quantity += line.get_unit().rounding;
+ split.quantity += line.get_unit().is_unit ? 1 : line.get_unit().rounding;
if(split.quantity > line.get_quantity()){
split.quantity = line.get_quantity();
}
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index d0fde9e74ad..8c928e11b77 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -1666,7 +1666,7 @@ class account_invoice(osv.Model):
else:
user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
- for order in purchase_order_obj.browse(cr, uid, po_ids, context=context):
+ for order in purchase_order_obj.browse(cr, user_id, po_ids, context=context):
purchase_order_obj.message_post(cr, user_id, order.id, body=_("Invoice received"), context=context)
invoiced = []
shipped = True
@@ -1679,8 +1679,8 @@ class account_invoice(osv.Model):
if all(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines):
invoiced.append(po_line.id)
if invoiced and shipped:
- self.pool['purchase.order.line'].write(cr, uid, invoiced, {'invoiced': True})
- workflow.trg_write(uid, 'purchase.order', order.id, cr)
+ self.pool['purchase.order.line'].write(cr, user_id, invoiced, {'invoiced': True})
+ workflow.trg_write(user_id, 'purchase.order', order.id, cr)
return res
def confirm_paid(self, cr, uid, ids, context=None):
diff --git a/addons/report/models/report.py b/addons/report/models/report.py
index 604bf5aa37b..11937235a77 100644
--- a/addons/report/models/report.py
+++ b/addons/report/models/report.py
@@ -39,7 +39,6 @@ import lxml.html
import os
import subprocess
from contextlib import closing
-from datetime import datetime
from distutils.version import LooseVersion
from functools import partial
from pyPdf import PdfFileWriter, PdfFileReader
@@ -141,7 +140,6 @@ class Report(osv.Model):
context = dict(context, translatable=context.get('lang') != request.website.default_lang_code)
values.update(
time=time,
- datetime=datetime,
context_timestamp=lambda t: fields.datetime.context_timestamp(cr, uid, t, context),
translate_doc=translate_doc,
editable=True,
diff --git a/addons/report/views/layouts.xml b/addons/report/views/layouts.xml
index 620bfb9b3b5..37d93226e7f 100644
--- a/addons/report/views/layouts.xml
+++ b/addons/report/views/layouts.xml
@@ -124,7 +124,7 @@
<div class="header">
<div class="row">
<div class="col-xs-3">
- <span t-esc="context_timestamp(datetime.now()).strftime('%Y-%m-%d %H:%M')"/>
+ <span t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/>
</div>
<div class="col-xs-2 col-xs-offset-2 text-center">
<span t-esc="company.name"/>
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 80d3553284a..c849331d5e0 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -363,6 +363,14 @@ class sale_order_line(osv.osv):
res.update({'warning': warning})
return res
+ def button_cancel(self, cr, uid, ids, context=None):
+ lines = self.browse(cr, uid, ids, context=context)
+ for procurement in lines.mapped('procurement_ids'):
+ for move in procurement.move_ids:
+ if move.state == 'done' and not move.scrapped:
+ raise osv.except_osv(_('Invalid Action!'), _('You cannot cancel a sale order line which is linked to a stock move already done.'))
+ return super(sale_order_line, self).button_cancel(cr, uid, ids, context=context)
+
class stock_move(osv.osv):
_inherit = 'stock.move'
@@ -389,7 +397,7 @@ class stock_move(osv.osv):
if move.procurement_id and move.procurement_id.sale_line_id and move.procurement_id.sale_line_id.order_id.order_policy == 'picking':
sale_order = move.procurement_id.sale_line_id.order_id
return sale_order.partner_invoice_id, sale_order.user_id.id, sale_order.pricelist_id.currency_id.id
- elif move.picking_id.sale_id and context.get('inv_type') == 'out_invoice':
+ elif move.picking_id.sale_id and context.get('inv_type') in ('out_invoice', 'out_refund'):
# In case of extra move, it is better to use the same data as the original moves
sale_order = move.picking_id.sale_id
return sale_order.partner_invoice_id, sale_order.user_id.id, sale_order.pricelist_id.currency_id.id
@@ -397,7 +405,7 @@ class stock_move(osv.osv):
def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None):
res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context)
- if move.procurement_id and move.procurement_id.sale_line_id:
+ if inv_type in ('out_invoice', 'out_refund') and move.procurement_id and move.procurement_id.sale_line_id:
sale_line = move.procurement_id.sale_line_id
res['invoice_line_tax_id'] = [(6, 0, [x.id for x in sale_line.tax_id])]
res['account_analytic_id'] = sale_line.order_id.project_id and sale_line.order_id.project_id.id or False
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 6b8fb997fad..8a502a10b78 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -794,7 +794,7 @@ class stock_picking(osv.osv):
'name': fields.char('Reference', select=True, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, copy=False),
'origin': fields.char('Source Document', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="Reference of the document", select=True),
'backorder_id': fields.many2one('stock.picking', 'Back Order of', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="If this shipment was split, then this field links to the shipment which contains the already processed part.", select=True, copy=False),
- 'note': fields.text('Notes', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}),
+ 'note': fields.text('Notes'),
'move_type': fields.selection([('direct', 'Partial'), ('one', 'All at once')], 'Delivery Method', required=True, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, help="It specifies goods to be deliver partially or all at once"),
'state': fields.function(_state_get, type="selection", copy=False,
store={
diff --git a/addons/stock/wizard/stock_transfer_details.py b/addons/stock/wizard/stock_transfer_details.py
index 17f302f6317..437509aacf3 100644
--- a/addons/stock/wizard/stock_transfer_details.py
+++ b/addons/stock/wizard/stock_transfer_details.py
@@ -91,7 +91,7 @@ class stock_transfer_details(models.TransientModel):
'owner_id': prod.owner_id.id,
}
if prod.packop_id:
- prod.packop_id.write(pack_datas)
+ prod.packop_id.with_context(no_recompute=True).write(pack_datas)
processed_ids.append(prod.packop_id.id)
else:
pack_datas['picking_id'] = self.picking_id.id
@@ -99,8 +99,7 @@ class stock_transfer_details(models.TransientModel):
processed_ids.append(packop_id.id)
# Delete the others
packops = self.env['stock.pack.operation'].search(['&', ('picking_id', '=', self.picking_id.id), '!', ('id', 'in', processed_ids)])
- for packop in packops:
- packop.unlink()
+ packops.unlink()
# Execute the transfer of the picking
self.picking_id.do_transfer()
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index 43efd2c38d7..5aaf63d034f 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -1183,6 +1183,7 @@ class Binary(http.Controller):
}
except Exception:
args = {'error': "Something horrible happened"}
+ _logger.exception("Fail to upload attachment %s" % ufile.filename)
return out % (simplejson.dumps(callback), simplejson.dumps(args))
@http.route([
diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js
index d0f77b77593..73cb4e1161c 100644
--- a/addons/web/static/src/js/views.js
+++ b/addons/web/static/src/js/views.js
@@ -1023,7 +1023,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
init: function(parent) {
var self = this;
this._super(parent);
- var view = this.getParent();
+ this.view = this.getParent();
this.sections = [
{ 'name' : 'print', 'label' : _t('Print'), },
{ 'name' : 'other', 'label' : _t('More'), }
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 379b28597ef..39173add5c6 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -625,12 +625,12 @@
</t>
<a class="oe_file_attachment" t-att-title="item.title or ''" t-att-data-section="section.name" t-att-data-index="item_index" t-att-href="item.url">
<t t-raw="item.label"/>
- <span t-if="section.name == 'files' and !item.callback" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">
+ <span t-if="widget.view.is_action_enabled('edit') &amp;&amp; section.name == 'files' and !item.callback" class="oe_sidebar_delete_item" t-att-data-id="item.id" title="Delete this attachment">
<i class="fa fa-trash-o"/>
</span>
</a>
</li>
- <li t-if="section.name == 'files'" class="oe_sidebar_add_attachment">
+ <li t-if="widget.view.is_action_enabled('edit') &amp;&amp; section.name == 'files'" class="oe_sidebar_add_attachment">
<t t-call="HiddenInputFile">
<t t-set="fileupload_id" t-value="widget.fileupload_id"/>
<t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t>
diff --git a/addons/website/static/src/js/website.translator.js b/addons/website/static/src/js/website.translator.js
index 12f6a1397f8..64683f7001f 100644
--- a/addons/website/static/src/js/website.translator.js
+++ b/addons/website/static/src/js/website.translator.js
@@ -60,9 +60,11 @@
ev.preventDefault();
var link = $('.js_language_selector a[data-default-lang]')[0];
if (link) {
- link.pathname = $(link).data('lang') + link.pathname;
link.search += (link.search ? '&' : '?') + 'enable_editor=1';
- window.location = link.attributes.href.value;
+ var url = link.pathname + link.search + window.location.hash;
+ link.pathname = '/website/lang/default';
+ link.search = '?' + $.param({r: url});
+ window.location = link.href;
}
},
translate: function () {
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index b8bdb8e0edd..071c7ff636d 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -92,8 +92,8 @@
<t t-set="languages" t-value="website.get_languages() if website else None"/>
<t t-if="request and request.website_multilang and website">
- <t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lang">
- <link rel="alternate" t-att-hreflang="lang['hreflang']" t-att-href="lang['href']"/>
+ <t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lg">
+ <link rel="alternate" t-att-hreflang="lg['hreflang']" t-att-href="lg['href']"/>
</t>
</t>