From 4fa0d275ad0931602fdb58decf3b9dc422d52c88 Mon Sep 17 00:00:00 2001 From: aliya Date: Mon, 4 Apr 2022 16:28:14 +0000 Subject: [PATCH] [IMP] account: change date for calculating the currency exchange Currently, the currency conversion rate used is based on the accounting date on invoices and bills. According to partner feedback and the official documentation we should use the exchange rate on the invoice/bill date. Moves that are not invoices or bills should still use the accounting date. closes odoo/odoo#87984 Task: 2807136 Signed-off-by: Quentin De Paoli --- addons/account/models/account_move.py | 21 +++++++++++-------- .../tests/test_account_move_in_invoice.py | 4 ++++ .../tests/test_account_move_in_refund.py | 4 ++++ .../tests/test_account_move_out_invoice.py | 9 +++++--- .../tests/test_account_move_out_refund.py | 5 ++++- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 72925850713..f3bdbaa0240 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -690,11 +690,12 @@ class AccountMove(models.Model): else: group_tax = self.env['account.tax'].browse(tax_id) + exchange_rate_date = self.invoice_date if self.is_invoice(include_receipts=True) else self.date tax_base_amount = sign * currency._convert( update_vals['tax_base_amount'], self.company_currency_id, self.company_id, - self.date or fields.Date.context_today(self), + exchange_rate_date or fields.Date.context_today(self), ) tax_base_amount = self._get_base_amount_to_display(tax_base_amount, tax_rep, group_tax) amount_currency = sign * tax_amount @@ -702,7 +703,7 @@ class AccountMove(models.Model): amount_currency, self.company_currency_id, self.company_id, - self.date or fields.Date.context_today(self), + exchange_rate_date or fields.Date.context_today(self), ) update_vals.update({ @@ -815,7 +816,7 @@ class AccountMove(models.Model): diff_amount_currency = diff_balance = difference else: diff_amount_currency = difference - diff_balance = self.currency_id._convert(diff_amount_currency, self.company_id.currency_id, self.company_id, self.date) + diff_balance = self.currency_id._convert(diff_amount_currency, self.company_id.currency_id, self.company_id, self.invoice_date) return diff_balance, diff_amount_currency def _apply_cash_rounding(self, diff_balance, diff_amount_currency, cash_rounding_line): @@ -1604,6 +1605,7 @@ class AccountMove(models.Model): payments_widget_vals['title'] = _('Outstanding debits') for line in self.env['account.move.line'].search(domain): + exchange_rate_date = line.move_id.invoice_date if line.move_id.is_invoice(include_receipts=True) else line.date if line.currency_id == move.currency_id: # Same foreign currency. @@ -1614,7 +1616,7 @@ class AccountMove(models.Model): abs(line.amount_residual), move.currency_id, move.company_id, - line.date, + exchange_rate_date, ) if move.currency_id.is_zero(amount): @@ -4078,7 +4080,8 @@ class AccountMoveLine(models.Model): def _onchange_amount_currency(self): for line in self: company = line.move_id.company_id - balance = line.currency_id._convert(line.amount_currency, company.currency_id, company, line.move_id.date or fields.Date.context_today(line)) + exchange_rate_date = line.move_id.invoice_date if line.move_id.is_invoice(include_receipts=True) else line.move_id.date + balance = line.currency_id._convert(line.amount_currency, company.currency_id, company, exchange_rate_date or fields.Date.context_today(line)) line.debit = line.move_id._get_debit_from_balance(balance, company.currency_id.id) line.credit = line.move_id._get_credit_from_balance(balance, company.currency_id.id) @@ -4093,9 +4096,8 @@ class AccountMoveLine(models.Model): for line in self: if not line.move_id.is_invoice(include_receipts=True): continue - line.update(line._get_price_total_and_subtotal()) - line.update(line._get_fields_onchange_subtotal()) + line.update(line._get_fields_onchange_subtotal(date=line.move_id.invoice_date)) @api.onchange('currency_id') def _onchange_currency(self): @@ -4479,7 +4481,7 @@ class AccountMoveLine(models.Model): move.move_type, currency, move.company_id, - move.date, + move.invoice_date, )) lines = super(AccountMoveLine, self).create(vals_list) @@ -4749,7 +4751,8 @@ class AccountMoveLine(models.Model): :return: a tuple of 1) list of vals for partial reconcilation creation, 2) the list of vals for the exchange difference entries to be created ''' def get_odoo_rate(line): - return recon_currency._get_conversion_rate(company_currency, recon_currency, line.company_id, line.date) + exchange_rate_date = line.move_id.invoice_date if line.move_id.is_invoice(include_receipts=True) else line.date + return recon_currency._get_conversion_rate(company_currency, recon_currency, line.company_id, exchange_rate_date) def get_accounting_rate(line): if company_currency.is_zero(line.balance) or line.currency_id.is_zero(line.amount_currency): diff --git a/addons/account/tests/test_account_move_in_invoice.py b/addons/account/tests/test_account_move_in_invoice.py index 2abec1e9643..8060e11f694 100644 --- a/addons/account/tests/test_account_move_in_invoice.py +++ b/addons/account/tests/test_account_move_in_invoice.py @@ -1048,6 +1048,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): move_form = Form(self.invoice) # Change the date to get another rate: 1/3 instead of 1/2. + move_form.invoice_date = fields.Date.from_string('2016-01-01') move_form.date = fields.Date.from_string('2016-01-01') move_form.save() @@ -1081,6 +1082,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'currency_id': self.currency_data['currency'].id, 'amount_currency': -1128.0, 'credit': 376.0, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -1136,6 +1138,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -208.006, 'amount_currency': -208.006, 'credit': 69.33, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -1178,6 +1181,7 @@ class TestAccountMoveInInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -208.01, 'amount_currency': -208.01, 'credit': 208.01, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_in_refund.py b/addons/account/tests/test_account_move_in_refund.py index 1d9c44b1cde..c44b32a3f7a 100644 --- a/addons/account/tests/test_account_move_in_refund.py +++ b/addons/account/tests/test_account_move_in_refund.py @@ -732,6 +732,7 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): move_form = Form(self.invoice) # Change the date to get another rate: 1/3 instead of 1/2. + move_form.invoice_date = fields.Date.from_string('2016-01-01') move_form.date = fields.Date.from_string('2016-01-01') move_form.save() @@ -765,6 +766,7 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'currency_id': self.currency_data['currency'].id, 'amount_currency': 1128.0, 'debit': 376.0, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -820,6 +822,7 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -208.006, 'amount_currency': 208.006, 'debit': 69.33, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -862,6 +865,7 @@ class TestAccountMoveInRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -208.01, 'amount_currency': 208.01, 'debit': 208.01, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_out_invoice.py b/addons/account/tests/test_account_move_out_invoice.py index 2d451a53dec..b29008f6921 100644 --- a/addons/account/tests/test_account_move_out_invoice.py +++ b/addons/account/tests/test_account_move_out_invoice.py @@ -1652,7 +1652,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): move_form = Form(self.invoice) # Change the date to get another rate: 1/3 instead of 1/2. - move_form.date = fields.Date.from_string('2016-01-01') + move_form.invoice_date = fields.Date.from_string('2016-01-01') move_form.save() self.assertInvoiceValues(self.invoice, [ @@ -1685,6 +1685,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'currency_id': self.currency_data['currency'].id, 'amount_currency': 1410.0, 'debit': 470.0, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -1740,6 +1741,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -260.006, 'amount_currency': 260.006, 'debit': 86.67, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -1782,6 +1784,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'price_total': -260.01, 'amount_currency': 260.01, 'debit': 260.01, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -2405,7 +2408,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): move = self.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, - 'invoice_date': fields.Date.from_string('2016-01-01'), + 'invoice_date': fields.Date.from_string('2017-01-15'), 'date': fields.Date.from_string('2015-01-01'), 'currency_id': self.currency_data['currency'].id, 'invoice_payment_term_id': self.pay_terms_a.id, @@ -2492,7 +2495,7 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon): 'amount_currency': 1430.0, 'debit': 715.0, 'credit': 0.0, - 'date_maturity': fields.Date.from_string('2016-01-01'), + 'date_maturity': fields.Date.from_string('2017-01-15'), }, ], { **self.move_vals, diff --git a/addons/account/tests/test_account_move_out_refund.py b/addons/account/tests/test_account_move_out_refund.py index bf78699c09c..9cdd3a6b81a 100644 --- a/addons/account/tests/test_account_move_out_refund.py +++ b/addons/account/tests/test_account_move_out_refund.py @@ -731,7 +731,7 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): move_form = Form(self.invoice) # Change the date to get another rate: 1/3 instead of 1/2. - move_form.date = fields.Date.from_string('2016-01-01') + move_form.invoice_date = fields.Date.from_string('2016-01-01') move_form.save() self.assertInvoiceValues(self.invoice, [ @@ -764,6 +764,7 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'currency_id': self.currency_data['currency'].id, 'amount_currency': -1410.0, 'credit': 470.0, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -819,6 +820,7 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -260.006, 'amount_currency': -260.006, 'credit': 86.67, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals, @@ -861,6 +863,7 @@ class TestAccountMoveOutRefundOnchanges(AccountTestInvoicingCommon): 'price_total': -260.01, 'amount_currency': -260.01, 'credit': 260.01, + 'date_maturity': fields.Date.from_string('2016-01-01'), }, ], { **self.move_vals,