[FIX] account: protect currency recompute without blocking completely
The previous fix[^1] was preventing the recomputation of the currency as soon as there was one set. For instance, the currency wouldn't change if we changed the journal for one with another currency. [^1]: 7f7743470ac1309d5e047563d06362e54edb552a closes odoo/odoo#125671 X-original-commit: 9f8bd34818414698f9b3fd9fe926659781c13c67 Signed-off-by: John Laterre (jol) <jol@odoo.com> Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
@@ -142,7 +142,7 @@ class AccountMove(models.Model):
|
||||
journal_id = fields.Many2one(
|
||||
'account.journal',
|
||||
string='Journal',
|
||||
compute='_compute_journal_id', store=True, readonly=False, precompute=True,
|
||||
compute='_compute_journal_id', inverse='_inverse_journal_id', store=True, readonly=False, precompute=True,
|
||||
required=True,
|
||||
states={'draft': [('readonly', False)]},
|
||||
check_company=True,
|
||||
@@ -660,10 +660,6 @@ class AccountMove(models.Model):
|
||||
def _compute_journal_id(self):
|
||||
for record in self.filtered(lambda r: r.journal_id.type not in r._get_valid_journal_types()):
|
||||
record.journal_id = record._search_default_journal()
|
||||
if not record.company_id or record.company_id != record.journal_id.company_id:
|
||||
self.env.add_to_compute(self._fields['company_id'], record)
|
||||
if not record.currency_id or record.journal_id.currency_id and record.currency_id != record.journal_id.currency_id:
|
||||
self.env.add_to_compute(self._fields['currency_id'], record)
|
||||
|
||||
def _get_valid_journal_types(self):
|
||||
if self.is_sale_document(include_receipts=True):
|
||||
@@ -687,10 +683,13 @@ class AccountMove(models.Model):
|
||||
domain = [('company_id', '=', company_id), ('type', 'in', journal_types)]
|
||||
|
||||
journal = None
|
||||
currency_id = self.currency_id.id or self._context.get('default_currency_id')
|
||||
if currency_id and currency_id != self.company_id.currency_id.id:
|
||||
currency_domain = domain + [('currency_id', '=', currency_id)]
|
||||
journal = self.env['account.journal'].search(currency_domain, limit=1)
|
||||
# the currency is not a hard dependence, it triggers via manual add_to_compute
|
||||
# avoid computing the currency before all it's dependences are set (like the journal...)
|
||||
if self.env.cache.contains(self, self._fields['currency_id']):
|
||||
currency_id = self.currency_id.id or self._context.get('default_currency_id')
|
||||
if currency_id and currency_id != self.company_id.currency_id.id:
|
||||
currency_domain = domain + [('currency_id', '=', currency_id)]
|
||||
journal = self.env['account.journal'].search(currency_domain, limit=1)
|
||||
|
||||
if not journal:
|
||||
journal = self.env['account.journal'].search(domain, limit=1)
|
||||
@@ -847,8 +846,7 @@ class AccountMove(models.Model):
|
||||
def _compute_currency_id(self):
|
||||
for invoice in self:
|
||||
currency = (
|
||||
invoice.currency_id
|
||||
or invoice.statement_line_id.foreign_currency_id
|
||||
invoice.statement_line_id.foreign_currency_id
|
||||
or invoice.journal_id.currency_id
|
||||
or invoice.journal_id.company_id.currency_id
|
||||
)
|
||||
@@ -1589,15 +1587,27 @@ class AccountMove(models.Model):
|
||||
|
||||
@api.onchange('company_id')
|
||||
def _inverse_company_id(self):
|
||||
for move in self:
|
||||
if move.journal_id.company_id != move.company_id:
|
||||
self.env.add_to_compute(self._fields['journal_id'], move)
|
||||
self._conditional_add_to_compute('journal_id', lambda m: (
|
||||
m.journal_id.company_id != m.company_id
|
||||
))
|
||||
|
||||
@api.onchange('currency_id')
|
||||
def _inverse_currency_id(self):
|
||||
for invoice in self:
|
||||
if invoice.journal_id.currency_id and invoice.journal_id.currency_id != invoice.currency_id:
|
||||
self.env.add_to_compute(self._fields['journal_id'], invoice)
|
||||
self._conditional_add_to_compute('journal_id', lambda m: (
|
||||
m.journal_id.currency_id
|
||||
and m.journal_id.currency_id != m.currency_id
|
||||
))
|
||||
|
||||
@api.onchange('journal_id')
|
||||
def _inverse_journal_id(self):
|
||||
self._conditional_add_to_compute('company_id', lambda m: (
|
||||
not m.company_id
|
||||
or m.company_id != m.journal_id.company_id
|
||||
))
|
||||
self._conditional_add_to_compute('currency_id', lambda m: (
|
||||
not m.currency_id
|
||||
or m.journal_id.currency_id and m.currency_id != m.journal_id.currency_id
|
||||
))
|
||||
|
||||
def _inverse_payment_reference(self):
|
||||
self.line_ids._conditional_add_to_compute('name', lambda line: (
|
||||
@@ -2313,8 +2323,13 @@ class AccountMove(models.Model):
|
||||
raise UserError(_('The Journal Entry sequence is not conform to the current format. Only the Accountant can change it.'))
|
||||
move.journal_id.sequence_override_regex = False
|
||||
|
||||
to_protect = []
|
||||
for fname in vals:
|
||||
field = self._fields[fname]
|
||||
if field.compute and not field.readonly:
|
||||
to_protect.append(field)
|
||||
container = {'records': self}
|
||||
with self._check_balanced(container):
|
||||
with self.env.protecting(to_protect, self), self._check_balanced(container):
|
||||
with self._sync_dynamic_lines(container):
|
||||
res = super(AccountMove, self.with_context(
|
||||
skip_account_move_synchronization=True,
|
||||
@@ -2377,7 +2392,10 @@ class AccountMove(models.Model):
|
||||
# del values[to_del]
|
||||
# KeyError: 'line_ids'
|
||||
values.pop(to_del, None)
|
||||
return super().onchange(values, field_name, field_onchange)
|
||||
if field_name and not isinstance(field_name, list):
|
||||
field_name = [field_name]
|
||||
with self.env.protecting([self._fields[fname] for fname in field_name or []], self):
|
||||
return super().onchange(values, field_name, field_onchange)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# RECONCILIATION METHODS
|
||||
@@ -4352,7 +4370,8 @@ class AccountMove(models.Model):
|
||||
field = self._fields[fname]
|
||||
to_reset = self.filtered(lambda move:
|
||||
condition(move)
|
||||
and not self.env.is_protected(field, move)
|
||||
and not self.env.is_protected(field, move._origin)
|
||||
and (move._origin or not move[fname])
|
||||
)
|
||||
to_reset.invalidate_recordset([fname])
|
||||
self.env.add_to_compute(field, to_reset)
|
||||
|
||||
@@ -3438,15 +3438,51 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
self.assertEqual(move.currency_id, self.currency_data['currency'])
|
||||
self.assertRecordValues(move.line_ids, [
|
||||
{
|
||||
'display_type': 'product',
|
||||
'currency_id': self.currency_data['currency'].id,
|
||||
'debit': 0.0,
|
||||
'credit': self.currency_data['currency']._convert(750.0, self.company_data['currency'], self.env.company, fields.Date.today()),
|
||||
'credit': 375.0,
|
||||
},
|
||||
{
|
||||
'debit': self.currency_data['currency']._convert(750.0, self.company_data['currency'], self.env.company, fields.Date.today()),
|
||||
'display_type': 'payment_term',
|
||||
'currency_id': self.currency_data['currency'].id,
|
||||
'debit': 375.0,
|
||||
'credit': 0.0,
|
||||
},
|
||||
])
|
||||
|
||||
move.currency_id = self.company_data['currency']
|
||||
with Form(move) as move_form:
|
||||
move_form.currency_id = self.currency_data['currency']
|
||||
self.assertEqual(move.currency_id, self.currency_data['currency'])
|
||||
|
||||
with Form(self.env['account.move'].with_context(default_move_type='out_invoice')) as move_form:
|
||||
move_form.currency_id = self.currency_data['currency']
|
||||
self.assertEqual(move_form.currency_id, self.currency_data['currency'])
|
||||
|
||||
def test_change_journal_currency(self):
|
||||
second_journal = self.company_data['default_journal_sale'].copy({
|
||||
'currency_id': self.currency_data['currency'].id,
|
||||
})
|
||||
move = self.env['account.move'].create({
|
||||
'move_type': 'out_invoice',
|
||||
'partner_id': self.partner_a.id,
|
||||
'journal_id': self.company_data['default_journal_sale'].id,
|
||||
'invoice_line_ids': [
|
||||
Command.create({
|
||||
'name': 'My super product.',
|
||||
'quantity': 1.0,
|
||||
'price_unit': 750.0,
|
||||
'account_id': self.product_a.property_account_income_id.id,
|
||||
'tax_ids': False,
|
||||
})
|
||||
],
|
||||
})
|
||||
|
||||
self.assertEqual(move.currency_id, self.company_data['currency'])
|
||||
move.journal_id = second_journal
|
||||
self.assertEqual(move.currency_id, self.currency_data['currency'])
|
||||
|
||||
@freeze_time('2019-01-01')
|
||||
def test_date_reversal_exchange_move(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user