-
-
Notifications
You must be signed in to change notification settings - Fork 816
[16.0][ADD] product_attribute_value_dependent_mixin #2022
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 16.0
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| ======================================= | ||
| Product Attribute Value Dependent Mixin | ||
| ======================================= | ||
|
|
||
| .. | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! This file is generated by oca-gen-addon-readme !! | ||
| !! changes will be overwritten. !! | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| !! source digest: sha256:ba5d1efad0e1d29166513c1a23b430a0477e8fc7f44fe2afe6dfea4f6718ea82 | ||
| !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
|
||
| .. |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_value_dependent_mixin | ||
| :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_value_dependent_mixin | ||
| :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/product-attribute&target_branch=16.0 | ||
| :alt: Try me on Runboat | ||
|
|
||
| |badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
|
||
| This technical module introduces a reusable mixin designed to enable any model to establish dependencies on specific product attribute values. | ||
| By inheriting from this mixin, developers can easily link business rules, configurations, or records to precise product variants without duplicating complex filtering logic. | ||
|
|
||
| - Automatically computes available products and attribute values based on the selected product.template. | ||
| - Supports domain construction to filter attribute values based on context. | ||
| - Matching Logic: Includes a is_matching_product(product) method to validate whether a specific product variant satisfies the configured attribute constraints. | ||
|
|
||
| **Table of contents** | ||
|
|
||
| .. contents:: | ||
| :local: | ||
|
|
||
| Bug Tracker | ||
| =========== | ||
|
|
||
| Bugs are tracked on `GitHub Issues <https://github.com/OCA/product-attribute/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 <https://github.com/OCA/product-attribute/issues/new?body=module:%20product_attribute_value_dependent_mixin%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
|
||
| Do not contact contributors directly about support or help with technical issues. | ||
|
|
||
| Credits | ||
| ======= | ||
|
|
||
| Authors | ||
| ~~~~~~~ | ||
|
|
||
| * Akretion | ||
|
|
||
| Contributors | ||
| ~~~~~~~~~~~~ | ||
|
|
||
| * `Akretion <https://www.akretion.com>`_ | ||
|
|
||
| * Chafique Delli <chafique.delli@akretion.com> | ||
|
|
||
| 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/product-attribute <https://github.com/OCA/product-attribute/tree/16.0/product_attribute_value_dependent_mixin>`_ project on GitHub. | ||
|
|
||
| You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
|
|
||
| from . import models |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Copyright 2023 Akretion | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
|
||
| { | ||
| "name": "Product Attribute Value Dependent Mixin", | ||
| "summary": "Mixin to make product attribute values fields on models", | ||
| "author": "Akretion,Odoo Community Association (OCA)", | ||
| "website": "https://github.com/OCA/product-attribute", | ||
| "license": "AGPL-3", | ||
| "application": False, | ||
| "installable": True, | ||
| "category": "Product", | ||
| "version": "16.0.1.0.0", | ||
| "depends": ["product"], | ||
| "data": [], | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
| from . import product_attribute_value_dependent_mixin | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # Copyright 2023-2026 Akretion | ||
| # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| import itertools | ||
| import json | ||
|
|
||
| from odoo import api, fields, models | ||
|
|
||
|
|
||
| class AttributeValueDependantMixin(models.AbstractModel): | ||
| _name = "attribute.value.dependant.mixin" | ||
| _description = "Attribute Value Dependant Mixin" | ||
|
|
||
| product_tmpl_id = fields.Many2one( | ||
| comodel_name="product.template", | ||
| string="Product Template", | ||
| ) | ||
| product_id = fields.Many2one( | ||
| comodel_name="product.product", | ||
| string="Product", | ||
| domain="[('id', 'in', available_product_ids)]", | ||
| ) | ||
| available_product_ids = fields.Many2many( | ||
| comodel_name="product.product", | ||
| string="Available Products", | ||
| compute="_compute_available_product_ids", | ||
| ) | ||
|
|
||
| attribute_value_ids = fields.Many2many( | ||
| comodel_name="product.attribute.value", | ||
| string="Attribute Values", | ||
| ) | ||
|
|
||
| available_attribute_value_domain = fields.Char( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In v16 and later, you can use |
||
| compute="_compute_available_attribute_value_domain", | ||
| ) | ||
|
|
||
| @api.depends("product_tmpl_id") | ||
| def _compute_available_product_ids(self): | ||
| for rec in self: | ||
| rec.available_product_ids = self.env["product.product"].search( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMHO, this should be avoided at all for performances reasons. Why using I would have done the search before the loop
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moreover, why not having used a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moreover, this One2many field already exists on product.template, it is the @chafique-delli or @Kev-Roche Do you remember a reason for using |
||
| [("product_tmpl_id", "=", self.product_tmpl_id._origin.id)] | ||
| ) | ||
|
|
||
| @api.depends( | ||
| "product_tmpl_id", | ||
| "product_tmpl_id.attribute_line_ids.value_ids", | ||
| "available_attribute_value_domain", | ||
| ) | ||
| def _compute_available_attribute_value_ids(self): | ||
| for rec in self: | ||
| if rec.product_tmpl_id: | ||
| rec.available_attribute_value_ids = rec.product_tmpl_id.mapped( | ||
| "attribute_line_ids.value_ids" | ||
| ).filtered_domain(json.loads(rec.available_attribute_value_domain)) | ||
| else: | ||
| rec.available_attribute_value_ids = None | ||
|
|
||
| @api.depends("product_tmpl_id", "product_tmpl_id.attribute_line_ids.value_ids") | ||
| def _compute_available_attribute_value_domain(self): | ||
| for rec in self: | ||
| domain = [] | ||
| if rec.product_tmpl_id: | ||
| domain = [ | ||
| ("id", "in", rec.product_tmpl_id.attribute_line_ids.value_ids.ids) | ||
| ] | ||
| rec.available_attribute_value_domain = json.dumps(domain) | ||
|
|
||
| def is_matching_product(self, product): | ||
| self.ensure_one() | ||
| if self.product_tmpl_id != product.product_tmpl_id: | ||
| return False | ||
| elif self.product_id: | ||
| if self.product_id == product: | ||
| return True | ||
| else: | ||
| return False | ||
| elif self.attribute_value_ids: | ||
| ptav = product.product_template_attribute_value_ids | ||
| attr2vals = { | ||
| attribute: set(values) | ||
| for attribute, values in itertools.groupby( | ||
| self.attribute_value_ids, lambda pav: pav.attribute_id | ||
| ) | ||
| } | ||
| for attribute in attr2vals: | ||
| if attribute not in ptav.attribute_id: | ||
| return False | ||
| elif not attr2vals[attribute] & set(ptav.product_attribute_value_id): | ||
| return False | ||
| return True | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| * `Akretion <https://www.akretion.com>`_ | ||
|
|
||
| * Chafique Delli <chafique.delli@akretion.com> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| This technical module introduces a reusable mixin designed to enable any model to establish dependencies on specific product attribute values. | ||
| By inheriting from this mixin, developers can easily link business rules, configurations, or records to precise product variants without duplicating complex filtering logic. | ||
|
|
||
| - Automatically computes available products and attribute values based on the selected product.template. | ||
| - Supports domain construction to filter attribute values based on context. | ||
| - Matching Logic: Includes a is_matching_product(product) method to validate whether a specific product variant satisfies the configured attribute constraints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @rousseldenis
Do you mean the file init.py itself is not necessary or the License statement ? Sorry, I don't understand why...