Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions product_class/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=============
Product Class
=============

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8dfa7798b73efea62709ac4d1d0249c5513baad66528c6adb67521cee96e68e7
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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%2Fproduct--attribute-lightgray.png?logo=github
:target: https://github.com/OCA/product-attribute/tree/19.0/product_class
: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-19-0/product-attribute-19-0-product_class
: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=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module introduces Product Classes to group product attributes and
standardize product setup.

Each product class defines the attributes that are allowed for products
assigned to that class. On products, a class can be selected, and Odoo
enforces that attribute lines only use attributes from the selected
class.

The module also provides menu entries and views to manage product
classes.

**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_class%0Aversion:%2019.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
-------

* Camptocamp

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-Ricardoalso| image:: https://github.com/Ricardoalso.png?size=40px
:target: https://github.com/Ricardoalso
:alt: Ricardoalso
.. |maintainer-ivantodorovich| image:: https://github.com/ivantodorovich.png?size=40px
:target: https://github.com/ivantodorovich
:alt: ivantodorovich

Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-Ricardoalso| |maintainer-ivantodorovich|

This module is part of the `OCA/product-attribute <https://github.com/OCA/product-attribute/tree/19.0/product_class>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions product_class/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
18 changes: 18 additions & 0 deletions product_class/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Product Class",
"version": "19.0.1.0.0",
"summary": "Product classification and attribute constraints",
"author": "Camptocamp, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/product-attribute",
"license": "AGPL-3",
"category": "Product",
"depends": ["product", "stock", "sale"],
"data": [
"security/ir.model.access.csv",
"views/product_class_views.xml",
"views/product_attribute_views.xml",
"views/product_template_views.xml",
],
"installable": True,
Comment thread
Ricardoalso marked this conversation as resolved.
"maintainers": ["Ricardoalso", "ivantodorovich"],
}
3 changes: 3 additions & 0 deletions product_class/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import product_attribute
from . import product_class
from . import product_template
32 changes: 32 additions & 0 deletions product_class/models/product_attribute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from odoo import api, fields, models


class ProductAttribute(models.Model):
_inherit = "product.attribute"

classes_count = fields.Integer(
string="Product Classes Count",
compute="_compute_classes_count",
)

class_ids = fields.Many2many(
comodel_name="product.class",
relation="product_class_attribute_rel",
column1="attribute_id",
column2="product_class_id",
string="Product Classes",
help="Product classes that include this attribute",
)
Comment thread
Ricardoalso marked this conversation as resolved.

@api.depends("class_ids")
def _compute_classes_count(self):
for attribute in self:
attribute.classes_count = len(attribute.class_ids)

def action_open_product_classes(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
"product_class.product_class_action"
)
action["domain"] = [("id", "in", self.class_ids.ids)]
return action
48 changes: 48 additions & 0 deletions product_class/models/product_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from odoo import api, fields, models
from odoo.exceptions import ValidationError


class ProductClass(models.Model):
_name = "product.class"
_description = "Product Class"
_order = "name"

_name_uniq = models.Constraint(
"unique(name)",
"A product class with this name already exists.",
)

name = fields.Char()
attribute_ids = fields.Many2many(
Comment thread
Ricardoalso marked this conversation as resolved.
comodel_name="product.attribute",
relation="product_class_attribute_rel",
column1="product_class_id",
column2="attribute_id",
string="Attributes",
help="Allowed attributes for products of this class",
)

@api.constrains("attribute_ids")
def _check_attribute_ids_used_by_products(self):
for product_class in self:
invalid_lines = self.env["product.template.attribute.line"].search(
[
("product_tmpl_id.class_id", "=", product_class.id),
("attribute_id", "not in", product_class.attribute_ids.ids),
]
)
if not invalid_lines:
continue

invalid_names = ", ".join(
sorted(set(invalid_lines.mapped("attribute_id.display_name")))
)
raise ValidationError(
self.env._(
"Cannot remove attributes used in products assigned to class "
"'%(product_class)s': %(attrs)s. Please remove these attributes "
"or change the product class.",
product_class=product_class.name,
attrs=invalid_names,
)
)
45 changes: 45 additions & 0 deletions product_class/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from odoo import api, fields, models
from odoo.exceptions import ValidationError


class ProductTemplate(models.Model):
_inherit = "product.template"

class_id = fields.Many2one(
comodel_name="product.class",
string="Product Class",
help="Product class that constrains which attributes can be used",
)

class_attribute_ids = fields.Many2many(
related="class_id.attribute_ids",
string="Class Attributes",
help="Attributes allowed by the selected product class",
)

@api.constrains("class_id", "attribute_line_ids")
def _check_class_attributes(self):
"""
Ensure all attribute_line_ids belong to the selected class.
"""
for product in self:
if not product.class_id:
continue

class_attributes = product.class_id.attribute_ids
invalid_attributes = (
product.attribute_line_ids.attribute_id - class_attributes
)

if invalid_attributes:
invalid_names = ", ".join(invalid_attributes.mapped("display_name"))
raise ValidationError(
self.env._(
"Product '%(product)s' has attribute lines that do not belong "
"to the selected class '%(product_class)s': %(attrs)s. "
"Please remove these attributes or change the product class.",
product=product.name,
product_class=product.class_id.name,
attrs=invalid_names,
)
)
3 changes: 3 additions & 0 deletions product_class/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
5 changes: 5 additions & 0 deletions product_class/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
This module introduces Product Classes to group product attributes and standardize product setup.

Each product class defines the attributes that are allowed for products assigned to that class. On products, a class can be selected, and Odoo enforces that attribute lines only use attributes from the selected class.

The module also provides menu entries and views to manage product classes.
3 changes: 3 additions & 0 deletions product_class/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_create,perm_read,perm_write,perm_unlink
access_product_class_user,product.class User,model_product_class,base.group_user,1,1,1,0
access_product_class_manager,product.class Manager,model_product_class,base.group_system,1,1,1,1
Loading
Loading