Skip to content

sdc-sdapp-w1-setup-taxation

Roadmap: apps/sd-app/ROADMAP.md → W1 · ADR: apps/sd-app/docs/adr/0001-taxation-parameter-model.md Parent planning thread: sdc-sdapp-full-levpro-port

LevPro’s Setup dialog let the advisor edit the full tax environment. sd-app exposes none of it — packages/sd-api/profiles.py hardcodes two RegionProfiles (ON, us-federal) and there is no user-editable tax parameter anywhere in the app. This is the largest remaining functional gap in the LevPro port.

The math model is not the blocker: sd_math.models.inputs.RegionProfile and TaxProfile already carry every field the Setup dialog edits, ported verbatim from modTypes.bas. This is a UI + API-surface job.

  • Parity target: D:\FSS\Software\Archive\Leverage Pro\Latest Release\frmProgramSetup.frm (1,705 lines), tabs Taxes and Investment Expenses.
  • Decision D1 (Talbot, 2026-08-31): curated per-province profiles plus an Advanced override panel — parity on capability, F.A.S.T. on default. See ADR-0001.
  • Acceptance gate: every input control on those two tabs is either mapped to a named RegionProfile/TaxProfile field, or listed in ADR-0001 as deliberately unmapped with a reason. A checkable list, not a visual comparison.
  • Risks escalation before production. SDC/IT/JOB_DESCRIPTION.md routes anything that changes what a mini-app claims about financial outcomes through SDC/Risks. Advisor-editable tax rates driving a client-facing projection are inside that rule — build and test freely, but shipping needs a Risks review. Recorded in ADR-0001 so it isn’t discovered at deploy.
  • Overridden values must appear in the generated PDF’s assumptions block (parity — Sample Printout.pdf already prints tax rate and deductibility percentage).
  • Do not write packages/i18n/messages/*.json directly while parallel workstreams are running — return the key/value pairs (EN + FR) for the orchestrator to merge. See ROADMAP “Working agreements”.
  • Inventory every Taxes / Investment Expenses control in frmProgramSetup.frm against RegionProfile / TaxProfile; record unmapped controls in ADR-0001.
  • Expose the parameter set through sd-api (profile selection + override payload).
  • Build the Setup surface in sd-app: curated default visible, full set behind See all, per Core/Processes/Design/Targets/Design-Apps.md.
  • Tests: overrides reach sd-math and change results; defaults unchanged when nothing is overridden.
  • Full green bar — sd-math + sd-api + sd-app vitest, pnpm check, pnpm build.

Shipped (monorepo 6dc9549). Control inventory in ADR-0001: 20 of 26 controls mapped, 6 unmapped with recorded reasons (the 4-bracket tax table only seeds a reference display and never reaches the math engine — traced through VB6 source; the two Investment Expenses fields are backed by VB6 fields commented “currently not in use”). Curated profiles + Advanced override panel live; wired into int-only and term-loan.

Finding: the override→math wiring already existed — POST /api/v1 with profile_id: 'custom' already accepts a full RegionProfile/TaxProfile and reaches sd-math. No new analyze endpoint or math change was needed.

Open, carried forward: shipping the Advanced override to production needs an SDC/Risks review (advisor-editable tax rates drive client-facing projections — SDC/IT/JOB_DESCRIPTION.md escalation rule, recorded in ADR-0001).