From bab2b14252a1d142f0286f328838073d313cb283 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Thu, 26 Oct 2023 21:42:55 +0700 Subject: [PATCH] [ADD] product_internal_reference_generator --- .../README.rst | 0 .../__init__.py | 1 + .../__manifest__.py | 18 + .../demo/demo.xml | 34 ++ .../models/__init__.py | 3 + .../models/product_code_sequence.py | 10 + .../models/product_product.py | 17 + .../models/product_template.py | 30 ++ .../readme/CONFIGURE.rst | 0 .../readme/CONTRIBUTORS.rst | 0 .../readme/DESCRIPTION.rst | 0 .../readme/USAGE.rst | 0 .../security/groups.xml | 7 + .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 28872 bytes .../static/description/index.html | 463 ++++++++++++++++++ .../views/product.xml | 110 +++++ .../product_internal_reference_generator | 1 + .../setup.py | 6 + 19 files changed, 703 insertions(+) create mode 100644 product_internal_reference_generator/README.rst create mode 100644 product_internal_reference_generator/__init__.py create mode 100644 product_internal_reference_generator/__manifest__.py create mode 100644 product_internal_reference_generator/demo/demo.xml create mode 100644 product_internal_reference_generator/models/__init__.py create mode 100644 product_internal_reference_generator/models/product_code_sequence.py create mode 100644 product_internal_reference_generator/models/product_product.py create mode 100644 product_internal_reference_generator/models/product_template.py create mode 100644 product_internal_reference_generator/readme/CONFIGURE.rst create mode 100644 product_internal_reference_generator/readme/CONTRIBUTORS.rst create mode 100644 product_internal_reference_generator/readme/DESCRIPTION.rst create mode 100644 product_internal_reference_generator/readme/USAGE.rst create mode 100644 product_internal_reference_generator/security/groups.xml create mode 100644 product_internal_reference_generator/security/ir.model.access.csv create mode 100644 product_internal_reference_generator/static/description/icon.png create mode 100644 product_internal_reference_generator/static/description/index.html create mode 100644 product_internal_reference_generator/views/product.xml create mode 120000 setup/product_internal_reference_generator/odoo/addons/product_internal_reference_generator create mode 100644 setup/product_internal_reference_generator/setup.py diff --git a/product_internal_reference_generator/README.rst b/product_internal_reference_generator/README.rst new file mode 100644 index 000000000..e69de29bb diff --git a/product_internal_reference_generator/__init__.py b/product_internal_reference_generator/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/product_internal_reference_generator/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_internal_reference_generator/__manifest__.py b/product_internal_reference_generator/__manifest__.py new file mode 100644 index 000000000..b8c430053 --- /dev/null +++ b/product_internal_reference_generator/__manifest__.py @@ -0,0 +1,18 @@ +{ + "name": "Product Internal Reference Generator", + "summary": """Product template and variant reference based on sequence""", + "author": "Ilyas, Ooops, Odoo Community Association (OCA)", + "license": "LGPL-3", + "website": "https://github.com/OCA/product-variant", + "category": "Sale", + "version": "14.0.1.0.0", + "depends": ["stock"], + "data": [ + "security/ir.model.access.csv", + "views/product.xml", + "security/groups.xml", + ], + "demo": ["demo/demo.xml"], + "installable": True, + "application": False, +} diff --git a/product_internal_reference_generator/demo/demo.xml b/product_internal_reference_generator/demo/demo.xml new file mode 100644 index 000000000..a156e3954 --- /dev/null +++ b/product_internal_reference_generator/demo/demo.xml @@ -0,0 +1,34 @@ + + + + + Good products sequence + GOOD + 4 + + + + Bad products sequence + BAD + 5 + + + + Good products + 3 + + + + + Bad products + 4 + + + + diff --git a/product_internal_reference_generator/models/__init__.py b/product_internal_reference_generator/models/__init__.py new file mode 100644 index 000000000..46826c77a --- /dev/null +++ b/product_internal_reference_generator/models/__init__.py @@ -0,0 +1,3 @@ +from . import product_code_sequence +from . import product_template +from . import product_product diff --git a/product_internal_reference_generator/models/product_code_sequence.py b/product_internal_reference_generator/models/product_code_sequence.py new file mode 100644 index 000000000..5e591867b --- /dev/null +++ b/product_internal_reference_generator/models/product_code_sequence.py @@ -0,0 +1,10 @@ +from odoo import fields, models + + +class ProductCodeSequence(models.Model): + _name = "product.code.sequence" + _description = "Internal Reference Template" + + name = fields.Char(required=True) + sequence_id = fields.Many2one("ir.sequence", required=True) + variant_reference_numbers = fields.Integer("Digits", default=3, required=True) diff --git a/product_internal_reference_generator/models/product_product.py b/product_internal_reference_generator/models/product_product.py new file mode 100644 index 000000000..e6295f578 --- /dev/null +++ b/product_internal_reference_generator/models/product_product.py @@ -0,0 +1,17 @@ +from odoo import api, models + + +class ProductProduct(models.Model): + _inherit = "product.product" + + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if vals.get("product_tmpl_id"): + pt = self.env["product.template"].browse(vals["product_tmpl_id"]) + if pt.variants_sequence_id: + vals["default_code"] = ( + pt.variants_prefix + pt.variants_sequence_id.next_by_id() + ) + res = super().create(vals_list) + return res diff --git a/product_internal_reference_generator/models/product_template.py b/product_internal_reference_generator/models/product_template.py new file mode 100644 index 000000000..9101e98ad --- /dev/null +++ b/product_internal_reference_generator/models/product_template.py @@ -0,0 +1,30 @@ +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + int_ref_template_id = fields.Many2one( + "product.code.sequence", "Internal Reference Template" + ) + variants_sequence_id = fields.Many2one("ir.sequence") + variants_prefix = fields.Char( + "Internal Reference Prefix", readonly=True, tracking=True + ) + + @api.onchange("int_ref_template_id") + def onchange_int_ref_template_id(self): + self.variants_prefix = False + + def btn_generate_sequence(self): + self.ensure_one() + self.variants_prefix = self.int_ref_template_id.sequence_id.get_next_char(0) + int_ref_next_val = self.int_ref_template_id.sequence_id.next_by_id() + var_seq = self.env["ir.sequence"].create( + { + "name": "variants " + int_ref_next_val, + "padding": self.int_ref_template_id.variant_reference_numbers, + } + ) + self.variants_sequence_id = var_seq + self.default_code = int_ref_next_val + var_seq.get_next_char(0) diff --git a/product_internal_reference_generator/readme/CONFIGURE.rst b/product_internal_reference_generator/readme/CONFIGURE.rst new file mode 100644 index 000000000..e69de29bb diff --git a/product_internal_reference_generator/readme/CONTRIBUTORS.rst b/product_internal_reference_generator/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..e69de29bb diff --git a/product_internal_reference_generator/readme/DESCRIPTION.rst b/product_internal_reference_generator/readme/DESCRIPTION.rst new file mode 100644 index 000000000..e69de29bb diff --git a/product_internal_reference_generator/readme/USAGE.rst b/product_internal_reference_generator/readme/USAGE.rst new file mode 100644 index 000000000..e69de29bb diff --git a/product_internal_reference_generator/security/groups.xml b/product_internal_reference_generator/security/groups.xml new file mode 100644 index 000000000..f5359480e --- /dev/null +++ b/product_internal_reference_generator/security/groups.xml @@ -0,0 +1,7 @@ + + + + Internal reference template always visible + + + diff --git a/product_internal_reference_generator/security/ir.model.access.csv b/product_internal_reference_generator/security/ir.model.access.csv new file mode 100644 index 000000000..4f399317e --- /dev/null +++ b/product_internal_reference_generator/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +pcs1,pcs1,model_product_code_sequence,base.group_user,1,1,0,0 +pcs2,pcs2,model_product_code_sequence,base.group_system,1,1,1,1 diff --git a/product_internal_reference_generator/static/description/icon.png b/product_internal_reference_generator/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ea708b0a29ee106a8799f18ff661aa6641f6478c GIT binary patch literal 28872 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 literal 0 HcmV?d00001 diff --git a/product_internal_reference_generator/static/description/index.html b/product_internal_reference_generator/static/description/index.html new file mode 100644 index 000000000..41204e82e --- /dev/null +++ b/product_internal_reference_generator/static/description/index.html @@ -0,0 +1,463 @@ + + + + + + +Ooops Product Variant Default Code + + + +
+

Ooops Product Variant Default Code

+ + +

Beta License: LGPL-3 ooops404/ooops-product Translate me on Weblate Try me on Runbot

+

This is an internal module depending on https://github.com/OCA/product-variant/tree/14.0/product_variant_default_code

+

it can be pushed in https://github.com/ooops404/ooops-product

+

It adds the following features to oca module:

+
    +
  1. make sure “Attribute code” is unique
  2. +
  3. add a flag in settings to make “attribute code” required for all attributes & attribute values (it’s optional)
  4. +
  5. Make “Attribute value code” unique for all attribute values
  6. +
  7. Product template code generation
  8. +
+

CONTEXT

+

Currently there is no automated flow to create an internal reference for a product template; +The flow is aimed at generating internal references for product variant and works as follows:

+
    +
  • write free text in field “Reference Prefix” for product template, eg: NEW-00001
  • +
  • add attributes and attribute values (each one set with their attribute and attr.val. code) > save;
  • +
  • Internal reference for variants is created accordingly:
  • +
+

Our goal is to use some sort of sequence to generate what is currently written by hand in “Reference Prefix”

+

A possible development could be:

+
    +
  • we create a new model “internal reference template”, with 2 fields: Name and sequence (the same “sequence” model that can be found in settings > technical > sequences, not a sequence to sort records)
  • +
+

Eg: create new record “Products for Company X”, with sequence set as follows:

+

In new product template, user selects record “Products for Company X” in field “Internal reference template” > clicks “generate” button

+

“Internal reference” is populated with code CX0001

+

If user adds attributes and values in product template, the flow of the main oca module is the same, only using the generated “internal reference” as base for variant internal reference

+

Note: you can see a similar flow with this module: https://github.com/OCA/stock-logistics-barcode/tree/14.0/barcodes_generator_product

+

Table of contents

+ +
+

Changelog

+
+

14.0.1.0.2 (2023-05-31)

+

Bugfixes

+
    +
  • Fix release run (#9783)
  • +
+
+
+

14.0.1.0.1 (2023-05-30)

+

Bugfixes

+
    +
  • Fix ooops-release: fix default code module (#9768)
  • +
+
+
+

14.0.1.0.0

+
    +
  • Initial release
  • +
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Ilyas
  • +
  • Ooops
  • +
+
+
+

Maintainers

+

This module is part of the ooops404/ooops-product project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/product_internal_reference_generator/views/product.xml b/product_internal_reference_generator/views/product.xml new file mode 100644 index 000000000..3b679251b --- /dev/null +++ b/product_internal_reference_generator/views/product.xml @@ -0,0 +1,110 @@ + + + + product.template + + + + + + + {'readonly': [('default_code', '!=', False)]} + + + + + + product.code.sequence.form.view + product.code.sequence + +
+ + + + + + + + + +
+
+
+ + + product.code.sequence.tree.view + product.code.sequence + + + + + + + + + + + Internal Reference Templates + ir.actions.act_window + product.code.sequence + tree,form + + + + + + product.product + + + + {'readonly': [('default_code', '!=', False)]} + + + + + + product.product + + + {'readonly': [('default_code', '!=', False)]} + + + + +
diff --git a/setup/product_internal_reference_generator/odoo/addons/product_internal_reference_generator b/setup/product_internal_reference_generator/odoo/addons/product_internal_reference_generator new file mode 120000 index 000000000..ee2c7dfac --- /dev/null +++ b/setup/product_internal_reference_generator/odoo/addons/product_internal_reference_generator @@ -0,0 +1 @@ +../../../../product_internal_reference_generator \ No newline at end of file diff --git a/setup/product_internal_reference_generator/setup.py b/setup/product_internal_reference_generator/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/product_internal_reference_generator/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)