diff options
| author | Fanny He <fah@odoo.com> | 2020-07-27 06:17:08 +0000 |
|---|---|---|
| committer | Fanny He <fah@odoo.com> | 2020-11-17 12:15:23 +0000 |
| commit | 478a42beb5876171afeab7df27fa69548edbf849 (patch) | |
| tree | b48182874ed6b96feed6c1d0092dccf9ae4fc477 /addons/product | |
| parent | 8a9617d045c2afda8d804a5863df927012f0692c (diff) | |
[FIX] product, decimal_precision, stock, mrp: Prevent quant reservation issue
One can set a Unit of Measure precision rounding more
precise than the overall Decimal Accuracy. This can trigger the error
'It is not possible to unreserve more products', as there will be
inconsistencies on reserved quantities due to decimal roundings.
We add 2 warnings on Units of Measure and Decimal Accuracy.
Therefore, users are warned when their UOM/decimal changes can
cause inconsistencies in quants reservation.
Also, we want to prevent the issue at the root by ensuring that both the move
and the quant have the same reserved quantity.
The contrary can happen e.g. when a product is defined in Liters (rounding .001)
but used in an operation in ml (rounding .01, so e.g. 187.5ml).
The conversions between the 2 UOM can cause the differences of reservations.
In _prepare_move_line_vals we make sure uom_quantity_back_to_product_uom
is not more precise than the overall Decimal Accuracy. That way, if
the reserved quantity changes between UOM conversions, the move line created
is in the quant/product UOM, and we do not have move line's reserved quantity >
quantity in stock.
We do the same for _update_reserved_quantity (stock.move), when updating
a move line.
In _update_move_lines, because of UOM conversions, new_quantity_done
can differ from ml.product_uom_qty, which triggers the creation of an extra
move line, leading to reserved quantity > quantity in stock. To prevent
that, we compare the reserved quantities in the product UOM.
opw 2206902 (Example 1)
opw 2171541
opw 2221227
opw 2233937
opw 2198775
and many more
closes odoo/odoo#61758
X-original-commit: 91318520314632655127142de674156802214a21
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
Diffstat (limited to 'addons/product')
| -rw-r--r-- | addons/product/i18n/product.pot | 25 | ||||
| -rw-r--r-- | addons/product/models/__init__.py | 1 | ||||
| -rw-r--r-- | addons/product/models/decimal_precision.py | 23 | ||||
| -rw-r--r-- | addons/product/models/uom_uom.py | 21 |
4 files changed, 70 insertions, 0 deletions
diff --git a/addons/product/i18n/product.pot b/addons/product/i18n/product.pot index 574530cf552..16fcc6f186a 100644 --- a/addons/product/i18n/product.pot +++ b/addons/product/i18n/product.pot @@ -2341,6 +2341,15 @@ msgid "" msgstr "" #. module: product +#: code:addons/product/models/uom_uom.py:0 +#, python-format +msgid "" +"This rounding precision is higher than the Decimal Accuracy (%s digits).\n" +"This may cause inconsistencies in computations.\n" +"Please set a precision between %s and 1." +msgstr "" + +#. module: product #: model:ir.model.fields,help:product.field_product_supplierinfo__product_code msgid "" "This vendor's product code will be used when printing a request for " @@ -2662,6 +2671,13 @@ msgid "Volume unit of measure label" msgstr "" #. module: product +#: code:addons/product/models/decimal_precision.py:0 +#: code:addons/product/models/uom_uom.py:0 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: product #: model_terms:ir.ui.view,arch_db:product.product_template_search_view msgid "Warnings" msgstr "" @@ -2695,6 +2711,15 @@ msgid "White" msgstr "" #. module: product +#: code:addons/product/models/decimal_precision.py:34 +#, python-format +msgid "You are setting a Decimal Accuracy less precise than the UOMs:\n" +"%s\n" +"This may cause inconsistencies in computations.\n" +"Please increase the rounding of those units of measure, or the digits of this Decimal Accuracy." +msgstr "" + +#. module: product #: model_terms:ir.actions.act_window,help:product.product_pricelist_action2 msgid "" "You can assign pricelists to your customers or select one when creating a " diff --git a/addons/product/models/__init__.py b/addons/product/models/__init__.py index 57917450de3..6e6333f642d 100644 --- a/addons/product/models/__init__.py +++ b/addons/product/models/__init__.py @@ -5,6 +5,7 @@ from . import res_config_settings from . import decimal_precision +from . import uom_uom # don't try to be a good boy and sort imports alphabetically. # `product.template` should be initialised before `product.product` diff --git a/addons/product/models/decimal_precision.py b/addons/product/models/decimal_precision.py index e8a46a90e2f..0539fbb32dc 100644 --- a/addons/product/models/decimal_precision.py +++ b/addons/product/models/decimal_precision.py @@ -15,3 +15,26 @@ class DecimalPrecision(models.Model): for precision in self): raise ValidationError(_("You cannot define the decimal precision of 'Account' as greater than the rounding factor of the company's main currency")) return True + + @api.onchange('digits') + def _onchange_digits(self): + if self.name != "Product Unit of Measure": # precision_get() relies on this name + return + # We are changing the precision of UOM fields; check whether the + # precision is equal or higher than existing units of measure. + rounding = 1.0 / 10.0**self.digits + dangerous_uom = self.env['uom.uom'].search([('rounding', '<', rounding)]) + if dangerous_uom: + uom_descriptions = [ + " - %s (id=%s, precision=%s)" % (uom.name, uom.id, uom.rounding) + for uom in dangerous_uom + ] + return {'warning': { + 'title': _('Warning!'), + 'message': _( + "You are setting a Decimal Accuracy less precise than the UOMs:\n" + "%s\n" + "This may cause inconsistencies in computations.\n" + "Please increase the rounding of those units of measure, or the digits of this Decimal Accuracy." + ) % ('\n'.join(uom_descriptions)), + }} diff --git a/addons/product/models/uom_uom.py b/addons/product/models/uom_uom.py new file mode 100644 index 00000000000..cae84ba1ba0 --- /dev/null +++ b/addons/product/models/uom_uom.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, models, _ + + +class UoM(models.Model): + _inherit = 'uom.uom' + + @api.onchange('rounding') + def _onchange_rounding(self): + precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') + if self.rounding < 1.0 / 10.0**precision: + return {'warning': { + 'title': _('Warning!'), + 'message': _( + "This rounding precision is higher than the Decimal Accuracy" + " (%s digits).\nThis may cause inconsistencies in computations.\n" + "Please set a precision between %s and 1." + ) % (precision, 1.0 / 10.0**precision), + }} |
