diff --git a/addons/account/data/invoice_action_data.xml b/addons/account/data/invoice_action_data.xml index 96fa2342f06..96e55557c1e 100644 --- a/addons/account/data/invoice_action_data.xml +++ b/addons/account/data/invoice_action_data.xml @@ -33,7 +33,7 @@ amounting in ${object.amount_total} ${object.currency_id.name} from ${object.company_id.name}.

-% if is_inline: +% if is_online:

View Invoice diff --git a/addons/account/models/account.py b/addons/account/models/account.py index eb0b26b6963..15e25f1d9fb 100644 --- a/addons/account/models/account.py +++ b/addons/account/models/account.py @@ -699,7 +699,18 @@ class AccountTax(models.Model): # the 'Account' decimal precision + 5), and that way it's like # rounding after the sum of the tax amounts of each line prec = currency.decimal_places - if company_id.tax_calculation_rounding_method == 'round_globally' or not bool(self.env.context.get("round", True)): + + # In some cases, it is necessary to force/prevent the rounding of the tax and the total + # amounts. For example, in SO/PO line, we don't want to round the price unit at the + # precision of the currency. + # The context key 'round' allows to force the standard behavior. + round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True + round_total = True + if 'round' in self.env.context: + round_tax = bool(self.env.context['round']) + round_total = bool(self.env.context['round']) + + if not round_tax: prec += 5 total_excluded = total_included = base = round(price_unit * quantity, prec) @@ -718,7 +729,7 @@ class AccountTax(models.Model): continue tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner) - if company_id.tax_calculation_rounding_method == 'round_globally' or not bool(self.env.context.get("round", True)): + if not round_tax: tax_amount = round(tax_amount, prec) else: tax_amount = currency.round(tax_amount) @@ -744,8 +755,8 @@ class AccountTax(models.Model): return { 'taxes': sorted(taxes, key=lambda k: k['sequence']), - 'total_excluded': currency.round(total_excluded) if bool(self.env.context.get("round", True)) else total_excluded, - 'total_included': currency.round(total_included) if bool(self.env.context.get("round", True)) else total_included, + 'total_excluded': currency.round(total_excluded) if round_total else total_excluded, + 'total_included': currency.round(total_included) if round_total else total_included, 'base': base, } diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 2b82cef6c85..8e4d908b176 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -1057,7 +1057,7 @@ class AccountMoveLine(models.Model): taxes = self.env['account.tax'].browse(tax_ids) currency = self.env['res.currency'].browse(vals.get('currency_id')) partner = self.env['res.partner'].browse(vals.get('partner_id')) - res = taxes.compute_all(amount, + res = taxes.with_context(round=True).compute_all(amount, currency, 1, vals.get('product_id'), partner) # Adjust line amount if any tax is price_include if abs(res['total_excluded']) < abs(amount): diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py index cf4fe079eba..fb5f90f96ec 100644 --- a/addons/account/report/account_aged_partner_balance.py +++ b/addons/account/report/account_aged_partner_balance.py @@ -61,7 +61,7 @@ class ReportAgedPartnerBalance(models.AbstractModel): # Build a string like (1,2,3) for easy use in SQL query partner_ids = [partner['partner_id'] for partner in partners if partner['partner_id']] - lines = dict([(partner['partner_id'], []) for partner in partners if partner['partner_id']]) + lines = dict((partner['partner_id'] or False, []) for partner in partners) if not partner_ids: return [], [], [] @@ -80,7 +80,7 @@ class ReportAgedPartnerBalance(models.AbstractModel): aml_ids = cr.fetchall() aml_ids = aml_ids and [x[0] for x in aml_ids] or [] for line in self.env['account.move.line'].browse(aml_ids): - partner_id = line.partner_id.id or None + partner_id = line.partner_id.id or False if partner_id not in undue_amounts: undue_amounts[partner_id] = 0.0 line_amount = line.balance @@ -131,7 +131,7 @@ class ReportAgedPartnerBalance(models.AbstractModel): aml_ids = cr.fetchall() aml_ids = aml_ids and [x[0] for x in aml_ids] or [] for line in self.env['account.move.line'].browse(aml_ids): - partner_id = line.partner_id.id or None + partner_id = line.partner_id.id or False if partner_id not in partners_amount: partners_amount[partner_id] = 0.0 line_amount = line.balance diff --git a/addons/account/static/src/js/account_reconciliation_widgets.js b/addons/account/static/src/js/account_reconciliation_widgets.js index 848b9b5093a..95cd682a9ee 100644 --- a/addons/account/static/src/js/account_reconciliation_widgets.js +++ b/addons/account/static/src/js/account_reconciliation_widgets.js @@ -16,6 +16,7 @@ var pyeval = require('web.pyeval'); var web_client = require('web.web_client'); var parse_value = require('web.web_client'); var Widget = require('web.Widget'); +var session = require('web.session'); var FieldMany2One = core.form_widget_registry.get('many2one'); var FieldChar = core.form_widget_registry.get('char'); @@ -71,8 +72,6 @@ var abstractReconciliation = Widget.extend(ControlPanelMixin, { this.action_manager = this.findAncestor(function(ancestor){ return ancestor instanceof ActionManager }); this.crash_manager = new CrashManager(); - // Method that tests if a monetary amount == 0, we use 4 digits because no currency uses more - this.monetaryIsZero = _.partial(utils.float_is_zero, _, 4); this.formatCurrencies; // Method that formats the currency ; loaded from the server this.model_res_users = new Model("res.users"); this.model_tax = new Model("account.tax"); @@ -365,6 +364,11 @@ var abstractReconciliation = Widget.extend(ControlPanelMixin, { if (line.ref && line.ref !== line.name) line.q_label = line.q_label + " : " + line.ref; }, + + // Method that tests if a monetary amount == 0, we use 4 digits because no currency uses more + monetaryIsZero: function(amount, digits) { + return utils.float_is_zero(amount, digits === undefined ? 4 : digits); + }, }); var abstractReconciliationLine = Widget.extend({ @@ -1868,7 +1872,11 @@ var bankStatementReconciliationLine = abstractReconciliationLine.extend({ // Find out if the counterpart is lower than, equal or greater than the transaction being reconciled var balance_type = undefined; - if (self.monetaryIsZero(self.get("balance"))) balance_type = "equal"; + var digits = 4; + if (this.get("currency_id") && session.get_currency(this.get("currency_id"))) { + digits = session.get_currency(this.get("currency_id")).digits[1]; + } + if (self.monetaryIsZero(self.get("balance"), digits)) balance_type = "equal"; else if (self.get("balance") * self.st_line.amount > 0) balance_type = "greater"; else if (self.get("balance") * self.st_line.amount < 0) balance_type = "lower"; @@ -2063,7 +2071,11 @@ var bankStatementReconciliationLine = abstractReconciliationLine.extend({ var payment_aml = _.filter(this.get("mv_lines_selected"), function(line) { return line.already_paid }); var payment_aml_ids = _.collect(payment_aml, function(line) { return line.id }); var new_aml_dicts = this.prepareCreatedMoveLinesForPersisting(this.getCreatedLines()); - if (! self.monetaryIsZero(this.get("balance"))) new_aml_dicts.push(this.prepareOpenBalanceForPersisting()); + var digits = 4; + if (this.get("currency_id") && session.get_currency(this.get("currency_id"))) { + digits = session.get_currency(this.get("currency_id")).digits[1]; + } + if (! self.monetaryIsZero(this.get("balance"), digits)) new_aml_dicts.push(this.prepareOpenBalanceForPersisting()); return { 'counterpart_aml_dicts': counterpart_aml_dicts, 'payment_aml_ids': payment_aml_ids, diff --git a/addons/barcodes/static/src/js/form_view_barcode_handler.js b/addons/barcodes/static/src/js/form_view_barcode_handler.js index a6fa4b55adf..b00bce51c5e 100644 --- a/addons/barcodes/static/src/js/form_view_barcode_handler.js +++ b/addons/barcodes/static/src/js/form_view_barcode_handler.js @@ -52,6 +52,11 @@ var FormViewBarcodeHandler = common.AbstractField.extend(BarcodeHandlerMixin, { } }, + destroy: function () { + this.stop_listening(); + this._super.apply(this, arguments); + }, + _display_no_edit_mode_warning: function() { this.do_warn(_t('Error : Document not editable'), _t('To modify this document, please first start edition.')); }, diff --git a/addons/crm/wizard/base_partner_merge.py b/addons/crm/wizard/base_partner_merge.py index d2ddf32afcf..44320807797 100644 --- a/addons/crm/wizard/base_partner_merge.py +++ b/addons/crm/wizard/base_partner_merge.py @@ -306,7 +306,7 @@ class MergePartnerAutomatic(models.TransientModel): raise UserError(_("You cannot merge a contact with one of his parent.")) # check only admin can merge partners with different emails - if SUPERUSER_ID != self.env.uid and len(set(partner.email for partner in Partner.browse(partner_ids))) > 1: + if SUPERUSER_ID != self.env.uid and len(set(partner.email for partner in partner_ids)) > 1: raise UserError(_("All contacts must have the same email. Only the Administrator can merge contacts with different emails.")) # remove dst_partner from partners to merge diff --git a/addons/hr_expense/i18n/hr_expense.pot b/addons/hr_expense/i18n/hr_expense.pot index 78f13f7787e..edc3c84a67d 100644 --- a/addons/hr_expense/i18n/hr_expense.pot +++ b/addons/hr_expense/i18n/hr_expense.pot @@ -1156,7 +1156,7 @@ msgstr "" #. module: hr_expense #: selection:hr.expense,state:0 #: model:ir.ui.view,arch_db:hr_expense.view_hr_expense_filter -msgid "To Report" +msgid "To Submit" msgstr "" #. module: hr_expense diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 9b4367f2992..84886443a37 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -35,7 +35,7 @@ class HrExpense(models.Model): payment_mode = fields.Selection([("own_account", "Employee (to reimburse)"), ("company_account", "Company")], default='own_account', states={'done': [('readonly', True)], 'post': [('readonly', True)]}, string="Payment By") attachment_number = fields.Integer(compute='_compute_attachment_number', string='Number of Attachments') state = fields.Selection([ - ('draft', 'To Report'), + ('draft', 'To Submit'), ('reported', 'Reported'), ('done', 'Posted'), ('refused', 'Refused') diff --git a/addons/hr_expense/views/hr_expense_views.xml b/addons/hr_expense/views/hr_expense_views.xml index 22073f88003..3c35430bf39 100644 --- a/addons/hr_expense/views/hr_expense_views.xml +++ b/addons/hr_expense/views/hr_expense_views.xml @@ -56,7 +56,7 @@ - + @@ -161,7 +161,7 @@ - + diff --git a/addons/im_livechat/views/im_livechat_channel_templates.xml b/addons/im_livechat/views/im_livechat_channel_templates.xml index bbb4c9663b6..0e3a4b911c8 100644 --- a/addons/im_livechat/views/im_livechat_channel_templates.xml +++ b/addons/im_livechat/views/im_livechat_channel_templates.xml @@ -112,6 +112,7 @@ + @@ -121,7 +122,11 @@ - + + + + + diff --git a/addons/project_issue/models/res_partner.py b/addons/project_issue/models/res_partner.py index 8bfe514987f..91dd0af3eec 100644 --- a/addons/project_issue/models/res_partner.py +++ b/addons/project_issue/models/res_partner.py @@ -11,6 +11,5 @@ class ResPartner(models.Model): def _compute_issue_count(self): Issue = self.env['project.issue'] - partners = {id: self.search([('id', 'child_of', self.ids)]).ids for id in self.ids} for partner in self: - partner.issue_count = Issue.search_count([('partner_id', 'in', partners[partner.id])]) + partner.issue_count = Issue.search_count([('partner_id', 'child_of', partner.commercial_partner_id.id)]) diff --git a/addons/project_issue/views/res_partner_views.xml b/addons/project_issue/views/res_partner_views.xml index aa2ac8a80b5..10aafb7d24f 100644 --- a/addons/project_issue/views/res_partner_views.xml +++ b/addons/project_issue/views/res_partner_views.xml @@ -10,7 +10,7 @@