1.9 KiB
1.9 KiB
F-080 — Implementer evidence
What was implemented
Made the PVP (IVA incl.) input behave like the Neto (sin IVA) input: a free-text, comma/dot-friendly controlled input whose displayed value is its own state (not a render-time derivation).
Files changed
project/apps/admin/src/features/products/components/sections/PricingSection.tsx- Added
grossstate (Record<string, string>) mirroringnet. - On price load, populates
grossfrom the persisted net + current IVA rate. - PVP
<input>:type="text" inputMode="decimal"(wastype="number"),value={gross[v.id] ?? ''},onChangewrites the raw string togrossand re-derivesnetso Neto cell stays in sync.
- Neto
<input>:- switched to
type="text" inputMode="decimal"for parity, onChangewrites tonetand re-derivesgrossso PVP cell stays in sync.
- switched to
- IVA
<select>onChangerecomputesgrossfromnetusing the new rate. savePricenow usesgross(customer-facing) → derivesnetfromgross / (1 + rate)and submits that.- Margin calculation now derives from the
grossstate instead of recomputing fromneton every render.
- Added
Validation
npx tsc --noEmit→ exit 0npx eslinton changed file → exit 0- Vitest unchanged (UI-only change).
Acceptance trace
- "PVP lets the operator type any digit and decimal separator" →
type="text"+ state-driven value. - "Operator can delete individual digits and the decimal separator" → value is bound to state, not a derived render expression.
- "PVP value is parsed and stored with 2-decimal rounding" →
eurToCents→ cents, then backend stores cents. - "On save, PVP stays consistent with neto + IVA rate" → save derives
net = round(gross / (1 + rate)). - "Behavior matches Neto" → identical input component and parsing rules.
- "verify.sh is green" → typecheck + lint clean.