How we imagine the pricing engine
A quote line goes in as (client, SKU, quantity). This is the path it takes to come out as a final price — built entirely from rules confirmed this week, not invented from scratch.
✅ confirmed ready to build now
🔧 needs build rule known, no data model yet
❓ open genuinely unresolved, needs a person
0
Routing — which Odoo company owns this order?
✅ SPAIN-1
- Proposal only, no sale yet → Odoo Spain
- Actual sale (dropship) → Odoo Portugal (Aronlight España as customer, real client only in delivery address)
- Not Spain-related → default company (Portugal)
↓
1
Resolve "Lista de Preços"
✅ LIQUIDO-1 / LIQUIDO-6
Read the order's own pricelist first. Fall back to the client's default (
property_product_pricelist) only if the order doesn't have one yet.
Confirmed twice now — by data (2026-07-13) and directly by Nuno on a call the same day: back office genuinely does switch a customer's pricelist manually on individual sale orders (Carla's Dinolux order used a different list than the client's stored default). This is a real mechanism, not a data error. Correction from the Nuno call: switching between the visible and non-visible ("sem desconto visível") variant of the same discount does NOT change the final price — they're designed to compute identically, just displayed differently. So the switch itself isn't why two prices differed on Carla's order; it just proves order-level overrides are real and must be read first. Still open: the actual criteria for when back office makes this switch — needs José Monteiro.
↓
2
Look for a líquido (fixed) price
✅ LIQUIDO-2 / LIQUIDO-3
Search the resolved pricelist for a product-specific fixed-price rule.
- 2+ quantity tiers on this product? → pick the highest tier ≤ requested quantity
- Found a líquido price? → use it, skip step 3 entirely
↓
3
Fallback — standard % discount
✅ LIQUIDO-2
Only reached if step 2 found nothing. Uses the pricelist's single global rule. Verified: one pricelist has exactly 231 fixed-price rules + 1 global percentage rule — this is Odoo's own rule-matching order, not custom logic we'd have to build.
↓
4
Second discount, market-specific
🔧 DISC-1
- Spain → ad hoc, salesperson-entered. Never computed — just preserved.
- Italy → fixed, per client. No storage exists yet (
aronlight#398). - Portugal / France → unknown. No evidence either way.
↓
5
Known gaps — flag, don't silently trust
❓ LIQUIDO-4 / LIQUIDO-5
- Sales-team ad hoc exceptions — trigger unknown, route to a human
- "Caixa fechada" (box quantity) — the data exists (
product.packaging, 215+ products), but it's not confirmed to affect price on the one product we checked - Pricelist rules may get hand-tuned over time — Carla's case shows a live example
↓
6
Display — show the discount, or hide it?
🔧 needs UI
Per-user default + always-available per-case override. The "sem desconto visível" pattern found this week suggests this may already be half-built at the Odoo level — the platform may just need to surface it, not invent it.
Rules confirmed so far
| ID | Rule | Confidence | Evidence |
|---|---|---|---|
SPAIN-1 | Proposal (Odoo Spain) vs. sale (Odoo Portugal) routing | HIGH | Confirmed by Adriana directly |
LIQUIDO-1 | Every pricelist duplicated across PT + ES companies, same name | HIGH | WhatsApp + Odoo data (40/43 pairs confirmed) |
LIQUIDO-2 | Líquido price always wins over computed discount | HIGH | WhatsApp + Odoo data (231 fixed + 1 global rule) |
LIQUIDO-3 | Volume tiers = líquido prices gated by min_quantity | HIGH | ES + Italy in Odoo; PT confirmed manual-only (Excel) |
LIQUIDO-6 | Back office manually switches pricelist on the sale order | MEDIUM | Confirmed live on Carla's Dinolux case with Nuno |
OD-4 | Tabela vs. Odoo source-of-truth split | HIGH (code) | Read directly in the matching code |
DISC-1 | Second-discount semantics are market-specific | MEDIUM | Spain + Italy confirmed; PT/France open |
LIQUIDO-4 | Ad hoc price-table exceptions — not yet codifiable | LOW | Explicitly "não sei" from Nuno — needs sales team |
LIQUIDO-5 | "Caixa fechada" — data location confirmed, pricing link not | MEDIUM (location) / LOW (link) | Odoo data + independently confirmed uncertain by Nuno too |
Answered on the 2026-07-13 Nuno call
- "Sem desconto visível" is deliberate, standard infrastructure — not ad hoc. It's a real Odoo mechanism (formula rule referencing the visible list, 0% adjustment), and Nuno independently suggested exposing both variants in the AI quoting tool.
- Portugal has zero volume tiers in Odoo — confirmed, 100% manual via an Excel owned by Manuel/José Monteiro.
- Back office does manually switch pricelists per order — confirmed live on Carla's own case. Criteria for when: still unknown.
- New risk surfaced, unprompted by Nuno: Odoo's volume-tier matching doesn't validate that tier prices decrease monotonically with quantity — a real data-entry risk our pricing engine needs to guard against itself.
Still open — needs José Monteiro (commercial director)
Nuno named him directly for all three of these.
- What are the switching criteria for when back office moves a customer between the visible and non-visible pricelist on a specific order?
- Volume-tier + "cache complète" Excel — same table for both? Which countries does each apply to? Is cache-complète ever applied automatically in Odoo?
- What are the known ad hoc pricing exceptions (
LIQUIDO-4)? Nuno pointed to the sales team for this — still the single biggest gap in what's buildable today. - Why is "ITALIA 50+20%" assigned to zero customers? The combined pricelist exists and works — just needs assignment, unless something's blocking it.
- The Spain +25% markup (some ES clients see prices above PT list) — legitimate separate base pricing, or a data error nobody's caught?
- Portugal / France second-discount behavior — do either follow Spain's ad hoc pattern, Italy's fixed pattern, or something else entirely?