diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa5945df6..8c3556f97 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,7 +39,7 @@ repos: language: fail files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools - rev: d5fab7ee87fceee858a3d01048c78a548974d935 + rev: f9b919b9868143135a9c9cb03021089cabba8223 hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons @@ -140,7 +140,7 @@ repos: - --settings=. exclude: /__init__\.py$ - repo: https://github.com/acsone/setuptools-odoo - rev: 3.1.8 + rev: 3.3.2 hooks: - id: setuptools-odoo-make-default - id: setuptools-odoo-get-requirements diff --git a/attribute_set_completeness/README.rst b/attribute_set_completeness/README.rst new file mode 100644 index 000000000..e2af32f28 --- /dev/null +++ b/attribute_set_completeness/README.rst @@ -0,0 +1,96 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================== +Attribute Set Completeness +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:0d5449d095ae3a41d503c45c38e4bea3c5322b60204615ac219fc5cede915eb3 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-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%2Fodoo--pim-lightgray.png?logo=github + :target: https://github.com/OCA/odoo-pim/tree/16.0/attribute_set_completeness + :alt: OCA/odoo-pim +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/odoo-pim-16-0/odoo-pim-16-0-attribute_set_completeness + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/odoo-pim&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows the user define a completion rate on the model linked to an attribute set. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Go on an attribute set and fill in the section 'Completeness'. +Select the fields you want to take in account and set them their proportion on the completeness rate. +Then on the model linked to the attribute set you'll get 2 fields: completion rate and completion state + +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 +~~~~~~~ + +* ACSONE SA/NV + +Contributors +~~~~~~~~~~~~ + +* Cédric PIGEON +* Xavier Bouquiaux +* `Camptocamp `_ + + * Iván Todorovich + +* Dhara Solanki +* `Heliconia Solutions Pvt. Ltd. `_ + + * Bhavesh Heliconia + +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. + +This module is part of the `OCA/odoo-pim `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/attribute_set_completeness/__init__.py b/attribute_set_completeness/__init__.py new file mode 100644 index 000000000..f24d3e242 --- /dev/null +++ b/attribute_set_completeness/__init__.py @@ -0,0 +1,2 @@ +from . import components +from . import models diff --git a/attribute_set_completeness/__manifest__.py b/attribute_set_completeness/__manifest__.py new file mode 100644 index 000000000..27c289385 --- /dev/null +++ b/attribute_set_completeness/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Attribute Set Completeness", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/odoo-pim", + "depends": ["attribute_set", "component_event"], + "data": [ + "views/attribute_set.xml", + "security/attribute_set_completeness.xml", + "views/attribute_set_completeness.xml", + ], + "demo": [], +} diff --git a/attribute_set_completeness/components/__init__.py b/attribute_set_completeness/components/__init__.py new file mode 100644 index 000000000..4502c4210 --- /dev/null +++ b/attribute_set_completeness/components/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2020 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import attribute_set_owner_event_listener diff --git a/attribute_set_completeness/components/attribute_set_owner_event_listener.py b/attribute_set_completeness/components/attribute_set_owner_event_listener.py new file mode 100644 index 000000000..6237bcd62 --- /dev/null +++ b/attribute_set_completeness/components/attribute_set_owner_event_listener.py @@ -0,0 +1,31 @@ +# Copyright 2020 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.component.core import AbstractComponent +from odoo.addons.component_event import skip_if + + +class AttributeSetOwnerEventListener(AbstractComponent): + _name = "attribute.set.owner.event.listener" + _inherit = "base.event.listener" + + def _get_skip_if_condition_fields(self, record): + """Return the field names that trigger the condition""" + attribute_set = record.attribute_set_id + attribute_set_completeness = attribute_set.attribute_set_completeness_ids + field_names = attribute_set_completeness.mapped("field_id.name") + field_names.append("attribute_set_id") + return field_names + + def _get_skip_if_condition(self, record, **kwargs): + if not record.attribute_set_id: + return True + if set(self._get_skip_if_condition_fields(record)) & set(kwargs["fields"]): + return False + return True + + @skip_if( + lambda self, record, **kwargs: self._get_skip_if_condition(record, **kwargs) + ) + def on_record_write(self, record, fields=None): + record._compute_attribute_set_completed_ids() diff --git a/attribute_set_completeness/i18n/attribute_set_completeness.pot b/attribute_set_completeness/i18n/attribute_set_completeness.pot new file mode 100644 index 000000000..5f3ccfbf5 --- /dev/null +++ b/attribute_set_completeness/i18n/attribute_set_completeness.pot @@ -0,0 +1,46 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attribute_set_completeness +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set +msgid "Attribute Set" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_completeness +msgid "Attribute Set Completeness" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_owner_mixin +msgid "Attribute set owner mixin" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_form_view +msgid "COMPLETNESS" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__attribute_set_owner_mixin__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_product__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_template__attribute_set_completion_state__complete +msgid "Complete" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_completeness_tree_view +msgid "Total" +msgstr "" diff --git a/attribute_set_completeness/i18n/de.po b/attribute_set_completeness/i18n/de.po new file mode 100644 index 000000000..b98959f67 --- /dev/null +++ b/attribute_set_completeness/i18n/de.po @@ -0,0 +1,50 @@ +msgid "" +msgstr "" +"Project-Id-Version: ametras-xsolutions\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: German\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Crowdin-Project: ametras-xsolutions\n" +"X-Crowdin-Project-ID: 530964\n" +"X-Crowdin-Language: de\n" +"X-Crowdin-File: /[AmetrasIntelligence.oca-migrated] 16.0/attribute_set_completeness/i18n/attribute_set_completeness.pot\n" +"X-Crowdin-File-ID: 21354\n" +"Language: de_DE\n" +"PO-Revision-Date: 2024-09-25 12:08\n" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set +msgid "Attribute Set" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_completeness +msgid "Attribute Set Completeness" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_owner_mixin +msgid "Attribute set owner mixin" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_form_view +msgid "COMPLETNESS" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__attribute_set_owner_mixin__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_product__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_template__attribute_set_completion_state__complete +msgid "Complete" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_completeness_tree_view +msgid "Total" +msgstr "" + diff --git a/attribute_set_completeness/i18n/es.po b/attribute_set_completeness/i18n/es.po new file mode 100644 index 000000000..1e76b83dd --- /dev/null +++ b/attribute_set_completeness/i18n/es.po @@ -0,0 +1,173 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attribute_set_completeness +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-03-27 18:34+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__attribute_set_id +msgid "Attribute Set" +msgstr "Conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_completeness +msgid "Attribute Set Completeness" +msgstr "Completitud del Conjunto de Atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completion_rate +msgid "Attribute Set Completion Rate" +msgstr "Tasa de cumplimentación del conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completion_state +msgid "Attribute Set Completion State" +msgstr "Estado de finalización del conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completed_ids +msgid "Attribute Set completed criterias" +msgstr "Conjunto de atributos Criterios completados" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_not_completed_ids +msgid "Attribute Set not completed criterias" +msgstr "Conjunto de atributos criterios no cumplidos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__available_field_ids +msgid "Attribute Set's fields" +msgstr "Campos del Conjunto de Atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,help:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completion_rate +msgid "Attribute set completeness percentage" +msgstr "Porcentaje de integridad del conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,help:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completion_state +msgid "Attribute set completeness status" +msgstr "Estado de integridad del conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_owner_mixin +msgid "Attribute set owner mixin" +msgstr "Mezcla de propietarios de conjuntos de atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__attribute_set_owner_mixin__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_template__attribute_set_completion_state__complete +msgid "Complete" +msgstr "Completo" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_form_view +msgid "Completeness" +msgstr "Integridad" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set__attribute_set_completeness_ids +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__attribute_set_completeness_ids +msgid "Completeness Requirements" +msgstr "Requisitos de Integridad" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__completion_rate +msgid "Completion Rate" +msgstr "Tasa de cumplimiento" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__completion_rate_progress +msgid "Completion Rate Progress" +msgstr "Tasa de finalización Progreso" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set__display_name +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__display_name +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__display_name +msgid "Display Name" +msgstr "Mostrar nombre" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__field_description +msgid "Field Description" +msgstr "Descripción del campo" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__field_id +msgid "Field Name" +msgstr "Nombre de Campo" + +#. module: attribute_set_completeness +#: model:ir.model.fields,help:attribute_set_completeness.field_attribute_set_completeness__available_field_ids +msgid "Fields related to the Attribute set's attributes" +msgstr "Campos relacionados con los atributos del conjunto de atributos" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set__id +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__id +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set____last_update +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness____last_update +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_owner_mixin____last_update +msgid "Last Modified on" +msgstr "Última Modificación el" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: attribute_set_completeness +#: model:ir.model.fields,field_description:attribute_set_completeness.field_attribute_set_completeness__model_id +msgid "Model" +msgstr "Modelo" + +#. module: attribute_set_completeness +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__attribute_set_owner_mixin__attribute_set_completion_state__not_complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_template__attribute_set_completion_state__not_complete +msgid "Not complete" +msgstr "No completo" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_completeness_tree_view +msgid "Total" +msgstr "Total" + +#. module: attribute_set_completeness +#: code:addons/attribute_set_completeness/models/attribute_set.py:0 +#, python-format +msgid "Total of completion rate must be 100 %" +msgstr "El porcentaje total de finalización debe ser del 100 %" diff --git a/attribute_set_completeness/i18n/fr.po b/attribute_set_completeness/i18n/fr.po new file mode 100644 index 000000000..b4fa681fe --- /dev/null +++ b/attribute_set_completeness/i18n/fr.po @@ -0,0 +1,50 @@ +msgid "" +msgstr "" +"Project-Id-Version: ametras-xsolutions\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: French\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Crowdin-Project: ametras-xsolutions\n" +"X-Crowdin-Project-ID: 530964\n" +"X-Crowdin-Language: fr\n" +"X-Crowdin-File: /[AmetrasIntelligence.oca-migrated] 16.0/attribute_set_completeness/i18n/attribute_set_completeness.pot\n" +"X-Crowdin-File-ID: 21354\n" +"Language: fr_FR\n" +"PO-Revision-Date: 2024-09-25 12:08\n" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set +msgid "Attribute Set" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_completeness +msgid "Attribute Set Completeness" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model,name:attribute_set_completeness.model_attribute_set_owner_mixin +msgid "Attribute set owner mixin" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_form_view +msgid "COMPLETNESS" +msgstr "" + +#. module: attribute_set_completeness +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__attribute_set_owner_mixin__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_product__attribute_set_completion_state__complete +#: model:ir.model.fields.selection,name:attribute_set_completeness.selection__product_template__attribute_set_completion_state__complete +msgid "Complete" +msgstr "" + +#. module: attribute_set_completeness +#: model_terms:ir.ui.view,arch_db:attribute_set_completeness.attribute_set_completeness_tree_view +msgid "Total" +msgstr "" + diff --git a/attribute_set_completeness/models/__init__.py b/attribute_set_completeness/models/__init__.py new file mode 100644 index 000000000..2f249ad79 --- /dev/null +++ b/attribute_set_completeness/models/__init__.py @@ -0,0 +1,3 @@ +from . import attribute_set_completeness +from . import attribute_set +from . import attribute_set_owner_mixin diff --git a/attribute_set_completeness/models/attribute_set.py b/attribute_set_completeness/models/attribute_set.py new file mode 100644 index 000000000..e2ec4caa3 --- /dev/null +++ b/attribute_set_completeness/models/attribute_set.py @@ -0,0 +1,25 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class AttributeSet(models.Model): + _inherit = "attribute.set" + + attribute_set_completeness_ids = fields.One2many( + comodel_name="attribute.set.completeness", + inverse_name="attribute_set_id", + string="Completeness Requirements", + auto_join=True, + ) + + @api.constrains("attribute_set_completeness_ids") + def _check_attribute_set_completeness_ids(self): + for attr_set in self: + completion_config = attr_set.attribute_set_completeness_ids + if completion_config: + total = sum([rule.completion_rate for rule in completion_config]) + if total != 100.0: + raise ValidationError(_("Total of completion rate must be 100 %")) diff --git a/attribute_set_completeness/models/attribute_set_completeness.py b/attribute_set_completeness/models/attribute_set_completeness.py new file mode 100644 index 000000000..68af5c77f --- /dev/null +++ b/attribute_set_completeness/models/attribute_set_completeness.py @@ -0,0 +1,45 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AttributeSetCompleteness(models.Model): + _name = "attribute.set.completeness" + _description = "Attribute Set Completeness" + _rec_name = "field_id" + + attribute_set_id = fields.Many2one( + "attribute.set", required=True, ondelete="cascade" + ) + available_field_ids = fields.Many2many( + string="Attribute Set's fields", + comodel_name="ir.model.fields", + compute="_compute_available_field_ids", + help="Fields related to the Attribute set's attributes", + ) + field_id = fields.Many2one( + "ir.model.fields", "Field Name", required=True, ondelete="cascade" + ) + field_description = fields.Char( + related="field_id.field_description", + string="Field Description", + store=True, + readonly=True, + ) + completion_rate = fields.Float() + completion_rate_progress = fields.Float( + string="Completion Rate Progress", related="completion_rate", readonly=True + ) + model_id = fields.Many2one(related="attribute_set_id.model_id", readonly=True) + + @api.depends("attribute_set_id") + def _compute_available_field_ids(self): + for rec in self: + att_set_field_ids = rec.attribute_set_id.attribute_ids.mapped("field_id") + att_set_complete_ids = rec.attribute_set_id.attribute_set_completeness_ids + choosen_field_ids = att_set_complete_ids.mapped("field_id") + rec.available_field_ids = att_set_field_ids - choosen_field_ids + + def name_get(self): + return [(rec.id, rec.field_id.field_description) for rec in self] diff --git a/attribute_set_completeness/models/attribute_set_owner_mixin.py b/attribute_set_completeness/models/attribute_set_owner_mixin.py new file mode 100644 index 000000000..18808c886 --- /dev/null +++ b/attribute_set_completeness/models/attribute_set_owner_mixin.py @@ -0,0 +1,73 @@ +# Copyright 2020 ACSONE SA/NV +# Copyright 2021 Camptocamp (http://www.camptocamp.com). +# @author Iván Todorovich +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AttributeSetOwnerMixin(models.AbstractModel): + _inherit = "attribute.set.owner.mixin" + + attribute_set_completeness_ids = fields.One2many( + related="attribute_set_id.attribute_set_completeness_ids", + ) + attribute_set_completed_ids = fields.Many2many( + comodel_name="attribute.set.completeness", + compute="_compute_attribute_set_completed_ids", + string="Attribute Set completed criterias", + ) + attribute_set_not_completed_ids = fields.Many2many( + comodel_name="attribute.set.completeness", + compute="_compute_attribute_set_not_completed_ids", + string="Attribute Set not completed criterias", + ) + attribute_set_completion_rate = fields.Float( + compute="_compute_attribute_set_completion_rate", + help="Attribute set completeness percentage", + store=True, + ) + attribute_set_completion_state = fields.Selection( + selection=[("complete", "Complete"), ("not_complete", "Not complete")], + compute="_compute_attribute_set_completion_state", + help="Attribute set completeness status", + store=True, + ) + + @api.depends("attribute_set_completeness_ids") + def _compute_attribute_set_completed_ids(self): + """Compute completed attribute set criterias""" + for rec in self: + rec.attribute_set_completed_ids = ( + rec.attribute_set_completeness_ids.filtered( + lambda c: bool(rec[c.field_id.name]) + ) + ) + + @api.depends("attribute_set_completed_ids") + def _compute_attribute_set_not_completed_ids(self): + """Compute not completed attribute set criterias""" + for rec in self: + rec.attribute_set_not_completed_ids = ( + rec.attribute_set_completeness_ids - rec.attribute_set_completed_ids + ) + + @api.depends("attribute_set_completed_ids") + def _compute_attribute_set_completion_rate(self): + """Compute the completion rate from completed criterias""" + for rec in self: + rec.attribute_set_completion_rate = ( + sum(rec.attribute_set_completed_ids.mapped("completion_rate")) + if rec.attribute_set_completed_ids + else 0.0 + ) + + @api.depends("attribute_set_completion_rate") + def _compute_attribute_set_completion_state(self): + """Compute the completion state""" + for rec in self: + rec.attribute_set_completion_state = ( + "complete" + if rec.attribute_set_completion_rate >= 100.0 + else "not_complete" + ) diff --git a/attribute_set_completeness/readme/CONTRIBUTORS.rst b/attribute_set_completeness/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..3a855e5ff --- /dev/null +++ b/attribute_set_completeness/readme/CONTRIBUTORS.rst @@ -0,0 +1,10 @@ +* Cédric PIGEON +* Xavier Bouquiaux +* `Camptocamp `_ + + * Iván Todorovich + +* Dhara Solanki +* `Heliconia Solutions Pvt. Ltd. `_ + + * Bhavesh Heliconia diff --git a/attribute_set_completeness/readme/DESCRIPTION.rst b/attribute_set_completeness/readme/DESCRIPTION.rst new file mode 100644 index 000000000..39fc3c1d3 --- /dev/null +++ b/attribute_set_completeness/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows the user define a completion rate on the model linked to an attribute set. diff --git a/attribute_set_completeness/readme/USAGE.rst b/attribute_set_completeness/readme/USAGE.rst new file mode 100644 index 000000000..fc01f51de --- /dev/null +++ b/attribute_set_completeness/readme/USAGE.rst @@ -0,0 +1,3 @@ +Go on an attribute set and fill in the section 'Completeness'. +Select the fields you want to take in account and set them their proportion on the completeness rate. +Then on the model linked to the attribute set you'll get 2 fields: completion rate and completion state diff --git a/attribute_set_completeness/security/attribute_set_completeness.xml b/attribute_set_completeness/security/attribute_set_completeness.xml new file mode 100644 index 000000000..a0c4a4117 --- /dev/null +++ b/attribute_set_completeness/security/attribute_set_completeness.xml @@ -0,0 +1,23 @@ + + + + + attribute.set.completeness access for user group + + + + + + + + + attribute.set.completeness access for erp manager + + + + + + + + diff --git a/attribute_set_completeness/static/description/icon.png b/attribute_set_completeness/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/attribute_set_completeness/static/description/icon.png differ diff --git a/attribute_set_completeness/static/description/index.html b/attribute_set_completeness/static/description/index.html new file mode 100644 index 000000000..9a074ea46 --- /dev/null +++ b/attribute_set_completeness/static/description/index.html @@ -0,0 +1,455 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Attribute Set Completeness

+ +

Beta License: AGPL-3 OCA/odoo-pim Translate me on Weblate Try me on Runboat

+

This module allows the user define a completion rate on the model linked to an attribute set.

+

Table of contents

+ +
+

Usage

+

Go on an attribute set and fill in the section ‘Completeness’. +Select the fields you want to take in account and set them their proportion on the completeness rate. +Then on the model linked to the attribute set you’ll get 2 fields: completion rate and completion state

+
+
+

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

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

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.

+

This module is part of the OCA/odoo-pim project on GitHub.

+

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

+
+
+
+
+ + diff --git a/attribute_set_completeness/test-requirements.txt b/attribute_set_completeness/test-requirements.txt new file mode 100644 index 000000000..66bc2cbae --- /dev/null +++ b/attribute_set_completeness/test-requirements.txt @@ -0,0 +1 @@ +odoo_test_helper diff --git a/attribute_set_completeness/tests/__init__.py b/attribute_set_completeness/tests/__init__.py new file mode 100644 index 000000000..139786b11 --- /dev/null +++ b/attribute_set_completeness/tests/__init__.py @@ -0,0 +1 @@ +from . import test_attribute_set_completeness diff --git a/attribute_set_completeness/tests/res_partner_event_listener.py b/attribute_set_completeness/tests/res_partner_event_listener.py new file mode 100644 index 000000000..ff5c44f44 --- /dev/null +++ b/attribute_set_completeness/tests/res_partner_event_listener.py @@ -0,0 +1,10 @@ +# Copyright 2020 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.addons.component.core import Component + + +class ResPartnerEventListener(Component): + _name = "res.partner.event.listener" + _inherit = ["attribute.set.owner.event.listener"] + + _apply_on = ["res.partner"] diff --git a/attribute_set_completeness/tests/test_attribute_set_completeness.py b/attribute_set_completeness/tests/test_attribute_set_completeness.py new file mode 100644 index 000000000..4e3cdb700 --- /dev/null +++ b/attribute_set_completeness/tests/test_attribute_set_completeness.py @@ -0,0 +1,120 @@ +# Copyright 2020 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo_test_helper import FakeModelLoader + +from odoo.exceptions import ValidationError + +from odoo.addons.component.tests.common import TransactionComponentCase + + +class TestAttributeSetCompleteness(TransactionComponentCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.model_id = cls.env.ref("base.model_res_partner").id + cls.group = cls.env["attribute.group"].create( + {"name": "My Group", "model_id": cls.model_id} + ) + vals = { + "nature": "custom", + "model_id": cls.model_id, + "attribute_type": "char", + "field_description": "Attribute test", + "name": "x_test", + "attribute_group_id": cls.group.id, + } + cls.attr1 = cls.env["attribute.attribute"].create(vals) + + vals.update({"name": "x_test2", "field_description": "Attribute test2"}) + cls.attr2 = cls.env["attribute.attribute"].create(vals) + + vals = { + "name": "My attribute Set", + "model_id": cls.model_id, + "attribute_ids": [(4, cls.attr1.id), (4, cls.attr2.id)], + "attribute_set_completeness_ids": [ + (0, 0, {"field_id": cls.attr1.field_id.id, "completion_rate": 50.0}), + (0, 0, {"field_id": cls.attr2.field_id.id, "completion_rate": 50.0}), + ], + } + cls.attr_set = cls.env["attribute.set"].create(vals) + + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + from odoo.addons.attribute_set.tests.models import ResPartner + + cls.loader.update_registry([ResPartner]) + + from .res_partner_event_listener import ResPartnerEventListener # noqa: F401 + + ResPartnerEventListener._build_component(cls._components_registry) + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + super().tearDownClass() + + def test_completion_rate_constrains_create(self): + vals = { + "name": "My attribute Set Test", + "model_id": self.model_id, + "attribute_ids": [(4, self.attr1.id), (4, self.attr2.id)], + "attribute_set_completeness_ids": [ + (0, 0, {"field_id": self.attr1.field_id.id, "completion_rate": 50.0}), + (0, 0, {"field_id": self.attr2.field_id.id, "completion_rate": 10.0}), + ], + } + error_msg = "Total of completion rate must be 100 %" + with self.assertRaisesRegex(ValidationError, error_msg): + self.env["attribute.set"].create(vals) + + def test_completion_rate_constrains_write_low(self): + completion_rules = self.attr_set.attribute_set_completeness_ids + vals = { + "attribute_set_completeness_ids": [ + (2, completion_rules[0].id), + (0, 0, {"field_id": self.attr1.field_id.id, "completion_rate": 10.0}), + ] + } + error_msg = "Total of completion rate must be 100 %" + with self.assertRaisesRegex(ValidationError, error_msg): + self.attr_set.write(vals) + + def test_completion_rate_constrains_write_high(self): + completion_rules = self.attr_set.attribute_set_completeness_ids + vals = { + "attribute_set_completeness_ids": [ + (2, completion_rules[0].id), + ( + 0, + 0, + {"field_id": self.attr1.field_id.id, "completion_rate": 200.0}, + ), + ] + } + error_msg = "Total of completion rate must be 100 %" + with self.assertRaisesRegex(ValidationError, error_msg): + self.attr_set.write(vals) + + def test_completion_rate(self): + vals = {"name": "Test Partner"} + # Case 1: Create the partner + partner = self.env["res.partner"].create(vals) + self.assertEqual(partner.attribute_set_completion_state, "not_complete") + self.assertEqual(partner.attribute_set_completion_rate, 0.0) + # Case 2: Set an attribute set + partner.write({"attribute_set_id": self.attr_set.id}) + partner.invalidate_model() + self.assertEqual(partner.attribute_set_completion_state, "not_complete") + self.assertEqual(partner.attribute_set_completion_rate, 0.0) + # Case 3: Set a field (50% completion) + partner.write({"x_test": "test"}) + partner.invalidate_model() + self.assertEqual(partner.attribute_set_completion_state, "not_complete") + self.assertEqual(partner.attribute_set_completion_rate, 50.0) + # Case 4: Set another field (100% completion) + partner.write({"x_test2": "test"}) + partner.invalidate_model() + self.assertEqual(partner.attribute_set_completion_state, "complete") + self.assertEqual(partner.attribute_set_completion_rate, 100.0) diff --git a/attribute_set_completeness/views/attribute_set.xml b/attribute_set_completeness/views/attribute_set.xml new file mode 100644 index 000000000..235193bbd --- /dev/null +++ b/attribute_set_completeness/views/attribute_set.xml @@ -0,0 +1,24 @@ + + + + + attribute.set.form (in attribute_set_completeness) + attribute.set + + + + + + + diff --git a/attribute_set_completeness/views/attribute_set_completeness.xml b/attribute_set_completeness/views/attribute_set_completeness.xml new file mode 100644 index 000000000..554df190f --- /dev/null +++ b/attribute_set_completeness/views/attribute_set_completeness.xml @@ -0,0 +1,27 @@ + + + + + attribute.set.completeness + + + + + + + + + + + + + diff --git a/setup/attribute_set_completeness/odoo/addons/attribute_set_completeness b/setup/attribute_set_completeness/odoo/addons/attribute_set_completeness new file mode 120000 index 000000000..5c35cedd5 --- /dev/null +++ b/setup/attribute_set_completeness/odoo/addons/attribute_set_completeness @@ -0,0 +1 @@ +../../../../attribute_set_completeness \ No newline at end of file diff --git a/setup/attribute_set_completeness/setup.py b/setup/attribute_set_completeness/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/attribute_set_completeness/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)