diff options
| author | Raphael Collet <rco@odoo.com> | 2020-04-17 13:09:35 +0000 |
|---|---|---|
| committer | Raphael Collet <rco@odoo.com> | 2020-04-18 09:46:33 +0000 |
| commit | e7b98b811c9b6668012108ab0bbe5b84e9c0101d (patch) | |
| tree | e22ebf1a1b5b529a4d438275ea2ecf12c0254d3c /odoo/fields.py | |
| parent | 72c48efc9924c92545f54be5ffb7ade0011c397a (diff) | |
[FIX] fields: screwing up cache when rounding monetary value
Consider a sales order with a single line. Edit the sales order: remove
the line, and add another line with the same subtotal. When saving, the
total of the sales order is 0.0.
Here is the explanation: the form view performs a `write` on the sales
order, and modifies the lines with a command `2` (remove line) and a
command `0` (create line).
After deleting the first order line, the cache is emptied, and a call to
`flush()` forces the recomputation of the total. The value is computed
to be 0, and assigned to the field. The assignment converts the value
for the cache, without prefetching the currency field (optimization),
and puts 0.0 in cache. The assignment then converts the value for the
database, which prefetches most fields on the sales order: the cache is
now inconsistent and contains the old value V, while the database is
then updated with 0.0.
After creating the new order line, the total is once again recomputed.
Its value is V, and because the cache also contains that value, no
update is performed to the database, which remains at 0.0!
The fix consists in avoiding the prefetching of fields when accessing
the currency field to round a monetary value.
opw-2223134
closes odoo/odoo#49741
X-original-commit: 048ea2f20a0a2fa6d629cbe262cbbe765248d36f
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Diffstat (limited to 'odoo/fields.py')
| -rw-r--r-- | odoo/fields.py | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/odoo/fields.py b/odoo/fields.py index 6fcf8692072..a96d0f9631a 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -1306,7 +1306,9 @@ class Monetary(Field): else: # Note: this is wrong if 'record' is several records with different # currencies, which is functional nonsense and should not happen - currency = record[:1][self.currency_field] + # BEWARE: do not prefetch other fields, because 'value' may be in + # cache, and would be overridden by the value read from database! + currency = record[:1].with_context(prefetch_fields=False)[self.currency_field] value = float(value or 0.0) if currency: @@ -1319,7 +1321,9 @@ class Monetary(Field): if value and validate: # FIXME @rco-odoo: currency may not be already initialized if it is # a function or related field! - currency = record.sudo()[self.currency_field] + # BEWARE: do not prefetch other fields, because 'value' may be in + # cache, and would be overridden by the value read from database! + currency = record.sudo().with_context(prefetch_fields=False)[self.currency_field] if len(currency) > 1: raise ValueError("Got multiple currencies while assigning values of monetary field %s" % str(self)) elif currency: |
