changeset 7ed95c461601 in modules/product:default
details: https://hg.tryton.org/modules/product?cmd=changeset;node=7ed95c461601
description:
        Make product code unique

        This allows to use the product code as SKU.

        issue9004
        review270831002
diffstat:

 CHANGELOG     |   1 +
 doc/index.rst |  10 ++++++----
 message.xml   |   3 +++
 product.py    |  16 +++++++++++++---
 4 files changed, 23 insertions(+), 7 deletions(-)

diffs (91 lines):

diff -r 88f15ac40dbe -r 7ed95c461601 CHANGELOG
--- a/CHANGELOG Thu Mar 19 00:28:43 2020 +0100
+++ b/CHANGELOG Thu Mar 19 00:33:37 2020 +0100
@@ -1,3 +1,4 @@
+* Make product code unique
 * Add code to template as variant prefix code
 * Hide product fields inherited from template when empty
 * Skip default products when template is created from product
diff -r 88f15ac40dbe -r 7ed95c461601 doc/index.rst
--- a/doc/index.rst     Thu Mar 19 00:28:43 2020 +0100
+++ b/doc/index.rst     Thu Mar 19 00:33:37 2020 +0100
@@ -61,10 +61,10 @@
 - Active, allow to disable a product.
 
 
-The Product model extend the Product Template with two fields: Code
-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 
+The Product model extends the Product Template with two fields: Code (aka SKU_)
+and Description. If a sequence is set on product configuration the code will be
+read-only 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)
@@ -74,6 +74,8 @@
     * International Securities Identification Number (ISIN)
     * International Standard Music Number (ISMN)
 
+.. _SKU: https://en.wikipedia.org/wiki/Stock_keeping_unit
+
 Configuration
 *************
 
diff -r 88f15ac40dbe -r 7ed95c461601 message.xml
--- a/message.xml       Thu Mar 19 00:28:43 2020 +0100
+++ b/message.xml       Thu Mar 19 00:33:37 2020 +0100
@@ -24,5 +24,8 @@
         <record model="ir.message" id="msg_invalid_code">
             <field name="text">The %(type)s "%(code)s" for product 
"%(product)s" is not valid.</field>
         </record>
+        <record model="ir.message" id="msg_product_code_unique">
+            <field name="text">Code of active product must be unique.</field>
+        </record>
     </data>
 </tryton>
diff -r 88f15ac40dbe -r 7ed95c461601 product.py
--- a/product.py        Thu Mar 19 00:28:43 2020 +0100
+++ b/product.py        Thu Mar 19 00:33:37 2020 +0100
@@ -7,12 +7,13 @@
 
 import stdnum
 import stdnum.exceptions
-from sql import Null, Column
+from sql import Null, Column, Literal
+from sql.operators import Equal
 
 from trytond.i18n import gettext
 from trytond.model import (
     ModelView, ModelSQL, Model, UnionMixin, DeactivableMixin, sequence_ordered,
-    fields)
+    Exclude, fields)
 from trytond.pyson import Eval
 from trytond.transaction import Transaction
 from trytond.pool import Pool
@@ -235,7 +236,8 @@
         states={
             'readonly': Eval('code_readonly', False),
             },
-        depends=['code_readonly'])
+        depends=['code_readonly'],
+        help="The unique identifier for the product (aka SKU).")
     code = fields.Char("Code", readonly=True, select=True)
     identifiers = fields.One2Many(
         'product.identifier', 'product', "Identifiers",
@@ -261,6 +263,14 @@
 
         super(Product, cls).__setup__()
 
+        t = cls.__table__()
+        cls._sql_constraints = [
+            ('code_exclude', Exclude(t, (t.code, Equal),
+                    where=(t.active == Literal(True))
+                    & (t.code != '')),
+                'product.msg_product_code_unique'),
+            ]
+
         for attr in dir(Template):
             tfield = getattr(Template, attr)
             if not isinstance(tfield, fields.Field):

Reply via email to