diff --git a/addons/mass_mailing/static/src/css/email_template.css b/addons/mass_mailing/static/src/css/email_template.css index f0b25ba612d..edd9c0c3f0d 100644 --- a/addons/mass_mailing/static/src/css/email_template.css +++ b/addons/mass_mailing/static/src/css/email_template.css @@ -9,6 +9,7 @@ } .kanban_html_preview { + pointer-events: none; width: 600px; -webkit-transform: scale(.50); -ms-transform: scale(.50); diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 8b02ee687b3..4d886bed176 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -256,8 +256,8 @@ class SaleOrder(models.Model): @api.model def create(self, vals): - if vals.get('name', 'New') == 'New': - vals['name'] = self.env['ir.sequence'].next_by_code('sale.order') or 'New' + if vals.get('name', _('New')) == _('New'): + vals['name'] = self.env['ir.sequence'].next_by_code('sale.order') or _('New') # Makes sure partner_invoice_id', 'partner_shipping_id' and 'pricelist_id' are defined if any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']): diff --git a/addons/sale_stock/models/sale_order.py b/addons/sale_stock/models/sale_order.py index dad6be47932..49f8652719d 100644 --- a/addons/sale_stock/models/sale_order.py +++ b/addons/sale_stock/models/sale_order.py @@ -184,7 +184,8 @@ class SaleOrderLine(models.Model): qty = 0.0 for move in self.procurement_ids.mapped('move_ids').filtered(lambda r: r.state == 'done' and not r.scrapped): if move.location_dest_id.usage == "customer": - qty += move.product_uom._compute_quantity(move.product_uom_qty, self.product_uom) + if not move.origin_returned_move_id: + qty += move.product_uom._compute_quantity(move.product_uom_qty, self.product_uom) elif move.location_dest_id.usage == "internal" and move.to_refund_so: qty -= move.product_uom._compute_quantity(move.product_uom_qty, self.product_uom) return qty diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index 5aede1cda52..0548a7e5ad7 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -573,7 +573,7 @@ class Warehouse(models.Model): routes = self.env['stock.location.route'].search([('supplied_wh_id', 'in', self.ids)]) self.env['procurement.rule'].search([ '&', ('route_id', 'in', routes.ids), - ('location_src_id.usage', '=', 'transit')]).write({'location_id': new_location}) + ('location_src_id.usage', '=', 'transit')]).write({'location_id': new_location.id}) @api.multi def _update_routes(self): diff --git a/addons/web/static/src/less/form_view.less b/addons/web/static/src/less/form_view.less index 22ce69a194f..d315bc3ada2 100644 --- a/addons/web/static/src/less/form_view.less +++ b/addons/web/static/src/less/form_view.less @@ -179,7 +179,7 @@ .o_form_invalid { &.o_form_input, .o_form_input, &.o_form_textarea, .o_form_textarea { - border-color: @brand-danger; + border-color: @brand-danger!important; // enterprise o_form_required rule overrides this without !important } } diff --git a/addons/web_calendar/static/src/js/web_calendar.js b/addons/web_calendar/static/src/js/web_calendar.js index f8f7317e93c..d6e2c5f6998 100644 --- a/addons/web_calendar/static/src/js/web_calendar.js +++ b/addons/web_calendar/static/src/js/web_calendar.js @@ -642,8 +642,8 @@ var CalendarView = View.extend({ date_stop = m_start.toDate(); } var r = { - 'start': moment(date_start).format('YYYY-MM-DD HH:mm:ss'), - 'end': moment(date_stop).format('YYYY-MM-DD HH:mm:ss'), + 'start': moment(date_start).toISOString(), + 'end': moment(date_stop).toISOString(), 'title': the_title, 'allDay': (this.fields[this.date_start].type == 'date' || (this.all_day && evt[this.all_day]) || false), 'id': evt.id, diff --git a/addons/web_editor/static/src/js/transcoder.js b/addons/web_editor/static/src/js/transcoder.js index 20d4f5844af..fa7b4023377 100644 --- a/addons/web_editor/static/src/js/transcoder.js +++ b/addons/web_editor/static/src/js/transcoder.js @@ -98,20 +98,28 @@ var getMatchedCSSRules = function (a) { if (style.display === 'block') { delete style.display; } - if (style['margin-top']) { - style.margin = (style['margin-top'] || 0) + ' ' + (style['margin-right'] || 0) + ' ' + (style['margin-bottom'] || 0) + ' ' + (style['margin-left'] || 0); - delete style['margin-top']; - delete style['margin-right']; - delete style['margin-bottom']; - delete style['margin-left']; - } - if (style['padding-top']) { - style.padding = (style['padding-top'] || 0) + ' ' + (style['padding-right'] || 0) + ' ' + (style['padding-bottom'] || 0) + ' ' + (style['padding-left'] || 0); - delete style['padding-top']; - delete style['padding-right']; - delete style['padding-bottom']; - delete style['padding-left']; - } + + _.each(['margin', 'padding'], function(p) { + if (style[p+'-top'] || style[p+'-right'] || style[p+'-bottom'] || style[p+'-left']) { + if (style[p+'-top'] === style[p+'-right'] && style[p+'-top'] === style[p+'-bottom'] && style[p+'-top'] === style[p+'-left']) { + // keep => property: [top/right/bottom/left value]; + style[p] = style[p+'-top']; + } + else { + // keep => property: [top value] [right value] [bottom value] [left value]; + style[p] = (style[p+'-top'] || 0) + ' ' + (style[p+'-right'] || 0) + ' ' + (style[p+'-bottom'] || 0) + ' ' + (style[p+'-left'] || 0); + if (style[p].indexOf('inherit') !== -1 || style[p].indexOf('initial') !== -1) { + // keep => property-top: [top value]; property-right: [right value]; property-bottom: [bottom value]; property-left: [left value]; + delete style[p]; + return; + } + } + delete style[p+'-top']; + delete style[p+'-right']; + delete style[p+'-bottom']; + delete style[p+'-left']; + } + }); return style; }; diff --git a/addons/web_editor/static/src/xml/backend.xml b/addons/web_editor/static/src/xml/backend.xml index 4035752cea5..5c85996e890 100644 --- a/addons/web_editor/static/src/xml/backend.xml +++ b/addons/web_editor/static/src/xml/backend.xml @@ -38,11 +38,11 @@ -webkit-border-radius: 3px; border-radius: 3px; background: white;"> + - diff --git a/addons/web_kanban/static/src/js/kanban_view.js b/addons/web_kanban/static/src/js/kanban_view.js index 2d6f8e7cd11..636be2ac2ab 100644 --- a/addons/web_kanban/static/src/js/kanban_view.js +++ b/addons/web_kanban/static/src/js/kanban_view.js @@ -63,7 +63,7 @@ var KanbanView = View.extend({ this.qweb = new QWeb(session.debug, {_s: session.origin}); this.limit = this.options.limit || parseInt(this.fields_view.arch.attrs.limit, 10) || 40; - this.fields = {}; + this.fields = this.fields_view.fields; this.fields_keys = _.keys(this.fields_view.fields); this.grouped = undefined; this.group_by_field = undefined; @@ -105,7 +105,7 @@ var KanbanView = View.extend({ this.qweb.add_template(utils.json_node_to_xml(child)); break; } else if (child.tag === 'field') { - var ftype = child.attrs.widget || this.fields_view.fields[child.attrs.name].type; + var ftype = child.attrs.widget || this.fields[child.attrs.name].type; if(ftype === "many2many" && "context" in child.attrs) { this.m2m_context[child.attrs.name] = child.attrs.context; } @@ -122,7 +122,7 @@ var KanbanView = View.extend({ do_search: function(domain, context, group_by) { var self = this; var group_by_field = group_by[0] || this.default_group_by; - var field = this.fields_view.fields[group_by_field]; + var field = this.fields[group_by_field]; var options = {}; var fields_def; if (field === undefined) { @@ -248,7 +248,7 @@ var KanbanView = View.extend({ _.each(groups, function (group) { var value = group.attributes.value; group.id = value instanceof Array ? value[0] : value; - var field = self.fields_view.fields[options.group_by_field]; + var field = self.fields[options.group_by_field]; if (field && field.type === "selection") { value= _.find(field.selection, function (s) { return s[0] === group.id; }); } @@ -304,7 +304,7 @@ var KanbanView = View.extend({ return this._super(action); }, has_active_field: function() { - return this.fields_view.fields.active; + return this.fields.active; }, _is_quick_create_enabled: function() { if (!this.quick_creatable || !this.is_action_enabled('create')) @@ -465,7 +465,7 @@ var KanbanView = View.extend({ var self = this; // Drag'n'drop activation/deactivation - var group_by_field_attrs = this.fields_view.fields[this.group_by_field] || this.fields[this.group_by_field]; + var group_by_field_attrs = this.fields[this.group_by_field]; // Deactivate the drag'n'drop if: // - field is a date or datetime since we group by month diff --git a/odoo/addons/base/ir/ir_qweb/fields.py b/odoo/addons/base/ir/ir_qweb/fields.py index c7dadb1ce8f..f0c7d576672 100644 --- a/odoo/addons/base/ir/ir_qweb/fields.py +++ b/odoo/addons/base/ir/ir_qweb/fields.py @@ -122,7 +122,7 @@ class IntegerConverter(models.AbstractModel): @api.model def value_to_html(self, value, options): - return unicodifier(self.user_lang().format('%d', value, grouping=True)) + return unicodifier(self.user_lang().format('%d', value, grouping=True).replace(r'-', u'\u2011')) class FloatConverter(models.AbstractModel): @@ -142,7 +142,7 @@ class FloatConverter(models.AbstractModel): value = float_utils.float_round(value, precision_digits=precision) fmt = '%.{precision}f'.format(precision=precision) - formatted = self.user_lang().format(fmt, value, grouping=True) + formatted = self.user_lang().format(fmt, value, grouping=True).replace(r'-', u'\u2011') # %f does not strip trailing zeroes. %g does but its precision causes # it to switch to scientific notation starting at a million *and* to @@ -322,7 +322,7 @@ class MonetaryConverter(models.AbstractModel): lang = self.user_lang() formatted_amount = lang.format(fmt, display_currency.round(value), - grouping=True, monetary=True).replace(r' ', u'\N{NO-BREAK SPACE}') + grouping=True, monetary=True).replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'\u2011') pre = post = u'' if display_currency.position == 'before': diff --git a/odoo/addons/test_converter/tests/test_html.py b/odoo/addons/test_converter/tests/test_html.py index d084e0c4055..85d2c511fcd 100644 --- a/odoo/addons/test_converter/tests/test_html.py +++ b/odoo/addons/test_converter/tests/test_html.py @@ -72,8 +72,8 @@ class TestFloatExport(TestBasicExport): def test_float(self): converter = self.get_converter('float') - value = converter(42.0) - self.assertEqual(value, "42.0") + value = converter(-42.0) + self.assertEqual(value, u"\u201142.0") value = converter(42.0100) self.assertEqual(value, "42.01") @@ -115,12 +115,12 @@ class TestCurrencyExport(TestExport): def test_currency_post(self): currency = self.create(self.Currency, name="Test", symbol=u"test") - obj = self.create(self.Model, value=0.12) + obj = self.create(self.Model, value=-0.12) converted = self.convert(obj, dest=currency) self.assertEqual( - converted, '0.12' + converted, '\u20110.12' u'\N{NO-BREAK SPACE}{symbol}'.format( obj=obj, symbol=currency.symbol.encode('utf-8')