addons-cm/product_pricelist_total_margin
2026-02-25 18:41:16 +01:00
..
models [IMP] product_pricelist_total_margin: Add global_margin_type for min/max limits 2026-02-21 19:16:16 +01:00
readme [DOC] Actualizar documentación a estándares OCA y preparar logo CriptoMart 2026-02-21 19:55:57 +01:00
static/description iconos 2026-02-25 18:41:16 +01:00
tests [IMP] product_pricelist_total_margin: Add global_margin_type for min/max limits 2026-02-21 19:16:16 +01:00
views [IMP] product_pricelist_total_margin: Add global_margin_type for min/max limits 2026-02-21 19:16:16 +01:00
__init__.py [ADD] product_pricelist_total_margin: New module for additive margin calculation 2026-02-21 16:11:13 +01:00
__manifest__.py [DOC] Actualizar documentación a estándares OCA y preparar logo CriptoMart 2026-02-21 19:55:57 +01:00
README.rst [DOC] Actualizar documentación a estándares OCA y preparar logo CriptoMart 2026-02-21 19:55:57 +01:00
README_DEV.md [DOC] Actualizar documentación a estándares OCA y preparar logo CriptoMart 2026-02-21 19:55:57 +01:00

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

====================================
Product Pricelist Total Margin
====================================

.. |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

|badge1| |badge2|

This module solves the problem of **compounded margins** when using chained pricelists in Odoo. By default, Odoo applies each pricelist rule's margin on top of the previous result, leading to compounded percentages. This module provides an option to calculate margins **additively** instead.

**Problem Solved:**

When you chain pricelists (Pricelist A → Pricelist B), standard Odoo applies margins in cascade:

* Base price: 4.68€
* Pricelist A: -5% discount → 4.68 × 0.95 = 4.446€
* Pricelist B: 25% markup → 4.446 × 1.25 = 5.5575€
* **Result:** 5.56€ (effective margin: 18.8%) ❌

**With this module (Total Margin Mode):**

Calculate the **total margin** by summing percentages:

* Base price: 4.68€
* Total margin: -5% + 25% = 20%
* **Markup (on cost):** 4.68 × 1.20 = 5.616€ ✅
* **Commercial Margin (on PVP):** 4.68 / 0.80 = 5.85€ ✅

**Key Features:**

* ✅ **Additive margin calculation** across chained pricelists
* ✅ **Two calculation methods:** Markup (on cost) or Commercial Margin (on PVP)
* ✅ **Global min/max margin limits** with independent calculation type
* ✅ **Opt-in via checkbox** - doesn't affect existing pricelists
* ✅ **Compatible with custom bases** (e.g., last_purchase_price)
* ✅ **Supports all formula extras** (price_round, price_surcharge, price_min/max_margin)
* ✅ **Multi-level chains** - works with 2+ pricelists in sequence
* ✅ **Currency conversion** - handles multi-currency scenarios
* ✅ **Detailed logging** - debug pricing calculations easily

**Table of contents**

.. contents::
   :local:

Installation
============

To install this module, you need to:

#. Ensure dependencies are installed:

   * product
   * product_price_category
   * product_sale_price_from_pricelist

#. Update the Apps list
#. Search for "Product Pricelist Total Margin"
#. Click Install
#. Restart Odoo service

Configuration
=============

**Step 1: Create Base Pricelist**

Create a pricelist that defines your base pricing logic:

#. Go to Sales → Configuration → Pricelists
#. Create a new pricelist: "Base Pricelist - Last Purchase Price"
#. Add a rule:

   * **Apply On:** All Products
   * **Based on:** Last Purchase Price (or List Price, Standard Price, etc.)
   * **Price Computation:** Formula
   * **Discount:** 5% (example for "cesta básica" category)

**Step 2: Create Chained Pricelist with Total Margin**

#. Create a new pricelist: "Category Margin - Your Category"
#. Add a rule:

   * **Apply On:** All Products (or specific category)
   * **Based on:** Other Pricelist → Select your base pricelist
   * **Price Computation:** Formula
   * **Discount:** -25% (negative = 25% markup)
   * **☑️ Total Margin Mode:** Check this box!
   * **Calculation Method:** Choose between:

     * **Markup (on cost)** - Default, calculates ``PVP = Cost × (1 + markup%)``
     * **Commercial Margin (on PVP)** - Calculates ``PVP = Cost / (1 - margin%)``

**Step 3: Configure Global Limits (Optional)**

Set enterprise-wide minimum and maximum margins:

#. Go to Settings → Sales → Total Margin Limits
#. Configure:

   * **Minimum Margin (%):** E.g., 10% (no product can have less margin)
   * **Maximum Margin (%):** E.g., 50% (no product can have more margin)
   * **Calculation Method:** Choose how these percentages are interpreted

     * **Markup (on cost)** - Default
     * **Commercial Margin (on PVP)**

**Important:** The global limits calculation method is independent from individual pricelist items.

**Step 4: Assign to Products**

* For automatic price calculation, configure the pricelist in Settings → Sales → Automatic Price Configuration
* Or assign the pricelist to specific customers/partners

Usage
=====

**Scenario: Cooperative Pricing System**

Your cooperative has two margin rules:

#. **Price Category Discount:** "Cesta Básica" products get -5% (to make them affordable)
#. **Product Category Markup:** "Repostería" products get +25% (higher margin category)

**Without this module (compound):**

::

  Product: Flour (cesta básica, repostería)
  Purchase price: 4.68€
  After price category (-5%): 4.446€
  After product category (+25%): 5.5575€
  ❌ Wrong effective margin: 18.8%

**With this module (total margin enabled):**

::

  Product: Flour (cesta básica, repostería)
  Purchase price: 4.68€
  Total margin: -5% + 25% = 20%

  Option 1 - Markup:
    Final price: 4.68 × 1.20 = 5.616€ ✅ Markup 20% on cost

  Option 2 - Commercial Margin:
    Final price: 4.68 / 0.80 = 5.85€ ✅ Margin 20% on PVP

**Which method to choose?**

* **Markup (on cost):** Traditional markup calculation, margin on cost base
* **Commercial Margin (on PVP):** Retail/commercial margin, ensures exact margin percentage on final price

**Monitoring and Debugging:**

* Enable debug mode to see detailed price calculation logs
* Check logs for [TOTAL_MARGIN] tagged messages
* Verify total margin calculations match expectations
* Use global limits to enforce business rules

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/Criptomart/addons-cm/issues>`_.
In case of trouble, please check there if your issue has already been reported.

Credits
=======

Authors
~~~~~~~

* Criptomart

Funding
~~~~~~~

* Elika Bilbo

Contributors
~~~~~~~~~~~~

* `Criptomart <https://criptomart.net>`_:

  * Main development and architecture
  * Mathematical implementation of margin calculation methods

Other credits
~~~~~~~~~~~~~

This module extends Odoo's pricelist functionality to support cooperative and group purchasing scenarios where transparent, additive margin calculations are essential.

The implementation provides two industry-standard margin calculation methods to accommodate different business practices.

Maintainers
~~~~~~~~~~~

This module is maintained by Criptomart.

.. image:: https://odoo-community.org/logo.png
   :alt: Odoo Community Association
   :target: https://odoo-community.org

This module is part of the `Criptomart/addons-cm <https://github.com/Criptomart/addons-cm/tree/18.0/product_pricelist_total_margin>`_ project on GitHub.