diff --git a/product_attribute_company_favorite/README.rst b/product_attribute_company_favorite/README.rst new file mode 100644 index 00000000000..d5f725dc532 --- /dev/null +++ b/product_attribute_company_favorite/README.rst @@ -0,0 +1,104 @@ +================================== +Product Attribute Company Favorite +================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-OCA%2Fproduct--attribute-lightgray.png?logo=github + :target: https://github.com/OCA/product-attribute/tree/16.0/product_attribute_company_favorite + :alt: OCA/product-attribute +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_attribute_company_favorite + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/135/16.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Set favorite product attributes per company. Only the favorite attributes will be displayed when adding an attribute in a product template form. +This is a flexible way to isolate product attributes per company, allowing a subset of companies to access the same attribute. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +There is a setting to allow to set new attribute as favorites for all companies, instead of the user's current company only. +Go to Settings>Inventory>Products and check "Set new attributes as favorite for all companies" + +Usage +===== + +At installation, all attributes will be set to favorites for all companies. + +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 +~~~~~~~ + +* Coop IT Easy SC + +Contributors +~~~~~~~~~~~~ + +* `Coop IT Easy SC `_: + + * Victor Champonnois + * Carmen Bianca Bakker + +* Akretion + + * David Beal + +* Grap + + * Sylvain LE GAL + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-victor-champonnois| image:: https://github.com/victor-champonnois.png?size=40px + :target: https://github.com/victor-champonnois + :alt: victor-champonnois + +Current `maintainer `__: + +|maintainer-victor-champonnois| + +This module is part of the `OCA/product-attribute `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_attribute_company_favorite/__init__.py b/product_attribute_company_favorite/__init__.py new file mode 100644 index 00000000000..c65f50034eb --- /dev/null +++ b/product_attribute_company_favorite/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2023 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later +from . import models +from .post_init_hook import initialize_attribute_is_favorite_field diff --git a/product_attribute_company_favorite/__manifest__.py b/product_attribute_company_favorite/__manifest__.py new file mode 100644 index 00000000000..e3b6d4e44fe --- /dev/null +++ b/product_attribute_company_favorite/__manifest__.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 Coop IT Easy SC +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +{ + "name": "Product Attribute Company Favorite", + "summary": """ + Possibility to set favorite product attributes per company""", + "version": "16.0.1.0.0", + "category": "Product", + "website": "https://github.com/OCA/product-attribute", + "author": "Coop IT Easy SC, Odoo Community Association (OCA)", + "maintainers": ["victor-champonnois"], + "license": "AGPL-3", + "application": False, + "depends": [ + "product", + "stock", + ], + "excludes": [], + "data": [ + "views/product_attribute_views.xml", + "views/res_config_settings_views.xml", + ], + "demo": [], + "qweb": [], + "post_init_hook": "initialize_attribute_is_favorite_field", +} diff --git a/product_attribute_company_favorite/models/__init__.py b/product_attribute_company_favorite/models/__init__.py new file mode 100644 index 00000000000..228a7e66d4b --- /dev/null +++ b/product_attribute_company_favorite/models/__init__.py @@ -0,0 +1,5 @@ +from . import product_attribute_is_favorite_mixin +from . import product_attribute +from . import product_attribute_value +from . import product_template_attribute_line +from . import res_config_settings diff --git a/product_attribute_company_favorite/models/product_attribute.py b/product_attribute_company_favorite/models/product_attribute.py new file mode 100644 index 00000000000..58ef467944b --- /dev/null +++ b/product_attribute_company_favorite/models/product_attribute.py @@ -0,0 +1,10 @@ +from odoo import models + + +class ProductAttribute(models.Model): + _inherit = ["product.attribute", "product.attribute.favorite.mixin"] + _name = "product.attribute" + + CREATION_ACROSS_COMPANY_CONFIG = ( + "product_attribute_company_favorite.new_attribute_favorite_for_all_companies" + ) diff --git a/product_attribute_company_favorite/models/product_attribute_is_favorite_mixin.py b/product_attribute_company_favorite/models/product_attribute_is_favorite_mixin.py new file mode 100644 index 00000000000..584d8a7edde --- /dev/null +++ b/product_attribute_company_favorite/models/product_attribute_is_favorite_mixin.py @@ -0,0 +1,43 @@ +from odoo import api, fields, models + + +class ProductAttributeIsFavoriteMixin(models.AbstractModel): + _name = "product.attribute.favorite.mixin" + _description = """Methods used both in product.attribute and + product.attribute.value to implement is_favorite functionalities + """ + + is_favorite = fields.Boolean( + string="Favorite", + company_dependent=True, + default=True, + help="If checked, this record can be linked to a product template.", + ) + + def _name_search( + self, name, args=None, operator="ilike", limit=100, name_get_uid=None + ): + args = list(args or []) + args += [("is_favorite", "=", True)] + return super()._name_search( + name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid + ) + + @api.model_create_multi + def create(self, vals_list): + new_record_favorite_for_all_companies = ( + self.env["ir.config_parameter"].sudo() + # Class constant stores the configuration boolean + # for its model to distinguish itself from other models. + .get_param(self.CREATION_ACROSS_COMPANY_CONFIG) + ) + records = super().create(vals_list) + if new_record_favorite_for_all_companies: + company_ids = ( + self.env["res.company"].with_context(active_test=False).search([]).ids + ) + for record in records: + for company_id in company_ids: + contextual_record = record.with_company(company_id) + contextual_record.is_favorite = record.is_favorite + return records diff --git a/product_attribute_company_favorite/models/product_attribute_value.py b/product_attribute_company_favorite/models/product_attribute_value.py new file mode 100644 index 00000000000..89733aca846 --- /dev/null +++ b/product_attribute_company_favorite/models/product_attribute_value.py @@ -0,0 +1,11 @@ +from odoo import models + + +class ProductAttributeValue(models.Model): + _inherit = ["product.attribute.value", "product.attribute.favorite.mixin"] + _name = "product.attribute.value" + + CREATION_ACROSS_COMPANY_CONFIG = ( + "product_attribute_company_favorite." + "new_attribute_value_favorite_for_all_companies" + ) diff --git a/product_attribute_company_favorite/models/product_template_attribute_line.py b/product_attribute_company_favorite/models/product_template_attribute_line.py new file mode 100644 index 00000000000..8a076eb08cd --- /dev/null +++ b/product_attribute_company_favorite/models/product_template_attribute_line.py @@ -0,0 +1,9 @@ +from odoo import fields, models + + +class ProductTemplateAttributeLine(models.Model): + _inherit = "product.template.attribute.line" + + is_favorite = fields.Boolean( + related="attribute_id.is_favorite", + ) diff --git a/product_attribute_company_favorite/models/res_config_settings.py b/product_attribute_company_favorite/models/res_config_settings.py new file mode 100644 index 00000000000..fd46afbaaaf --- /dev/null +++ b/product_attribute_company_favorite/models/res_config_settings.py @@ -0,0 +1,27 @@ +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + new_attribute_favorite_for_all_companies = fields.Boolean( + config_parameter=( + "product_attribute_company_favorite." + "new_attribute_favorite_for_all_companies" + ), + string="Set new attribute as favorite for all companies", + help="""When a new attribute is created, + set it as favorite for all companies. + Otherwise it is only set as favorite for the user's current company""", + ) + + new_attribute_value_favorite_for_all_companies = fields.Boolean( + config_parameter=( + "product_attribute_company_favorite." + "new_attribute_value_favorite_for_all_companies" + ), + string="Set new attributes value as favorite for all companies", + help="""When a new attribute value is created, + set it as favorite for all companies. + Otherwise it is only set as favorite for the user's current company""", + ) diff --git a/product_attribute_company_favorite/post_init_hook.py b/product_attribute_company_favorite/post_init_hook.py new file mode 100644 index 00000000000..c40e594a534 --- /dev/null +++ b/product_attribute_company_favorite/post_init_hook.py @@ -0,0 +1,20 @@ +import logging + +from odoo import SUPERUSER_ID, api + +_logger = logging.getLogger(__name__) + + +def initialize_attribute_is_favorite_field(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + for company in env["res.company"].with_context(active_test=False).search([]): + _logger.info("Configure is_favorite field for the company %s" % (company.name)) + product_attributes = ( + env["product.attribute"].sudo().with_company(company.id).search([]) + ) + product_attributes.write({"is_favorite": True}) + + product_attribute_values = ( + env["product.attribute.value"].sudo().with_company(company.id).search([]) + ) + product_attribute_values.write({"is_favorite": True}) diff --git a/product_attribute_company_favorite/readme/CONFIGURE.rst b/product_attribute_company_favorite/readme/CONFIGURE.rst new file mode 100644 index 00000000000..ba591aa2280 --- /dev/null +++ b/product_attribute_company_favorite/readme/CONFIGURE.rst @@ -0,0 +1,5 @@ +There is two setting to allow to set new attribute and new attribute values as favorites at creation for all companies, instead of the user's current company only. + +Go to Settings>Inventory>Products and check +- "Set new attribute as favorite for all companies" +- "Set new attribute value as favorite for all companies" diff --git a/product_attribute_company_favorite/readme/CONTRIBUTORS.rst b/product_attribute_company_favorite/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..6b75ca2ae30 --- /dev/null +++ b/product_attribute_company_favorite/readme/CONTRIBUTORS.rst @@ -0,0 +1,12 @@ +* `Coop IT Easy SC `_: + + * Victor Champonnois + * Carmen Bianca Bakker + +* Akretion + + * David Beal + +* Grap + + * Sylvain LE GAL diff --git a/product_attribute_company_favorite/readme/DESCRIPTION.rst b/product_attribute_company_favorite/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..fd3ca4748fd --- /dev/null +++ b/product_attribute_company_favorite/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Set favorite product attributes and attribute values per company. Only the favorite attributes and values will be displayed in the dropdown menu in a product template form. diff --git a/product_attribute_company_favorite/readme/USAGE.rst b/product_attribute_company_favorite/readme/USAGE.rst new file mode 100644 index 00000000000..e5945e94889 --- /dev/null +++ b/product_attribute_company_favorite/readme/USAGE.rst @@ -0,0 +1 @@ +At installation, all attributes will be set to favorites for all companies. diff --git a/product_attribute_company_favorite/static/description/index.html b/product_attribute_company_favorite/static/description/index.html new file mode 100644 index 00000000000..88293c7de16 --- /dev/null +++ b/product_attribute_company_favorite/static/description/index.html @@ -0,0 +1,445 @@ + + + + + + +Product Attribute Company Favorite + + + +
+

Product Attribute Company Favorite

+ + +

Beta License: AGPL-3 OCA/product-attribute Translate me on Weblate Try me on Runbot

+

Set favorite product attributes per company. Only the favorite attributes will be displayed when adding an attribute in a product template form. +This is a flexible way to isolate product attributes per company, allowing a subset of companies to access the same attribute.

+

Table of contents

+ +
+

Configuration

+

There is a setting to allow to set new attribute as favorites for all companies, instead of the user’s current company only. +Go to Settings>Inventory>Products and check “Set new attributes as favorite for all companies”

+
+
+

Usage

+

At installation, all attributes will be set to favorites for all companies.

+
+
+

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

+
    +
  • Coop IT Easy SC
  • +
+
+
+

Contributors

+
    +
  • Coop IT Easy SC:
      +
    • Victor Champonnois
    • +
    • Carmen Bianca Bakker
    • +
    +
  • +
  • Akretion
      +
    • David Beal
    • +
    +
  • +
  • Grap
      +
    • Sylvain LE GAL
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

victor-champonnois

+

This module is part of the OCA/product-attribute project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/product_attribute_company_favorite/tests/__init__.py b/product_attribute_company_favorite/tests/__init__.py new file mode 100644 index 00000000000..2ef99fc758c --- /dev/null +++ b/product_attribute_company_favorite/tests/__init__.py @@ -0,0 +1 @@ +from . import test_product_attribute diff --git a/product_attribute_company_favorite/tests/test_product_attribute.py b/product_attribute_company_favorite/tests/test_product_attribute.py new file mode 100644 index 00000000000..827ffc8a964 --- /dev/null +++ b/product_attribute_company_favorite/tests/test_product_attribute.py @@ -0,0 +1,165 @@ +from odoo.tests.common import TransactionCase + + +class TestProductAttributeMultiCompany(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company1 = cls.env.ref("base.main_company") + cls.company2 = cls.env["res.company"].create( + { + "name": "company 2", + "parent_id": cls.env.ref("base.main_company").id, + } + ) + cls.user1 = cls.env.ref("base.user_admin") + cls.user2 = cls.user1.copy( + { + "company_id": cls.company2.id, + "company_ids": [(6, 0, [cls.company2.id])], + } + ) + + cls.attribute = cls.env["product.attribute"] + cls.attribute_value = cls.env["product.attribute.value"] + + cls.attribute_1 = cls.attribute.create( + { + "name": "attribute_1", + } + ) + cls.attribute_1_value_1 = cls.attribute_value.create( + { + "name": "attribute_1_value_1", + "attribute_id": cls.attribute_1.id, + } + ) + + ###################### + # Tests for attributes + ###################### + + def test_new_attribute_is_favorite_for_current_company(self): + + attribute_list1 = ( + self.env["product.attribute"] + .with_user(self.user1.id) + .search([("is_favorite", "=", True), ("id", "=", self.attribute_1.id)]) + ) + self.assertEqual(len(attribute_list1), 1) + + def test_new_attribute_is_not_favorite_for_other_company(self): + + attribute_list1 = ( + self.env["product.attribute"] + .with_user(self.user2.id) + .search([("is_favorite", "=", True), ("id", "=", self.attribute_1.id)]) + ) + self.assertEqual(len(attribute_list1), 0) + + def test_not_favorite_attribute_in_name_search_for_current_company(self): + + attribute_list1 = ( + self.env["product.attribute"] + .with_user(self.user1.id) + .name_search(name="attribute_1") + ) + self.assertEqual(len(attribute_list1), 1) + + def test_not_favorite_attribute_not_in_name_search_for_other_company(self): + + attribute_list1 = ( + self.env["product.attribute"] + .with_user(self.user2.id) + .name_search(name="attribute_1") + ) + self.assertEqual(len(attribute_list1), 0) + + def test_new_attribute_is_favorite_for_other_company_if_settings_all_company(self): + """if the setting new_attribute_favorite_for_all_companies is True, + a new attribute should be favorite for other companies""" + + self.env["ir.config_parameter"].sudo().set_param( + "product_attribute_company_favorite.new_attribute_favorite_for_all_companies", + True, + ) + self.attribute_2 = self.attribute.create( + { + "name": "attribute_2", + } + ) + attribute_list1 = ( + self.env["product.attribute"] + .with_user(self.user2.id) + .search([("is_favorite", "=", True), ("id", "=", self.attribute_2.id)]) + ) + self.assertEqual(len(attribute_list1), 1) + + ############################ + # Tests for attribute values + ############################ + + def test_new_attribute_value_is_favorite_for_current_company(self): + + attribute_value_list = ( + self.env["product.attribute.value"] + .with_user(self.user1.id) + .search( + [("is_favorite", "=", True), ("id", "=", self.attribute_1_value_1.id)] + ) + ) + self.assertEqual(len(attribute_value_list), 1) + + def test_new_attribute_value_is_not_favorite_for_other_company(self): + + attribute_value_list = ( + self.env["product.attribute.value"] + .with_user(self.user2.id) + .search( + [("is_favorite", "=", True), ("id", "=", self.attribute_1_value_1.id)] + ) + ) + self.assertEqual(len(attribute_value_list), 0) + + def test_not_favorite_attrib_value_not_in_name_search_for_current_company(self): + + attribute_value_list = ( + self.env["product.attribute.value"] + .with_user(self.user1.id) + .name_search(name="attribute_1") + ) + self.assertEqual(len(attribute_value_list), 1) + + def test_not_favorite_attribute_value_not_in_name_search_for_other_company(self): + + attribute_value_list = ( + self.env["product.attribute.value"] + .with_user(self.user2.id) + .name_search(name="attribute_value_1") + ) + self.assertEqual(len(attribute_value_list), 0) + + def test_new_attribute_is_favorite_value_for_other_company_if_settings_all_company( + self, + ): + """if the setting new_attribute_values_favorite_for_all_companies is True, + a new attribute value should be favorite for other companies""" + + self.env["ir.config_parameter"].sudo().set_param( + "product_attribute_company_favorite.new_attribute_value_favorite_for_all_companies", + True, + ) + self.attribute_1_value_2 = self.attribute_value.create( + { + "name": "attribute_1_value_2", + "attribute_id": self.attribute_1.id, + } + ) + attribute_value_list = ( + self.env["product.attribute.value"] + .with_user(self.user2.id) + .search( + [("is_favorite", "=", True), ("id", "=", self.attribute_1_value_2.id)] + ) + ) + self.assertEqual(len(attribute_value_list), 1) diff --git a/product_attribute_company_favorite/views/product_attribute_views.xml b/product_attribute_company_favorite/views/product_attribute_views.xml new file mode 100644 index 00000000000..58f54d0ca29 --- /dev/null +++ b/product_attribute_company_favorite/views/product_attribute_views.xml @@ -0,0 +1,60 @@ + + + + + product.attribute + + + + + + + + + product.attribute + + + + + + + is_favorite == True + + + + + + product.attribute + + + + + + + + + + + + + {"search_default_is_favorite":1} + + + + product_template_form_view + product.template + + + + + + + + diff --git a/product_attribute_company_favorite/views/res_config_settings_views.xml b/product_attribute_company_favorite/views/res_config_settings_views.xml new file mode 100644 index 00000000000..f8956fa74d1 --- /dev/null +++ b/product_attribute_company_favorite/views/res_config_settings_views.xml @@ -0,0 +1,39 @@ + + + + res.config.settings + + +
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
diff --git a/setup/product_attribute_company_favorite/odoo/addons/product_attribute_company_favorite b/setup/product_attribute_company_favorite/odoo/addons/product_attribute_company_favorite new file mode 120000 index 00000000000..f9246e8b885 --- /dev/null +++ b/setup/product_attribute_company_favorite/odoo/addons/product_attribute_company_favorite @@ -0,0 +1 @@ +../../../../product_attribute_company_favorite \ No newline at end of file diff --git a/setup/product_attribute_company_favorite/setup.py b/setup/product_attribute_company_favorite/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/product_attribute_company_favorite/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)