{ "feature_id": "F-080", "verdict": "APPROVED", "trace": [ { "acceptance": "PVP input lets the operator type any digit and decimal separator (\",\" or \".\")", "result": "PASS", "evidence": "type=text inputMode=decimal; value bound to gross state; eurToCents handles both separators." }, { "acceptance": "Operator can delete individual digits and the decimal separator inside the value", "result": "PASS", "evidence": "Value is the user's raw string; no render-time derivation overwrites it." }, { "acceptance": "PVP value is parsed and stored as a real number with 2-decimal rounding", "result": "PASS", "evidence": "eurToCents() -> Math.round(*100) -> backend stores cents." }, { "acceptance": "On blur/save, PVP stays consistent with neto + IVA rate", "result": "PASS", "evidence": "savePrice derives net = round(gross / (1 + rate/100))." }, { "acceptance": "Behavior matches the Neto (sin IVA) input UX", "result": "PASS", "evidence": "Both use the same component, same parsing, same controlled-state pattern." }, { "acceptance": "verify.sh is green", "result": "PASS", "evidence": "tsc --noEmit exit 0, eslint exit 0." } ], "regression_checks": [ "IVA select still updates tax rate", "Save still posts to pricingApi.setVariantPrice", "Margin percentage still renders", "Coste / Oferta inputs still work" ], "verdict_reason": "All acceptance criteria trace to PASS.", "reviewer": "qa", "reviewed_at": "2026-08-20T04:02:00Z", "agent": "qa" }