From 6c2512d7dc78eb439e44ffec5ccf0c4f66e49806 Mon Sep 17 00:00:00 2001 From: Sergi Almacellas Abellana Date: Mon, 19 Aug 2019 11:43:26 +0200 Subject: [PATCH] Allow the product code to be set by a sequence issue8545 review261921004 --- CHANGELOG | 1 + configuration.py | 5 ++++ doc/index.rst | 10 ++++---- product.py | 46 +++++++++++++++++++++++++++++++++++-- product.xml | 14 +++++++++++ view/configuration_form.xml | 2 ++ 6 files changed, 72 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0e08176b29..79f21908d0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Allow the product code to be set by a sequence * Allow UoM conversion between different categories * Add product identifiers diff --git a/configuration.py b/configuration.py index 051bbe94cc..5eeca5c24d 100644 --- a/configuration.py +++ b/configuration.py @@ -26,6 +26,11 @@ class Configuration(ModelSingleton, ModelSQL, ModelView, MultiValueMixin): default_cost_price_method = fields.MultiValue(default_cost_price_method) get_cost_price_methods = get_cost_price_methods + product_sequence = fields.Many2One('ir.sequence', 'Product Sequence', + domain=[ + ('code', '=', 'product.product'), + ], + help="Used to generate the product code.") @classmethod def default_default_cost_price_method(cls, **pattern): diff --git a/doc/index.rst b/doc/index.rst index 8c04fc65e7..6d0ae5c850 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -53,16 +53,18 @@ The Product Template model contains the following fields: - Cost Price Method, which can be *Fixed* or *Average*. Defines how the cost price should be updated. *Fixed* means that the cost price stay unchanged. *Average* means that the cost price is the average - cost of all the items that are in stock. + cost of all the items that are in stock. It's default value can be defined + on product configuration. - Default UOM. The default UOM for this product. Used for example to express stock levels. - Active, allow to disable a product. The Product model extend the Product Template with two fields: Code -and Description. It's also possible to define a list of identifiers on product. -An identifier is composed by a type and a code. The following types are -available: +and Description. If a sequence is set on product configuration the code will +be readonly and will be filled in using the sequence. It's also possible to +define a list of identifiers on product. An identifier is composed by a type +and a code. The following types are available: * International Article Number (EAN) * International Standard Audiovisual Number (ISAN) diff --git a/product.py b/product.py index 4b18ce6b62..f6f4a25d3e 100644 --- a/product.py +++ b/product.py @@ -205,8 +205,13 @@ class Product( template = fields.Many2One('product.template', 'Product Template', required=True, ondelete='CASCADE', select=True, states=STATES, depends=DEPENDS) - code = fields.Char("Code", size=None, select=True, states=STATES, - depends=DEPENDS) + code_readonly = fields.Function(fields.Boolean('Code Readonly'), + 'get_code_readonly') + code = fields.Char("Code", size=None, select=True, + states={ + 'readonly': STATES['readonly'] | Eval('code_readonly', False), + }, + depends=DEPENDS + ['code_readonly']) identifiers = fields.One2Many('product.identifier', 'product', "Identifiers", states=STATES, depends=DEPENDS, help="Add other identifiers to the variant.") @@ -353,6 +358,43 @@ class Product( icon = icon or 'tryton-product' yield id_, rec_name, icon + @classmethod + def default_code_readonly(cls): + pool = Pool() + Configuration = pool.get('product.configuration') + config = Configuration(1) + return bool(config.product_sequence) + + def get_code_readonly(self, name): + return self.default_code_readonly() + + @classmethod + def _new_code(cls): + pool = Pool() + Sequence = pool.get('ir.sequence') + Configuration = pool.get('product.configuration') + config = Configuration(1) + sequence = config.product_sequence + if sequence: + return Sequence.get_id(sequence.id) + + @classmethod + def create(cls, vlist): + vlist = [x.copy() for x in vlist] + for values in vlist: + if not values.get('code'): + values['code'] = cls._new_code() + return super().create(vlist) + + @classmethod + def copy(cls, products, default=None): + if default is None: + default = {} + else: + default = default.copy() + default.setdefault('code', None) + return super().copy(products, default=default) + class ProductListPrice(ModelSQL, CompanyValueMixin): "Product List Price" diff --git a/product.xml b/product.xml index f40d65a166..b0c4573344 100644 --- a/product.xml +++ b/product.xml @@ -220,6 +220,20 @@ this repository contains the full copyright notices and license terms. --> + + Product + product.product + + + + + + + + + diff --git a/view/configuration_form.xml b/view/configuration_form.xml index 04fea15e09..f6924a096e 100644 --- a/view/configuration_form.xml +++ b/view/configuration_form.xml @@ -4,4 +4,6 @@ this repository contains the full copyright notices and license terms. -->