From fea5768ce7eab4fc5495a4995c723eeef58aa324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 17 Feb 2022 00:45:45 +0100 Subject: [PATCH] Forbid to decrease digits of unit of measure issue11187 review364711002 --- CHANGELOG | 1 + exceptions.py | 6 ++++- message.xml | 3 +++ tests/test_product.py | 52 +++++++++++++++++++++++++++++++++++++++++++ uom.py | 24 +++++++++----------- 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 60fdc69178..7cb0841933 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Forbid to decrease digits of unit of measure * Add support for Python 3.10 * Remove support for Python 3.6 diff --git a/exceptions.py b/exceptions.py index 609f13efbc..607e69d214 100644 --- a/exceptions.py +++ b/exceptions.py @@ -1,7 +1,7 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from trytond.model.exceptions import ValidationError +from trytond.model.exceptions import AccessError, ValidationError class TemplateValidationError(ValidationError): @@ -16,5 +16,9 @@ class UOMValidationError(ValidationError): pass +class UOMAccessError(AccessError): + pass + + class InvalidIdentifierCode(ValidationError): pass diff --git a/message.xml b/message.xml index d8b1f2f10e..340ec37af8 100644 --- a/message.xml +++ b/message.xml @@ -12,6 +12,9 @@ this repository contains the full copyright notices and license terms. --> You cannot modify the category of UOM "%(uom)s". + + You cannot decrease the digits of UOM "%(uom)s". + If the UOM is still not used, you can delete it otherwise you can deactivate it and create a new one. diff --git a/tests/test_product.py b/tests/test_product.py index 27d4bc8021..78b8ac473d 100644 --- a/tests/test_product.py +++ b/tests/test_product.py @@ -11,6 +11,7 @@ from trytond.tests.test_tryton import ( ModuleTestCase, doctest_checker, doctest_teardown, with_transaction) from trytond.transaction import Transaction +from ..exceptions import UOMAccessError from ..product import round_price @@ -261,6 +262,57 @@ class ProductTestCase(CompanyTestMixin, ModuleTestCase): Uom.compute_price(g, price, m3, **keys), result, msg=msg) + @with_transaction() + def test_uom_modify_factor_rate(self): + "Test can not modify factor or rate of uom" + pool = Pool() + Uom = pool.get('product.uom') + g, = Uom.search([('name', '=', "Gram")]) + + g.factor = 1 + g.rate = 1 + + with self.assertRaises(UOMAccessError): + g.save() + + @with_transaction() + def test_uom_modify_category(self): + "Test can not modify category of uom" + pool = Pool() + Uom = pool.get('product.uom') + Category = pool.get('product.uom.category') + g, = Uom.search([('name', '=', "Gram")]) + units, = Category.search([('name', '=', "Units")]) + + g.category = units + + with self.assertRaises(UOMAccessError): + g.save() + + @with_transaction() + def test_uom_increase_digits(self): + "Test can increase digits of uom" + pool = Pool() + Uom = pool.get('product.uom') + g, = Uom.search([('name', '=', "Gram")]) + + g.digits += 1 + + g.save() + + @with_transaction() + def test_uom_decrease_digits(self): + "Test can not decrease digits of uom" + pool = Pool() + Uom = pool.get('product.uom') + g, = Uom.search([('name', '=', "Gram")]) + + g.digits -= 1 + g.rounding = 1 + + with self.assertRaises(UOMAccessError): + g.save() + @with_transaction() def test_product_search_domain(self): 'Test product.product search_domain function' diff --git a/uom.py b/uom.py index 74ee707a79..b636a6567e 100644 --- a/uom.py +++ b/uom.py @@ -9,11 +9,10 @@ from trytond.i18n import gettext from trytond.model import ( Check, DeactivableMixin, DigitsMixin, ModelSQL, ModelView, SymbolMixin, fields) -from trytond.model.exceptions import AccessError from trytond.pyson import Eval from trytond.transaction import Transaction -from .exceptions import UOMValidationError +from .exceptions import UOMAccessError, UOMValidationError __all__ = ['uom_conversion_digits'] @@ -153,26 +152,25 @@ class Uom(SymbolMixin, DigitsMixin, DeactivableMixin, ModelSQL, ModelView): super(Uom, cls).write(*args) return - actions = iter(args) - all_uoms = [] - for uoms, values in zip(actions, actions): - if 'rate' not in values and 'factor' not in values \ - and 'category' not in values: - continue - all_uoms += uoms - - old_uom = dict((uom.id, (uom.factor, uom.rate, uom.category)) - for uom in all_uoms) + all_uoms = sum(args[0:None:2], []) + old_uom = { + uom.id: (uom.factor, uom.rate, uom.category) for uom in all_uoms} + old_digits = {uom.id: uom.digits for uom in all_uoms} super(Uom, cls).write(*args) for uom in all_uoms: for i, field in enumerate(['factor', 'rate', 'category']): if getattr(uom, field) != old_uom[uom.id][i]: - raise AccessError( + raise UOMAccessError( gettext('product.msg_uom_modify_%s' % field, uom=uom.rec_name), gettext('product.msg_uom_modify_options')) + if uom.digits < old_digits[uom.id]: + raise UOMAccessError( + gettext('product.msg_uom_decrease_digits', + uom=uom.rec_name), + gettext('product.msg_uom_modify_options')) @property def accurate_field(self):