From 4ad699af14bc72608ff47c2d57e34f01332a1da8 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 | 12 +++++-- 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 | 34 +++++++++++-------- 7 files changed, 76 insertions(+), 34 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 2305583ff..046a264fb 100644 --- a/product_standard_margin/README.rst +++ b/product_standard_margin/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ============================== Product Margin and Margin Rate ============================== @@ -13,7 +17,7 @@ Product Margin and Margin Rate .. |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 +.. |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%2Fmargin--analysis-lightgray.png?logo=github @@ -57,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 1545d0ede..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.3", + "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 8ff848885..1cfb9a071 100644 --- a/product_standard_margin/models/product_template.py +++ b/product_standard_margin/models/product_template.py @@ -59,25 +59,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 d9318c3f5..46cfbdbcb 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 -
-

Product Margin and Margin Rate

+
+ + +Odoo Community Association + +
+

Product Margin and Margin Rate

-

Beta License: AGPL-3 OCA/margin-analysis Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/margin-analysis Translate me on Weblate Try me on Runboat

Add 2 fields on the product form that compute the standard (or theorical) margin and markup based on the current values of sale and standard price present in the product form. We take care of taxe included or excluded.

@@ -402,14 +407,14 @@

Product Margin and Margin Rate

-

Known issues / Roadmap

-
    -
  • This module will not work properly if used in a multicompany context with product -prices depending on the company.
  • -
+

Known issues / Roadmap

+

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

+

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 @@ -417,16 +422,16 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Camptocamp
  • GRAP
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -451,5 +456,6 @@

Maintainers

+