Skip to content
Draft
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/hb-special-disregard.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added the Housing Benefit special standard earnings disregard with regime-specific qualifying routes, explicit residual pre-assessment and no stacking with ordinary amounts.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
description: Weekly Housing Benefit special standard earnings disregard, replacing the ordinary single or couple amount.
values:
2015-04-01: 20
metadata:
period: week
unit: currency-GBP
label: Housing Benefit special earnings disregard
reference:
- title: GB working-age earnings disregards, paragraphs 3 and 5 to 9
href: https://www.legislation.gov.uk/uksi/2006/213/schedule/4
- title: GB pension-age earnings disregards, paragraphs 1 to 7
href: https://www.legislation.gov.uk/uksi/2006/214/schedule/4
- title: NI working-age earnings disregards
href: https://www.legislation.gov.uk/nisr/2006/405/schedule/5
- title: NI pension-age earnings disregards
href: https://www.legislation.gov.uk/nisr/2006/406/schedule/5
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@
# One member must work 30 hours; hours are not added across the couple.
housing_benefit_applicable_income_disregard: 520 # £10 × 52

- name: Disabled single person working 20 hours gets £5 plus the additional disregard (model limitation; the law gives £20 plus it)
- name: Disabled single person working 20 hours gets £20 plus the additional disregard
period: 2026
absolute_error_margin: 0.01
input:
Expand All @@ -448,15 +448,13 @@
# Para 17(2)(b)(iv)(aa): a single claimant with the disability premium
# working 16 hours or more meets the condition.
meets_housing_benefit_additional_earnings_disregard_conditions: true
# KNOWN LIMITATION: the law gives £1,929.20. Intended model limitation.
# In law the same disability premium brings in
# the £20 disregard in place of £5: Sch 4 para 3(2), "This paragraph
# applies where the claimant's applicable amount includes an amount by
# way of the disability premium". The law gives (£20 + £17.10) × 52 =
# £1,929.20 (£8,000 ≥ £1,040 + £889.20). The £20 disregards are out of
# scope for this change and tracked as a follow-up; until then the model
# gives (£5 + £17.10) × 52.
housing_benefit_applicable_income_disregard: 1_149.20
# The disability premium gives the £20 standard disregard under Sch 4
# para 3(2), replacing £5. Net earnings cover that amount and the
# additional disregard: £8,000 ≥ £1,040 + £889.20.
# (£20 + £17.10) × 52 = £1,929.20.
# https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/3
# https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/17
housing_benefit_applicable_income_disregard: 1_929.20

- name: Working-age claimant on Income Support has all earnings disregarded
period: 2026
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Cases: working disability/severe; working carer-only; pension carer;
# pension generic disability premium; pension/working DLA; non-dependant DLA;
# pension/working blindness.
- name: ENGLAND statutory regime distinguishes automatic qualifying routes
period: 2024
input:
country: [ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND, ENGLAND]
housing_benefit_pension_age_regulations_apply: [false, false, false, true, true, true, false, true, true, false]
disability_premium: [100, 0, 0, 0, 100, 0, 0, 0, 0, 0]
severe_disability_premium: [0, 100, 0, 0, 0, 0, 0, 0, 0, 0]
carer_premium: [0, 0, 100, 100, 0, 0, 0, 0, 0, 0]
dla_sc: [0, 0, 0, 0, 0, 100, 100, 100, 0, 0]
dla_m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pip_dl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pip_m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
attendance_allowance: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
armed_forces_independence_payment: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
is_blind: [false, false, false, false, false, false, false, false, true, true]
is_claimant_or_partner: [true, true, true, true, true, true, true, false, true, true]
housing_benefit_net_earnings: [5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000]
is_lone_parent: [false, false, false, false, false, false, false, false, false, false]
is_couple: [false, false, false, false, false, false, false, false, false, false]
output:
housing_benefit_special_earnings_disregard_eligible: [true, true, false, true, false, true, false, false, true, false]
housing_benefit_special_earnings_disregard: [1040, 1040, 260, 1040, 260, 1040, 260, 260, 1040, 260]

# Cases: working disability/severe; working carer-only; pension carer;
# pension generic disability premium; pension/working DLA; non-dependant DLA;
# pension/working blindness.
- name: NORTHERN_IRELAND statutory regime distinguishes automatic qualifying routes
period: 2024
input:
country: [NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND, NORTHERN_IRELAND]
housing_benefit_pension_age_regulations_apply: [false, false, false, true, true, true, false, true, true, false]
disability_premium: [100, 0, 0, 0, 100, 0, 0, 0, 0, 0]
severe_disability_premium: [0, 100, 0, 0, 0, 0, 0, 0, 0, 0]
carer_premium: [0, 0, 100, 100, 0, 0, 0, 0, 0, 0]
dla_sc: [0, 0, 0, 0, 0, 100, 100, 100, 0, 0]
dla_m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pip_dl: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
pip_m: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
attendance_allowance: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
armed_forces_independence_payment: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
is_blind: [false, false, false, false, false, false, false, false, true, true]
is_claimant_or_partner: [true, true, true, true, true, true, true, false, true, true]
housing_benefit_net_earnings: [5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000]
is_lone_parent: [false, false, false, false, false, false, false, false, false, false]
is_couple: [false, false, false, false, false, false, false, false, false, false]
output:
housing_benefit_special_earnings_disregard_eligible: [true, true, false, true, false, true, false, false, true, false]
housing_benefit_special_earnings_disregard: [1040, 1040, 260, 1040, 260, 1040, 260, 260, 1040, 260]

- name: Standard replacement, lone-parent precedence and earnings cap
period: 2024
input:
housing_benefit_special_earnings_disregard_eligible: [true, true, true, true, false, false]
housing_benefit_net_earnings: [5000, 5000, 5000, 500, 5000, 5000]
is_couple: [false, true, false, true, false, true]
is_lone_parent: [false, false, true, false, false, false]
housing_benefit_specified_or_temporary_accommodation_disregard: [0, 0, 0, 0, 0, 0]
housing_benefit_applicable_income_childcare_element: [0, 0, 0, 0, 0, 0]
meets_housing_benefit_additional_earnings_disregard_conditions: [false, false, false, false, false, false]
housing_benefit_on_passporting_benefit: [false, false, false, false, false, false]
output:
housing_benefit_applicable_income_disregard: [1040, 1040, 1300, 500, 260, 520]

- name: Special standard amount participates in additional-disregard threshold
period: 2024
absolute_error_margin: 0.01
input:
housing_benefit_special_earnings_disregard_eligible: [true, true, true]
housing_benefit_net_earnings: [1929.19, 1929.20, 5000]
is_couple: [false, true, false]
is_lone_parent: [false, false, false]
housing_benefit_specified_or_temporary_accommodation_disregard: [0, 0, 0]
housing_benefit_applicable_income_childcare_element: [0, 0, 0]
meets_housing_benefit_additional_earnings_disregard_conditions: [true, true, true]
housing_benefit_on_passporting_benefit: [false, false, true]
output:
housing_benefit_applicable_income_disregard: [1040, 1929.20, 5000]

- name: A zero special-amount reform is not replaced with the ordinary amount
period: 2024
input:
gov.dwp.housing_benefit.means_test.income_disregard.special: 0
housing_benefit_special_earnings_disregard_eligible: true
housing_benefit_net_earnings: 5000
is_lone_parent: false
is_couple: true
output:
housing_benefit_special_earnings_disregard: 0

- name: Missing residual qualification preserves ordinary treatment
period: 2024
input:
disability_premium: 0
severe_disability_premium: 0
housing_benefit_pension_age_regulations_apply: false
housing_benefit_net_earnings: 5000
is_lone_parent: false
is_couple: false
output:
housing_benefit_special_earnings_disregard_eligible: false
housing_benefit_special_earnings_disregard: 260
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ class housing_benefit_applicable_income_disregard(Variable):
"(housing_benefit_on_passporting_benefit) has all earnings "
"disregarded, at any age: the working-age Regulations then apply "
"(SI 2006/213 reg 5(1)(b)). The "
"£20 disregards for disabled people, carers and some part-time "
"occupations are not modelled, nor is the working-age permitted work "
"£20 standard disregard uses established qualifying routes or an "
"explicit full-amount pre-assessment, without reconstructing partial "
"carer/occupation earnings allocations. The permitted-work "
"disregard (Sch 4 para 10A), which replaces paras 3 to 10 but not "
"para 18."
"para 18, is not yet modelled here."
)
definition_period = YEAR
unit = GBP
Expand All @@ -42,12 +43,7 @@ def formula(benunit, period, parameters):
p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard
net_earnings = benunit("housing_benefit_net_earnings", period)
# Working age Sch 4 paras 4, 7 and 10; pension age Sch 4 paras 2 and 7.
weekly_amount = select(
[benunit("is_lone_parent", period), benunit("is_couple", period)],
[p.lone_parent, p.couple],
default=p.single,
)
standard = min_(weekly_amount * WEEKS_IN_YEAR, net_earnings)
standard = benunit("housing_benefit_special_earnings_disregard", period)
# Working age Sch 4 para 18 (NI Sch 5 para 18), from 5 October 2026:
# specified or temporary accommodation. It applies alongside paras 3
# to 10A, none of which excludes it, and takes the earnings they
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from policyengine_uk.model_api import *


class housing_benefit_special_earnings_disregard(Variable):
value_type = float
entity = BenUnit
definition_period = YEAR
unit = GBP
label = "Housing Benefit selected standard earnings disregard"
documentation = (
"Standard disregard selected before the additional/accommodation "
"amounts: lone-parent precedence, otherwise the special amount for "
"a qualifying family, otherwise the ordinary couple/single amount. "
"It is a replacement, not £20 added to £5 or £10. The total standard "
"deduction is capped at the claimant's and partner's net earnings."
)
reference = (
"https://www.legislation.gov.uk/uksi/2006/213/schedule/4",
"https://www.legislation.gov.uk/uksi/2006/214/schedule/4",
"https://www.legislation.gov.uk/nisr/2006/405/schedule/5",
"https://www.legislation.gov.uk/nisr/2006/406/schedule/5",
)

def formula(benunit, period, parameters):
p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard
weekly = select(
[
benunit("is_lone_parent", period),
benunit("housing_benefit_special_earnings_disregard_eligible", period),
benunit("is_couple", period),
],
[p.lone_parent, p.special, p.couple],
default=p.single,
)
return min_(
weekly * WEEKS_IN_YEAR, benunit("housing_benefit_net_earnings", period)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from policyengine_uk.model_api import *


class housing_benefit_special_earnings_disregard_eligible(Variable):
value_type = bool
entity = BenUnit
definition_period = YEAR
default_value = False
label = "Qualifies for the full Housing Benefit special earnings disregard"
documentation = (
"Whether the full special standard amount may legally be deducted "
"from the benefit unit's combined earnings, subject to the earnings "
"cap. Derived for working-age disability/severe-premium routes and "
"pension-age qualifying benefit receipt, blindness or carer premium. "
"Other full-amount routes may be pre-assessed as an input, including "
"the applicable job/partner earnings allocation: mere occupation or "
"carer status is not sufficient. Partial carer/occupation allocations "
"below the full amount are not reconstructed by this Boolean. Existing "
"premium/benefit qualification approximations are inherited. No "
"dataset mapping for residual pre-assessment is verified; a false "
"fallback may omit qualifying ESA phase/history/occupation routes."
)
reference = (
"https://www.legislation.gov.uk/uksi/2006/213/schedule/4",
"https://www.legislation.gov.uk/uksi/2006/214/schedule/4",
"https://www.legislation.gov.uk/nisr/2006/405/schedule/5",
"https://www.legislation.gov.uk/nisr/2006/406/schedule/5",
)

def formula(benunit, period, parameters):
working = (benunit("disability_premium", period) > 0) | (
benunit("severe_disability_premium", period) > 0
)
person = benunit.members
qualifying_receipt = (
add(
person,
period,
[
"attendance_allowance",
"dla_sc",
"dla_m",
"pip_dl",
"pip_m",
"armed_forces_independence_payment",
],
)
> 0
)
pension = benunit.any(
person("is_claimant_or_partner", period)
& (qualifying_receipt | person("is_blind", period))
) | (benunit("carer_premium", period) > 0)
# Working-age carer/occupation routes restrict which person's/job's
# earnings may be disregarded. Do not automatically apply £20 to an
# ordinary earner solely because their non-earning partner cares.
return where(
benunit("housing_benefit_pension_age_regulations_apply", period),
pension,
working,
)