Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/1967.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Store the Class 1 secondary threshold from 2025-26 as £5,000 / 52 a week, so employer National Insurance uses the statutory annual £5,000 (SI 2001/1004 reg 11(3A)(b)) rather than 52 x the rounded weekly £96 = £4,992. Employer NI falls by up to £1.20 a year per employee earning above the threshold.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ metadata:
- https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/882271/Table-a4.pdf
- https://www.gov.uk/government/publications/rates-and-allowances-national-insurance-contributions/rates-and-allowances-national-insurance-contributions
unit: currency-GBP
# The model stores the weekly £96 in reg 10(d) and annualises it as 52 weeks
# (£4,992); reg 11(3A)(b) gives £5,000 a year (#1967).
# From 2025-26 the value is the annual £5,000 in SI 2001/1004 reg 11(3A)(b)
# divided by 52 (96.153846 = 5,000 / 52), so that the model's 52-week
# annualisation gives £5,000. This is the convention reg 11(3)(c) and
# 11(2A)(c) use for the primary threshold and upper earnings limit, which the
# model also stores as annual / 52. The rounded weekly figure in reg 10(d) is
# £96, which would annualise to £4,992 (#1967). Before 2025-26 the weekly
# figure times 52 equals the annual one (for example £175 x 52 = £9,100).
# Legal status: SI 2001/1004 reg 10 sets the amounts for 2026-27 only. The
# 2027-28 to 2030-31 values are announced policy (Autumn Budget 2024 and
# Budget 2025), to be set in each year's rates, limits and thresholds
Expand All @@ -30,43 +35,45 @@ values:
value: 175
2024-01-01: 175
2025-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: National Insurance Contributions (Secondary Class 1 Contributions) Act 2025 s.2
href: https://www.legislation.gov.uk/ukpga/2025/11/section/2
- title: The Social Security (Contributions) Regulations 2001 reg 11(3A)(b) (£5,000 where the earnings period is a year)
href: https://www.legislation.gov.uk/uksi/2001/1004/regulation/11
2026-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: The Social Security (Contributions) Regulations 2001 reg 10(d) and reg 11(3A), for 2026-27 (reg 10's tax year set by SI 2026/231 reg 5(2)(a))
href: https://www.legislation.gov.uk/uksi/2001/1004/regulation/11/2026-04-06
- title: SI 2026/231 reg 5
href: https://www.legislation.gov.uk/uksi/2026/231/regulation/5/made
2027-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: "HMRC: Changes to the Class 1 National Insurance Contributions Secondary Threshold, the Secondary Class 1 National Insurance contributions rate, and the Employment Allowance from 6 April 2025 (Autumn Budget 2024)"
href: https://www.gov.uk/government/publications/changes-to-the-class-1-national-insurance-contributions-secondary-threshold-the-secondary-class-1-national-insurance-contributions-rate-and-the-empl/changes-to-the-class-1-national-insurance-contributions-secondary-threshold-the-secondary-class-1-national-insurance-contributions-rate-and-the-empl
2028-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: Budget 2025 (HC 1492) para 4.112
href: https://assets.publishing.service.gov.uk/media/6929b353345e31ab14ecf735/E03444720_Budget_2025_Web_Accessible.pdf#page=113
- title: Explanatory Memorandum to SI 2026/231 para 5.26
href: https://www.legislation.gov.uk/uksi/2026/231/pdfs/uksiem_20260231_en_001.pdf
2029-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: Budget 2025 (HC 1492) para 4.112
href: https://assets.publishing.service.gov.uk/media/6929b353345e31ab14ecf735/E03444720_Budget_2025_Web_Accessible.pdf#page=113
- title: Explanatory Memorandum to SI 2026/231 para 5.26
href: https://www.legislation.gov.uk/uksi/2026/231/pdfs/uksiem_20260231_en_001.pdf
2030-04-06:
value: 96
value: 96.153846
metadata:
reference:
- title: Budget 2025 (HC 1492) para 4.112
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
# SSCBA 1992 s.6(3) ends primary Class 1 at pensionable age "without prejudice
# to any liability to pay secondary Class 1 contributions". Secondary
# contributions are due on earners over 16 (s.6(1)(b)) with no upper age.
# The model annualises the weekly secondary threshold as 52 weeks: 2026-27 is
# £96 x 52 = £4,992 at 15%; 2024-25 is £175 x 52 = £9,100 at 13.8%.
# The annual secondary threshold is £5,000 at 15% in 2026-27 (SI 2001/1004
# reg 11(3A)(b)) and £175 x 52 = £9,100 at 13.8% in 2024-25.

- name: Employer NI is charged on an employee aged 70 (2026)
period: 2026
Expand All @@ -28,11 +28,11 @@
employment_income: 40_000
output:
ni_class_1_employee: 0
ni_class_1_employer: 5_251.20 # 0.15 x (40,000 - 4,992)
ni_employer: 5_251.20
ni_class_1_employer: 5_250.00 # 0.15 x (40,000 - 5,000)
ni_employer: 5_250.00
national_insurance: 0
total_national_insurance: 5_251.20
employer_cost: 45_251.20
total_national_insurance: 5_250.00
employer_cost: 45_250.00

- name: Employer NI is charged on an employee aged 70 (2024)
period: 2024
Expand All @@ -52,7 +52,7 @@
employment_income: 60_000
output:
ni_class_1_employee: 0
ni_class_1_employer: 8_251.20 # 0.15 x (60,000 - 4,992)
ni_class_1_employer: 8_250.00 # 0.15 x (60,000 - 5,000)

- name: Earnings below the secondary threshold over state pension age
period: 2026
Expand All @@ -77,7 +77,7 @@
ni_liable: true
ni_class_1_secondary_liable: true
ni_class_1_employee: 2_194.40 # 0.08 x (40,000 - 12,570)
ni_class_1_employer: 5_251.20
ni_class_1_employer: 5_250.00

- name: At state pension age, only the employer side is charged
period: 2026
Expand All @@ -90,7 +90,7 @@
ni_liable: false
ni_class_1_secondary_liable: true
ni_class_1_employee: 0
ni_class_1_employer: 5_251.20
ni_class_1_employer: 5_250.00

- name: No employer NI on an earner under 16
period: 2026
Expand All @@ -101,3 +101,42 @@
output:
ni_class_1_employee: 0
ni_class_1_employer: 0

# SI 2001/1004 reg 11(3A)(b): the annual secondary threshold is £5,000 from
# 2025-26, not 52 x the rounded weekly £96 = £4,992 (#1967).

- name: No employer NI on annual earnings of exactly £5,000 (2025-26)
period: 2025
absolute_error_margin: 0.01
input:
age: 40
ni_class_1_income: 5_000
output:
ni_class_1_employer: 0

- name: Employer NI on annual earnings of £4,992 to £5,000 is nil (2026-27)
period: 2026
absolute_error_margin: 0.01
input:
age: 40
ni_class_1_income: 4_996
output:
ni_class_1_employer: 0

- name: Employer NI starts above £5,000 a year (2026-27)
period: 2026
absolute_error_margin: 0.01
input:
age: 40
ni_class_1_income: 6_000
output:
ni_class_1_employer: 150 # 0.15 x (6,000 - 5,000)

- name: Employer NI on £40,000 in 2025-26 uses the £5,000 annual threshold
period: 2025
absolute_error_margin: 0.01
input:
age: 40
ni_class_1_income: 40_000
output:
ni_class_1_employer: 5_250 # 0.15 x (40,000 - 5,000)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# UPL £50,270, ST £5,000 (£96 a week). 2027-28 was already frozen by
# Autumn Statement 2022 (PT, UEL, LPL, UPL) and Autumn Budget 2024 (ST).
# Rates: Class 1 8% / 2%, employer 15%, Class 4 6% / 2%.
# The model annualises the weekly ST as 52 x £96 = £4,992.
# The model stores the ST as 5,000 / 52 a week (reg 11(3A)), so 52 weeks give
# £5,000 (#1967).

- name: 2027-28 employee Class 1 at the primary threshold
period: 2027
Expand All @@ -22,7 +23,7 @@
employment_income: 30_000
output:
ni_class_1_employee: (30_000 - 12_570) * 0.08 # 1,394.40
ni_class_1_employer: (30_000 - 4_992) * 0.15 # 3,751.20
ni_class_1_employer: (30_000 - 5_000) * 0.15 # 3,750.00

- name: 2027-28 employee Class 1 above the UEL
period: 2027
Expand All @@ -33,7 +34,7 @@
output:
ni_class_1_employee_primary: (50_270 - 12_570) * 0.08 # 3,016
ni_class_1_employee_additional: (60_000 - 50_270) * 0.02 # 194.60
ni_class_1_employer: (60_000 - 4_992) * 0.15 # 8,251.20
ni_class_1_employer: (60_000 - 5_000) * 0.15 # 8,250.00

- name: 2027-28 Class 4 at the lower profits limit
period: 2027
Expand Down Expand Up @@ -79,7 +80,7 @@
employment_income: 30_000
output:
ni_class_1_employee: (30_000 - 12_570) * 0.08 # 1,394.40
ni_class_1_employer: (30_000 - 4_992) * 0.15 # 3,751.20
ni_class_1_employer: (30_000 - 5_000) * 0.15 # 3,750.00

- name: 2030-31 employee Class 1 above the UEL
period: 2030
Expand All @@ -90,7 +91,7 @@
output:
ni_class_1_employee_primary: (50_270 - 12_570) * 0.08 # 3,016
ni_class_1_employee_additional: (60_000 - 50_270) * 0.02 # 194.60
ni_class_1_employer: (60_000 - 4_992) * 0.15 # 8,251.20
ni_class_1_employer: (60_000 - 5_000) * 0.15 # 8,250.00

- name: 2030-31 Class 4 at the lower profits limit
period: 2030
Expand Down
26 changes: 11 additions & 15 deletions policyengine_uk/tests/test_ni_threshold_freeze.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
Earnings Limit is not frozen: it rose with CPI to £129 a week in 2026-27.

Model year Y is the fiscal year starting 6 April Y. The model stores PT and UEL
as the annual amounts over 52 (12,570 / 52 and 50,270 / 52, as SI 2001/1004
reg 11(3)(c) and 11(2A)(c) do for periods of whole weeks) and ST as the reg
10(d) weekly amount (£96), and annualises weekly thresholds as 52 weeks. So the
model's annual ST is £4,992, where reg 11(3A)(b) gives £5,000 (#1967); the
statute table follows the model here, and a strict xfail marks the gap.
and ST as the annual amounts over 52 (12,570 / 52, 50,270 / 52 and 5,000 / 52,
as SI 2001/1004 reg 11(3)(c), 11(2A)(c) and 11(3A)(c) do for periods of whole
weeks), and annualises weekly thresholds as 52 weeks. So the model's annual ST
is the £5,000 in reg 11(3A)(b), not 52 x the rounded reg 10(d) weekly £96
(£4,992) (#1967).

Invariants:

Expand Down Expand Up @@ -59,8 +59,7 @@
STATUTORY_2026_27 = {
"lower_earnings_limit": Fraction(129), # weekly, CPI-uprated
"primary_threshold": Fraction(12_570, 52), # annual / 52
# reg 10(d) weekly, as the model stores it; see #1967 for the annual £5,000.
"secondary_threshold": Fraction(96),
"secondary_threshold": Fraction(5_000, 52), # annual / 52 (#1967)
"upper_earnings_limit": Fraction(50_270, 52), # annual / 52
"lower_profits_limit": Fraction(12_570), # annual
"upper_profits_limit": Fraction(50_270), # annual
Expand Down Expand Up @@ -129,15 +128,12 @@ def test_lower_earnings_limit_2025_26_and_2026_27(system):
assert threshold(system, "lower_earnings_limit", 2026) == 129


@pytest.mark.xfail(
strict=True,
reason="#1967: the model annualises the weekly ST as 52 x £96 = £4,992; "
"SI 2001/1004 reg 11(3A)(b) gives £5,000 a year.",
)
@pytest.mark.parametrize("year", FROZEN_YEARS)
@pytest.mark.parametrize("year", [2025, *FROZEN_YEARS])
def test_annual_secondary_threshold_is_statutory(system, year):
# SI 2001/1004 reg 11(3A)(b): £5,000 where the earnings period is a year
# (#1967). 52 x the rounded weekly £96 would give £4,992.
annual = 52 * threshold(system, "secondary_threshold", year)
assert annual == pytest.approx(5_000, abs=0.5)
assert annual == pytest.approx(5_000, abs=0.01)


# Invariant 2: cash freeze.
Expand Down Expand Up @@ -328,7 +324,7 @@ def check_liabilities(earnings, profits, years):
# Every threshold, a penny and a pound either side, plus seeded random levels.
EDGES = [
edge + offset
for edge in [4_992, 12_570, 50_270]
for edge in [4_992, 5_000, 12_570, 50_270]
for offset in (-1, -0.01, 0, 0.01, 1)
]

Expand Down
Loading