Where pricing sits in the quote pipeline
Pricing is not the first thing that happens to a request — it's step 3. Everything below assumes the line items are already matched to real SKUs before pricing ever starts.
How Aronlight's price lists are actually structured
Confirmed directly by Nuno, screen-share walkthrough, 2026-07-13 (docs/calls/2026-07-13-nuno-pricing.md). This is the data structure — the algorithm below is how the agent should read it.
LIQUIDO-1). Verified: 40 of 43 unique pricelists confirmed as an exact pair. 3 known exceptions: 2 ES-only custom deals, 1 PT-only list.property_product_pricelist (client) / pricelist_id (order). This field is not a layer in the stack below — it's the pointer that picks ONE specific list out of everything in the row below, for this one quote.LIQUIDO-1): 43 unique pricelists exist (86 records = ×2, one per company). Real names include "Lista PT 48%," "Lista PT 52% + Liquidos," "Lista España 60% + Netos (Jan 2026)," "Lista PT Cliente Contera," and dozens more. The 4 boxes below are the patterns those 43 lists follow — not a count of the choices. Back office can manually assign any of the 43 to a specific order, not just pick a "kind."LIQUIDO-2)LIQUIDO-3)LIQUIDO-6) — any discount-bearing list can exist as two separate assignable records computing the same price, shown differently — see below.This enumeration may not be exhaustive.
LIQUIDO-4 (sales-team ad hoc exceptions) is still unconfirmed — there may be pricing paths outside all of the above that nobody has described to us yet.
sales_price straight off the product record, 0% discount. Can't even be exported the same way as the other three.base_pricelist_id actually points to. ES / FR / Others each carry a catch-all rule: price = €0 if the product isn't listed here. Deliberate — blocks Odoo's native behavior of silently falling back to the Portuguese price on a non-PT quote.Visible vs. non-visible — same math, different display
formula rule referencing the visible list as its base, with 0% additional adjustment — designed to compute the identical price, just displayed without the discount column. Confirmed real: back office manually points a specific sale order at either variant (Carla's Dinolux order used the non-visible one, while the client's stored default is the visible one) — a genuine order-level override, independent of the client record. Still unknown: the criteria for when back office makes this switch. (LIQUIDO-6)
How our system should work
A quote line goes in as (client, SKU, quantity) — SKU and quantity already resolved by matching, upstream. This is the path our agent takes to come out with a final price, framed the way we'd actually build it: a pre-pricing rule, then pricing itself.
LIQUIDO-1 means the entire pricelist stack (all 43 lists) exists once per company. Get this wrong and Step 1 looks up the right list in the wrong company's copy.
- Portugal (the common case) → straightforward, default company, nothing special to decide.
- Spain → NOT automatically "use the Spain company." Depends on what this actually is: a proposal (no sale yet) lives in Odoo Spain — could even end up living entirely outside of Spain's own numbers, structurally, since it's Aronlight España as its own supplier. An actual sale (dropship) lives in Odoo Portugal instead, with Aronlight España as the customer field and the real client only in the delivery address.
- Everything else (Italy, France, etc.) → default company (Portugal) today — no separate entity exists yet for these markets.
property_product_pricelist. This is the single most load-bearing lookup in the whole flow: nothing downstream has anything to search until this resolves, and every price computed after it inherits whatever mistake happens here.
- Blank (new client, never assigned) — don't guess or default silently. Flag for manual assignment.
- Wrong (data entry error, deal changed, nobody updated the record) — the agent has no way to catch this on its own; it will compute a confident, wrong price and never know it's wrong.
LIQUIDO-6). That's a human editing a quote that already exists. When WE create a new proposal, we assign the client's own pricelist onto it — we don't start from an override that doesn't exist yet.
- Base / full price → use the list price as-is, 0% discount.
- Pure discount → base list price × (1 − discount %).
- Mixed / líquido → this is where it gets specific: search the list's own rules for a product-specific fixed (líquido) price for this exact SKU. Found one? Use it, done. Not found? Fall back to that list's own standard % discount.
- Volume tier → same líquido search as Mixed, but check every
min_quantitytier for this SKU and pick the highest one ≤ the requested quantity. No tier matches? Same % fallback.
- 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.
- 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
- Validate volume-tier monotonicity ourselves — Odoo only matches minimum quantity, it does NOT check that a higher tier is actually cheaper than a lower one or the fallback. Confirmed as a real risk by Nuno unprompted, on the 2026-07-13 call. If a tier price is higher than what a smaller order would pay, flag it — don't just apply whatever Odoo returns.
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
Nuno named José Monteiro directly for these 2, on the 2026-07-13 call:
- 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?
Carried over from earlier — likely also need José Monteiro or the sales team, but weren't raised with Nuno by name in this call:
- What are the known ad hoc pricing exceptions (
LIQUIDO-4)? Nuno pointed to the sales team generally for this, in the earlier WhatsApp thread — 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?