From 4c79aa8d9d57a4e7e5cde083d3f8fb755e0a8693 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Mon, 13 Mar 2017 15:56:45 +0100 Subject: [PATCH 01/11] [FIX] sale: translate default name at creation When a sale order is created from the interface, the name field is read-only so not given in the create call. However, if the create values are filled with the default value, the string 'New' is translated and the condition is not met in the create method. This commit makes the create consistent with the default `lambda self: _('New')` Fixes #15839 --- addons/sale/sale.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 83dcb3111df..22418745668 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -224,8 +224,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']): From 5b4f7c13f32f36d86805eb7865d8a077746181d8 Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Tue, 14 Mar 2017 11:41:48 +0100 Subject: [PATCH 02/11] [FIX] web_kanban: use string when group by selection In the kanban view, if we try to group by a selection field that is not defined in the arch, the key will be used as column name (instead of the string). A fix has already been pushed to load all the fields in this case (see 0e6eb96) but these fields were not correctly used in this particular case. --- addons/web_kanban/static/src/js/kanban_view.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban_view.js b/addons/web_kanban/static/src/js/kanban_view.js index ff669072413..a0ed0761dcf 100644 --- a/addons/web_kanban/static/src/js/kanban_view.js +++ b/addons/web_kanban/static/src/js/kanban_view.js @@ -65,7 +65,7 @@ var KanbanView = View.extend({ this.qweb.default_dict = _.clone(QWeb.default_dict); 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; @@ -106,7 +106,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; } @@ -123,7 +123,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) { @@ -247,7 +247,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; }); } @@ -303,7 +303,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')) @@ -376,7 +376,7 @@ var KanbanView = View.extend({ this.record_options = { editable: this.is_action_enabled('edit'), deletable: this.is_action_enabled('delete'), - fields: this.fields_view.fields, + fields: this.fields, qweb: this.qweb, model: this.model, read_only_mode: this.options.read_only_mode, @@ -427,7 +427,7 @@ var KanbanView = View.extend({ grouped_by_m2o: this.grouped_by_m2o, relation: this.relation, qweb: this.qweb, - fields: this.fields_view.fields, + fields: this.fields, quick_create: this._is_quick_create_enabled(), }; }, @@ -436,7 +436,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 From d32e275ad1e31dc0c52d37563e406d052d3d8a32 Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Tue, 14 Mar 2017 13:16:43 +0100 Subject: [PATCH 03/11] [FIX] web: force red color for invalid form elements When an input is saved with an invalid value, it gets the `o_form_invalid` class. This makes the border red. In enterprise, there was a bug as required inputs have also a different border color and the rule was more important. Unfortunately there is no avoiding the !important rule here. Indeed, other solutions would require to make more rules in enterprise or to change the order of files (which would create many problems). --- addons/web/static/src/less/form_view.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/less/form_view.less b/addons/web/static/src/less/form_view.less index ef0bcb44be4..da425d5a69f 100644 --- a/addons/web/static/src/less/form_view.less +++ b/addons/web/static/src/less/form_view.less @@ -174,7 +174,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 } } From a873890f2842cb238152717d83739465898acd68 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Tue, 14 Mar 2017 16:19:04 +0100 Subject: [PATCH 04/11] [FIX] mass_mailing: link in kanban - Go to Mass Mailing > Configuration > Mail Templates - In the Kanban view, find a template which contains a link (http, mailto, whatever) - Click on the link You are redirected to the link instead of being redirected to the record. opw-706047 --- addons/mass_mailing/static/src/css/email_template.css | 1 + 1 file changed, 1 insertion(+) 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); From 945679176a6e53cb7b20b1ba041323b9d1cd6a7e Mon Sep 17 00:00:00 2001 From: Pierre Masereel Date: Tue, 14 Mar 2017 16:46:42 +0100 Subject: [PATCH 05/11] [FIX] stock: warehouse check_reception_resupply When we are trying to change the reception route of a warehouse when there are existing resupply routes, we are getting a traceback. This bug comes from a migration error introduced in rev: https://github.com/odoo-dev/odoo/commit/70e1d5d5bc1a3cb325dbcb091fc2135e23084145 --- addons/stock/models/stock_warehouse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index a580f071848..40dfa3ace5c 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): From e542b450a34d5c3723c92cb95d7132a288c46e60 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 16 Mar 2017 13:15:46 +0100 Subject: [PATCH 06/11] [FIX] sale_stock: duplicate qty - Create a stockable product, create a SO selling 1 unit. - Confirm the SO, validate the Picking 1 => delivered qty is 1 - Return Picking 1 and validate Picking 2 => delivered qty is 1 - Return Picking 2 and validate Picking 3 => delivered qty is 2 The delivered quantity should remain 1. opw-715685 --- addons/sale_stock/sale_stock.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 63f03f4a64f..2f817e09978 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -197,7 +197,8 @@ class SaleOrderLine(models.Model): #Note that we don't decrease quantity for customer returns on purpose: these are exeptions that must be treated manually. Indeed, #modifying automatically the delivered quantity may trigger an automatic reinvoicing (refund) of the SO, which is definitively not wanted if move.location_dest_id.usage == "customer": - qty += self.env['product.uom']._compute_qty_obj(move.product_uom, move.product_uom_qty, self.product_uom) + if not move.origin_returned_move_id: + qty += self.env['product.uom']._compute_qty_obj(move.product_uom, move.product_uom_qty, self.product_uom) return qty @api.multi From f50ba68be72c8b63af87e8dcd0e726e5e3b77092 Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Thu, 16 Mar 2017 17:42:39 +0100 Subject: [PATCH 07/11] [FIX] web_editor: handle margin:initial correctly The transcoder (which transforms stylesheet rules to inline style) did some compression of the padding and margin css properties to not always have margin-top + margin-right + margin-bottom + margin-left. This could cause an issue when the value of margin or padding contained an initial or inherit value because browsers (at least firefox and google chrome) doesn't allow it. Thus the preview could for example have bigger veritcal spaces arround `

` tag than what was seen when editing. With this fix instead of invalid: margin:initial initial initial initial we have: margin:initial And instead of invalid: margin:initial 5px 6px 7px we have: margin-top: initial; margin-right: 5px; margin-bottom: 6px; margin-left: 7px; opw-706535 --- addons/web_editor/static/src/js/transcoder.js | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/addons/web_editor/static/src/js/transcoder.js b/addons/web_editor/static/src/js/transcoder.js index d327252b63d..306369cddfa 100644 --- a/addons/web_editor/static/src/js/transcoder.js +++ b/addons/web_editor/static/src/js/transcoder.js @@ -99,20 +99,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 a.className ? cache[a.tagName + "." +a.className] = style : style; }; From fb05d8845d92b1ca9013307664fa6d52be64aa3d Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Thu, 16 Mar 2017 16:07:29 +0100 Subject: [PATCH 08/11] [FIX] web_calendar: events not appearing in arabic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fullcalendar expect as `start` and `end` property of an event object: > When specifying Event Objects for events or eventSources, you may > specify a string in IETF format (ex: "Wed, 18 Oct 2009 13:00:00 EST"), > a string in ISO8601 format (ex: "2009-11-05T13:15:30Z") or a UNIX > timestamp. (as seen in https://fullcalendar.io/docs1/event_data/Event_Object/) Before this commit we could for example in arabic provide an invalid date string "٢٠١٧-٠٣-١٦ ١٦:٠٠:٠٦" instead of "2017-03-16 16:00:06". This commit solves this by always providing fullcalendar an ISO8601 date string. opw-705752 --- addons/web_calendar/static/src/js/web_calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_calendar/static/src/js/web_calendar.js b/addons/web_calendar/static/src/js/web_calendar.js index b98f155ad9a..89d125c48af 100644 --- a/addons/web_calendar/static/src/js/web_calendar.js +++ b/addons/web_calendar/static/src/js/web_calendar.js @@ -639,8 +639,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, From 508a002e699f6e0935b43798637a6603823d9524 Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Fri, 17 Mar 2017 07:39:39 +0100 Subject: [PATCH 09/11] [FIX] web_editor: glitch english several times When using the iframed editor with multilang selector (present if there is another lang installed than en_US) an "English" language was present before each translation language. opw-696891 --- addons/web_editor/static/src/xml/backend.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/web_editor/static/src/xml/backend.xml b/addons/web_editor/static/src/xml/backend.xml index 957f38dac3c..c5b668cc01a 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;"> + - From af64780a2d8df2ec5ec91bab4bc0cc0a7f2c050a Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 16 Mar 2017 15:46:38 +0100 Subject: [PATCH 10/11] [FIX] base: no-break hyphen - Create an invoice with two products - Each line has a long description (spread on 2 lines) - The second line has a negative value - Print the invoice (PDF) The amount spreads on two lines, split as: $ - 1,000.00 This is due to the wkhtmltopdf version with patched QT. Unfortunately, upgrading to the latest version 0.12.4 doesn't solve the problem. The solution is to replace the '-' by a non-breakable hyphen. opw-711002 --- openerp/addons/base/ir/ir_qweb.py | 8 ++++---- openerp/addons/test_converter/tests/test_html.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index 4d7e5a02061..ea996769f88 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -686,7 +686,7 @@ class IntegerConverter(osv.AbstractModel): context = {} lang_code = context.get('lang') or 'en_US' - return self.pool['res.lang'].format(cr, uid, [lang_code], '%d', value, grouping=True) + return self.pool['res.lang'].format(cr, uid, [lang_code], '%d', value, grouping=True).replace(r'-', u'\u2011') class FloatConverter(osv.AbstractModel): _name = 'ir.qweb.field.float' @@ -704,7 +704,7 @@ class FloatConverter(osv.AbstractModel): lang_code = context.get('lang') or 'en_US' lang = self.pool['res.lang'] - formatted = lang.format(cr, uid, [lang_code], fmt.format(precision=precision), value, grouping=True) + formatted = lang.format(cr, uid, [lang_code], fmt.format(precision=precision), 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 @@ -889,7 +889,7 @@ class MonetaryConverter(osv.AbstractModel): lang = self.pool['res.lang'] formatted_amount = lang.format(cr, uid, [lang_code], fmt, Currency.round(cr, uid, display_currency, from_amount), - 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': @@ -1056,7 +1056,7 @@ class QwebWidgetMonetary(osv.AbstractModel): lang_code = qwebcontext.context.get('lang') or 'en_US' formatted_amount = self.pool['res.lang'].format( qwebcontext.cr, qwebcontext.uid, [lang_code], fmt, inner, grouping=True, monetary=True - ).replace(r' ', u'\N{NO-BREAK SPACE}') + ).replace(r' ', u'\N{NO-BREAK SPACE}').replace(r'-', u'\u2011') pre = post = u'' if display.position == 'before': pre = u'{symbol}\N{NO-BREAK SPACE}' diff --git a/openerp/addons/test_converter/tests/test_html.py b/openerp/addons/test_converter/tests/test_html.py index 2f50602c115..5810e24c288 100644 --- a/openerp/addons/test_converter/tests/test_html.py +++ b/openerp/addons/test_converter/tests/test_html.py @@ -67,8 +67,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") @@ -120,7 +120,7 @@ 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) @@ -129,7 +129,7 @@ class TestCurrencyExport(TestExport): '' - '0.12' + u'\u20110.12' u'\N{NO-BREAK SPACE}{symbol}'.format( obj=obj, symbol=currency.symbol.encode('utf-8') From 22e7b6befb77005d1b1945977191ca11739f38fa Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Fri, 17 Mar 2017 11:11:42 +0100 Subject: [PATCH 11/11] [FIX] web_kanban: only give fields in view to record This commit partially reverts 5b4f7c1 where `fields_view.fields` had been replaced by `fields`, which could have been set to all fields in the model. This modification can sometimes lead to a problem, during the fields value transformation. The ID, which wasn't given previously is now parsed. When creating a new record, the field ID is not an integer but a string (representing the virtual ID). If the field is in the arch, it will be postprocessed (see https://github.com/odoo/odoo/blob/saas-11/addons/web/static/src/js/framework/data_manager.js#L201) and its type will become `id`. As this postprocessing is not done if the field in the view, the parsing was on the original type (integer) and not the special id type. --- addons/web_kanban/static/src/js/kanban_view.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban_view.js b/addons/web_kanban/static/src/js/kanban_view.js index a0ed0761dcf..30a3517a7bc 100644 --- a/addons/web_kanban/static/src/js/kanban_view.js +++ b/addons/web_kanban/static/src/js/kanban_view.js @@ -376,7 +376,7 @@ var KanbanView = View.extend({ this.record_options = { editable: this.is_action_enabled('edit'), deletable: this.is_action_enabled('delete'), - fields: this.fields, + fields: this.fields_view.fields, qweb: this.qweb, model: this.model, read_only_mode: this.options.read_only_mode, @@ -427,7 +427,7 @@ var KanbanView = View.extend({ grouped_by_m2o: this.grouped_by_m2o, relation: this.relation, qweb: this.qweb, - fields: this.fields, + fields: this.fields_view.fields, quick_create: this._is_quick_create_enabled(), }; },