Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ addon | version | maintainers | summary
[nutritional_info](nutritional_info/) | 18.0.1.0.0 | <a href='https://github.com/CarlosRoca13'><img src='https://github.com/CarlosRoca13.png' width='32' height='32' style='border-radius:50%;' alt='CarlosRoca13'/></a> | Nutritional information.
[nutritional_info_stock_lot](nutritional_info_stock_lot/) | 18.0.1.0.0 | <a href='https://github.com/CarlosRoca13'><img src='https://github.com/CarlosRoca13.png' width='32' height='32' style='border-radius:50%;' alt='CarlosRoca13'/></a> | Nutritional information for lots.
[pos_product_cost_security](pos_product_cost_security/) | 18.0.1.0.0 | | Compatibility between Point of Sale and Product Cost Security
[product_abc_classification](product_abc_classification/) | 18.0.2.0.0 | | ABC classification for sales and warehouse management
[product_abc_classification](product_abc_classification/) | 18.0.2.1.0 | | ABC classification for sales and warehouse management
[product_abc_classification_sale_stock](product_abc_classification_sale_stock/) | 18.0.1.0.0 | <a href='https://github.com/rousseldenis'><img src='https://github.com/rousseldenis.png' width='32' height='32' style='border-radius:50%;' alt='rousseldenis'/></a> <a href='https://github.com/lmignon'><img src='https://github.com/lmignon.png' width='32' height='32' style='border-radius:50%;' alt='lmignon'/></a> <a href='https://github.com/lmarion-source'><img src='https://github.com/lmarion-source.png' width='32' height='32' style='border-radius:50%;' alt='lmarion-source'/></a> | Compute ABC classification from the number of delivered sale order line by product
[product_assortment](product_assortment/) | 18.0.1.0.1 | | Adds the ability to manage products assortment
[product_attachment_zipped_download](product_attachment_zipped_download/) | 18.0.1.0.0 | <a href='https://github.com/victoralmau'><img src='https://github.com/victoralmau.png' width='32' height='32' style='border-radius:50%;' alt='victoralmau'/></a> | Product Attachment Zipped Download
Expand Down
2 changes: 1 addition & 1 deletion product_abc_classification/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Product Abc Classification
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:7449408f8b05c5c6727fa26edf48fe6059b4c340378555629377ca12e0bb0b6b
!! source digest: sha256:0b89f1d5229ad6e783124e9478615b65f3122c6ca9c6a4da1445205147b44da2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down
3 changes: 2 additions & 1 deletion product_abc_classification/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"name": "Product Abc Classification",
"summary": """
ABC classification for sales and warehouse management""",
"version": "18.0.2.0.0",
"version": "18.0.2.1.0",
"license": "AGPL-3",
"author": "ACSONE SA/NV, ForgeFlow, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/product-attribute",
Expand All @@ -18,6 +18,7 @@
"views/product_product.xml",
"views/product_category.xml",
"security/ir.model.access.csv",
"security/security.xml",
"data/ir_cron.xml",
],
}
15 changes: 15 additions & 0 deletions product_abc_classification/i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ msgstr "El nivel de clasificación es obligatorio"
msgid "Classification not in sync with computed"
msgstr "Clasificación no sincronizada con el cálculo"

#. module: product_abc_classification
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_product_level__company_id
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_profile__company_id
msgid "Company"
msgstr ""

#. module: product_abc_classification
#: model_terms:ir.ui.view,arch_db:product_abc_classification.abc_classification_profile_form_view
msgid "Computation"
Expand Down Expand Up @@ -398,6 +404,15 @@ msgstr "El nombre del perfil debe ser único"
msgid "Ratings"
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_profile.py:0
msgid ""
"The ABC Classification Profile %(profile)s is assigned to company %"
"(company)s, but the following products belong to another company: %"
"(products)s."
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_level.py:0
Expand Down
15 changes: 15 additions & 0 deletions product_abc_classification/i18n/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ msgstr "La classe / niveau est obligatoire"
msgid "Classification not in sync with computed"
msgstr "Classes ABC manuelle et calculée divergentes"

#. module: product_abc_classification
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_product_level__company_id
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_profile__company_id
msgid "Company"
msgstr ""

#. module: product_abc_classification
#: model_terms:ir.ui.view,arch_db:product_abc_classification.abc_classification_profile_form_view
msgid "Computation"
Expand Down Expand Up @@ -404,6 +410,15 @@ msgstr "Le nom du profil doit être unique"
msgid "Ratings"
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_profile.py:0
msgid ""
"The ABC Classification Profile %(profile)s is assigned to company %"
"(company)s, but the following products belong to another company: %"
"(products)s."
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_level.py:0
Expand Down
15 changes: 15 additions & 0 deletions product_abc_classification/i18n/it.po
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ msgstr "Il livello classificazione è obbligatorio"
msgid "Classification not in sync with computed"
msgstr "Classificazione non sincronizzata con il calcolo"

#. module: product_abc_classification
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_product_level__company_id
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_profile__company_id
msgid "Company"
msgstr ""

#. module: product_abc_classification
#: model_terms:ir.ui.view,arch_db:product_abc_classification.abc_classification_profile_form_view
msgid "Computation"
Expand Down Expand Up @@ -398,6 +404,15 @@ msgstr "Il nome profilo deve essere univoco"
msgid "Ratings"
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_profile.py:0
msgid ""
"The ABC Classification Profile %(profile)s is assigned to company %"
"(company)s, but the following products belong to another company: %"
"(products)s."
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_level.py:0
Expand Down
15 changes: 15 additions & 0 deletions product_abc_classification/i18n/product_abc_classification.pot
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ msgstr ""
msgid "Classification not in sync with computed"
msgstr ""

#. module: product_abc_classification
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_product_level__company_id
#: model:ir.model.fields,field_description:product_abc_classification.field_abc_classification_profile__company_id
msgid "Company"
msgstr ""

#. module: product_abc_classification
#: model_terms:ir.ui.view,arch_db:product_abc_classification.abc_classification_profile_form_view
msgid "Computation"
Expand Down Expand Up @@ -387,6 +393,15 @@ msgstr ""
msgid "Ratings"
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_profile.py:0
msgid ""
"The ABC Classification Profile %(profile)s is assigned to company "
"%(company)s, but the following products belong to another company: "
"%(products)s."
msgstr ""

#. module: product_abc_classification
#. odoo-python
#: code:addons/product_abc_classification/models/abc_classification_level.py:0
Expand Down
26 changes: 26 additions & 0 deletions product_abc_classification/migrations/18.0.2.1.0/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2026 ForgeFlow
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging

_logger = logging.getLogger(__name__)


def migrate(cr, version):
if not version:
return
cr.execute(
"""
UPDATE abc_classification_product_level AS lvl
SET company_id = tmpl.company_id
FROM product_product AS pp,
product_template AS tmpl
WHERE lvl.product_id = pp.id
AND pp.product_tmpl_id = tmpl.id
AND tmpl.company_id IS NOT NULL
AND lvl.company_id IS NULL;
"""
)
_logger.info(
"Backfilled company_id on %s abc.classification.product.level rows",
cr.rowcount,
)
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class AbcClassificationProductLevel(models.Model):
_inherit = "mail.thread"
_description = "Abc Classification Product Level"
_rec_name = "level_id"
_check_company_auto = True

manual_level_id = fields.Many2one(
"abc.classification.level",
Expand Down Expand Up @@ -43,18 +44,27 @@ class AbcClassificationProductLevel(models.Model):
index=True,
required=True,
ondelete="cascade",
check_company=True,
)
product_tmpl_id = fields.Many2one(
"product.template",
string="Product template",
index=True,
readonly=True,
)
company_id = fields.Many2one(
"res.company",
compute="_compute_company_id",
store=True,
readonly=True,
index=True,
)
# percentage
profile_id = fields.Many2one(
"abc.classification.profile",
string="Profile",
required=True,
check_company=True,
)
profile_type = fields.Selection(
related="profile_id.profile_type",
Expand Down Expand Up @@ -124,6 +134,13 @@ def _compute_flag(self):
rec.computed_level_id and rec.manual_level_id != rec.computed_level_id
)

@api.depends("product_id.company_id", "profile_id.company_id")
def _compute_company_id(self):
for rec in self:
rec.company_id = (
rec.profile_id.company_id or rec.product_id.company_id or False
)

@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
Expand Down
28 changes: 28 additions & 0 deletions product_abc_classification/models/abc_classification_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class AbcClassificationProfile(models.Model):
string="Period on which to compute the classification (Days)",
required=True,
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
)

product_variant_ids = fields.Many2many(
comodel_name="product.product",
Expand All @@ -47,6 +51,30 @@ class AbcClassificationProfile(models.Model):

_sql_constraints = [("name_uniq", "UNIQUE(name)", "Profile name must be unique")]

@api.constrains("company_id", "product_variant_ids")
def _check_company_products(self):
for profile in self:
if not profile.company_id:
continue
bad = self.env["product.product"].search(
[
("id", "in", profile.product_variant_ids.ids),
("company_id", "!=", False),
("company_id", "!=", profile.company_id.id),
]
)
if bad:
raise ValidationError(
self.env._(
"The ABC Classification Profile %(profile)s is assigned "
"to company %(company)s, but the following products "
"belong to another company: %(products)s.",
profile=profile.display_name,
company=profile.company_id.display_name,
products=", ".join(bad.mapped("display_name")),
)
)

@api.constrains("level_ids")
def _check_levels(self):
for profile in self:
Expand Down
1 change: 1 addition & 0 deletions product_abc_classification/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class ProductProduct(models.Model):
column1="product_id",
column2="profile_id",
index=True,
check_company=True,
)
abc_classification_profile_updatable_from_category = fields.Boolean(default=True)

Expand Down
1 change: 1 addition & 0 deletions product_abc_classification/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ProductTemplate(models.Model):
compute="_compute_abc_classification_profile_ids",
inverse="_inverse_abc_classification_profile_ids",
store=True,
check_company=True,
)
abc_classification_product_level_ids = fields.One2many(
"abc.classification.product.level",
Expand Down
19 changes: 19 additions & 0 deletions product_abc_classification/security/security.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="abc_classification_profile_rule" model="ir.rule">
<field name="name">ABC Classification Profile multi-company</field>
<field name="model_id" ref="model_abc_classification_profile" />
<field eval="True" name="global" />
<field
name="domain_force"
>['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
<record id="abc_classification_product_level_rule" model="ir.rule">
<field name="name">ABC Classification Product Level multi-company</field>
<field name="model_id" ref="model_abc_classification_product_level" />
<field eval="True" name="global" />
<field
name="domain_force"
>['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
</odoo>
2 changes: 1 addition & 1 deletion product_abc_classification/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ <h1>Product Abc Classification</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:7449408f8b05c5c6727fa26edf48fe6059b4c340378555629377ca12e0bb0b6b
!! source digest: sha256:0b89f1d5229ad6e783124e9478615b65f3122c6ca9c6a4da1445205147b44da2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/product-attribute/tree/18.0/product_abc_classification"><img alt="OCA/product-attribute" src="https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/product-attribute-18-0/product-attribute-18-0-product_abc_classification"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/product-attribute&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This modules provides the bases to build ABC analysis (or ABC
Expand Down
1 change: 1 addition & 0 deletions product_abc_classification/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from . import test_abc_classification_profile
from . import test_abc_classification_manual_profile
from . import test_product
from . import test_multi_company
Loading