[DOC] product_pricelist_total_margin: Update docs and version to 18.0.1.2.0

Changelog:
- Document global_margin_type feature for independent global limits calculation
- Update version from 18.0.1.1.0 to 18.0.1.2.0
- Update test coverage count (11 → 13 tests)
- Update manifest summary to include global limits enforcement
This commit is contained in:
snt 2026-02-21 19:19:25 +01:00
parent 449bb75bb6
commit b31df7b9d8
2 changed files with 85 additions and 9 deletions

View file

@ -45,13 +45,16 @@ Effective margin: (5.85 - 4.68) / 5.85 = 20%
## Features
- ✅ **Additive margin calculation** across chained pricelists
- ✅ **Two calculation methods:**
- ✅ **Two calculation methods per pricelist:**
- **Markup (on cost):** `PVP = Cost × (1 + markup%)`
- **Commercial Margin (on PVP):** `PVP = Cost / (1 - margin%)`
- ✅ **Global min/max margin limits** with independent calculation type:
- Configure minimum and maximum margin percentages
- Choose between Markup or Commercial Margin interpretation for limits
- Limits can use different calculation method than individual pricelists
- ✅ **Opt-in via checkbox** - doesn't affect existing pricelists
- ✅ **Compatible with custom bases** (`last_purchase_price` from `product_sale_price_from_pricelist`)
- ✅ **Supports all formula extras** (price_round, price_surcharge, price_min/max_margin)
- ✅ **Global min/max margin limits** (configurable in Settings > Sales)
- ✅ **Multi-level chains** - works with 2+ pricelists in sequence
- ✅ **Currency conversion** - handles multi-currency scenarios
- ✅ **Detailed logging** - debug pricing calculations easily
@ -105,7 +108,24 @@ Create a pricelist that chains to the base one:
- **Markup (on cost)** - Default, calculates `PVP = Cost × (1 + markup%)`
- **Commercial Margin (on PVP)** - Calculates `PVP = Cost / (1 - margin%)`
### Step 3: Assign to Products
### Step 3: Configure Global Limits (Optional)
Set enterprise-wide minimum and maximum margins:
1. Go to **Settings > Sales > Total Margin Limits**
2. 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, `Min: Cost × 1.10`, `Max: Cost × 1.50`
- **Commercial Margin (on PVP)** - `Min: Cost / 0.90`, `Max: Cost / 0.50`
**Important:** The global limits calculation method is independent from individual pricelist items. You can have:
- Items using Markup, with global limits as Commercial Margin
- Items using Commercial Margin, with global limits as Markup
- Both using the same method
### 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
@ -165,6 +185,30 @@ Option 2 - Commercial Margin:
- **Visibility:** Only shown when `use_total_margin = True`
- **Purpose:** Choose the calculation method for the total margin
### Global Configuration Fields
- **Model:** `res.config.settings`
#### `total_margin_min_percent` (Float)
- **Default:** 0.0 (disabled)
- **Purpose:** Minimum margin percentage for all products using Total Margin Mode
- **Interpretation:** Depends on `global_margin_type` setting
#### `total_margin_max_percent` (Float)
- **Default:** 0.0 (disabled)
- **Purpose:** Maximum margin percentage for all products using Total Margin Mode
- **Interpretation:** Depends on `global_margin_type` setting
#### `global_margin_type` (Selection)
- **Default:** `'markup'`
- **Options:**
- `'markup'` - Limits are interpreted as markup on cost
- `'margin'` - Limits are interpreted as commercial margin on PVP
- **Purpose:** Define how min/max percentages are converted to prices
- **Example:** Min 25%:
- Markup: `Min Price = Cost × 1.25`
- Commercial Margin: `Min Price = Cost / 0.75` (ensures 25% margin on final price)
### Methods
#### `_get_base_price_and_margins(product, quantity, uom, date, currency)`
@ -191,16 +235,33 @@ Applies additional formula options:
- `price_min_margin`: Enforce minimum margin
- `price_max_margin`: Enforce maximum margin
#### `_apply_global_margin_limits(price, base_price)`
Enforces global minimum and maximum margins configured in Settings:
1. Reads `total_margin_min_percent`, `total_margin_max_percent`, and `global_margin_type` from configuration
2. Calculates min/max allowed prices based on `global_margin_type`:
- **Markup:** `Price = Cost × (1 + margin%)`
- **Commercial Margin:** `Price = Cost / (1 - margin%)`
3. Adjusts price if it falls outside configured limits
4. Returns adjusted price
**Note:** Global limits are applied AFTER the item's margin calculation, and can use a different margin type than the item itself.
**Example:**
- Item calculates 15% markup → Price = 100 × 1.15 = 115€
- Global min is 20% commercial margin → Min Price = 100 / 0.80 = 125€
- Result: Price adjusted from 115€ to 125€ to meet global minimum
#### `_compute_price(product, quantity, uom, date, currency)` [OVERRIDE]
Main override that:
1. Checks if `use_total_margin=True` and conditions are met
2. Calls helper methods to get base price and margins
3. Sums margins additively: `total_margin = sum(margins)`
4. Applies global min/max margin limits if configured
5. Applies total margin using selected method:
4. Applies total margin using item's selected method:
- **Markup:** `price = base_price * (1 + total_margin / 100)`
- **Commercial Margin:** `price = base_price / (1 - total_margin / 100)`
5. Applies global min/max margin limits (may use different margin type)
6. Applies formula extras
7. Falls back to standard behavior if conditions not met
@ -240,12 +301,14 @@ docker-compose run odoo odoo -d odoo --test-enable --stop-after-init -u product_
- ✅ Total margin with Markup calculation
- ✅ Total margin with Commercial Margin calculation
- ✅ Formula extras (round, surcharge, min/max)
- ✅ Global min/max margin limits
- ✅ Global min/max margin limits with Markup type
- ✅ Global min/max margin limits with Commercial Margin type
- ✅ Mixed margin types (item vs global with different types)
- ✅ 3-level pricelist chains
- ✅ Different base types (last_purchase_price, list_price)
- ✅ Currency conversions
**Total:** 11 tests, all passing
**Total:** 13 tests, all passing
## Compatibility
@ -323,6 +386,19 @@ AGPL-3.0 or later
## Changelog
### 18.0.1.2.0 (2026-02-21)
- **[IMP]** Add `global_margin_type` field for independent global limits calculation
- Configure how min/max percentages are interpreted (Markup or Commercial Margin)
- Global limits can use different calculation method than individual pricelist items
- Enables flexible business rules (e.g., items use Markup, global limits enforce Commercial Margin)
- Refactor `_apply_global_margin_limits()` to work with prices instead of percentages
- Now calculates min/max prices based on `global_margin_type`
- Applied after item's margin calculation, not before
- Add 2 new tests for global limits with Commercial Margin type
- Update configuration UI with global margin type selector
- Total: 13 tests passing
### 18.0.1.1.0 (2026-02-21)
- **[IMP]** Add `margin_type` field to choose between calculation methods