diff --git a/changelog.d/hb-pension-age-severe-disability-premium.fixed.md b/changelog.d/hb-pension-age-severe-disability-premium.fixed.md new file mode 100644 index 0000000000..af80310425 --- /dev/null +++ b/changelog.d/hb-pension-age-severe-disability-premium.fixed.md @@ -0,0 +1 @@ +- Corrected pension-age Housing Benefit and Council Tax Reduction premiums by removing adult disability and adult enhanced disability premiums absent from their statutory schedules and applying the severe disability premium's qualifying-benefit, couple, Housing Benefit non-dependant and shared carer-attribution conditions. The carer condition does not yet count Universal Credit carer-element awards (#2120). diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_premiums.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_premiums.yaml new file mode 100644 index 0000000000..6a6f03994f --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_premiums.yaml @@ -0,0 +1,279 @@ +# Pension-age Housing Benefit and Council Tax Reduction premiums. +# HB(SPC) Regs 2006 Sch 3 paras 4-12 and CTR (Prescribed Requirements) +# (England) Regs 2012 Sch 2 paras 4-12: the severe disability premium applies +# HB's qualifying benefit, non-dependant and carer conditions; there is no +# adult disability or enhanced disability premium. 2026-27 weekly rates: +# pension-age personal allowance (attained pensionable age before 1 April 2021) 256.00, +# couple 383.35; severe disability premium 86.05 (172.10 for a couple who +# both qualify); carer premium 48.15. Cases that assert an applicable amount +# use claimants who reached State Pension age before 1 April 2021, whose +# allowance does not depend on the April 2021 cohort split. + +- name: AA claimant just above the Guarantee Credit boundary keeps the severe disability premium in HB and CTR + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 72} + state_pension: {2026: 6_000} + private_pension_income: {2026: 12_000} + aa_category: {2026: HIGHER} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + council_tax: {2026: 2_000} + output: + guarantee_credit: 0 + severe_disability_minimum_guarantee_addition: 86.05 * 52 + pension_age_severe_disability_premium: 86.05 * 52 + benefits_premiums: 86.05 * 52 + # The claimant reached pension age before 1 April 2021, so the older + # allowance applies. HB income 16,914 is below the applicable amount, + # (256.00 + 86.05) * 52 = 17,786.60, so HB and CTR are at their maximum. + housing_benefit: 6_240 + council_tax_benefit: 2_000 + +- name: Same claimant just below the boundary is passported to maximum HB + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 72} + state_pension: {2026: 6_000} + private_pension_income: {2026: 11_900} + aa_category: {2026: HIGHER} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + council_tax: {2026: 2_000} + output: + guarantee_credit: 16.60 + housing_benefit: 6_240 + council_tax_benefit: 2_000 + +- name: Pension-age applicable amount has no adult disability or enhanced disability premium + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 80} + dla_sc_category: {2026: HIGHER} + is_disabled_for_benefits: {2026: true} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + # Only the severe disability premium applies: 86.05 * 52 = 4,474.60. + benefits_premiums: 4_474.60 + housing_benefit_applicable_amount: 13_312 + 4_474.60 + +- name: Pensioner couple who both receive AA get two severe disability rates + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 72} + aa_category: {2026: HIGHER} + partner: + age: {2026: 70} + aa_category: {2026: LOWER} + benunits: + benunit: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + # 172.10 * 52 = 8,949.20; couple allowance 383.35 * 52 = 19,934.20. + benefits_premiums: 8_949.20 + housing_benefit_applicable_amount: 19_934.20 + 8_949.20 + +- name: Pension-age carer premium is kept + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 70} + care_hours: {2026: 40} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + carer_premium: 48.15 * 52 + benefits_premiums: 48.15 * 52 + +- name: Working-age continuing HB award keeps the legacy premiums + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 50} + is_disabled_for_benefits: {2026: true} + housing_benefit_reported: {2026: 1} + benunits: + benunit: + members: [claimant] + would_claim_uc: {2026: false} + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + pension_age_severe_disability_premium: 0 + # Legacy disability premium (single) 44.85 * 52 = 2,332.20. + benefits_premiums: 44.85 * 52 + +- name: Scottish pension-age CTR applicable amount includes the severe disability premium + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 80} + pip_dl_category: {2026: STANDARD} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: SCOTLAND} + region: {2026: SCOTLAND} + tenure_type: {2026: OWNED_OUTRIGHT} + output: + # SSI 2012/319 Sch 1 para 7: PIP daily living at the standard rate + # qualifies. (256.00 + 86.05) * 52 = 17,786.60. + benefits_premiums: 86.05 * 52 + council_tax_reduction_applicable_amount: 17_786.60 + +- name: A dependent child does not withhold the pensioner's severe disability premium + # SPC Regs 2002 Sch I para 1(1)(a)(ii) counts only residents aged 18 or + # over, and para 2(2)(f) ignores qualifying young people. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: {2026: 80} + dla_sc_category: {2026: HIGHER} + child: + age: {2026: 12} + benunits: + benunit: + members: [parent, child] + households: + household: + members: [parent, child] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + severe_disability_minimum_guarantee_addition: 86.05 * 52 + pension_age_severe_disability_premium: 86.05 * 52 + +- name: A pensioner's own Carer's Allowance does not withhold their severe disability premium + # The addition is withheld only for a carer benefit paid "in respect of + # caring for him" (Sch I para 1(1)(a)(iii); HB(SPC) Sch 3 para 6(2)(a)(iii)). + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 80} + dla_sc_category: {2026: HIGHER} + care_hours: {2026: 40} + carers_allowance_reported: {2026: 4_000} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + receives_carer_benefit: true + pension_age_severe_disability_premium: 86.05 * 52 + # Severe disability premium plus carer premium. + benefits_premiums: (86.05 + 48.15) * 52 + +- name: Couple who both receive AA, one paid Carer's Allowance for the other, get one rate + # Sch I para 1(1)(b) and reg 6(5)(a): one rate where a carer benefit is + # paid for caring for one only of the partners. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 80} + aa_category: {2026: HIGHER} + partner: + age: {2026: 78} + aa_category: {2026: LOWER} + care_hours: {2026: 40} + carers_allowance_reported: {2026: 4_000} + benunits: + benunit: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: {2026: ENGLAND} + tenure_type: {2026: RENT_FROM_COUNCIL} + rent: {2026: 6_240} + output: + severe_disability_minimum_guarantee_addition: 86.05 * 52 + +- name: The pension-age premium is zero below State Pension age + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: {2026: 40} + pip_dl_category: {2026: STANDARD} + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + country: {2026: ENGLAND} + output: + pension_age_severe_disability_premium: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml new file mode 100644 index 0000000000..34bb2652a1 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml @@ -0,0 +1,209 @@ +# HB(SPC) Regs 2006 Sch 3 para 6, with the non-dependant definition in +# reg 3: these cases assert final awards without a Guarantee Credit passport. +# The final HB and CTR awards include the model's current income rules, +# including two known defects outside this PR: no Savings Credit in HB +# income for a savings-credit-only claimant (#2112), and no non-dependant +# deduction exemption for a claimant on Attendance Allowance (#2007). The +# premium and applicable-amount assertions do not depend on them. Each HB +# award is the rent less 65% of income after tax above the applicable +# amount; State Pension gets no earnings disregard (#1908). + +- name: One qualifying pensioner and a non-blind partner get no HB or CTR severe premium + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 13_000 + aa_category: HIGHER + partner: + age: 78 + state_pension: 13_000 + benunits: + pensioners: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: 0 + severe_disability_minimum_guarantee_addition: 0 + pension_age_severe_disability_premium: 0 + housing_benefit: 2_409.03 + council_tax_benefit: 821.24 + +- name: Both qualifying pensioners keep two rates in their final HB and CTR awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 15_000 + aa_category: HIGHER + partner: + age: 78 + state_pension: 15_000 + aa_category: LOWER + benunits: + pensioners: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: 0 + pension_age_severe_disability_premium: 172.10 * 52 + housing_benefit: 6_146.01 + council_tax_benefit: 1_857.22 + +- name: A qualifying pensioner with a blind non-qualifying partner gets one HB and CTR rate + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 13_000 + aa_category: HIGHER + partner: + age: 78 + state_pension: 13_000 + is_blind: true + benunits: + pensioners: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: 0 + pension_age_severe_disability_premium: 86.05 * 52 + housing_benefit: 5_317.52 + council_tax_benefit: 1_704.27 + +- name: A non-ignored adult resident blocks the pensioner's HB and CTR severe premium + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 6_000 + private_pension_income: 12_000 + aa_category: HIGHER + resident: + age: 40 + benunits: + pensioner: + members: [claimant] + other_family: + members: [resident] + households: + household: + members: [claimant, resident] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: [0, 0] + has_non_dependant_for_severe_disability_premium: [true, false] + pension_age_severe_disability_premium: [0, 0] + housing_benefit: [3_898.70, 0] + council_tax_benefit: [1_279.60, 0] + +- name: An 18-year-old of another family blocks HB and CTR although Pension Credit ignores him + # The daughter is ignored under para 6(6)(a); her son is not part of + # the claimant's family under reg 3(2)(a). SPC Sch I para 2(2)(f) differs. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 6_000 + private_pension_income: 12_000 + aa_category: HIGHER + daughter: + age: 50 + pip_dl_category: STANDARD + grandson: + age: 18 + current_education: UPPER_SECONDARY + benunits: + pensioner: + members: [claimant] + other_family: + members: [daughter, grandson] + households: + household: + members: [claimant, daughter, grandson] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: [0, 0] + # 86.05 * 52 for each family; expected vectors use numeric literals. + severe_disability_minimum_guarantee_addition: [4_474.60, 4_474.60] + has_non_dependant_for_severe_disability_premium: [true, false] + pension_age_severe_disability_premium: [0, 0] + housing_benefit_applicable_amount: [13_312, 0] + housing_benefit: [3_898.70, 0] + council_tax_benefit: [1_097.91, 0] + +- name: A qualifying-benefit resident in another benefit unit can still be the pensioner's paid carer + # The carer's disability benefit exempts her from the residence test; + # withholding is therefore due to attribution, rather than residence. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 80 + state_pension: 6_000 + private_pension_income: 12_000 + aa_category: HIGHER + carer: + age: 50 + pip_dl_category: STANDARD + care_hours: 40 + carers_allowance_reported: 4_000 + benunits: + pensioner: + members: [claimant] + # HB(SPC) reg 55(6) and England CTR Sch 1 para 8(6): AA exempts + # the claimant from deductions. Supply these independently of the + # current generic deduction formulas to isolate the premium rule. + housing_benefit_non_dep_deductions: 0 + council_tax_reduction_non_dep_deductions: 0 + other_family: + members: [carer] + households: + household: + members: [claimant, carer] + country: ENGLAND + tenure_type: RENT_FROM_COUNCIL + rent: 6_240 + council_tax: 2_000 + output: + guarantee_credit: [0, 0] + has_non_dependant_for_severe_disability_premium: [false, false] + is_cared_for_by_carer_benefit_recipient: [true, false] + pension_age_severe_disability_premium: [0, 0] + housing_benefit: [3_898.70, 0] + council_tax_benefit: [1_279.60, 0] diff --git a/policyengine_uk/tests/test_pension_age_severe_disability_premium_properties.py b/policyengine_uk/tests/test_pension_age_severe_disability_premium_properties.py new file mode 100644 index 0000000000..1475662ab8 --- /dev/null +++ b/policyengine_uk/tests/test_pension_age_severe_disability_premium_properties.py @@ -0,0 +1,247 @@ +"""Pension-age severe disability premium and the Guarantee Credit boundary. + +These properties compare the pension-age Housing Benefit and Council Tax +Reduction applicable amounts with the Pension Credit minimum guarantee, +and exercise the income step where Guarantee Credit ends. + +The structural and boundary properties draw single people and couples aged +at least 72 without children, carers or other household residents, who rent +from the council in England in 2026. The schedule property also draws +younger claimants: + +1. Structural: where Housing Benefit is available, its applicable amount is + at least the Pension Credit minimum guarantee, and so is the Council Tax + Reduction applicable amount. In law the pension-age personal allowances + (HB(SPC) Regs 2006 Sch 3 para 1; CTR (Prescribed Requirements) (England) + Regs 2012 Sch 2 para 1) are at least the standard minimum guarantee (SPC + Regs 2002 reg 6(1)). The severe disability premium (Sch 3 paras 6 and + 12(1)) equals the severe disability addition (SPC Regs Sch I para 1 and + reg 6(5)) for these households. Their residence conditions differ: an + 18-year-old qualifying young person of another family can leave the + Pension Credit addition payable while barring the HB premium. The + property excludes other residents rather than asserting equivalence for + them. Where only one partner qualifies and the other is blind, the model + assumes the qualifying partner makes the HB claim, as reg 63(1) allows. +2. Boundary: on the private-pension step where Guarantee Credit ends, + household net income, excluding the TV licence fee, does not fall. The + free TV licence for over-75s on Pension Credit is a genuine statutory + cliff, so it is excluded. +3. Schedule: over State Pension age the premium is a whole number (0, 1 or + 2) of weekly severe disability rates, equals severe_disability_premium + and, for these households in 2026, the separately calculated Pension + Credit severe disability addition, and is the only premium besides the + carer premium; + below State Pension age it is zero and benefits_premiums is the sum of the + four legacy premiums, so working-age applicable amounts are unchanged. + +Carers and other household residents have separate attribution and residence +cases in the YAML tests. The income property checks the Guarantee Credit +boundary rather than asserting monotonicity at every possible income step. +""" + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +YEAR = 2026 +PENSIONS = np.arange(0, 20_001, 500) +PROPERTY_SETTINGS = settings( + max_examples=12, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +DISABILITY = st.sampled_from( + [ + {}, + {"aa_category": "LOWER"}, + {"aa_category": "HIGHER"}, + {"dla_sc_category": "LOWER"}, + {"dla_sc_category": "MIDDLE"}, + {"dla_sc_category": "HIGHER"}, + {"pip_dl_category": "STANDARD"}, + {"pip_dl_category": "ENHANCED"}, + ] +) + + +def money(high): + return st.floats(0, high, allow_nan=False, allow_infinity=False) + + +@st.composite +def adult(draw, minimum_age=67): + return dict( + age=draw(st.integers(minimum_age, 95)), + disability=draw(DISABILITY), + blind=draw(st.booleans()), + state_pension=draw(money(15_000)), + ) + + +@st.composite +def standalone_family(draw): + """Only a claimant and optional partner, in the older allowance cohort. + + No other residents, children or carers are added by situation(). This + keeps the HB and Pension Credit residence conditions aligned, including + the absence of young people belonging to another benefit unit. + """ + return dict( + adults=[draw(adult(minimum_age=72)) for _ in range(draw(st.integers(1, 2)))], + rent=draw(money(12_000)), + council_tax=draw(money(3_000)), + savings=draw(st.one_of(st.just(0.0), money(15_000))), + ) + + +def situation(families): + """Each family once per private pension on the PENSIONS grid.""" + people, benunits, households = {}, {}, {} + for i, fam in enumerate(families): + for k, pension in enumerate(PENSIONS): + names = [] + for j, a in enumerate(fam["adults"]): + name = f"p{i}_{k}_{j}" + person = { + "age": {YEAR: a["age"]}, + "state_pension": {YEAR: a["state_pension"]}, + # All private pension goes to the first adult. + "private_pension_income": {YEAR: float(pension) * (j == 0)}, + "is_blind": {YEAR: a["blind"]}, + } + for variable, value in a["disability"].items(): + person[variable] = {YEAR: value} + people[name] = person + names.append(name) + benunits[f"b{i}_{k}"] = {"members": names} + households[f"h{i}_{k}"] = { + "members": names, + "country": {YEAR: "ENGLAND"}, + "region": {YEAR: "NORTH_WEST"}, + "tenure_type": {YEAR: "RENT_FROM_COUNCIL"}, + "rent": {YEAR: fam["rent"]}, + "council_tax": {YEAR: fam["council_tax"]}, + "savings": {YEAR: fam["savings"]}, + } + return {"people": people, "benunits": benunits, "households": households} + + +def grid(families): + simulation = Simulation(situation=situation(families)) + shape = (len(families), len(PENSIONS)) + return { + variable: np.asarray(simulation.calculate(variable, YEAR)).reshape(shape) + for variable in [ + "household_net_income", + "tv_licence", + "minimum_guarantee", + "guarantee_credit", + "housing_benefit_eligible", + "housing_benefit_applicable_amount", + "council_tax_reduction_applicable_amount", + "housing_benefit", + "council_tax_benefit", + ] + } + + +@PROPERTY_SETTINGS +@given(st.lists(standalone_family(), min_size=1, max_size=4)) +def test_pension_age_applicable_amounts_cover_the_minimum_guarantee(families): + """Compare only older-cohort households with no other residents or carers. + + HB and Pension Credit do not have identical residence conditions: a + qualifying young person of another family may bar only HB's premium. + Those households are excluded by the generator. Couples can nominate + the qualifying partner as claimant where the other partner is blind. + """ + g = grid(families) + for i, fam in enumerate(families): + eligible = g["housing_benefit_eligible"][i].astype(bool) + minimum_guarantee = g["minimum_guarantee"][i] + hb = g["housing_benefit_applicable_amount"][i] + ctr = g["council_tax_reduction_applicable_amount"][i] + assert np.all(hb[eligible] >= minimum_guarantee[eligible] - 0.01), fam + assert np.all(ctr >= minimum_guarantee - 0.01), fam + + +@PROPERTY_SETTINGS +@given(st.lists(standalone_family(), min_size=1, max_size=4)) +def test_net_income_does_not_fall_where_guarantee_credit_ends(families): + g = grid(families) + net = g["household_net_income"] + g["tv_licence"] + step = np.diff(net, axis=1) + gc = g["guarantee_credit"] + ends = (gc[:, :-1] > 0) & (gc[:, 1:] <= 0) + for i, fam in enumerate(families): + for k in np.flatnonzero(ends[i]): + assert step[i, k] >= -0.01, ( + fam, + f"private pension {PENSIONS[k]} -> {PENSIONS[k + 1]}", + f"net income change {step[i, k]:.2f}", + f"HB {g['housing_benefit'][i, k]:.2f} -> " + f"{g['housing_benefit'][i, k + 1]:.2f}", + f"CTR {g['council_tax_benefit'][i, k]:.2f} -> " + f"{g['council_tax_benefit'][i, k + 1]:.2f}", + ) + + +@PROPERTY_SETTINGS +@given( + st.lists(adult(), min_size=1, max_size=2), + st.integers(18, 95), +) +def test_premiums_follow_the_pension_age_and_working_age_schedules(adults, age): + people = {} + for j, a in enumerate(adults): + person = { + "age": {YEAR: age if j == 0 else a["age"]}, + "is_blind": {YEAR: a["blind"]}, + } + for variable, value in a["disability"].items(): + person[variable] = {YEAR: value} + people[f"p{j}"] = person + simulation = Simulation( + situation={ + "people": people, + "benunits": {"b": {"members": list(people)}}, + "households": {"h": {"members": list(people)}}, + } + ) + + def get(variable): + return float(simulation.calculate(variable, YEAR)[0]) + + pension_age = bool(simulation.calculate("is_SP_age", YEAR).any()) + premium = get("pension_age_severe_disability_premium") + if pension_age: + weekly_rate = float( + simulation.tax_benefit_system.parameters( + YEAR + ).gov.dwp.disability_premia.severe_single + ) + rates = premium / (weekly_rate * 52) + assert min(abs(rates - k) for k in (0, 1, 2)) < 1e-6, rates + assert abs(premium - get("severe_disability_premium")) < 0.005 + # A cross-check, not the definition: with no other residents the + # Pension Credit addition has the same conditions and, in 2026, the + # same amounts, but its own parameter and residence test. + assert ( + abs(premium - get("severe_disability_minimum_guarantee_addition")) < 0.005 + ) + expected = premium + get("carer_premium") + else: + assert premium == 0 + expected = sum( + get(variable) + for variable in [ + "disability_premium", + "enhanced_disability_premium", + "severe_disability_premium", + "carer_premium", + ] + ) + assert abs(get("benefits_premiums") - expected) < 0.005 diff --git a/policyengine_uk/variables/household/demographic/has_non_dependant_for_severe_disability_premium.py b/policyengine_uk/variables/household/demographic/has_non_dependant_for_severe_disability_premium.py index 5c6d489a77..9006302de7 100644 --- a/policyengine_uk/variables/household/demographic/has_non_dependant_for_severe_disability_premium.py +++ b/policyengine_uk/variables/household/demographic/has_non_dependant_for_severe_disability_premium.py @@ -7,7 +7,8 @@ class has_non_dependant_for_severe_disability_premium(Variable): label = "Has a non-dependant who blocks the severe disability premium" documentation = ( "A non-dependant aged 18 or over normally resides with the claimant, " - "which bars the legacy severe disability premium. Non-dependants who " + "which bars the working-age and pension-age Housing Benefit severe " + "disability premiums. Non-dependants who " "receive a severe disability premium qualifying benefit, or who are " "blind, are ignored. Every household member aged 18 or over is " "treated as a non-dependant unless they are in the claimant's family: " @@ -40,6 +41,9 @@ class has_non_dependant_for_severe_disability_premium(Variable): "https://www.legislation.gov.uk/uksi/2006/213/regulation/3", "https://www.legislation.gov.uk/uksi/2006/213/regulation/19", "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/14", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/3", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/19", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/6", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/3", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/14", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/2/paragraph/13", diff --git a/policyengine_uk/variables/household/demographic/pension_age_severe_disability_premium.py b/policyengine_uk/variables/household/demographic/pension_age_severe_disability_premium.py new file mode 100644 index 0000000000..7921327326 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/pension_age_severe_disability_premium.py @@ -0,0 +1,45 @@ +from policyengine_uk.model_api import * + + +class pension_age_severe_disability_premium(Variable): + value_type = float + entity = BenUnit + label = "Severe disability premium for pension-age Housing Benefit and CTR" + documentation = ( + "The severe disability premium in the Housing Benefit and Council Tax " + "Reduction applicable amount of a family over State Pension age. " + "HB(SPC) Regs 2006 Sch 3 para 6 sets the same conditions as the " + "working-age premium (HB Regs 2006 Sch 3 para 14): the qualifying " + "benefits, both partners qualifying unless the other is blind, no " + "non-dependant aged 18 or over with the same exceptions (para 6(6), " + "reg 3), and no carer benefit paid for caring for the claimant or " + "partner. Para 12 sets the same weekly amounts. So this is " + "severe_disability_premium for a family over State Pension age, with " + "its amounts and its documented assumptions: where only one partner " + "qualifies and the other is blind, the qualifying partner is taken to " + "claim, as a couple may agree under HB(SPC) reg 63(1) and the CTR " + "schemes (England SI 2012/2885 Sch 8 para 4(1)); carers are attributed " + "by is_cared_for_by_carer_benefit_recipient, which does not count " + "Universal Credit carer-element awards. The Pension Credit severe " + "disability addition has the same conditions apart from its wider " + "residence exceptions, but its own amount parameter, so a Pension " + "Credit reform does not move this premium." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/3", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/63", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/6", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/8/paragraph/4", + "https://www.legislation.gov.uk/ssi/2012/319/schedule/1/paragraph/7", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/6", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/I/paragraph/1", + "https://www.legislation.gov.uk/uksi/2002/1792/regulation/6", + ) + + def formula(benunit, period, parameters): + pension_age = benunit.any(benunit.members("is_SP_age", period)) + return where(pension_age, benunit("severe_disability_premium", period), 0) diff --git a/policyengine_uk/variables/household/income/benefits_premiums.py b/policyengine_uk/variables/household/income/benefits_premiums.py index 071f8c4fb6..17780055eb 100644 --- a/policyengine_uk/variables/household/income/benefits_premiums.py +++ b/policyengine_uk/variables/household/income/benefits_premiums.py @@ -1,16 +1,53 @@ from policyengine_uk.model_api import * +WORKING_AGE_PREMIUMS = [ + "disability_premium", + "enhanced_disability_premium", + "severe_disability_premium", + "carer_premium", +] + +# The pension-age schedules (HB(SPC) Regs 2006 Sch 3 Part 3; CTR (Prescribed +# Requirements) (England) Regs 2012 Sch 2 Part 3; the Scottish and Welsh +# pension-age CTR schedules) have only the severe disability, enhanced +# disability (children only), disabled child and carer premiums. The two +# child premiums are not modelled. +PENSION_AGE_PREMIUMS = [ + "pension_age_severe_disability_premium", + "carer_premium", +] + class benefits_premiums(Variable): value_type = float entity = BenUnit label = "Value of premiums for disability and carer status" + documentation = ( + "Premiums in the Housing Benefit, Council Tax Reduction and Income " + "Support applicable amounts. A family with a member over State " + "Pension age uses the pension-age schedules: the severe disability " + "premium and the carer premium. Those schedules have no adult disability or " + "enhanced disability premium." + ) definition_period = YEAR unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2", + "https://www.legislation.gov.uk/ssi/2012/319/schedule/1", + "https://www.legislation.gov.uk/wsi/2013/3035/schedule/2", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/2", + ) - adds = [ - "disability_premium", - "enhanced_disability_premium", - "severe_disability_premium", - "carer_premium", - ] + def formula(benunit, period, parameters): + # Same switch as the aged personal allowance in the Housing Benefit + # and Council Tax Reduction applicable amounts. Income Support is not + # paid to a family with a member over State Pension age. + pension_age = benunit.any(benunit.members("is_SP_age", period)) + return where( + pension_age, + add(benunit, period, PENSION_AGE_PREMIUMS), + add(benunit, period, WORKING_AGE_PREMIUMS), + )