Skip to content

National Insurance: split params into Class 1/2/3/4 sub-structs#78

Open
vahid-ahmadi wants to merge 1 commit into
mainfrom
vahid/ni-class-split
Open

National Insurance: split params into Class 1/2/3/4 sub-structs#78
vahid-ahmadi wants to merge 1 commit into
mainfrom
vahid/ni-class-split

Conversation

@vahid-ahmadi

Copy link
Copy Markdown
Contributor

Closes #43

Completes the National Insurance class split. PR #63 already surfaced the per-class outputs (ni_class1_employee, ni_class2, ni_class4, employer_ni) and explicitly deferred restructuring NationalInsuranceParams itself as a follow-up slice of #43 — this PR delivers that restructuring, so all four issue items are now covered.

Changes

  • src/parameters/mod.rs — split the flat NationalInsuranceParams into class-specific sub-structs mirroring the Python gov/hmrc/national_insurance/class_* tree:

    • NiClass1Params — primary (employee) + secondary (employer) thresholds and rates
    • NiClass2Params — flat self-employed rate + small-profits threshold (abolished, zero default)
    • NiClass3Params — voluntary-contribution stub (documented; never charged — no FRS input identifies voluntary contributors)
    • NiClass4Params — lower/upper profit limits + main/additional rates

    The sub-structs are #[serde(flatten)]ed, so the on-disk per-year YAML (all 36 files) and the JSON reform-overlay surface consumed by the Python wrapper keep their historical flat key layout — no parameter files, Python models, or the parameter_impact dotted-path test change.

  • src/variables/income_tax.rs — per-class compute functions (Class 1 employee calculate_ni_class1, Class 1 employer calculate_ni_employer, Class 2, Class 4, and a Class 3 stub) read through the new class-organised API. Employer (secondary) NIC remains a separate employer_ni output; the aggregate employee national_insurance total is unchanged and still equals the sum of the relevant classes.

  • parameters/2025_26.yaml — added the Class 3 standard weekly rate (£17.75) for parity; Class 1/2/4 HMRC 2025/26 values unchanged.

  • LEGISLATIVE_REFERENCE.md — new Class 3 (voluntary) subsection with SSCBA 1992 s.13 citation.

Scope note

Class 3 is a deliberate documented stub: the FRS has no field identifying voluntary contributors, so it always returns zero. The rate parameter is carried so the calculation can be wired up if such data is added.

Tests

Added worked-HMRC-example unit tests for each class (Class 1 employee £2,194.40, Class 1 employer £5,250.00, Class 4 £1,645.80 on £40k) plus a flatten serialization round-trip test asserting the on-disk form stays flat. Pre-existing parameter-reform tests updated to the nested paths. cargo build and cargo test pass — 195 tests, 0 failures across both test binaries (including parameter_impact).

🤖 Generated with Claude Code

Split the flat NI parameter struct into class-specific sub-structs
(NiClass1Params, NiClass2Params, NiClass3Params, NiClass4Params)
mirroring the Python gov/hmrc/national_insurance/class_* tree:

- Class 1: primary (employee) + secondary (employer) thresholds and rates
- Class 2: flat self-employed rate + small-profits threshold (abolished, zero default)
- Class 3: voluntary-contribution stub (documented; never charged, no FRS input)
- Class 4: lower/upper profit limits + main/additional rates

The sub-structs are serde(flatten)ed, so the on-disk per-year YAML and
the JSON reform-overlay surface used by the Python wrapper keep their
historical flat key layout - no parameter files or external consumers
change. The aggregate employee `national_insurance` output and the
separate `employer_ni` output are unchanged.

Per-class compute functions (Class 1 employee/employer, Class 2,
Class 4, Class 3 stub) now read through the class-organised API. Added
worked-HMRC-example unit tests for each class plus a flatten
serialization round-trip test. Added a Class 3 legislative-reference
subsection and a Class 3 standard-rate value in 2025_26.yaml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

National Insurance: split into Class 1 / 2 / 3 / 4 with employee, employer, self-employed detail

1 participant