diff --git a/create_recursive_abstract/README.rst b/create_recursive_abstract/README.rst new file mode 100644 index 00000000..e69de29b diff --git a/create_recursive_abstract/__init__.py b/create_recursive_abstract/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/create_recursive_abstract/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/create_recursive_abstract/__manifest__.py b/create_recursive_abstract/__manifest__.py new file mode 100644 index 00000000..c39eb7f1 --- /dev/null +++ b/create_recursive_abstract/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Recursive creation tools", + "summary": "Create recursively parents item.", + "version": "16.0.1.0.0", + "category": "Tools", + "author": "GRAP", + "website": "https://github.com/grap/grap-odoo-incubator", + "license": "AGPL-3", + "depends": ["web_notify"], + "installable": True, +} diff --git a/create_recursive_abstract/models/__init__.py b/create_recursive_abstract/models/__init__.py new file mode 100644 index 00000000..f74d1fc6 --- /dev/null +++ b/create_recursive_abstract/models/__init__.py @@ -0,0 +1 @@ +from . import create_recursive_mixin diff --git a/create_recursive_abstract/models/create_recursive_mixin.py b/create_recursive_abstract/models/create_recursive_mixin.py new file mode 100644 index 00000000..937cd217 --- /dev/null +++ b/create_recursive_abstract/models/create_recursive_mixin.py @@ -0,0 +1,50 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, models + + +class CreateRecursiveMixin(models.AbstractModel): + _name = "create.recursive.mixin" + _description = "Mixin providing recurring creation of parents" + + def _create_recursive_get_or_create_parent_id(self, item_name): + data = self.name_search(name=item_name, operator="=") + if data: + return data[0][0] + else: + parent_id, _parent_name = self.name_create(item_name) + return parent_id + + @api.model + def name_create(self, name): + """Natively, this function is called if a search of 'name' fails + to create simply an item, with {'name': name} value. + This overload will alter the function if the name contains a '/'. + For exemple, if the name is 'Parent / Child', it will not create + an item with such name. It will: + - search an item named 'Parent' (or create it if it doesn't exist) + - then, create an item named 'Child' with the parent found as parent_id. + """ + if "/" in name: + splitted_name = name.split("/") + parent_name = (" / ".join(splitted_name[:-1])).strip() + item_name = splitted_name[-1:][0].strip() + parent_id = self._create_recursive_get_or_create_parent_id(parent_name) + item = self.create({"name": item_name, "parent_id": parent_id}) + return item.name_get()[0] + res = super().name_create(name) + return res + + @api.model_create_multi + def create(self, vals_list): + for value in vals_list: + if "name" in value: + value["name"] = value["name"].replace("/", "-") + return super().create(vals_list) + + def write(self, vals): + if "name" in vals: + vals["name"] = vals["name"].replace("/", "-") + return super().write(vals) diff --git a/create_recursive_abstract/readme/CONTRIBUTORS.rst b/create_recursive_abstract/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9f76a75b --- /dev/null +++ b/create_recursive_abstract/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sylvain LE GAL diff --git a/create_recursive_abstract/readme/DESCRIPTION.rst b/create_recursive_abstract/readme/DESCRIPTION.rst new file mode 100644 index 00000000..e2945256 --- /dev/null +++ b/create_recursive_abstract/readme/DESCRIPTION.rst @@ -0,0 +1,7 @@ +This module is a technical tools to create recursively parents, +when creating items, if the name contains one or many **'/'** chars. + +See implementation in the following modules: + +- ``create_recursive_product_category`` +- ``create_recursive_pos_category`` diff --git a/create_recursive_abstract/readme/DEVELOP.rst b/create_recursive_abstract/readme/DEVELOP.rst new file mode 100644 index 00000000..8a46fb4f --- /dev/null +++ b/create_recursive_abstract/readme/DEVELOP.rst @@ -0,0 +1,10 @@ +This module define a new mixin ``create.recursive.mixin`` that can be used +on any model that contains the following code. + +.. code:: python + + _parent_name = "parent_id" + _parent_store = True + _rec_name = "complete_name" + +(See example in the ``product.category`` model in the odoo ``product`` module) diff --git a/create_recursive_abstract/tests/__init__.py b/create_recursive_abstract/tests/__init__.py new file mode 100644 index 00000000..402101cc --- /dev/null +++ b/create_recursive_abstract/tests/__init__.py @@ -0,0 +1 @@ +from . import test_create_recursive_abstract diff --git a/create_recursive_abstract/tests/fake_models.py b/create_recursive_abstract/tests/fake_models.py new file mode 100644 index 00000000..25d64355 --- /dev/null +++ b/create_recursive_abstract/tests/fake_models.py @@ -0,0 +1,34 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ModelCreateRecursiveMixin(models.Model): + _name = "model.create.recursive.mixin" + _description = "model.create.recursive.mixin" + _inherit = ["create.recursive.mixin"] + _parent_name = "parent_id" + _parent_store = True + _rec_name = "complete_name" + + name = fields.Char() + + parent_id = fields.Many2one(comodel_name="model.create.recursive.mixin") + + parent_path = fields.Char(index=True, unaccent=False) + + complete_name = fields.Char( + compute="_compute_complete_name", recursive=True, store=True + ) + + @api.depends("name", "parent_id.complete_name") + def _compute_complete_name(self): + for category in self: + if category.parent_id: + category.complete_name = ( + "{category.parent_id.complete_name} / {category.name}" + ) + else: + category.complete_name = category.name diff --git a/create_recursive_abstract/tests/test_create_recursive_abstract.py b/create_recursive_abstract/tests/test_create_recursive_abstract.py new file mode 100644 index 00000000..f5903920 --- /dev/null +++ b/create_recursive_abstract/tests/test_create_recursive_abstract.py @@ -0,0 +1,40 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo_test_helper import FakeModelLoader + +from odoo.tests.common import TransactionCase + + +class TestModule(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Load a test model using odoo_test_helper + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + from .fake_models import ModelCreateRecursiveMixin + + cls.loader.update_registry((ModelCreateRecursiveMixin,)) + + cls.model = cls.env["model.create.recursive.mixin"] + + cls.parent_item = cls.model.create({"name": "Parent"}) + + cls.child_item = cls.model.create( + {"name": "Child", "parent_id": cls.parent_item.id} + ) + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + return super().tearDownClass() + + def test_remove_slash_create(self): + item = self.model.create({"name": "Fruits / Vegetables"}) + self.assertEqual(item.name, "Fruits - Vegetables") + + def test_remove_slash_write(self): + self.parent_item.write({"name": "Fruits / Vegetables"}) + self.assertEqual(self.parent_item.name, "Fruits - Vegetables") diff --git a/create_recursive_pos_category/README.rst b/create_recursive_pos_category/README.rst new file mode 100644 index 00000000..d1df4681 --- /dev/null +++ b/create_recursive_pos_category/README.rst @@ -0,0 +1,64 @@ +==================================================================== +GRAP - Custom Import Product Supplierinfo Quantity Multiplier Module +==================================================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9b8df078c1fb893b68650c2ee64e375d840edd6d1f8f7bfdb0f1a4da37012215 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-grap%2Fgrap--odoo--import-lightgray.png?logo=github + :target: https://github.com/grap/grap-odoo-import/tree/16.0/grap_custom_import_product_supplierinfo_qty_multiplier + :alt: grap/grap-odoo-import + +|badge1| |badge2| |badge3| + +This module improve the "import" features provided by Odoo. + +* ``product.product``: + + * Allow to recover ``multiplier_qty`` field in the supplier info level. + +**Table of contents** + +.. contents:: + :local: + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* GRAP + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL + +Maintainers +~~~~~~~~~~~ + +This module is part of the `grap/grap-odoo-import `_ project on GitHub. + +You are welcome to contribute. diff --git a/create_recursive_pos_category/__init__.py b/create_recursive_pos_category/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/create_recursive_pos_category/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/create_recursive_pos_category/__manifest__.py b/create_recursive_pos_category/__manifest__.py new file mode 100644 index 00000000..6b18b360 --- /dev/null +++ b/create_recursive_pos_category/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright (C) 2019 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "GRAP - Custom Product Import - Point Of Sale Module", + "summary": "Extra GRAP Tools to import product data for" " Point of sale module", + "version": "16.0.1.0.0", + "category": "Tools", + "author": "GRAP", + "website": "https://github.com/grap/grap-odoo-incubator", + "license": "AGPL-3", + "depends": ["create_recursive_abstract", "point_of_sale"], + "installable": True, +} diff --git a/create_recursive_pos_category/models/__init__.py b/create_recursive_pos_category/models/__init__.py new file mode 100644 index 00000000..9a1a22a5 --- /dev/null +++ b/create_recursive_pos_category/models/__init__.py @@ -0,0 +1 @@ +from . import pos_category diff --git a/create_recursive_pos_category/models/pos_category.py b/create_recursive_pos_category/models/pos_category.py new file mode 100644 index 00000000..1ac92130 --- /dev/null +++ b/create_recursive_pos_category/models/pos_category.py @@ -0,0 +1,10 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class PosCategory(models.Model): + _name = "pos.category" + _inherit = ["pos.category", "create.recursive.mixin"] diff --git a/create_recursive_pos_category/readme/CONTRIBUTORS.rst b/create_recursive_pos_category/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9f76a75b --- /dev/null +++ b/create_recursive_pos_category/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sylvain LE GAL diff --git a/create_recursive_pos_category/readme/DESCRIPTION.rst b/create_recursive_pos_category/readme/DESCRIPTION.rst new file mode 100644 index 00000000..28526c10 --- /dev/null +++ b/create_recursive_pos_category/readme/DESCRIPTION.rst @@ -0,0 +1,14 @@ +Implement the recursive creation of parent for the model PoS Categories. +(``pos.category``). + +In the product view, if a user enter in the PoS category field the name +**'Chairs / Little'**, it will not create a category with such name. +Instead, it will look for a category named **'Chairs'** (and create it if it +doesn't exists), then create a new category named **'Little'** with the category +**'Chairs'** as parent. + +If a user create or update the name of a PoS category, any **'/'** char will +be replaced by the char **'-'**. + +At the installation, all **'/'** in the names of the PoS categories +will be replaced by **'-'**. \ No newline at end of file diff --git a/create_recursive_pos_category/tests/__init__.py b/create_recursive_pos_category/tests/__init__.py new file mode 100644 index 00000000..d9b96c4f --- /dev/null +++ b/create_recursive_pos_category/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/create_recursive_pos_category/tests/test_module.py b/create_recursive_pos_category/tests/test_module.py new file mode 100644 index 00000000..58ef61f2 --- /dev/null +++ b/create_recursive_pos_category/tests/test_module.py @@ -0,0 +1,32 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +# from odoo.tests import tagged + +# from odoo.addons.grap_custom_import_product.tests.test_module import TestModuleProduct + + +# @tagged("post_install", "-at_install") +# class TestModuleProductPos(TestModuleProduct): +# @classmethod +# def setUpClass(cls): +# super().setUpClass() +# cls.ProductProduct = cls.env["product.product"] + +# # def _test_import_product_supplierinfo_qty_multiplier(self, model): +# # products, messages = self._test_import_file( +# # "grap_custom_import_product_supplierinfo_qty_multiplier", +# # model, +# # "product.csv", +# # folder="product", +# # ) +# # self.assertFalse(messages) +# # self.assertEqual(len(products), 1) +# # self.assertEqual(products.mapped("seller_ids.multiplier_qty"), [24.0]) + +# # def test_01_import_product_supplierinfo_qty_multiplier_product(self): +# # self._test_import_product_supplierinfo_qty_multiplier("product.product") + +# # def test_02_import_product_supplierinfo_qty_multiplier_template(self): +# # self._test_import_product_supplierinfo_qty_multiplier("product.template") diff --git a/create_recursive_product_category/README.rst b/create_recursive_product_category/README.rst new file mode 100644 index 00000000..403eb01a --- /dev/null +++ b/create_recursive_product_category/README.rst @@ -0,0 +1,68 @@ +=================================== +GRAP - Custom Import Product Module +=================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f1edf2e49664874548baa2a31b5a7f89fc363cfed20297f007038186bbc81142 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-grap%2Fgrap--odoo--import-lightgray.png?logo=github + :target: https://github.com/grap/grap-odoo-import/tree/16.0/grap_custom_import_product + :alt: grap/grap-odoo-import + +|badge1| |badge2| |badge3| + +This module improve the "import" features provided by Odoo. + +It provides generic tools for that purpose, and improve imports for some models. + +* ``product.product``: + + * Prevent to create duplicates regarding ``name`` and ``barcode`` fields. + + * Allow to create main ``seller_ids``, based on supplier information fields. + +**Table of contents** + +.. contents:: + :local: + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* GRAP + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL + +Maintainers +~~~~~~~~~~~ + +This module is part of the `grap/grap-odoo-import `_ project on GitHub. + +You are welcome to contribute. diff --git a/create_recursive_product_category/__init__.py b/create_recursive_product_category/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/create_recursive_product_category/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/create_recursive_product_category/__manifest__.py b/create_recursive_product_category/__manifest__.py new file mode 100644 index 00000000..b50310a2 --- /dev/null +++ b/create_recursive_product_category/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright (C) 2019 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + "name": "Product Categories - Recursive creation", + "summary": "Create recursively parents item for the Product" " Categories model.", + "version": "16.0.1.0.0", + "category": "Tools", + "author": "GRAP", + "website": "https://github.com/grap/grap-odoo-incubator", + "license": "AGPL-3", + "depends": ["create_recursive_abstract", "product"], + "installable": True, +} diff --git a/create_recursive_product_category/models/__init__.py b/create_recursive_product_category/models/__init__.py new file mode 100644 index 00000000..53553f3f --- /dev/null +++ b/create_recursive_product_category/models/__init__.py @@ -0,0 +1 @@ +from . import product_category diff --git a/create_recursive_product_category/models/product_category.py b/create_recursive_product_category/models/product_category.py new file mode 100644 index 00000000..c2dc129e --- /dev/null +++ b/create_recursive_product_category/models/product_category.py @@ -0,0 +1,10 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models + + +class ProductCategory(models.Model): + _name = "product.category" + _inherit = ["product.category", "create.recursive.mixin"] diff --git a/create_recursive_product_category/readme/CONTRIBUTORS.rst b/create_recursive_product_category/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..9f76a75b --- /dev/null +++ b/create_recursive_product_category/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Sylvain LE GAL diff --git a/create_recursive_product_category/readme/DESCRIPTION.rst b/create_recursive_product_category/readme/DESCRIPTION.rst new file mode 100644 index 00000000..a1e3c038 --- /dev/null +++ b/create_recursive_product_category/readme/DESCRIPTION.rst @@ -0,0 +1,13 @@ +Implement the recursive creation of parent for the model Product Categories. +(``product.category``). + +In the product view, if a user enter in the category field the name +**'All / New Category'**, it will not create a category with such name. +Instead, it will look for a category named **'All'** (and create it if it +doesn't exists), then create a new category named **'New Category'** with the category **'All'** as parent. + +If a user create or update the name of a category, any **'/'** char will +be replaced by the char **'-'**. + +At the installation, all **'/'** in the names of the categories +will be replaced by **'-'**. \ No newline at end of file diff --git a/create_recursive_product_category/tests/__init__.py b/create_recursive_product_category/tests/__init__.py new file mode 100644 index 00000000..d9b96c4f --- /dev/null +++ b/create_recursive_product_category/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/create_recursive_product_category/tests/test_module.py b/create_recursive_product_category/tests/test_module.py new file mode 100644 index 00000000..0ecf1b38 --- /dev/null +++ b/create_recursive_product_category/tests/test_module.py @@ -0,0 +1,3 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). diff --git a/setup/create_recursive_abstract/odoo/addons/create_recursive_abstract b/setup/create_recursive_abstract/odoo/addons/create_recursive_abstract new file mode 120000 index 00000000..5e0b85f9 --- /dev/null +++ b/setup/create_recursive_abstract/odoo/addons/create_recursive_abstract @@ -0,0 +1 @@ +../../../../create_recursive_abstract \ No newline at end of file diff --git a/setup/create_recursive_abstract/setup.py b/setup/create_recursive_abstract/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/create_recursive_abstract/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/create_recursive_pos_category/odoo/addons/create_recursive_pos_category b/setup/create_recursive_pos_category/odoo/addons/create_recursive_pos_category new file mode 120000 index 00000000..0d435649 --- /dev/null +++ b/setup/create_recursive_pos_category/odoo/addons/create_recursive_pos_category @@ -0,0 +1 @@ +../../../../create_recursive_pos_category \ No newline at end of file diff --git a/setup/create_recursive_pos_category/setup.py b/setup/create_recursive_pos_category/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/create_recursive_pos_category/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/setup/create_recursive_product_category/odoo/addons/create_recursive_product_category b/setup/create_recursive_product_category/odoo/addons/create_recursive_product_category new file mode 120000 index 00000000..f7bff7ff --- /dev/null +++ b/setup/create_recursive_product_category/odoo/addons/create_recursive_product_category @@ -0,0 +1 @@ +../../../../create_recursive_product_category \ No newline at end of file diff --git a/setup/create_recursive_product_category/setup.py b/setup/create_recursive_product_category/setup.py new file mode 100644 index 00000000..28c57bb6 --- /dev/null +++ b/setup/create_recursive_product_category/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)