From 78a556601e6b1e72c6d1ac776e31588dd2ffa28f Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Tue, 23 Jan 2018 14:10:48 +0100 Subject: [PATCH 01/70] [FIX] web_editor: prevent crash when dropping snippets For some unknown reasons, the editor sometimes crashes when dropping a snippet. As a temporary fix, the non-critical line that causes the problem is try/catch protected by this commit. --- addons/web_editor/static/src/js/rte.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js index 20c70e9d235..7748ccf7762 100644 --- a/addons/web_editor/static/src/js/rte.js +++ b/addons/web_editor/static/src/js/rte.js @@ -280,7 +280,15 @@ var RTE = Widget.extend({ } else { rng = $editable.data('range') || rng; } - rng.select(); + try { + // TODO this line might break for unknown reasons. I suppose that + // the created range is an invalid one. As it might be tricky to + // adapt that line and that it is not a critical one, temporary fix + // is to ignore the errors that this generates. + rng.select(); + } catch (e) { + console.log('error', e); + } history.recordUndo($editable, event, internal_history); }, /** From 2fad2e43b855e728f0534012012ec3720035768c Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Tue, 23 Jan 2018 16:16:20 +0100 Subject: [PATCH 02/70] [FIX] web_editor: solve all triple-click issues ... hopefully. This *must* be forward-ported. Depending on the browser, the triple-click behavior is different. This is especially problematic on Chrome, where blank characters at the start of the neighbor of the clicked element are selected. A weak attempt to solve that was made by commit https://github.com/odoo/odoo/commit/b85bd358234684974f9af63bc5f28cfabb527767 This commit hopes to solve all the issues once and for all by fully reimplementing the triple-click for all browsers. The concept is simple: when a triple-click occurs, select the whole *inner* content of the deepest DOM *element* that was clicked. --- addons/web_editor/static/src/js/rte.js | 34 +++++++++----------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/addons/web_editor/static/src/js/rte.js b/addons/web_editor/static/src/js/rte.js index 7748ccf7762..adbc7d4bd49 100644 --- a/addons/web_editor/static/src/js/rte.js +++ b/addons/web_editor/static/src/js/rte.js @@ -583,8 +583,8 @@ var RTE = Widget.extend({ onEnableEditableArea: function ($editable) { }, - onMouseup: function (event) { - var $target = $(event.target); + onMouseup: function (ev) { + var $target = $(ev.target); var $editable = $target.closest('.o_editable'); if (!$editable.size()) { @@ -596,26 +596,16 @@ var RTE = Widget.extend({ self.historyRecordUndo($target, 'activate', true); },0); - // To Fix Google Chrome Tripleclick Issue, which selects the ending - // whitespace characters (so Tripleclicking then typing text will remove - // the whole paragraph instead of its content). - // http://stackoverflow.com/questions/38467334/why-does-google-chrome-always-add-space-after-selected-text - if ($.browser.chrome === true && event.originalEvent.detail === 3) { - var currentSelection = range.create(); - if (currentSelection.sc.parentNode === currentSelection.ec) { - _selectSC(currentSelection); - } else if (currentSelection.eo === 0) { - var $hasNext = $(currentSelection.sc).parent(); - while (!$hasNext.next().length && !$hasNext.is('body')) { - $hasNext = $hasNext.parent(); - } - if ($hasNext.next()[0] === currentSelection.ec) { - _selectSC(currentSelection); - } - } - } - function _selectSC(selection) { - range.create(selection.sc, selection.so, selection.sc, selection.sc.length).select(); + // Browsers select different content from one to another after a + // triple click (especially: if triple-clicking on a paragraph on + // Chrome, blank characters of the element following the paragraph are + // selected too) + // + // The triple click behavior is reimplemented for all browsers here + if (ev.originalEvent.detail === 3) { + // Select the whole content inside the deepest DOM element that was + // triple-clicked + range.create(ev.target, 0, ev.target, ev.target.childNodes.length).select(); } }, From d62a26a4295b1b4ae7755604cdc89c0188f4d41b Mon Sep 17 00:00:00 2001 From: Gustavo Valverde Date: Tue, 23 Jan 2018 13:55:52 -0400 Subject: [PATCH 03/70] [FIX] account_asset: Import UserError to show real error to user The UserError was not being imported, causing the crash of this warning Closes #22460 --- addons/account_asset/models/account_invoice.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/account_asset/models/account_invoice.py b/addons/account_asset/models/account_invoice.py index b993f40e907..f0fff5517c4 100644 --- a/addons/account_asset/models/account_invoice.py +++ b/addons/account_asset/models/account_invoice.py @@ -3,7 +3,8 @@ from datetime import datetime from dateutil.relativedelta import relativedelta -from odoo import api, fields, models +from odoo import api, fields, models, _ +from odoo.exceptions import UserError from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF import odoo.addons.decimal_precision as dp From edac5550ec4cf38236f54278c9f2e11a59c3ebbf Mon Sep 17 00:00:00 2001 From: Romain Derie Date: Thu, 25 Jan 2018 13:09:31 +0100 Subject: [PATCH 04/70] [FIX] website_blog: copy dict correctly The 'copy_vals' dict would refer to the same 'vals' dict since list are mutables. This was not the expected behavior. --- addons/website_blog/models/website_blog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py index e5c39e8b594..94c423b3153 100644 --- a/addons/website_blog/models/website_blog.py +++ b/addons/website_blog/models/website_blog.py @@ -209,7 +209,7 @@ class BlogPost(models.Model): def write(self, vals): result = True for post in self: - copy_vals = vals + copy_vals = dict(vals) if 'website_published' in vals and 'published_date' not in vals and post.published_date <= fields.Datetime.now(): copy_vals['published_date'] = vals['website_published'] and fields.Datetime.now() or False result &= super(BlogPost, self).write(copy_vals) From 7ee7262ccbc23a0e4d5fd241d6c740a6c80307c8 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Thu, 25 Jan 2018 13:31:39 +0100 Subject: [PATCH 05/70] [FIX] point_of_sale: include untaxed amounts in tax lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If some orders have no taxes (e.g. manual reimbursement with a negative amount) the sum of taxes lines gave a different result than the total amount sold. e.g.: order 1: price 10€, including 2€ for taxes order 2: price -5€, no taxes report: taxes: 20%, 2€ taxes, 8€ base amount total sold: 5€ 2+8 != 5 Also change line.price_subtotal as it was computed twice if there was two taxes on a line (although it will probably never happen in the pos) opw-805415 --- addons/point_of_sale/i18n/point_of_sale.pot | 6 ++++++ addons/point_of_sale/models/pos_order.py | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/i18n/point_of_sale.pot b/addons/point_of_sale/i18n/point_of_sale.pot index 47f0c69bb4e..93dbbeaea58 100644 --- a/addons/point_of_sale/i18n/point_of_sale.pot +++ b/addons/point_of_sale/i18n/point_of_sale.pot @@ -1649,6 +1649,12 @@ msgstr "" msgid "No sequence defined on the journal" msgstr "" +#. module: point_of_sale +#: code:addons/point_of_sale/models/pos_order.py:986 +#, python-format +msgid "No Taxes" +msgstr "" + #. module: point_of_sale #. openerp-web #: code:addons/point_of_sale/static/src/js/screens.js:2018 diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index be3879bbbd7..855ae283775 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -981,7 +981,10 @@ class ReportSaleDetails(models.AbstractModel): for tax in line_taxes['taxes']: taxes.setdefault(tax['id'], {'name': tax['name'], 'tax_amount':0.0, 'base_amount':0.0}) taxes[tax['id']]['tax_amount'] += tax['amount'] - taxes[tax['id']]['base_amount'] += line.price_subtotal + taxes[tax['id']]['base_amount'] += tax['base'] + else: + taxes.setdefault(0, {'name': _('No Taxes'), 'tax_amount':0.0, 'base_amount':0.0}) + taxes[0]['base_amount'] += line.price_subtotal_incl st_line_ids = self.env["account.bank.statement.line"].search([('pos_statement_id', 'in', orders.ids)]).ids if st_line_ids: From fb81c331f869a06ffa9332a294492d4307ea65b3 Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Thu, 25 Jan 2018 12:38:32 +0100 Subject: [PATCH 06/70] [FIX] web_editor: fix double Shift + Enter Pressing Shift + Enter twice was buggy because of small refactoring made by https://github.com/odoo/odoo/commit/c227b8fd88e0ed635a8e807501b559b46fee7786#diff-cc5180b5ec2395c1df5c4e475aff43fbL416 opw-806003 --- addons/web_editor/static/src/js/rte.summernote.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/web_editor/static/src/js/rte.summernote.js b/addons/web_editor/static/src/js/rte.summernote.js index 5f28c9510bb..b8f3198dae2 100644 --- a/addons/web_editor/static/src/js/rte.summernote.js +++ b/addons/web_editor/static/src/js/rte.summernote.js @@ -422,6 +422,9 @@ dom.isImg = function (node) { }; var fn_is_forbidden_node = dom.isForbiddenNode || function () {}; dom.isForbiddenNode = function (node) { + if (node.tagName === "BR") { + return false; + } return fn_is_forbidden_node(node) || $(node).is(".media_iframe_video"); }; var fn_is_img_font = dom.isImgFont || function () {}; From 25849e918651eba080dac3af4e4fcdc8f1280241 Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Thu, 25 Jan 2018 14:25:35 +0100 Subject: [PATCH 07/70] [FIX] web_editor: properly allow formatting text (normal/header 1/...) Sometimes the formatting buttons had no effect or formatted more than they should (like a whole column when triple clicking on a paragraph only). This was because of the `listBetween` function implementation. This is supposed to return all the nodes between one element and another one... but the logic is wrong without saying from which *point* to start and which *point* to end. For example, when asking the list between an element and its parent, the result is very wrong as there is no way to go from the beginning of an element to the beginning of its parent using the `walkPoint` function as the `listBetween` function is doing. Ideally, the function should be entirely fixed but this can be tricky. For now, the function is just extended to allow to specify points instead of nodes, and those are used by the `formatBlock` function to solve the current problem. --- addons/web_editor/static/src/js/summernote.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js index 1f2176f3751..cdf4329c0b9 100644 --- a/addons/web_editor/static/src/js/summernote.js +++ b/addons/web_editor/static/src/js/summernote.js @@ -703,10 +703,16 @@ dom.isRemovableEmptyNode = function (node) { dom.isForbiddenNode = function (node) { return node.tagName === "BR" || $(node).is(".fa, img"); }; -dom.listBetween = function (sc, ec) { +/** + * @todo 'so' and 'eo' were added as a bugfix and are not given everytime. They + * however should be as the function may be wrong without them (for example, + * when asking the list between an element and its parent, as there is no path + * from the beginning of the former to the beginning of the later). + */ +dom.listBetween = function (sc, ec, so, eo) { var nodes = []; var ancestor = dom.commonAncestor(sc, ec); - dom.walkPoint({'node': sc, 'offset': 0}, {'node': ec, 'offset': 0}, function (point) { + dom.walkPoint({'node': sc, 'offset': so || 0}, {'node': ec, 'offset': eo || 0}, function (point) { if (ancestor !== point.node || ancestor === sc || ancestor === ec) { nodes.push(point.node); } @@ -1923,7 +1929,7 @@ $.summernote.pluginEvents.formatBlock = function (event, editor, layoutInfo, sTa } // fix by odoo because if you select a style in a li with no p tag all the ul is wrapped by the style tag - var nodes = dom.listBetween(r.sc, r.ec); + var nodes = dom.listBetween(r.sc, r.ec, r.so, r.eo); for (var i=0; i Date: Tue, 23 Jan 2018 17:02:33 +0100 Subject: [PATCH 08/70] [FIX] web_editor: ready when translations ready $('web_editor.base').ready() returns a deferred that: - wait at least for $(document).ready() - wait at least for require('web.ajax').loadXML() - at most once starts translations configuration But there is an issue since there is unexpectedly no reference to the translations, whilst it should have also been ready when ready was resolved. This commit keep the reference so translations can be used after $('web_editor.base').ready() is resolved as it was before 7dfdfa0103. note: in 11.0 it should be solved with 29729769 (so fix is for [10,11[) opw-804148 closes #22522 --- addons/web_editor/static/src/js/base.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/addons/web_editor/static/src/js/base.js b/addons/web_editor/static/src/js/base.js index 7bf9c2aa641..3135f7def66 100644 --- a/addons/web_editor/static/src/js/base.js +++ b/addons/web_editor/static/src/js/base.js @@ -32,14 +32,13 @@ data.dom_ready = dom_ready; var all_ready; data.ready = function () { if (!all_ready) { - all_ready = $.when(dom_ready, ajax.loadXML()); + all_ready = dom_ready; if (!odoo._modules) { - all_ready.then(translations); + all_ready = all_ready.then(translations); } - } else { // can add async template - all_ready = $.when(dom_ready, ajax.loadXML()); } - return all_ready; + // also load new templates since previous ready call + return $.when(all_ready, ajax.loadXML()); }; function translations() { From 21c1b1acd34406d1c568a66976c69511a656861e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 25 Jan 2018 15:25:30 +0100 Subject: [PATCH 09/70] [FIX] web: add target=_blank to url field widgets Url in the web client are supposed to open in a new tab. This was the way it worked in v10.0 and was lost with the refactoring of the new views. We just reintroduce that behaviour with this commit. Closes github issue #22389 --- addons/web/static/src/js/fields/basic_fields.js | 1 + addons/web/static/tests/fields/basic_fields_tests.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 09406b43711..26e7d86fabc 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1068,6 +1068,7 @@ var UrlWidget = InputField.extend({ _renderReadonly: function () { this.$el.text(this.attrs.text || this.value) .addClass('o_form_uri o_text_overflow') + .attr('target', '_blank') .attr('href', this.value); } }); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 9ea423250e4..fdc8c530af8 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1073,7 +1073,7 @@ QUnit.module('basic_fields', { QUnit.module('UrlWidget'); QUnit.test('url widget in form view', function (assert) { - assert.expect(8); + assert.expect(9); var form = createView({ View: FormView, @@ -1093,6 +1093,8 @@ QUnit.module('basic_fields', { "should have a anchor with correct classes"); assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('href'), 'yop', "should have proper href link"); + assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').attr('target'), '_blank', + "should have target attribute set to _blank"); assert.strictEqual(form.$('a.o_form_uri.o_field_widget.o_text_overflow').text(), 'yop', "the value should be displayed properly"); From 842e02020b9d15ed32c9c8b1e4698674d49f61f1 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 25 Jan 2018 13:53:28 +0100 Subject: [PATCH 10/70] [FIX] purchase: change invoice date - Main currency: USD - Create a PO in EUR - Create an invoice from the PO - The invoice is in USD and the exchange rate is applied - Change the currency to EUR The conversion is not applied anymore. The original issue was that changing the date would overwrite any amount modified in the invoice. Actually, the dependency on the date is not really necessary. Indeed, this is supposed to help enconding invoices, but it is likely that: - If the PO is issued in a currency A, the bill received is in currency A. => no conversion necessary (solved from 11.1). - If the PO is issued in a currency A and the bill received is in currency B, the exchange rate used by the vendor is different from ours. => manual corrections are necessary Therefore, we remove the dependency on the date for the amount recomputation. However, we still use it in the onchange. This way: - the amount estimated should be close to the amount requested - we avoid unexpected recomputation of amounts Introduced with d8112b0238. opw-805926 --- addons/purchase/models/account_invoice.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/addons/purchase/models/account_invoice.py b/addons/purchase/models/account_invoice.py index 90c86f82d55..c602de4087e 100644 --- a/addons/purchase/models/account_invoice.py +++ b/addons/purchase/models/account_invoice.py @@ -85,13 +85,11 @@ class AccountInvoice(models.Model): self.purchase_id = False return {} - @api.onchange('currency_id', 'date_invoice') + @api.onchange('currency_id') def _onchange_currency_id(self): if self.currency_id: for line in self.invoice_line_ids.filtered(lambda r: r.purchase_line_id): - if line.purchase_id.currency_id != self.currency_id: - line.price_unit = line.purchase_id.currency_id.with_context(date=self.date_invoice)\ - .compute(line.purchase_line_id.price_unit, self.currency_id, round=False) + line.price_unit = line.purchase_id.currency_id.with_context(date=self.date_invoice).compute(line.purchase_line_id.price_unit, self.currency_id, round=False) @api.onchange('invoice_line_ids') def _onchange_origin(self): From 3afe5b65089b92a0df6d3056f3f123457d7a677c Mon Sep 17 00:00:00 2001 From: Nicolas Lempereur Date: Thu, 25 Jan 2018 17:39:46 +0100 Subject: [PATCH 11/70] [FIX] hr_timesheet: allow duplication of project When duplicating a project, a command [(6, _, ids)] may be generated. This fail with the commit aa8a39fc4f because all comodels records with id not in `ids` will have their inverse field unset. But eg. in the case of copy, this would trigger an error because this would be done to an empty recordset and unexpectedly trigger an error. opw-807655 closes #22525 --- addons/hr_timesheet/models/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index af27e3094a4..237e280ed65 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -67,7 +67,7 @@ class Task(models.Model): if 'project_id' in values: project_id = values.get('project_id') # a timesheet must have an analytic account (and a project) - if not project_id: + if self and not project_id: raise UserError(_('This task must have a project since they are linked to timesheets.')) self.sudo().mapped('timesheet_ids').write({ 'project_id': project_id, From 222cadda41539de03cb54a042c4f404bc03bf45d Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Thu, 25 Jan 2018 20:20:09 +0100 Subject: [PATCH 12/70] [FIX] base: sort ir.actions.act_window.view records deterministically --- openerp/addons/base/ir/ir_actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 963f4290be9..1c03a7ec5b6 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -430,7 +430,7 @@ class ir_actions_act_window_view(osv.osv): _name = 'ir.actions.act_window.view' _table = 'ir_act_window_view' _rec_name = 'view_id' - _order = 'sequence' + _order = 'sequence,id' _columns = { 'sequence': fields.integer('Sequence'), 'view_id': fields.many2one('ir.ui.view', 'View'), From 927e13436aaf42bb11d1e74fe8a78af9fed7b082 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Fri, 26 Jan 2018 08:32:35 +0100 Subject: [PATCH 13/70] [FIX] account: duplicated field `currency_exchange_journal_id` was duplicated due to forward port. opw-807839 --- addons/account/views/res_config_settings_views.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/account/views/res_config_settings_views.xml b/addons/account/views/res_config_settings_views.xml index 2b48b3c37a2..f61cf860d84 100644 --- a/addons/account/views/res_config_settings_views.xml +++ b/addons/account/views/res_config_settings_views.xml @@ -168,10 +168,6 @@