[DOC] product_pricelist_total_margin: Update documentation for v1.1.0

- Update README with margin_type field documentation
- Add detailed explanations for both calculation methods:
  * Markup (on cost): PVP = Cost × (1 + markup%)
  * Commercial Margin (on PVP): PVP = Cost / (1 - margin%)
- Add examples comparing both methods
- Update features list with new capabilities
- Update configuration steps to include margin_type selector
- Update technical details with new field specifications
- Update test coverage section (11 tests)
- Add logging examples for both methods
- Update changelog with v18.0.1.1.0 release notes
- Bump version to 18.0.1.1.0 in __manifest__.py
- Update summary to reflect new features
This commit is contained in:
snt 2026-02-21 19:11:01 +01:00
parent 55406ca22d
commit 07cc0eb517
2 changed files with 76 additions and 13 deletions

View file

@ -22,20 +22,36 @@ Pricelist B: 25% markup → 4.446 × 1.25 = 5.5575€
With this module, you can calculate the **total margin** by summing percentages:
#### Option 1: Markup (on cost)
```
Base price: 4.68€
Total margin: -5% + 25% = 20%
Final price: 4.68 × 1.20 = 5.616€
Effective margin: (5.616 - 4.68) / 5.616 = 16.67%
```
**Result:** 5.62€ (effective margin: 20%)
**Result:** 5.62€ (20% markup on cost)
#### Option 2: Commercial Margin (on PVP)
```
Base price: 4.68€
Total margin: -5% + 25% = 20%
Final price: 4.68 / 0.80 = 5.85€
Effective margin: (5.85 - 4.68) / 5.85 = 20%
```
**Result:** 5.85€ (20% commercial margin on PVP)
## Features
- ✅ **Additive margin calculation** across chained pricelists
- ✅ **Two calculation methods:**
- **Markup (on cost):** `PVP = Cost × (1 + markup%)`
- **Commercial Margin (on PVP):** `PVP = Cost / (1 - margin%)`
- ✅ **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
@ -84,7 +100,10 @@ Create a pricelist that chains to the base one:
- **Based on:** Other Pricelist → Select "Base Pricelist - Last Purchase Price"
- **Price Computation:** Formula
- **Discount:** -25% (negative = 25% markup)
- **☑️ Use Total Margin:** Check this box!
- **☑️ 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: Assign to Products
@ -113,19 +132,38 @@ After product category (+25%): 5.5575€ ❌ Wrong effective margin: 18.8%
Product: Flour (cesta básica, repostería)
Purchase price: 4.68€
Total margin: -5% + 25% = 20%
Final price: 5.616€ ✅ Correct effective margin: 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
## Technical Details
### New Field
### New Fields
- **Model:** `product.pricelist.item`
- **Field:** `use_total_margin` (Boolean)
#### `use_total_margin` (Boolean)
- **Default:** False (opt-in)
- **Visibility:** Only shown when:
- `compute_price = 'formula'`
- `base = 'pricelist'` (chained pricelist)
- **Purpose:** Enable additive margin calculation instead of compound
#### `margin_type` (Selection)
- **Default:** `'markup'`
- **Options:**
- `'markup'` - Markup (on cost): `PVP = Cost × (1 + markup%)`
- `'margin'` - Commercial Margin (on PVP): `PVP = Cost / (1 - margin%)`
- **Visibility:** Only shown when `use_total_margin = True`
- **Purpose:** Choose the calculation method for the total margin
### Methods
@ -159,9 +197,14 @@ 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 total margin: `price = base_price * (1 + total_margin / 100)`
5. Applies formula extras
6. Falls back to standard behavior if conditions not met
4. Applies global min/max margin limits if configured
5. Applies total margin using selected method:
- **Markup:** `price = base_price * (1 + total_margin / 100)`
- **Commercial Margin:** `price = base_price / (1 - total_margin / 100)`
6. Applies formula extras
7. Falls back to standard behavior if conditions not met
**Safety:** Commercial margin >= 100% is capped at 99% to avoid division by zero
### Logging
@ -170,7 +213,12 @@ All calculations are logged with `[TOTAL MARGIN]` prefix for easy debugging:
```python
_logger.info("[TOTAL MARGIN] Item %s: base=%s, margin=%.2f%%", ...)
_logger.info("[TOTAL MARGIN] Margins: ['5.0%', '25.0%'] = 20.0% total")
_logger.info("[TOTAL MARGIN] Base price 4.68 * (1 + 20.0%) = 5.616")
# Markup method:
_logger.info("[TOTAL MARGIN] Markup: Base 4.68 * (1 + 20.0%) = 5.616")
# Commercial Margin method:
_logger.info("[TOTAL MARGIN] Commercial Margin: Base 4.68 / (1 - 20.0%) = 5.85")
```
View logs:
@ -189,12 +237,16 @@ docker-compose run odoo odoo -d odoo --test-enable --stop-after-init -u product_
### Test Coverage
- ✅ Compound margin (default behavior preserved)
- ✅ Total margin (additive calculation)
- ✅ Total margin with Markup calculation
- ✅ Total margin with Commercial Margin calculation
- ✅ Formula extras (round, surcharge, min/max)
- ✅ Global min/max margin limits
- ✅ 3-level pricelist chains
- ✅ Different base types (last_purchase_price, list_price)
- ✅ Currency conversions
**Total:** 11 tests, all passing
## Compatibility
- **Odoo Version:** 18.0
@ -271,10 +323,21 @@ AGPL-3.0 or later
## Changelog
### 18.0.1.1.0 (2026-02-21)
- **[IMP]** Add `margin_type` field to choose between calculation methods
- **Markup (on cost):** `PVP = Cost × (1 + markup%)`
- **Commercial Margin (on PVP):** `PVP = Cost / (1 - margin%)`
- Add 2 new tests for both calculation methods
- Add safety cap for commercial margin >= 100% (caps at 99%)
- Improve logging to show which calculation method is used
- Total: 11 tests passing
### 18.0.1.0.0 (2026-02-21)
- Initial implementation
- Support for additive margin calculation in chained pricelists
- Compatible with `last_purchase_price` custom base
- Comprehensive test suite
- Global min/max margin limits configuration
- Comprehensive test suite (9 tests)
- Detailed logging for debugging