From 488dbe3c0e5a3cbdcd6534796bdefdfb668ed4fd Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Tue, 4 Aug 2026 12:23:38 +0200 Subject: [PATCH] [FIX] product_standard_margin: fix margin fields computation in case of multicompany context, with product related to a single company. Provide migration script to fix bad computation --- product_standard_margin/README.rst | 6 ++-- product_standard_margin/__manifest__.py | 2 +- .../migrations/16.0.2.0.0/post-migration.py | 30 +++++++++++++++++++ .../models/product_product.py | 13 ++++---- .../models/product_template.py | 13 ++++---- product_standard_margin/readme/ROADMAP.rst | 6 ++-- .../static/description/index.html | 10 +++---- 7 files changed, 56 insertions(+), 24 deletions(-) create mode 100644 product_standard_margin/migrations/16.0.2.0.0/post-migration.py diff --git a/product_standard_margin/README.rst b/product_standard_margin/README.rst index cec579ce5..c9fa9c52a 100644 --- a/product_standard_margin/README.rst +++ b/product_standard_margin/README.rst @@ -61,8 +61,10 @@ have added a dependency on sale module. Known issues / Roadmap ====================== -* This module will not work properly if used in a multicompany context with product - prices depending on the company. +This module will not work properly if used in a multicompany context with "global" products +that are not related to any company. +This is due to current odoo limitation that compute field with a sudo user, and due to the field `standard_price` +that is weirdly company dependent, unlike the selling price. Bug Tracker =========== diff --git a/product_standard_margin/__manifest__.py b/product_standard_margin/__manifest__.py index a3aab10d6..1804d0c92 100644 --- a/product_standard_margin/__manifest__.py +++ b/product_standard_margin/__manifest__.py @@ -5,7 +5,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { "name": "Product Margin and Margin Rate", - "version": "16.0.1.0.4", + "version": "16.0.2.0.0", "author": "Camptocamp,GRAP,Odoo Community Association (OCA)", "category": "Product", "depends": ["account"], diff --git a/product_standard_margin/migrations/16.0.2.0.0/post-migration.py b/product_standard_margin/migrations/16.0.2.0.0/post-migration.py new file mode 100644 index 000000000..98de141d0 --- /dev/null +++ b/product_standard_margin/migrations/16.0.2.0.0/post-migration.py @@ -0,0 +1,30 @@ +import logging + +from odoo import SUPERUSER_ID, api + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + if not version: + return + + env = api.Environment(cr, SUPERUSER_ID, {}) + + for company in env["res.company"].with_context(active_test=False).search([]): + products = ( + env["product.product"] + .with_company(company) + .search( + [ + ("company_id", "=", company.id), + ("standard_markup_rate", "=", 999.0), + ("standard_price", "!=", 0.0), + ] + ) + ) + _logger.info( + f"Company {company.name}:" + f" Trying to recomputing margin fields for {len(products)} products ..." + ) + products._compute_margin() diff --git a/product_standard_margin/models/product_product.py b/product_standard_margin/models/product_product.py index bc1ede620..0ca44c8d1 100644 --- a/product_standard_margin/models/product_product.py +++ b/product_standard_margin/models/product_product.py @@ -61,25 +61,24 @@ class ProductProduct(models.Model): ) def _compute_margin(self): for product in self: + standard_price = product.with_company(product.company_id).standard_price product.list_price_vat_excl = product.taxes_id.compute_all( product.lst_price, product=product )["total_excluded"] - product.standard_margin = ( - product.list_price_vat_excl - product.standard_price - ) + product.standard_margin = product.list_price_vat_excl - standard_price if product.list_price_vat_excl == 0: product.standard_margin_rate = 999.0 else: product.standard_margin_rate = ( - (product.list_price_vat_excl - product.standard_price) + (product.list_price_vat_excl - standard_price) / product.list_price_vat_excl * 100 ) - if product.standard_price == 0: + if standard_price == 0: product.standard_markup_rate = 999.0 else: product.standard_markup_rate = ( - (product.list_price_vat_excl - product.standard_price) - / product.standard_price + (product.list_price_vat_excl - standard_price) + / standard_price * 100 ) diff --git a/product_standard_margin/models/product_template.py b/product_standard_margin/models/product_template.py index 30b9739d0..9be95e4f0 100644 --- a/product_standard_margin/models/product_template.py +++ b/product_standard_margin/models/product_template.py @@ -63,25 +63,24 @@ def _compute_margin(self): # because otherwise, the recomputation is not done correctly # when the product datas are changed from the template view for template in self: + standard_price = template.with_company(template.company_id).standard_price template.list_price_vat_excl = template.taxes_id.compute_all( template.list_price, product=template )["total_excluded"] - template.standard_margin = ( - template.list_price_vat_excl - template.standard_price - ) + template.standard_margin = template.list_price_vat_excl - standard_price if template.list_price_vat_excl == 0: template.standard_margin_rate = 999.0 else: template.standard_margin_rate = ( - (template.list_price_vat_excl - template.standard_price) + (template.list_price_vat_excl - standard_price) / template.list_price_vat_excl * 100 ) - if template.standard_price == 0: + if standard_price == 0: template.standard_markup_rate = 999.0 else: template.standard_markup_rate = ( - (template.list_price_vat_excl - template.standard_price) - / template.standard_price + (template.list_price_vat_excl - standard_price) + / standard_price * 100 ) diff --git a/product_standard_margin/readme/ROADMAP.rst b/product_standard_margin/readme/ROADMAP.rst index 354994f4a..4b5c25f9d 100644 --- a/product_standard_margin/readme/ROADMAP.rst +++ b/product_standard_margin/readme/ROADMAP.rst @@ -1,2 +1,4 @@ -* This module will not work properly if used in a multicompany context with product - prices depending on the company. +This module will not work properly if used in a multicompany context with "global" products +that are not related to any company. +This is due to current odoo limitation that compute field with a sudo user, and due to the field `standard_price` +that is weirdly company dependent, unlike the selling price. diff --git a/product_standard_margin/static/description/index.html b/product_standard_margin/static/description/index.html index f58627cb2..188278d89 100644 --- a/product_standard_margin/static/description/index.html +++ b/product_standard_margin/static/description/index.html @@ -3,7 +3,7 @@ -Product Margin and Margin Rate +README.rst