SRV-12 — Pricing engine
Three selling prices per variant (super-gros, demi-gros, détail) chosen by the reseller's customer type, VAT, price history; prices withheld from guests; promotions applied on top by the cart engine.
| Field | Details |
|---|---|
| Task code | SRV-12 |
| Phase | P1 — V1 build & integration |
| Product scope | V1 |
| Status | Done (Sun 18 Oct 2026) |
| Start | Sun 18 Oct 2026 |
| Due | Sun 18 Oct 2026 |
| Responsible | Anis — Full-stack developer |
| Co-responsible | — |
| Effort | 0.5 person-day(s) planned · 4 from scratch · size XS |
| Area · app | Server · server |
| Depends on | SRV-11 |
| Unblocks | SRV-15, DSH-04 |
| Milestones | — |
Summary
Three selling prices per variant (super-gros, demi-gros, détail) chosen by the reseller's customer type, VAT, price history; prices withheld from guests; promotions applied on top by the cart engine.
Description
The 17 Oct decision replaces segment price lists with three selling prices per variant, one per customer type (PRC-01, PRC-02, PRC-04, PRC-05; cahier §4.3, §4.7, §8): priceSuperGros, priceDemiGros, priceDetail in integer centimes HT, plus vatRate (default 19 %), recommendedPrice and the restricted purchasePrice. This task implements the price resolver used by catalog, cart, orders and assisted orders — the reseller's Reseller.customerType selects the base price, promotions are applied on top by the cart engine (SRV-19 hook), guests get null — the HT/VAT/TTC computation and rounding rules for lines and documents, the PriceChange history for every price edit with admin.variants.priceHistory, margin computation for authorised staff, and cache invalidation when a price or a reseller's customer type changes. Per-reseller agreements and level prices stay V2 (PRC-03); quantity tiers are dropped. Out of scope: promotion rules (SRV-19) and the pricing UI (DSH-04).
Subtasks
| # | Subtask | Owner |
|---|---|---|
| 1 | resolveBasePrice(variant, viewer): customerType → priceSuperGros / priceDemiGros / priceDetail; null for guests; pending accounts per catalog.visibleBeforeValidation | Anis |
| 2 | Tax computation: line HT = unit × qty, VAT per line rounded to the centime, TTC; documented rounding rule shared with PDFs | Anis |
| 3 | Price display rule (TTC vs HT, decision from PRJ-03) as a setting applied in response shaping | Anis |
| 4 | Price edits on variants with validation (positive integers, warning when super-gros > demi-gros > détail order is broken) and PriceChange rows (price type, old, new, actor, reason) | Anis |
| 5 | admin.variants.priceHistory and margin fields (price − purchasePrice) gated by pricing.administer | Anis |
| 6 | Promotion hook interface (applyPromotions(lines, viewer)) consumed by the cart engine | Anis |
| 7 | Cache invalidation on price change and on customerType change (catalog caches per customer type, carts re-priced on next read) | Anis |
| 8 | Bulk price update path reused by the product import (SRV-27) | Anis |
Deliverables
- apps/server/src/modules/pricing/{resolver.ts,tax.ts,price-history.service.ts,router.ts}
- packages/shared/src/money.ts (centimes arithmetic, VAT, formatting 1 250,00 DA)
- Pricing rules section in /docs/srs/business-rules updated with the rounding rule
Acceptance criteria
- A SUPER_GROS, a DEMI_GROS and a DETAIL reseller each see their own price for the same variant, and never another type's price (PRC-02, PRC-05)
- A guest sees price null on every catalog and promotion read (AUTH-10)
- Every price edit creates one PriceChange row per changed price with actor and timestamp (PRC-01, AUD-02)
- Order and invoice totals equal the sum of rounded line totals: HT + VAT = TTC to the centime (PRC-04)
- Changing a reseller's customerType in the back-office re-prices their cart on the next cart.get
Requirements covered
| Requirement | Title | Release |
|---|---|---|
| PRC-01 | Three selling prices per variant — super-gros, demi-gros, détail — plus purchase price and recommended retail price, with change history | V1 |
| PRC-02 | Price resolution: the reseller's customer type selects one of the three prices; then promotions; guests see no price | V1 |
| PRC-04 | Taxes: VAT rate per product, HT/VAT/TTC totals on documents | V1 |
| PRC-05 | Prices and stock re-validated at cart and at checkout; the reseller only ever sees their own price | V1 |
Screens
| Screen | Name | App |
|---|---|---|
| BO-31 | Price grid — three customer-type prices (bulk edit) | BO |
API surface
| Endpoint group | Operations |
|---|---|
| Catalog & pricing | 19 |
Test measures
- Unit tests for resolver and tax rounding with edge cases (1 centime lines, 0 % VAT)
- Property test: sum of line TTC equals document TTC
- DB test for PriceChange writes on concurrent edits
Risks
- HOCO decides TTC display late — the display rule is a setting and amounts are always stored HT with VAT, so only presentation changes
KPI
- Delivered by Sun 18 Oct 2026 within 0.5 person-day(s).
- Every acceptance criterion above demonstrated before hand-off; linked requirements' acceptance criteria pass.
- Zero open critical defects, permission gaps or data-integrity regressions at sign-off.
Generated from content/plan/tasks.json by scripts/generate-team-tasks.mjs. Dates are computed by the scheduler (Sunday–Thursday weeks, holidays excluded) — change the plan, not this page.
SRV-11 — Catalog module
Brands, category tree with sub-categories, products, variants, images, specs, per-category filterable attributes, statuses (incl. automatic out-of-stock), visibility, guest-safe search with combinable filters, facets with counts and barcode lookup.
SRV-13 — Inventory module
Warehouses, stock levels, reservations and deductions by order status, automatic restock on cancellation and on return reception, movement ledger, thresholds and alerts, inventory sessions. Resellers only ever see availability.