From b522ab5772e19c41ea47484b80bca0dc054859a6 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 8 Mar 2018 10:42:31 +0100 Subject: [PATCH 01/23] [FIX] account: tax rounding - Set 'Round Globally' - Create an excluded tax of 10 % - Create an invoice for a product costing 34.55, and apply the tax. The tax on the invoice is 3.46, while the tax on the tax line is 3.45. When rounded in `compute_all`, the tax amount is 3.455, which is the value expected. However, the `create` method won't round this value before storing, leading to the inconsistency. We make sure to round the amount to the currency precision, so the value 3.46 is recorded. opw-1819902 --- addons/account/models/account_invoice.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py index 89348f2dacc..7939d463a3c 100644 --- a/addons/account/models/account_invoice.py +++ b/addons/account/models/account_invoice.py @@ -1410,7 +1410,14 @@ class AccountInvoiceTax(models.Model): currency_id = fields.Many2one('res.currency', related='invoice_id.currency_id', store=True, readonly=True) base = fields.Monetary(string='Base', compute='_compute_base_amount') - + # DO NOT FORWARD-PORT!!! ONLY FOR v10 + def create(self, vals): + inv_tax = super(AccountInvoiceTax, self).create(vals) + # Workaround to make sure the tax amount is rounded to the currency precision since the ORM + # won't round it automatically at creation. + if inv_tax.company_id.tax_calculation_rounding_method == 'round_globally': + inv_tax.amount = inv_tax.currency_id.round(inv_tax.amount) + return inv_tax class AccountPaymentTerm(models.Model): From 0c5841dccf6d8afa266e1181364c410222acc140 Mon Sep 17 00:00:00 2001 From: len-odoo Date: Thu, 8 Mar 2018 08:40:46 +0100 Subject: [PATCH 02/23] [FIX] website_sale: display prices using public user pricelist on the shop When a pricelist was set on the public user that was different from that of the website, the prices were displayed using the public user default currency, but the currency symbol displayed was the website default currency. The issue was that in the template, the currency was accessed as a computed, related field of website while the price was obtained using a function call. In the first case the field was obtained using sudo, and thus the call would not get the public user pricelist. Equivalent to #23519 for odoo 11.0 opw-1819230 --- addons/website_sale/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index 83189c95c9b..1c757098a32 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -193,7 +193,7 @@ class Website(models.Model): _inherit = 'website' pricelist_id = fields.Many2one('product.pricelist', compute='_compute_pricelist_id', string='Default Pricelist') - currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', string='Default Currency') + currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id', related_sudo=False, string='Default Currency') salesperson_id = fields.Many2one('res.users', string='Salesperson') salesteam_id = fields.Many2one('crm.team', string='Sales Team') pricelist_ids = fields.One2many('product.pricelist', compute="_compute_pricelist_ids", From 255f9ee330c3f4da47c7747c9a2744354f574e98 Mon Sep 17 00:00:00 2001 From: mrshelly Date: Tue, 13 Mar 2018 21:29:25 +0800 Subject: [PATCH 03/23] [FIX] hw_scanner: add missing import `os.path.isdir` was not being imported --- addons/hw_scanner/controllers/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/hw_scanner/controllers/main.py b/addons/hw_scanner/controllers/main.py index fc2724dd31d..2ef49b7e6fd 100644 --- a/addons/hw_scanner/controllers/main.py +++ b/addons/hw_scanner/controllers/main.py @@ -4,7 +4,7 @@ import logging import time from os import listdir -from os.path import join +from os.path import join, isdir from Queue import Queue, Empty from select import select from threading import Thread, Lock @@ -121,7 +121,7 @@ class Scanner(Thread): if not evdev: return [] - if not os.path.isdir(self.input_dir): + if not isdir(self.input_dir): return [] new_devices = [device for device in listdir(self.input_dir) From f521606d128ddcb2d33191bab62dd76732841609 Mon Sep 17 00:00:00 2001 From: Bole Date: Tue, 13 Mar 2018 14:45:27 +0100 Subject: [PATCH 04/23] [CLA] signature for dajmi5 Done at #23606 --- doc/cla/corporate/dajmi5.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 doc/cla/corporate/dajmi5.md diff --git a/doc/cla/corporate/dajmi5.md b/doc/cla/corporate/dajmi5.md new file mode 100644 index 00000000000..e26ab73ef0d --- /dev/null +++ b/doc/cla/corporate/dajmi5.md @@ -0,0 +1,15 @@ +Croatia, 2017-10-31 + +DAJ MI 5 agrees to the terms of the Odoo Corporate Contributor License +Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Davor Bojkić bole@dajmi5.com https://github.com/dajmi5 + +List of contributors: + +Davor Bojkić bole@dajmi5.com https://github.com/badbole \ No newline at end of file From 4252cd705366c5b9364526122041f2544fbfbbbe Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 13 Mar 2018 15:39:12 +0100 Subject: [PATCH 05/23] [FIX] doc: update footer links Synchronize footer from odoo.com with the documentation. --- doc/_extensions/odoo_ext/layout.html | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/_extensions/odoo_ext/layout.html b/doc/_extensions/odoo_ext/layout.html index 000019b32cf..183bf7599fc 100644 --- a/doc/_extensions/odoo_ext/layout.html +++ b/doc/_extensions/odoo_ext/layout.html @@ -290,29 +290,33 @@ - From f1608829a17639fe03ef495aa627a557d0138108 Mon Sep 17 00:00:00 2001 From: Laurent Smet Date: Tue, 13 Mar 2018 16:55:36 +0100 Subject: [PATCH 06/23] [FIX] account: add missing constrains dependencies Create a move line having: amount_currency = 1000 debit = 0 credit = 1000 The error is raised, it's ok. Now, create a move line having: amount_currency = 1000 debit = 1000 credit = 0 Then save, edit and write: debit = 0 credit = 1000 No error raised, it's wrong! -opw 1818714 --- addons/account/models/account_move.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 922e30a0b67..ee1aded3938 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -444,7 +444,7 @@ class AccountMoveLine(models.Model): raise UserError(_("You cannot create journal items with a secondary currency without filling both 'currency' and 'amount currency' field.")) @api.multi - @api.constrains('amount_currency') + @api.constrains('amount_currency', 'debit', 'credit') def _check_currency_amount(self): for line in self: if line.amount_currency: From 9fc44bef8331bd6c1a2bac0c9a0c1aa1c7ae2e2a Mon Sep 17 00:00:00 2001 From: Ivan Yelizariev Date: Wed, 14 Mar 2018 06:31:55 -0400 Subject: [PATCH 07/23] [IMP] web_tour: specify timeout per step RUNNING_TOUR_TIMEOUT is equal to 10 seconds, which sometimes is not enough on travis and we need a way to increase timeout per step. Note: Exact same commit was already merged for version 11.0 here: 67e2372 Note 2: this is technically a IMP, not a fix, but I (GED) will accept this, since this should only impact the testing functionality. Also, this was done in 11.0, so in some sense, it was proved to work. (PR: #21750) --- addons/web_tour/static/src/js/tour_manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web_tour/static/src/js/tour_manager.js b/addons/web_tour/static/src/js/tour_manager.js index ba7adfc5443..654efc01a76 100644 --- a/addons/web_tour/static/src/js/tour_manager.js +++ b/addons/web_tour/static/src/js/tour_manager.js @@ -457,7 +457,7 @@ return core.Class.extend({ this._stop_running_tour_timeout(); this.running_tour_timeout = setTimeout((function() { this._consume_tour(tour_name, _.str.sprintf("Tour %s failed at step %s", tour_name, step.trigger)); - }).bind(this), RUNNING_TOUR_TIMEOUT + this.running_step_delay); + }).bind(this), (step.timeout || RUNNING_TOUR_TIMEOUT) + this.running_step_delay); }, _stop_running_tour_timeout: function () { clearTimeout(this.running_tour_timeout); From b669c71aa394d1ed7908555d54d69aec38590e20 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Wed, 14 Mar 2018 15:39:15 +0100 Subject: [PATCH 08/23] [FIX] calendar: in multicompany user cannot access own calendar Let's consider user1 and user2 allowed to access company1 and company2 In multicompany with shared partners unchecked in general settings, if one of two users sharing the same event tried to access the event when they are not in the same current company at this moment, an access error was raised. opw:1817475 --- addons/calendar/models/calendar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index ab0ce39373e..7103a103b06 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -841,7 +841,7 @@ class Meeting(models.Model): @api.multi def _compute_color_partner(self): - for meeting in self: + for meeting in self.sudo(): meeting.color_partner_id = meeting.user_id.partner_id.id @api.constrains('start_datetime', 'stop_datetime', 'start_date', 'stop_date') From e03a06b3e9c202d9a87bc4f9bfe38e2643b95b20 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Thu, 15 Mar 2018 11:00:32 +0100 Subject: [PATCH 09/23] [FIX] crm: favorite filters - Go to CRM > Reports > Pipeline - Click on one of the Favorites filters (e.g. 'Opportunities Won Per Team') A JS error arises. The filters are not correct. `__count` should be `__count__` and `expected revenue` should be `expected_revenue`. opw-1825759 --- addons/crm/report/crm_opportunity_report_views.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/crm/report/crm_opportunity_report_views.xml b/addons/crm/report/crm_opportunity_report_views.xml index 6eb888b2662..1a7175419e8 100644 --- a/addons/crm/report/crm_opportunity_report_views.xml +++ b/addons/crm/report/crm_opportunity_report_views.xml @@ -55,20 +55,20 @@ crm.opportunity.report [('probability', '=', 100)] - {'group_by': ['date_closed:month'],'col_group_by': ['create_date:month'], 'measures': ['__count']} + {'group_by': ['date_closed:month'],'col_group_by': ['create_date:month'], 'measures': ['__count__']} Opportunities Won Per Team crm.opportunity.report [('probability', '=', 100)] - {'group_by': ['team_id'], 'col_group_by': ['date_last_stage_update:month'], 'measures': ['expected revenue']} + {'group_by': ['team_id'], 'col_group_by': ['date_last_stage_update:month'], 'measures': ['expected_revenue']} Leads By Salespersons crm.opportunity.report - {'col_group_by': ['create_date:month'], 'group_by': ['user_id'], 'measures': ['__count']} + {'col_group_by': ['create_date:month'], 'group_by': ['user_id'], 'measures': ['__count__']} Won By Country @@ -81,7 +81,7 @@ Expected Revenue by Team crm.opportunity.report - {'group_by': ['create_date:month', 'team_id'], 'measures': ['expected_revenue', '__count']} + {'group_by': ['create_date:month', 'team_id'], 'measures': ['expected_revenue', '__count__']} Team Activities From 3bf9cf4f36e036495e3b1e54a77eadf39a1ccee2 Mon Sep 17 00:00:00 2001 From: Stephane Bidoul Date: Thu, 15 Mar 2018 15:34:58 +0100 Subject: [PATCH 10/23] [FIX] l10n_multilang: correctly set src While it is the name of the record that is set most of the time, it can also be different value (like tax description) Closes #21651 --- addons/l10n_multilang/models/l10n_multilang.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/l10n_multilang/models/l10n_multilang.py b/addons/l10n_multilang/models/l10n_multilang.py index de0ef064bcd..8d19f69bd36 100644 --- a/addons/l10n_multilang/models/l10n_multilang.py +++ b/addons/l10n_multilang/models/l10n_multilang.py @@ -37,7 +37,7 @@ class AccountChartTemplate(models.Model): 'type': 'model', 'res_id': out_ids[counter].id, 'lang': lang, - 'src': element.name, + 'src': element[in_field], 'value': value[element.id], }) else: From c4a11cb42a4a3f3f49c2024fb2b081d638e383b0 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Fri, 16 Mar 2018 12:12:30 +0100 Subject: [PATCH 11/23] [FIX] stock: use correct warehouse name in multicompany At stock installation, the warehouse0 has the name of the first company found (order "sequence, name"), while the comapny_id field is `_company_default_get('stock.inventory')` (the company of the user installing the stock module). In a multi-company environment, it is possible than both results are different and having name = 'Company A' and company_id = 'Company B'. Use the name of the default company as default value for the field name. Note that 'stock.inventory' is not needed in _company_default_get call but kept to match the default of company_id (in case of override). Using a default on the field will impact all the future records but should, hopefully, not be problematic as it is a valid default value. Closes #19563 --- addons/stock/data/stock_data.xml | 1 - addons/stock/models/stock_warehouse.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/stock/data/stock_data.xml b/addons/stock/data/stock_data.xml index 078273fb32d..35f2c008729 100644 --- a/addons/stock/data/stock_data.xml +++ b/addons/stock/data/stock_data.xml @@ -145,7 +145,6 @@ watch your stock valuation, and track production lots (based on serial numbers). - WH diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index 83b571e80ce..d81efe07404 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -21,7 +21,7 @@ class Warehouse(models.Model): # namedtuple used in helper methods generating values for routes Routing = namedtuple('Routing', ['from_loc', 'dest_loc', 'picking_type']) - name = fields.Char('Warehouse Name', index=True, required=True) + name = fields.Char('Warehouse Name', index=True, required=True, default=lambda self: self.env['res.company']._company_default_get('stock.inventory').name) active = fields.Boolean('Active', default=True) company_id = fields.Many2one( 'res.company', 'Company', default=lambda self: self.env['res.company']._company_default_get('stock.inventory'), From 0ee76b664c7413a5302aeeeb9118df171a61a09f Mon Sep 17 00:00:00 2001 From: Jerther Date: Fri, 16 Mar 2018 07:57:16 -0400 Subject: [PATCH 12/23] [IMP] doc: add a tip to create a model without any table As explained in #17386, _auto=False on a model is used for report where the table is explicitely created in init method. To create a model without any table, AbstractModel should be used. Closes #19448 --- doc/reference/orm.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/reference/orm.rst b/doc/reference/orm.rst index 00b284f9cb2..bec009411b7 100644 --- a/doc/reference/orm.rst +++ b/doc/reference/orm.rst @@ -630,6 +630,9 @@ Model Reference If set to ``False``, override :meth:`.init` to create the database table + + .. tip:: To create a model without any table, inherit + from ``odoo.models.AbstractModel`` .. attribute:: _table From 854943379bfebb5f1c501167c5f4b5ef3942132c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Fri, 16 Mar 2018 13:23:54 +0100 Subject: [PATCH 13/23] [FIX] hr_expense: fix Not Refused filter "cancel" is not a valid hr.expense state This filter should be the opposite of the one above. Closes #18823 --- addons/hr_expense/views/hr_expense_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/hr_expense/views/hr_expense_views.xml b/addons/hr_expense/views/hr_expense_views.xml index d05fcd7abf6..6961788cfc3 100644 --- a/addons/hr_expense/views/hr_expense_views.xml +++ b/addons/hr_expense/views/hr_expense_views.xml @@ -164,7 +164,7 @@ - + From 06737c3441e5ec15a1e05e6122a84189d503f81d Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 16 Mar 2018 14:15:17 +0100 Subject: [PATCH 14/23] [FIX] account_check_printing: compare float correctly Example failing before this commit: - amount = 11.01 - decimal = 11.01 % 1 = 0.009999999999999787 - 0.009999999999999787 < 0.01 Use correct float_is_zero method to test if there is decimal or not Closes #18306 --- addons/account_check_printing/models/account_payment.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/account_check_printing/models/account_payment.py b/addons/account_check_printing/models/account_payment.py index ef33dc05ae4..ab6623b3068 100644 --- a/addons/account_check_printing/models/account_payment.py +++ b/addons/account_check_printing/models/account_payment.py @@ -4,7 +4,7 @@ import math from odoo import models, fields, api, _ -from odoo.tools import amount_to_text_en, float_round +from odoo.tools import amount_to_text_en, float_round, float_is_zero from odoo.exceptions import UserError, ValidationError @@ -55,7 +55,7 @@ class AccountPayment(models.Model): check_amount_in_words = amount_to_text_en.amount_to_text(math.floor(amount), lang='en', currency='') check_amount_in_words = check_amount_in_words.replace(' and Zero Cent', '') # Ugh decimals = amount % 1 - if decimals >= 10**-2: + if not float_is_zero(decimals, precision_digits=2): check_amount_in_words += _(' and %s/100') % str(int(round(float_round(decimals*100, precision_rounding=1)))) return check_amount_in_words From 38e4b2b50a7fe6b1f9310c490e64843bdf68d08c Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 16 Mar 2018 15:22:27 +0100 Subject: [PATCH 15/23] [FIX] l10n_multilang: followup of 3bf9cf4f36 The change was made in the code but not in the error message Courtesy of Stephane Bidoul --- addons/l10n_multilang/models/l10n_multilang.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/l10n_multilang/models/l10n_multilang.py b/addons/l10n_multilang/models/l10n_multilang.py index 8d19f69bd36..fe2f48a79e2 100644 --- a/addons/l10n_multilang/models/l10n_multilang.py +++ b/addons/l10n_multilang/models/l10n_multilang.py @@ -41,7 +41,7 @@ class AccountChartTemplate(models.Model): 'value': value[element.id], }) else: - _logger.info('Language: %s. Translation from template: there is no translation available for %s!' % (lang, element.name)) + _logger.info('Language: %s. Translation from template: there is no translation available for %s!' % (lang, element[in_field])) counter += 1 return True From 9035378d4bf8054111f86564c411842d6fcf7fc2 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Sun, 15 Oct 2017 16:06:55 -0500 Subject: [PATCH 16/23] [FIX] stock: use full name in error message IT was not possible to differenciate between variants as using the product.template name in the message. Same for the location were it was using the last level name (e.g. 'Shelve 42') instead of the full path Closes #20174 --- addons/stock/models/stock_inventory.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/stock/models/stock_inventory.py b/addons/stock/models/stock_inventory.py index 0f1c5f15419..283dc12ee5f 100644 --- a/addons/stock/models/stock_inventory.py +++ b/addons/stock/models/stock_inventory.py @@ -395,7 +395,8 @@ class InventoryLine(models.Model): if existings: raise UserError(_("You cannot have two inventory adjustements in state 'in Progess' with the same product" "(%s), same location(%s), same package, same owner and same lot. Please first validate" - "the first inventory adjustement with this product before creating another one.") % (res.product_id.name, res.location_id.name)) + "the first inventory adjustement with this product before creating another one.") % + (res.product_id.display_name, res.location_id.display_name)) return res def _get_quants(self): From 9f1438d5f1b7097c7643290c4195216ff51c9a81 Mon Sep 17 00:00:00 2001 From: Romain Derie Date: Fri, 17 Nov 2017 12:02:44 +0100 Subject: [PATCH 17/23] [IMP] website: Script injected in DOM: window.onerror empty params Cherry-pick (and improvement) of 4bd8e3e (11.0) which should have landed in 10.0 Closes #21032 --- .../web/static/src/js/abstract_web_client.js | 37 ++++++++++++++++--- .../static/src/js/website.backendDashboard.js | 5 +++ .../static/src/xml/website.backend.xml | 1 + 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/addons/web/static/src/js/abstract_web_client.js b/addons/web/static/src/js/abstract_web_client.js index 115a58a654f..8c82abf846c 100644 --- a/addons/web/static/src/js/abstract_web_client.js +++ b/addons/web/static/src/js/abstract_web_client.js @@ -120,12 +120,37 @@ var WebClient = Widget.extend({ // crash manager integration session.on('error', crash_manager, crash_manager.rpc_error); window.onerror = function (message, file, line, col, error) { - var traceback = error ? error.stack : ''; - crash_manager.show_error({ - type: _t("Client Error"), - message: message, - data: {debug: file + ':' + line + "\n" + _t('Traceback:') + "\n" + traceback} - }); + // Scripts injected in DOM (eg: google API's js files) won't return a clean error on window.onerror. + // The browser will just give you a 'Script error.' as message and nothing else for security issue. + // To enable onerror to work properly with CORS file, you should: + // 1. add crossorigin="anonymous" to your