Skip to content

Commit 922ef2b

Browse files
authored
Merge pull request #1768 from PolicyEngine/codex/fix-class4-maximum-steps-20260606
Fix remaining Class 4 NI annual maximum steps
2 parents a77e4b4 + e3d70ee commit 922ef2b

4 files changed

Lines changed: 34 additions & 9 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Apply the Class 4 National Insurance annual maximum's Step Six and Step Nine calculations from Regulation 100.

policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance/class_4/ni_class_4_maximum.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
self_employment_income: 100_000
66
employment_income: 100_000
77
output:
8-
ni_class_4_maximum: 48_661
8+
ni_class_4_maximum: 3_083.22

policyengine_uk/tests/test_ni_class_4_maximum.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from policyengine_uk import Simulation
44

55

6-
def test_class_4_annual_maximum_uses_current_main_rate_factor():
6+
def test_class_4_annual_maximum_applies_case_3_steps():
77
year = 2026
88
monthly_primary_class_1 = {f"{year}-{month:02d}": 500 for month in range(1, 13)}
99
sim = Simulation(
@@ -21,6 +21,29 @@ def test_class_4_annual_maximum_uses_current_main_rate_factor():
2121
)
2222

2323
assert sim.calculate("ni_class_4_maximum", year)[0] == pytest.approx(
24-
46_484,
24+
1_748.60,
2525
abs=0.01,
2626
)
27+
assert sim.calculate("ni_class_4", year)[0] == pytest.approx(1_748.60, abs=0.01)
28+
29+
30+
def test_class_4_annual_maximum_does_not_bind_without_class_1():
31+
year = 2026
32+
sim = Simulation(
33+
situation={
34+
"people": {
35+
"person": {
36+
"age": {year: 40},
37+
"self_employment_income": {year: 60_000},
38+
}
39+
},
40+
"benunits": {"benunit": {"members": ["person"]}},
41+
"households": {"household": {"members": ["person"]}},
42+
}
43+
)
44+
45+
assert sim.calculate("ni_class_4_maximum", year)[0] == pytest.approx(
46+
2_456.60,
47+
abs=0.01,
48+
)
49+
assert sim.calculate("ni_class_4", year)[0] == pytest.approx(2_456.60, abs=0.01)

policyengine_uk/variables/gov/hmrc/national_insurance/class_4/ni_class_4_maximum.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,23 @@ def formula(person, period, parameters):
2020
step_3 = step_2 + 53 * ni.class_2.flat_rate
2121
class_2_contributions = person("ni_class_2", period)
2222
primary_class_1_contributions = person("ni_class_1_employee_primary", period)
23-
step_4 = step_3 - class_2_contributions - primary_class_1_contributions
23+
step_4_raw = step_3 - class_2_contributions - primary_class_1_contributions
24+
step_4 = max_(step_4_raw, 0)
2425
class_4_main_contributions = person("ni_class_4_main", period)
2526
other_aggregate_contributions = (
2627
primary_class_1_contributions
2728
+ class_2_contributions
2829
+ class_4_main_contributions
2930
)
30-
case_1 = (step_4 >= 0) & (step_4 > other_aggregate_contributions)
31-
case_2 = (step_4 >= 0) & (step_4 <= other_aggregate_contributions)
32-
case_3 = step_4 < 0
31+
case_1 = (step_4_raw >= 0) & (step_4_raw > other_aggregate_contributions)
32+
case_2 = (step_4_raw >= 0) & (step_4_raw <= other_aggregate_contributions)
33+
case_3 = step_4_raw < 0
3334
step_5 = step_4 / main_rate
3435
profits = person("self_employment_income", period)
35-
step_6 = lpl - min_(upl, profits)
36+
step_6 = min_(upl, profits) - lpl
3637
step_7 = max_(0, step_6 - step_5)
3738
step_8 = step_7 * add_rate
38-
step_9 = max_(0, profits - upl)
39+
step_9 = max_(0, profits - upl) * add_rate
3940

4041
return select(
4142
[

0 commit comments

Comments
 (0)