diff --git a/changelog.d/hb-universal-credit-passport.fixed.md b/changelog.d/hb-universal-credit-passport.fixed.md new file mode 100644 index 0000000000..d9cb9bad7f --- /dev/null +++ b/changelog.d/hb-universal-credit-passport.fixed.md @@ -0,0 +1 @@ +- Disregard the earnings, whole income and whole capital of a Housing Benefit claimant on Universal Credit, as SI 2006/213 Schedule 4 paragraph 12, Schedule 5 paragraph 4 and Schedule 6 paragraph 5 (Northern Ireland: SR 2006/405 Schedule 5 paragraph 12, Schedule 6 paragraph 4 and Schedule 7 paragraph 5) require, so where Housing Benefit is paid alongside Universal Credit the means test gives the maximum. Being on Universal Credit means being entitled to it, whether it is in payment or not (regulation 2(3B)), which the model reads as Universal Credit above nil before the benefit cap and deductions. The limb applies from 28 October 2013 in Great Britain and 8 May 2018 in Northern Ireland (`gov.dwp.housing_benefit.means_test.universal_credit_passport`). Adds `housing_benefit_on_passporting_benefit`, which the three passports now read. No family receives both benefits in the model yet, so outputs on the Enhanced FRS do not change. diff --git a/docs/book/programs/gov/dwp/housing-benefit.ipynb b/docs/book/programs/gov/dwp/housing-benefit.ipynb index 324139a598..39d1e4fbbd 100644 --- a/docs/book/programs/gov/dwp/housing-benefit.ipynb +++ b/docs/book/programs/gov/dwp/housing-benefit.ipynb @@ -41,7 +41,7 @@ "1. **Eligible rent**: the rent the benunit is liable for (`benunit_rent`). Where the Local Housing Allowance applies (`LHA_eligible`: renting, and no member in social housing), the eligible rent is the maximum rent (LHA), which is the LHA rate or, where the rent is lower, the rent (`LHA_cap`; SI 2006/213 regs [12D(2)(a)](https://www.legislation.gov.uk/uksi/2006/213/regulation/12D) and [13D(5)](https://www.legislation.gov.uk/uksi/2006/213/regulation/13D)).\n", "2. **Applicable amount** (`housing_benefit_applicable_amount`): a personal allowance derived from the benunit's composition (single, couple, lone parent) and age, plus any disability/carer premiums. This is the \"minimum income\" the household needs before HB tapers begin.\n", "3. **Means test** (`housing_benefit_entitlement`): the appropriate maximum Housing Benefit is the eligible rent less `housing_benefit_non_dep_deductions` for any non-dependant adults living in the household ([reg. 70](https://www.legislation.gov.uk/uksi/2006/213/regulation/70)). The published `withdrawal_rate` (currently 0.65) of the benunit's `housing_benefit_applicable_income` in excess of the applicable amount is deducted from that maximum ([SSCBA 1992 s. 130(3)(b)](https://www.legislation.gov.uk/ukpga/1992/4/section/130), [reg. 71](https://www.legislation.gov.uk/uksi/2006/213/regulation/71)). Because the LHA caps the eligible rent, the taper comes off the LHA: a private tenant with rent above the LHA and income above the applicable amount receives the LHA less the taper, not the lower of the LHA and the rent less the taper. The pension-age regulations (SI 2006/214) have the same rules at regs 12D, 13D, 50 and 51, and the Northern Ireland regulations at SR 2006/405 regs 13C, 14D, 68 and 69 and SR 2006/406 regs 13C, 14D, 48 and 49.\n", - " If the benunit is in receipt of Income Support, income-based Jobseeker's Allowance or income-related Employment and Support Allowance (`in_receipt_of_income_support_jsa_ib_or_esa_ir`: a positive amount of any of them), the whole of its income and capital is disregarded ([SI 2006/213 Sch. 5 para. 4](https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4) and [Sch. 6 para. 5](https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5); Northern Ireland: [SR 2006/405 Sch. 6 para. 4](https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4) and [Sch. 7 para. 5](https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5)). `housing_benefit_applicable_income` and `housing_benefit_assessable_capital` are then zero, so the award is that maximum. This applies at any age: a mixed-age couple whose younger member is on one of these benefits is assessed under the working-age regulations ([SI 2006/213 reg. 5(1)(b)](https://www.legislation.gov.uk/uksi/2006/213/regulation/5)). The universal credit limb of those paragraphs is not modelled, because no benunit receives both Housing Benefit and Universal Credit.\n", + " If the benunit is on Universal Credit, Income Support, income-based Jobseeker's Allowance or income-related Employment and Support Allowance (`housing_benefit_on_passporting_benefit`), the whole of its earnings, other income and capital is disregarded ([SI 2006/213 Sch. 4 para. 12](https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/12), [Sch. 5 para. 4](https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4) and [Sch. 6 para. 5](https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5); Northern Ireland: [SR 2006/405 Sch. 5 para. 12](https://www.legislation.gov.uk/nisr/2006/405/schedule/5/paragraph/12), [Sch. 6 para. 4](https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4) and [Sch. 7 para. 5](https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5)). `housing_benefit_applicable_income` and `housing_benefit_assessable_capital` are then zero, so the award is that maximum. This applies at any age: a mixed-age couple whose younger member is on one of these benefits is assessed under the working-age regulations ([SI 2006/213 reg. 5(1)(b)](https://www.legislation.gov.uk/uksi/2006/213/regulation/5)). Income Support, income-based Jobseeker's Allowance and income-related Employment and Support Allowance count when a positive amount is paid (`in_receipt_of_income_support_jsa_ib_or_esa_ir`). A person is on Universal Credit on any day they are entitled to it, whether it is in payment or not ([reg. 2(3B)](https://www.legislation.gov.uk/uksi/2006/213/regulation/2)); PolicyEngine reads that as Universal Credit above nil before the benefit cap and deductions (`is_uc_entitled`), for a family that claims it, so the passport adds no circular dependency through the benefit cap. The universal credit limb applies from 28 October 2013 in Great Britain and 8 May 2018 in Northern Ireland (`gov.dwp.housing_benefit.means_test.universal_credit_passport`). It matters only where Housing Benefit is paid alongside Universal Credit, for specified or temporary accommodation, which the eligibility rules above do not yet model.\n", "4. **Benefit cap** (`housing_benefit`): the post-means-test award is finally reduced by `benefit_cap_reduction` if the household's total benefit income exceeds the cap and no cap exemption applies.\n", "\n", "The take-up gate (`would_claim_housing_benefit`) is applied inside `housing_benefit_pre_benefit_cap`." diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/universal_credit_passport.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/universal_credit_passport.yaml new file mode 100644 index 0000000000..bb93a1a7e3 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/universal_credit_passport.yaml @@ -0,0 +1,50 @@ +description: >- + Whether the Housing Benefit passport covers a claimant on Universal Credit: + the whole of the earnings, other income and capital of a claimant who is + entitled to Universal Credit, whether it is in payment or not, is + disregarded, as it is for a claimant on Income Support, income-based + Jobseeker's Allowance or income-related Employment and Support Allowance. + The universal credit words came into force on different dates in Great + Britain and Northern Ireland. Annual formulas read the value sampled on + 30 April of the model year, so the limb applies from 2014-15 in Great + Britain and 2019-20 in Northern Ireland. +great_britain: + description: Whether the Housing Benefit passport covers a claimant on Universal Credit in Great Britain. SI 2013/2070 inserted "universal credit," into SI 2006/213 Sch 4 para 12, Sch 5 para 4 and Sch 6 para 5, and the meaning of being on Universal Credit as reg 2(3B), from 28 October 2013. + values: + 2006-03-06: false + 2013-10-28: true + metadata: + label: Housing Benefit passport covers Universal Credit in Great Britain + unit: bool + period: year + reference: + - title: The Housing Benefit Regulations 2006, Schedule 4 paragraph 12 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/12 + - title: The Housing Benefit Regulations 2006, Schedule 5 paragraph 4 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4 + - title: The Housing Benefit Regulations 2006, Schedule 6 paragraph 5 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5 + - title: The Housing Benefit Regulations 2006, regulation 2(3B) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/2 + - title: The Universal Credit (Transitional Provisions) and Housing Benefit (Amendment) Regulations 2013, regulation 7 + href: https://www.legislation.gov.uk/uksi/2013/2070/regulation/7 +northern_ireland: + description: Whether the Housing Benefit passport covers a claimant on Universal Credit in Northern Ireland. SR 2018/92 inserted "universal credit," into SR 2006/405 Sch 5 para 12, Sch 6 para 4 and Sch 7 para 5, and the meaning of being on Universal Credit as reg 2(3B), from 8 May 2018. + values: + 2006-11-20: false + 2018-05-08: true + metadata: + label: Housing Benefit passport covers Universal Credit in Northern Ireland + unit: bool + period: year + reference: + - title: The Housing Benefit Regulations (Northern Ireland) 2006, Schedule 5 paragraph 12 + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/5/paragraph/12 + - title: The Housing Benefit Regulations (Northern Ireland) 2006, Schedule 6 paragraph 4 + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4 + - title: The Housing Benefit Regulations (Northern Ireland) 2006, Schedule 7 paragraph 5 + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5 + - title: The Housing Benefit Regulations (Northern Ireland) 2006, regulation 2(3B) + href: https://www.legislation.gov.uk/nisr/2006/405/regulation/2 + - title: The Universal Credit (Persons Required to Provide Information, Miscellaneous Amendments and Saving and Transitional Provision) Regulations (Northern Ireland) 2018, regulation 4 + href: https://www.legislation.gov.uk/nisr/2018/92/regulation/4 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income.yaml index 9cb749c7cd..f5218d1b0b 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income.yaml @@ -1,6 +1,7 @@ - name: Capped at 0 period: 2025 input: + would_claim_uc: false # not on Universal Credit, which passports the means test # Benefits child_benefit: 1_000 income_support: 0 @@ -25,6 +26,7 @@ - name: Baseline inputs period: 2025 input: + would_claim_uc: false # not on Universal Credit, which passports the means test # Benefits child_benefit: 1_000 income_support: 0 @@ -51,6 +53,7 @@ # earnings. 3,250 - 1,500 / 2 = 2,500. period: 2025 input: + would_claim_uc: false # not on Universal Credit, which passports the means test # Benefits child_benefit: 0 income_support: 0 @@ -77,6 +80,7 @@ # para 56 does not apply. 3,250 + 2,000 - 1,500 / 2 = 4,500. period: 2025 input: + would_claim_uc: false # not on Universal Credit, which passports the means test # Benefits child_benefit: 0 income_support: 0 @@ -102,6 +106,7 @@ # Applicable income is floored at nil: 3,250 - 100,000 / 2 < 0. period: 2025 input: + would_claim_uc: false # not on Universal Credit, which passports the means test # Benefits child_benefit: 0 income_support: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml index 95d4477903..7cf5e90192 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml @@ -35,6 +35,7 @@ employment_income: 156 # £3 × 52 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 156 # min(£5, £3) × 52 @@ -49,6 +50,7 @@ employment_income: 5_200 # £100 × 52 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 260 # £5 × 52, not uprated @@ -63,6 +65,7 @@ employment_income: 5_200 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 260 # £5 × 52, not uprated @@ -79,6 +82,7 @@ age: 38 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] output: housing_benefit_applicable_income_disregard: 520 # £10 × 52 @@ -96,6 +100,7 @@ employment_income: 208 # £4 × 52 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] output: # Para 7: the partner's earnings make up the £10 where the claimant's @@ -115,6 +120,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: housing_benefit_applicable_income_disregard: 1_040 # min(£25, £20) × 52 @@ -132,6 +138,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: housing_benefit_applicable_income_disregard: 1_300 # £25 × 52 @@ -209,6 +216,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 260 # £5 × 52 @@ -224,6 +232,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 1_149.20 # (£5 + £17.10) × 52 @@ -239,6 +248,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: # Para 17(1): net earnings "equal or exceed" £5 × 52 + £0 childcare + @@ -256,6 +266,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: housing_benefit_applicable_income_disregard: 260 # £5 × 52 @@ -273,6 +284,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # £8,000 ≥ (£25 + £17.10) × 52 = £2,189.20. @@ -291,6 +303,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # £2,080 < (£25 + £17.10) × 52 = £2,189.20. @@ -309,6 +322,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # Para 17(1): £2,189.20 "equal or exceed" £1,300 + £0 childcare + £889.20. @@ -327,6 +341,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: housing_benefit_applicable_income_disregard: 1_300 # £25 × 52 @@ -345,6 +360,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # Childcare deducted is min(£4,160, one-child maximum) = £4,160. @@ -366,6 +382,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # £5,200 ≥ £1,300 + £1,040 + £889.20 = £3,229.20. @@ -387,6 +404,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner, child] output: housing_benefit_applicable_income_disregard: 1_409.20 # (£10 + £17.10) × 52 @@ -406,6 +424,7 @@ weekly_hours: 16 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] output: # One member must work 30 hours; hours are not added across the couple. @@ -423,6 +442,7 @@ is_disabled_for_benefits: true benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: # Para 17(2)(b)(iv)(aa): a single claimant with the disability premium @@ -448,6 +468,7 @@ employment_income: 1_040 # £20 a week benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] income_support: 3_000 output: @@ -465,6 +486,7 @@ employment_income: 3_000 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] esa_income: 4_000 output: @@ -486,6 +508,7 @@ employment_income: 2_000 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: housing_benefit_net_earnings: 0 @@ -507,6 +530,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, young_person, child] output: # A qualifying young person is a "young person" (SI 2006/213 reg diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_net_earnings.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_net_earnings.yaml index b6707a83bb..81e4733ddc 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_net_earnings.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_net_earnings.yaml @@ -136,6 +136,7 @@ age: 0 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: # SI 2006/213 reg 35(1)(i). £8,000 is below the personal allowance and diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_specified_or_temporary_accommodation_disregard.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_specified_or_temporary_accommodation_disregard.yaml index b26c44135c..d6027e8a89 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_specified_or_temporary_accommodation_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_specified_or_temporary_accommodation_disregard.yaml @@ -109,6 +109,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] in_specified_or_temporary_accommodation: true output: @@ -128,6 +129,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] in_specified_or_temporary_accommodation: true output: @@ -175,6 +177,7 @@ is_claimant_or_partner: true benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] in_specified_or_temporary_accommodation: true output: @@ -195,6 +198,7 @@ age: 20 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] in_specified_or_temporary_accommodation: true output: @@ -214,6 +218,7 @@ age: 25 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] in_specified_or_temporary_accommodation: true output: @@ -258,6 +263,7 @@ weekly_hours: 10 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] in_specified_or_temporary_accommodation: true output: @@ -278,6 +284,7 @@ weekly_hours: 10 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner] in_specified_or_temporary_accommodation: true output: @@ -297,6 +304,7 @@ weekly_hours: 10 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -330,6 +338,7 @@ age: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -474,6 +483,7 @@ employment_income: 1_040 # £20 a week benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] income_support: 3_000 in_specified_or_temporary_accommodation: true @@ -517,6 +527,7 @@ statutory_maternity_pay: 5_200 # £100 a week, earnings under reg 35(1)(i) benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -534,6 +545,7 @@ self_employment_income: -2_000 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -578,6 +590,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -596,6 +609,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -613,6 +627,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] in_specified_or_temporary_accommodation: true output: @@ -630,6 +645,7 @@ weekly_hours: 30 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person] output: # £5,148 ≥ £260 + £889.20 = £1,149.20. @@ -648,6 +664,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] in_specified_or_temporary_accommodation: true output: @@ -668,6 +685,7 @@ age: 5 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] in_specified_or_temporary_accommodation: true output: @@ -694,6 +712,7 @@ age: 1 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, partner, child] in_specified_or_temporary_accommodation: true output: diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml index f598331f3a..af28ec2ca0 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml @@ -140,8 +140,10 @@ age: 30 benunits: benunit_1: + would_claim_uc: false # not on Universal Credit, which passports the means test members: person_1 benunit_2: + would_claim_uc: false # not on Universal Credit, which passports the means test members: person_2 households: household: diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_eligible.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_eligible.yaml index b00f14f60d..3a1990c8a0 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_eligible.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_eligible.yaml @@ -1,7 +1,7 @@ - name: Social housing eligible period: 2021 - absolute_error_margin: 5 input: + would_claim_uc: false # continuing award route: not claiming Universal Credit in_social_housing: true housing_benefit_reported: 1 LHA_eligible: false @@ -10,8 +10,8 @@ - name: LHA eligible period: 2021 - absolute_error_margin: 5 input: + would_claim_uc: false # continuing award route: not claiming Universal Credit in_social_housing: false housing_benefit_reported: 1 LHA_eligible: true @@ -20,8 +20,8 @@ - name: Not already enrolled period: 2021 - absolute_error_margin: 5 input: + would_claim_uc: false # continuing award route: not claiming Universal Credit in_social_housing: false housing_benefit_reported: 0 LHA_eligible: true @@ -30,8 +30,8 @@ - name: Not eligible period: 2021 - absolute_error_margin: 5 input: + would_claim_uc: false # continuing award route: not claiming Universal Credit in_social_housing: false housing_benefit_reported: 1 LHA_eligible: false diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_universal_credit_passport.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_universal_credit_passport.yaml new file mode 100644 index 0000000000..4c7eabd6eb --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_universal_credit_passport.yaml @@ -0,0 +1,337 @@ +# SI 2006/213 Sch 4 para 12, Sch 5 para 4 and Sch 6 para 5 (NI: SR 2006/405 +# Sch 5 para 12, Sch 6 para 4 and Sch 7 para 5): where a claimant is on +# universal credit, income support, an income-based jobseeker's allowance or an +# income-related employment and support allowance, the claimant's earnings, the +# whole of the claimant's income and the whole of the claimant's capital are +# disregarded. A person is on universal credit on any day they are entitled to +# it, whether it is in payment or not (reg 2(3B)). With nil income Housing +# Benefit is the appropriate maximum: the eligible rent less non-dependant +# deductions (SSCBA 1992 s.130(3)(a); reg 70). +# +# In law working-age Housing Benefit is paid alongside Universal Credit for +# specified or temporary accommodation (UC (Transitional Provisions) Regs 2014 +# reg 5(2)(a)), whose rent is excluded from the Universal Credit housing costs +# element (UC Regs 2013 Sch 1 para 3(h)-(i)). The model has no such route yet +# (PolicyEngine/policyengine-uk#1910 adds one), so these cases supply +# housing_benefit_eligible and a nil uc_housing_costs_element as inputs. +# +# Expected values are hand-computed from the regulations: council tenancies +# (no LHA), no non-dependants, 2025-26 amounts. Universal Credit: standard +# allowance £400.14 a month for a single claimant aged 25 or over (UC Regs +# reg 36), a 55% taper on earnings with no work allowance (reg 22), and +# tariff income of £4.35 a month for each £250 of capital over £6,000 +# (reg 72). Housing Benefit: £5 a week single earnings disregard (Sch 4 +# para 10), tariff income of £1 a week for each £250 of capital over £6,000 +# (reg 52), 65% taper (reg 71), 52 weeks a year. + +- name: Single claimant on Universal Credit has earnings, income and capital disregarded and gets maximum Housing Benefit + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + employment_income: 8_000 + # Under 30 hours: no additional earnings disregard (Sch 4 para 17). + weekly_hours: 12 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + housing_benefit_eligible: true + uc_housing_costs_element: 0 + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 7_000 + output: + # 400.14 x 12 = 4,801.68, less 55% of 8,000 = 4,400, less tariff income + # ceil((7,000 - 6,000) / 250) = 4 x 4.35 x 12 = 208.80: 192.88. + universal_credit_pre_benefit_cap: 192.88 + is_uc_entitled: true + universal_credit: 192.88 + housing_benefit_on_passporting_benefit: true + # Sch 4 para 12: all the earnings. + housing_benefit_applicable_income_disregard: 8_000 + # Sch 6 para 5: the £7,000 is disregarded, so there is no tariff income. + housing_benefit_assessable_capital: 0 + housing_benefit_tariff_income: 0 + # Sch 5 para 4: the whole income. + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 5_200 + housing_benefit_pre_benefit_cap: 5_200 + housing_benefit: 5_200 + +- name: The same claimant not on Universal Credit is means-tested on earnings and capital + # Not claiming Universal Credit, so on the continuing-award route. Applicable + # income = 8,000 - 260 (£5 x 52) + tariff income 208 (4 x £1 x 52) = 7,948. + # With the applicable amount set to 4,000, entitlement = 5,200 - 0.65 x + # (7,948 - 4,000) = 5,200 - 2,566.20 = 2,633.80. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + employment_income: 8_000 + # Under 30 hours: no additional earnings disregard (Sch 4 para 17). + weekly_hours: 12 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: false + housing_benefit_applicable_amount: 4_000 + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 7_000 + output: + is_uc_entitled: false + housing_benefit_on_passporting_benefit: false + housing_benefit_applicable_income_disregard: 260 + housing_benefit_assessable_capital: 7_000 + housing_benefit_tariff_income: 208 + housing_benefit_applicable_income: 7_948 + housing_benefit_eligible: true + housing_benefit_entitlement: 2_633.80 + +- name: Universal Credit reduced to nil by deductions still passports Housing Benefit + # Reg 2(3B): on universal credit "whether it is in payment or not". The + # £1,000 entitlement is all deducted, so nothing is paid. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 30 + employment_income: 3_000 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + universal_credit_pre_benefit_cap: 1_000 + uc_deductions: 1_000 + housing_benefit_eligible: true + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 10_000 + output: + is_uc_entitled: true + universal_credit: 0 + housing_benefit_on_passporting_benefit: true + housing_benefit_applicable_income_disregard: 3_000 + housing_benefit_assessable_capital: 0 + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 5_200 + +- name: Universal Credit of one penny passports Housing Benefit + # The minimum Universal Credit award is one penny (WRA 2012 s.5(1)(b); UC + # Regs reg 17), so an entitlement of £0.01 is an entitlement. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 30 + employment_income: 3_000 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + universal_credit_pre_benefit_cap: 0.01 + housing_benefit_eligible: true + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 10_000 + output: + is_uc_entitled: true + housing_benefit_on_passporting_benefit: true + housing_benefit_applicable_income: 0 + housing_benefit_assessable_capital: 0 + housing_benefit_entitlement: 5_200 + +- name: A Universal Credit claim that comes to nil does not passport Housing Benefit + # No entitlement below one penny. Applicable income = 3,000 - 260 + tariff + # income 832 (ceil((10,000 - 6,000) / 250) = 16, x £1 x 52) = 3,572; with + # the applicable amount set to 3,000, entitlement = 5,200 - 0.65 x 572 = + # 4,828.20. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 30 + employment_income: 3_000 + # Under 30 hours: no additional earnings disregard (Sch 4 para 17). + weekly_hours: 6 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + universal_credit_pre_benefit_cap: 0 + housing_benefit_eligible: true + housing_benefit_applicable_amount: 3_000 + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 10_000 + output: + is_uc_entitled: false + housing_benefit_on_passporting_benefit: false + housing_benefit_applicable_income_disregard: 260 + housing_benefit_assessable_capital: 10_000 + housing_benefit_tariff_income: 832 + housing_benefit_applicable_income: 3_572 + housing_benefit_entitlement: 4_828.20 + +- name: Couple on a joint Universal Credit claim has both members' earnings and the household capital disregarded + # Joint claimants are both entitled to Universal Credit (WRA 2012 s.3(2)), and + # the partner's income and capital are treated as the claimant's (reg 25). + # Without the passport the couple's net earnings would be 9,000, less the + # £10 a week couple disregard. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + employment_income: 3_000 + housing_benefit_reported: 1 + partner: + age: 33 + employment_income: 6_000 + benunits: + benunit: + members: [claimant, partner] + would_claim_uc: true + universal_credit_pre_benefit_cap: 2_000 + housing_benefit_eligible: true + households: + household: + members: [claimant, partner] + tenure_type: RENT_FROM_HA + rent: 6_240 + savings: 14_000 + output: + housing_benefit_on_passporting_benefit: true + housing_benefit_applicable_income_disregard: 9_000 + housing_benefit_assessable_capital: 0 + housing_benefit_tariff_income: 0 + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 6_240 + +- name: Mixed-age couple on Universal Credit is assessed under the working-age regulations with its income disregarded + # Reg 5(1)(b): the working-age regulations apply to a claimant over the + # qualifying age for State Pension Credit whose partner is on universal + # credit, so the older member's pension is disregarded too (Sch 5 para 4). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 70 + private_pension_income: 5_000 + housing_benefit_reported: 1 + partner: + age: 40 + employment_income: 2_000 + benunits: + benunit: + members: [claimant, partner] + would_claim_uc: true + universal_credit_pre_benefit_cap: 3_000 + housing_benefit_eligible: true + guarantee_credit: 0 + households: + household: + members: [claimant, partner] + tenure_type: RENT_FROM_COUNCIL + rent: 5_720 + savings: 9_000 + output: + housing_benefit_pension_age_regulations_apply: false + housing_benefit_on_passporting_benefit: true + housing_benefit_applicable_income_disregard: 2_000 + housing_benefit_assessable_capital: 0 + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 5_720 + +- name: Northern Ireland claimant on Universal Credit has earnings, income and capital disregarded + # SR 2006/405 Sch 5 para 12, Sch 6 para 4 and Sch 7 para 5, in force for + # universal credit from 8 May 2018 (SR 2018/92). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 45 + employment_income: 3_000 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + universal_credit_pre_benefit_cap: 1_000 + housing_benefit_eligible: true + households: + household: + members: [claimant] + country: NORTHERN_IRELAND + tenure_type: RENT_FROM_COUNCIL + rent: 4_160 + savings: 10_000 + output: + housing_benefit_on_passporting_benefit: true + housing_benefit_applicable_income_disregard: 3_000 + housing_benefit_assessable_capital: 0 + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 4_160 + +- name: A family on Universal Credit with income and capital gets the same Housing Benefit as on income-based JSA + # The universal credit and income-based JSA limbs of the passport have the + # same effect: maximum Housing Benefit. Same household as the income-based + # JSA case in housing_benefit_income_related_benefit_passport.yaml. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + employment_income: 1_000 + housing_benefit_reported: 1 + benunits: + benunit: + members: [claimant] + would_claim_uc: true + universal_credit_pre_benefit_cap: 3_500 + housing_benefit_eligible: true + households: + household: + members: [claimant] + tenure_type: RENT_FROM_COUNCIL + rent: 5_200 + savings: 12_000 + output: + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + housing_benefit_on_passporting_benefit: true + housing_benefit_assessable_capital: 0 + housing_benefit_tariff_income: 0 + housing_benefit_applicable_income: 0 + housing_benefit_entitlement: 5_200 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_capital.yaml index b1ff157058..d89602c192 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_capital.yaml @@ -12,8 +12,10 @@ age: 30 benunits: claimant_benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant] unrelated_benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [unrelated_claimant] households: household: @@ -39,8 +41,10 @@ age: 30 benunits: claimant_benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [claimant, student] unrelated_benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [unrelated_claimant] households: household: diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_claimant_relationships.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_claimant_relationships.yaml index 64f8469107..e30e13c8b2 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_claimant_relationships.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/legacy_claimant_relationships.yaml @@ -22,6 +22,7 @@ is_in_non_advanced_education: true benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person0, person1] housing_benefit_eligible: true benefits_premiums: 0 @@ -61,6 +62,7 @@ is_in_non_advanced_education: true benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person0, person1, person2] housing_benefit_eligible: true benefits_premiums: 0 @@ -125,6 +127,7 @@ is_claimant_or_partner: true benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person0, person1] housing_benefit_eligible: true benefits_premiums: 0 @@ -159,6 +162,7 @@ weekly_hours: 0 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [person0, person1] housing_benefit_eligible: true benefits_premiums: 0 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_on_passporting_benefit.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_on_passporting_benefit.yaml new file mode 100644 index 0000000000..655939c656 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_on_passporting_benefit.yaml @@ -0,0 +1,128 @@ +# A benefit unit is on a benefit that passports the Housing Benefit means test +# when it is on universal credit, income support, an income-based jobseeker's +# allowance or an income-related employment and support allowance (SI 2006/213 +# Sch 4 para 12, Sch 5 para 4, Sch 6 para 5; NI: SR 2006/405 Sch 5 para 12, +# Sch 6 para 4, Sch 7 para 5). On universal credit means entitled to it, +# whether in payment or not (reg 2(3B)). The universal credit words came into +# force on 28 October 2013 in Great Britain (SI 2013/2070 reg 7) and on 8 May +# 2018 in Northern Ireland (SR 2018/92 reg 4). Model years are fiscal years +# read on 30 April, so the limb applies from 2014 in Great Britain and 2019 in +# Northern Ireland. + +- name: Not on any of the benefits + period: 2025 + input: + is_uc_entitled: false + income_support: 0 + jsa_income: 0 + esa_income: 0 + output: + housing_benefit_on_passporting_benefit: false + +- name: Entitled to Universal Credit + period: 2025 + input: + is_uc_entitled: true + income_support: 0 + jsa_income: 0 + esa_income: 0 + output: + housing_benefit_on_passporting_benefit: true + +- name: Income Support alone, without Universal Credit + period: 2025 + input: + is_uc_entitled: false + income_support: 0.01 + jsa_income: 0 + esa_income: 0 + output: + housing_benefit_on_passporting_benefit: true + +- name: Claims Universal Credit but the amount before the cap is nil + period: 2025 + input: + would_claim_uc: true + universal_credit_pre_benefit_cap: 0 + income_support: 0 + jsa_income: 0 + esa_income: 0 + output: + is_uc_entitled: false + housing_benefit_on_passporting_benefit: false + +- name: Universal Credit before the benefit cap counts even when the cap leaves nothing to pay + period: 2025 + input: + would_claim_uc: true + universal_credit_pre_benefit_cap: 2_000 + benefit_cap_reduction: 2_000 + income_support: 0 + jsa_income: 0 + esa_income: 0 + output: + universal_credit: 0 + housing_benefit_on_passporting_benefit: true + +- name: Great Britain in 2013-14, before the universal credit limb on 28 October 2013 + period: 2013 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: ENGLAND + output: + housing_benefit_on_passporting_benefit: false + +- name: Great Britain in 2013-14, Income Support still passports + period: 2013 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: true + country: ENGLAND + output: + housing_benefit_on_passporting_benefit: true + +- name: Great Britain in 2014-15, the first year with the universal credit limb + period: 2014 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: SCOTLAND + output: + housing_benefit_on_passporting_benefit: true + +- name: Wales in 2018-19 has the limb + period: 2018 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: WALES + output: + housing_benefit_on_passporting_benefit: true + +- name: Northern Ireland in 2018-19, read on 30 April 2018, before the limb on 8 May 2018 + period: 2018 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: NORTHERN_IRELAND + output: + housing_benefit_on_passporting_benefit: false + +- name: Northern Ireland in 2019-20 has the limb + period: 2019 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: NORTHERN_IRELAND + output: + housing_benefit_on_passporting_benefit: true + +- name: Northern Ireland in 2025-26 with Universal Credit + period: 2025 + input: + is_uc_entitled: true + in_receipt_of_income_support_jsa_ib_or_esa_ir: false + country: NORTHERN_IRELAND + output: + housing_benefit_on_passporting_benefit: true diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/lifetime_isa_capital.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/lifetime_isa_capital.yaml index ad7433be18..723937bda3 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/lifetime_isa_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/lifetime_isa_capital.yaml @@ -228,8 +228,10 @@ lifetime_isa_balance: 10_000 benunits: parents: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent_1, parent_2] child: + would_claim_uc: false # not on Universal Credit, which passports the means test members: adult_child households: household: @@ -370,6 +372,7 @@ lifetime_isa_balance: 10_000 benunits: family: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, young_person] households: household: @@ -398,6 +401,7 @@ lifetime_isa_balance: 10_000 benunits: family: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, dependant] households: household: @@ -421,6 +425,7 @@ lifetime_isa_balance: 10_000 benunits: family: + would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, dependant] households: household: @@ -509,6 +514,7 @@ lifetime_isa_balance: 10_000 benunits: benunit: + would_claim_uc: false # not on Universal Credit, which passports the means test members: person households: household: diff --git a/policyengine_uk/tests/test_carer_support_payment.py b/policyengine_uk/tests/test_carer_support_payment.py index c8594b7581..c833bfae38 100644 --- a/policyengine_uk/tests/test_carer_support_payment.py +++ b/policyengine_uk/tests/test_carer_support_payment.py @@ -126,7 +126,11 @@ def test_partner_csp_for_caring_gives_couple_severe_disability_single_rate_or_ni def test_csp_counts_for_uc_non_dep_exemption_and_housing_benefit_income(): - sim = Simulation(situation=_situation(YEAR_2025)) + situation = _situation(YEAR_2025) + # Not claiming Universal Credit: on it, the whole of the Housing Benefit + # income would be disregarded (SI 2006/213 Sch 5 para 4). + situation["benunits"]["benunit"]["would_claim_uc"] = {YEAR_2025: False} + sim = Simulation(situation=situation) csp_amount = sim.calculate("carer_support_payment", YEAR_2025)[0] hb_disregard = sim.calculate( diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_earnings_disregard_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_earnings_disregard_properties.py index 34b3c49c58..0db11ccbd2 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_earnings_disregard_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_earnings_disregard_properties.py @@ -34,8 +34,9 @@ every year from 2015 to 2030, at working and pension age: £5, £10 or £25 (SI 2006/213 Sch 4 paras 4, 7, 10; SI 2006/214 Sch 4 paras 2, 7), plus £17.10 (£37.10 in 2020, SI 2020/371 reg 5) where a work condition holds, - for families with enough earnings and no Income Support, income-based JSA - or income-related ESA (whose working-age earnings are all disregarded). + for families with enough earnings and on none of Universal Credit, Income + Support, income-based JSA or income-related ESA (whose working-age + earnings are all disregarded, Sch 4 para 12). """ import numpy as np @@ -129,6 +130,7 @@ def situation(units, year, earnings_bump=0.0, no_income_related_benefits=False): if no_income_related_benefits: for benefit in ("income_support", "jsa_income", "esa_income"): benunits[f"b{i}"][benefit] = {year: 0.0} + benunits[f"b{i}"]["would_claim_uc"] = {year: False} households[f"h{i}"] = { "members": names, "country": {year: unit["nation"]}, diff --git a/policyengine_uk/tests/test_housing_benefit_earnings_disregard_properties.py b/policyengine_uk/tests/test_housing_benefit_earnings_disregard_properties.py index c20932dfd2..06c0663331 100644 --- a/policyengine_uk/tests/test_housing_benefit_earnings_disregard_properties.py +++ b/policyengine_uk/tests/test_housing_benefit_earnings_disregard_properties.py @@ -5,11 +5,12 @@ else's, plus the £17.10 additional earnings disregard where a work condition is met and net earnings at least equal the other disregards, the deductible childcare charges and £17.10. A claimant who, or whose partner, is on -Income Support, income-based JSA or income-related ESA has all earnings -disregarded (SI 2006/213 Sch 4 para 12), at any age: SI 2006/213 then applies -whatever the claimant's age (reg 5(1)(b)). +Universal Credit, Income Support, income-based JSA or income-related ESA has +all earnings disregarded (SI 2006/213 Sch 4 para 12), at any age: SI 2006/213 +then applies whatever the claimant's age (reg 5(1)(b)). -Invariants, for any generated population of families not on those benefits: +Invariants, for any generated population of families not on those benefits +(none claims Universal Credit): 1. Bounds: 0 <= disregard <= min(net earnings, (£25 + £17.10) x 52), and net earnings never exceed the claimant's and partner's gross earnings. @@ -143,6 +144,7 @@ def situation(units, earnings_bump=0.0, income_support=0.0, age_map=None): names.append(name) benunits[f"b{i}"] = { "members": names, + "would_claim_uc": {YEAR: False}, "income_support": {YEAR: income_support}, "jsa_income": {YEAR: 0.0}, "esa_income": {YEAR: 0.0}, diff --git a/policyengine_uk/tests/test_housing_benefit_specified_accommodation_disregard_properties.py b/policyengine_uk/tests/test_housing_benefit_specified_accommodation_disregard_properties.py index a07f36cf55..0306c17183 100644 --- a/policyengine_uk/tests/test_housing_benefit_specified_accommodation_disregard_properties.py +++ b/policyengine_uk/tests/test_housing_benefit_specified_accommodation_disregard_properties.py @@ -177,6 +177,9 @@ def situation(units, earnings_bump=0.0, income_support=0.0, accommodation=None): names.append(name) benunits[f"b{i}"] = { "members": names, + # Not on Universal Credit, whose passport would disregard all the + # earnings (Sch 4 para 12). + "would_claim_uc": {YEAR: False}, "income_support": {YEAR: income_support}, "jsa_income": {YEAR: 0.0}, "esa_income": {YEAR: 0.0}, diff --git a/policyengine_uk/tests/test_housing_benefit_universal_credit_passport_properties.py b/policyengine_uk/tests/test_housing_benefit_universal_credit_passport_properties.py new file mode 100644 index 0000000000..e7d2d7143a --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_universal_credit_passport_properties.py @@ -0,0 +1,430 @@ +"""Property-based tests for the universal credit limb of the Housing Benefit +passport. + +SI 2006/213 Sch 4 para 12, Sch 5 para 4 and Sch 6 para 5 (NI: SR 2006/405 +Sch 5 para 12, Sch 6 para 4 and Sch 7 para 5) disregard the earnings, the +whole income and the whole capital of a claimant on universal credit, as for +one on income support, income-based JSA or income-related ESA. A person is on +universal credit on any day they are entitled to it, whether it is in payment +or not (reg 2(3B)); the model reads Universal Credit before the benefit cap +and deductions. Housing Benefit is then the appropriate maximum: the eligible +rent, capped at the LHA rate for LHA tenants, less non-dependant deductions +(SSCBA 1992 s.130(3)(a); reg 70). + +The model has no route yet to Housing Benefit alongside Universal Credit +(specified or temporary accommodation, UC (Transitional Provisions) Regs 2014 +reg 5(2)(a)), so each claimant benefit unit supplies housing_benefit_eligible. + +Invariants, for any generated population of renting families (some with a +non-dependant in the household), each on Universal Credit (a supplied amount +before the cap, or one the model computes), not on it, or on a legacy benefit: + +1. Definition: housing_benefit_on_passporting_benefit is true exactly when + Income Support, income-based JSA or income-related ESA is positive, or the + family claims Universal Credit and its amount before the cap is positive. +2. Passport: a passported family has nil applicable income, assessable capital + and tariff income; its earnings disregard is its net earnings; and its + entitlement is exactly the maximum Housing Benefit. Every family's + entitlement is at most that maximum. +3. Metamorphic: for a family on Universal Credit, raising its earnings, + pensions and savings changes neither the passport nor its entitlement. +4. Differential: the universal credit limb and the Income Support limb give + the same Housing Benefit means test. +5. Monotonic: putting a family on Universal Credit never lowers its Housing + Benefit before the cap or its eligibility. (After the cap it can: Universal + Credit counts towards the cap. The test reads the pre-cap amount.) +6. Dates: the universal credit limb applies in every model year from 2014 in + Great Britain and from 2019 in Northern Ireland (in force 28 October 2013 + and 8 May 2018; model years are read on 30 April), and never before. +7. Order independence: with Housing Benefit and Universal Credit both paid, + calculating Housing Benefit, Universal Credit, the benefit cap, the + passport or household net income first gives the same means test, the + same Housing Benefit, Universal Credit and benefit cap reduction for every + benefit unit, and the same household net income. Each population includes + a family whose cap binds, so the passport (which reads Universal Credit + before the cap) adds no circular dependency through the cap. +""" + +import itertools + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation +from policyengine_uk.system import system + +YEAR = 2025 +PROPERTY_SETTINGS = settings( + max_examples=5, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +# State Pension age is 66 until 2026-27; 67 and over is unambiguously pension +# age and 60 and under unambiguously working age. A family whose members are +# all over pension age cannot claim Universal Credit, so there is no such +# shape here. +PENSION_AGE = st.integers(67, 90) +WORKING_AGE = st.integers(18, 60) +SHAPES = { + "single_working": ([WORKING_AGE], 0), + "couple_working": ([WORKING_AGE, WORKING_AGE], 0), + "lone_parent": ([WORKING_AGE], 2), + "couple_with_children": ([WORKING_AGE, WORKING_AGE], 1), + "mixed_age": ([PENSION_AGE, WORKING_AGE], 0), +} +RENTING_TENURES = ["RENT_FROM_COUNCIL", "RENT_FROM_HA", "RENT_PRIVATELY"] +LEGACY = ["income_support", "jsa_income", "esa_income"] +COUNTRIES = ["ENGLAND", "SCOTLAND", "WALES", "NORTHERN_IRELAND"] +money = st.floats(0, 20_000, allow_nan=False, allow_infinity=False) +# A supplied Universal Credit amount before the cap: nil, the one-penny +# minimum, or more. +uc_amount = st.one_of( + st.just(0.0), st.just(0.01), st.floats(1, 15_000, allow_nan=False) +) + + +@st.composite +def families(draw, uc_modes=("off", "supplied", "computed"), legacy=True): + shape = draw(st.sampled_from(sorted(SHAPES))) + ages, n_children = SHAPES[shape] + mode = draw(st.sampled_from(uc_modes)) + # At most one legacy benefit, and none for half the families, so that + # most families on Universal Credit are passported by it alone. + legacy_benefit = draw(st.sampled_from([None] * 3 + LEGACY)) if legacy else None + legacy_amount = draw(st.floats(1, 12_000, allow_nan=False)) + return dict( + adults=[ + dict( + age=draw(age), + employment_income=draw(st.one_of(st.just(0.0), money)), + private_pension_income=draw(st.one_of(st.just(0.0), money)), + ) + for age in ages + ], + children=[draw(st.integers(0, 15)) for _ in range(n_children)], + tenure=draw(st.sampled_from(RENTING_TENURES)), + country=draw(st.sampled_from(COUNTRIES)), + rent=draw(money), + savings=draw(st.one_of(st.just(0.0), st.floats(0, 40_000))), + uc_mode=mode, + uc_amount=draw(uc_amount) if mode == "supplied" else None, + legacy={ + benefit: legacy_amount if benefit == legacy_benefit else 0.0 + for benefit in LEGACY + }, + non_dependant_earnings=draw(st.one_of(st.none(), st.floats(0, 40_000))), + ) + + +# Appended to the order test's population: a lone parent with four children +# paying £18,000 private rent, on Universal Credit (computed) and Housing +# Benefit, whose benefit cap binds. +CAPPED_ON_UNIVERSAL_CREDIT = dict( + adults=[dict(age=30, employment_income=3_000.0, private_pension_income=0.0)], + children=[1, 3, 5, 7], + tenure="RENT_PRIVATELY", + country="ENGLAND", + rent=18_000.0, + savings=0.0, + uc_mode="computed", + uc_amount=None, + legacy={benefit: 0.0 for benefit in LEGACY}, + non_dependant_earnings=None, +) +PAID = ["housing_benefit", "universal_credit", "benefit_cap_reduction"] + + +# Appended to every generated population, so that each example has a family +# passported by Universal Credit alone, with earnings and capital the passport +# must disregard. +ON_UNIVERSAL_CREDIT_ONLY = dict( + adults=[dict(age=40, employment_income=8_000.0, private_pension_income=0.0)], + children=[], + tenure="RENT_FROM_COUNCIL", + country="ENGLAND", + rent=5_200.0, + savings=12_000.0, + uc_mode="supplied", + uc_amount=1_000.0, + legacy={benefit: 0.0 for benefit in LEGACY}, + non_dependant_earnings=None, +) + + +def situation(units, bump=0.0, overrides=None): + """Build one claimant benefit unit per family, first in its household, + followed by any non-dependant's own benefit unit. + + bump raises every adult's earnings and pensions and the savings; overrides + replaces fields of each family (for example its uc_mode or legacy amounts). + """ + people, benunits, households = {}, {}, {} + for i, unit in enumerate(units): + unit = {**unit, **(overrides[i] if overrides else {})} + members = [] + for j, adult in enumerate(unit["adults"]): + name = f"a{i}_{j}" + person = { + "age": {YEAR: adult["age"]}, + "employment_income": {YEAR: adult["employment_income"] + bump}, + "private_pension_income": { + YEAR: adult["private_pension_income"] + bump + }, + } + if j == 0: + person["housing_benefit_reported"] = {YEAR: 1.0} + people[name] = person + members.append(name) + for k, child_age in enumerate(unit["children"]): + name = f"c{i}_{k}" + people[name] = {"age": {YEAR: child_age}} + members.append(name) + benunit = { + "members": list(members), + # Stands in for a claim in specified or temporary accommodation. + "housing_benefit_eligible": {YEAR: True}, + # Pension Credit's guarantee credit passports a pension-age + # family in its own right; hold it at nil to isolate this one. + "guarantee_credit": {YEAR: 0.0}, + **{benefit: {YEAR: unit["legacy"][benefit]} for benefit in LEGACY}, + } + if unit["uc_mode"] == "off": + benunit["would_claim_uc"] = {YEAR: False} + else: + benunit["would_claim_uc"] = {YEAR: True} + if unit["uc_mode"] == "supplied": + benunit["universal_credit_pre_benefit_cap"] = {YEAR: unit["uc_amount"]} + benunits[f"b{i}"] = benunit + household_members = list(members) + if unit["non_dependant_earnings"] is not None: + name = f"n{i}" + people[name] = { + "age": {YEAR: 30}, + "employment_income": {YEAR: unit["non_dependant_earnings"]}, + } + benunits[f"nb{i}"] = {"members": [name], "would_claim_uc": {YEAR: False}} + household_members.append(name) + households[f"h{i}"] = { + "members": household_members, + "country": {YEAR: unit["country"]}, + "tenure_type": {YEAR: unit["tenure"]}, + "rent": {YEAR: unit["rent"]}, + "savings": {YEAR: unit["savings"] + bump}, + } + return {"people": people, "benunits": benunits, "households": households} + + +VARIABLES = [ + "housing_benefit_on_passporting_benefit", + "in_receipt_of_income_support_jsa_ib_or_esa_ir", + "is_uc_entitled", + "would_claim_uc", + "universal_credit_pre_benefit_cap", + "housing_benefit_net_earnings", + "housing_benefit_applicable_income_disregard", + "housing_benefit_applicable_income", + "housing_benefit_assessable_capital", + "housing_benefit_tariff_income", + "housing_benefit_entitlement", + "housing_benefit_eligible", + "housing_benefit_pre_benefit_cap", + "housing_benefit_non_dep_deductions", + "benunit_rent", + "LHA_eligible", + "LHA_cap", +] +MEANS_TEST = [ + "housing_benefit_applicable_income_disregard", + "housing_benefit_applicable_income", + "housing_benefit_assessable_capital", + "housing_benefit_tariff_income", + "housing_benefit_entitlement", +] + + +def calculate(units, **kwargs): + sim = Simulation(situation=situation(units, **kwargs)) + values = {v: np.asarray(sim.calculate(v, YEAR)) for v in VARIABLES} + benunit_ids = list(sim.populations["benunit"].ids) + claimants = [benunit_ids.index(f"b{i}") for i in range(len(units))] + return {k: v[claimants] for k, v in values.items()} + + +def maximum_housing_benefit(values): + rent = values["benunit_rent"] + lha = values["LHA_eligible"].astype(bool) + capped_rent = np.where(lha, np.minimum(rent, values["LHA_cap"]), rent) + return np.maximum(0, capped_rent - values["housing_benefit_non_dep_deductions"]) + + +def passported(values): + return values["housing_benefit_on_passporting_benefit"].astype(bool) + + +@PROPERTY_SETTINGS +@given(st.lists(families(), min_size=1, max_size=20)) +def test_definition_passport_and_maximum(units): + units = units + [ON_UNIVERSAL_CREDIT_ONLY] + values = calculate(units) + passport = passported(values) + # 1. Definition. + legacy = np.array([any(u["legacy"][b] > 0 for b in LEGACY) for u in units]) + claims_uc = values["would_claim_uc"].astype(bool) + on_uc = claims_uc & (values["universal_credit_pre_benefit_cap"] > 0) + assert np.array_equal(values["is_uc_entitled"].astype(bool), on_uc) + assert np.array_equal(passport, legacy | on_uc) + # 2. Passport. + for variable in [ + "housing_benefit_applicable_income", + "housing_benefit_assessable_capital", + "housing_benefit_tariff_income", + ]: + assert np.all(values[variable][passport] == 0), variable + assert np.allclose( + values["housing_benefit_applicable_income_disregard"][passport], + values["housing_benefit_net_earnings"][passport], + atol=0.01, + ) + maximum = maximum_housing_benefit(values) + entitlement = values["housing_benefit_entitlement"] + assert np.all(entitlement <= maximum + 0.01) + assert np.allclose(entitlement[passport], maximum[passport], atol=0.01) + + +@PROPERTY_SETTINGS +@given( + st.lists(families(uc_modes=("supplied",), legacy=False), min_size=1, max_size=20), + st.floats(1, 50_000, allow_nan=False), +) +def test_universal_credit_passport_ignores_income_and_capital(units, bump): + units = units + [ON_UNIVERSAL_CREDIT_ONLY] + before = calculate(units) + after = calculate(units, bump=bump) + passport = passported(before) + # A supplied amount does not move with income, so neither does the + # passport, which holds exactly where the amount is positive. + amounts = np.array([unit["uc_amount"] for unit in units]) + assert np.array_equal(passport, amounts > 0) + assert np.array_equal(passport, passported(after)) + for variable in ["housing_benefit_entitlement", "housing_benefit_eligible"]: + assert np.allclose( + before[variable][passport], after[variable][passport], atol=0.01 + ), variable + + +@PROPERTY_SETTINGS +@given( + st.lists(families(legacy=False), min_size=1, max_size=20), + st.floats(0.01, 15_000, allow_nan=False), +) +def test_universal_credit_and_income_support_limbs_agree(units, amount): + no_legacy = {benefit: 0.0 for benefit in LEGACY} + on_uc = calculate( + units, + overrides=[ + {"uc_mode": "supplied", "uc_amount": amount, "legacy": no_legacy} + for _ in units + ], + ) + on_income_support = calculate( + units, + overrides=[ + {"uc_mode": "off", "legacy": {**no_legacy, "income_support": amount}} + for _ in units + ], + ) + assert passported(on_uc).all() + assert passported(on_income_support).all() + assert not on_uc["in_receipt_of_income_support_jsa_ib_or_esa_ir"].any() + for variable in MEANS_TEST: + assert np.allclose(on_uc[variable], on_income_support[variable], atol=0.01), ( + variable + ) + + +@PROPERTY_SETTINGS +@given( + st.lists(families(legacy=False), min_size=1, max_size=20), + st.floats(0.01, 15_000, allow_nan=False), +) +def test_universal_credit_never_lowers_pre_cap_housing_benefit(units, amount): + off = calculate(units, overrides=[{"uc_mode": "off"} for _ in units]) + on = calculate( + units, + overrides=[{"uc_mode": "supplied", "uc_amount": amount} for _ in units], + ) + assert not passported(off).any() + assert passported(on).all() + assert np.all( + on["housing_benefit_pre_benefit_cap"] + >= off["housing_benefit_pre_benefit_cap"] - 0.01 + ) + assert np.all( + on["housing_benefit_entitlement"] >= off["housing_benefit_entitlement"] - 0.01 + ) + assert np.all(on["housing_benefit_eligible"] >= off["housing_benefit_eligible"]) + + +def test_universal_credit_limb_dates(): + in_force = {"great_britain": 2014, "northern_ireland": 2019} + for year, country in itertools.product(range(2013, 2031), COUNTRIES): + jurisdiction = ( + "northern_ireland" if country == "NORTHERN_IRELAND" else "great_britain" + ) + sim = Simulation( + situation={ + "people": {"p": {"age": {year: 40}}}, + "benunits": { + "b": { + "members": ["p"], + "is_uc_entitled": {year: True}, + "in_receipt_of_income_support_jsa_ib_or_esa_ir": {year: False}, + } + }, + "households": {"h": {"members": ["p"], "country": {year: country}}}, + } + ) + expected = year >= in_force[jurisdiction] + result = sim.calculate("housing_benefit_on_passporting_benefit", year)[0] + assert bool(result) == expected, (year, country) + p = system.parameters(year).gov.dwp.housing_benefit.means_test + assert bool(p.universal_credit_passport[jurisdiction]) == expected + + +@PROPERTY_SETTINGS +@given( + st.lists(families(uc_modes=("computed",), legacy=False), min_size=1, max_size=10) +) +def test_calculation_order_does_not_change_results(units): + units = units + [CAPPED_ON_UNIVERSAL_CREDIT] + capped = f"b{len(units) - 1}" + results = [] + for first in [ + "housing_benefit", + "universal_credit", + "benefit_cap_reduction", + "housing_benefit_on_passporting_benefit", + "household_net_income", + ]: + sim = Simulation(situation=situation(units)) + sim.calculate(first, YEAR) + values = { + v: np.asarray(sim.calculate(v, YEAR), dtype=float) for v in VARIABLES + PAID + } + values["household_net_income"] = np.asarray( + sim.calculate("household_net_income", YEAR), dtype=float + ) + results.append(values) + # The sentinel is passported by Universal Credit and capped, so a + # dependency of the passport on the capped amounts would show here. + i = list(sim.populations["benunit"].ids).index(capped) + assert results[0]["housing_benefit_on_passporting_benefit"][i] == 1 + assert results[0]["benefit_cap_reduction"][i] > 0 + assert results[0]["housing_benefit_pre_benefit_cap"][i] > 0 + for other in results[1:]: + for variable in results[0]: + assert np.allclose(results[0][variable], other[variable], atol=0.01), ( + variable + ) diff --git a/policyengine_uk/tests/test_lifetime_isa_capital.py b/policyengine_uk/tests/test_lifetime_isa_capital.py index c06f16af6d..09b1c3434b 100644 --- a/policyengine_uk/tests/test_lifetime_isa_capital.py +++ b/policyengine_uk/tests/test_lifetime_isa_capital.py @@ -70,8 +70,16 @@ def test_emptying_a_person_sources_list_disregards_the_lifetime_isa_there_only() "2025-01-01.2100-12-31": [] } } - baseline = Simulation(situation=LIFETIME_ISA_HOLDER) - reformed = Simulation(situation=LIFETIME_ISA_HOLDER, reform=reform) + # Not claiming Universal Credit: on it, the whole of the Housing Benefit + # capital would be disregarded (SI 2006/213 Sch 6 para 5). + holder = { + **LIFETIME_ISA_HOLDER, + "benunits": { + "benunit": {"members": ["person"], "would_claim_uc": {"2025": False}} + }, + } + baseline = Simulation(situation=holder) + reformed = Simulation(situation=holder, reform=reform) assert baseline.calculate("uc_assessable_capital", 2025)[0] == 8_500 assert reformed.calculate("uc_assessable_capital", 2025)[0] == 1_000 diff --git a/policyengine_uk/tests/test_means_test_income_properties.py b/policyengine_uk/tests/test_means_test_income_properties.py index fcfb8f56a2..49a9088ef2 100644 --- a/policyengine_uk/tests/test_means_test_income_properties.py +++ b/policyengine_uk/tests/test_means_test_income_properties.py @@ -8,6 +8,10 @@ Each example builds families twice in one simulation: once with the other member's income and once without, in separate households and benefit units. +It does so with every family claiming Universal Credit (the default) and with +none claiming it: a family on Universal Credit has its whole Housing Benefit +income disregarded (SI 2006/213 Sch 5 para 4), so the Housing Benefit means +test is only exercised off it. """ import numpy as np @@ -76,7 +80,7 @@ def families(draw): return family -def situation(families_): +def situation(families_, would_claim_uc=None): people, benunits, households = {}, {}, {} for i, family in enumerate(families_): names = [] @@ -85,6 +89,8 @@ def situation(families_): people[name] = {k: {YEAR: v} for k, v in inputs.items()} names.append(name) benunits[f"b{i}"] = {"members": names} + if would_claim_uc is not None: + benunits[f"b{i}"]["would_claim_uc"] = {YEAR: would_claim_uc} households[f"h{i}"] = {"members": names} return {"people": people, "benunits": benunits, "households": households} @@ -109,15 +115,20 @@ def test_income_of_non_claimants_never_counts(units): ] for family in units ] - sim = Simulation(situation=situation(units + without)) - offsets = np.cumsum([0] + [len(f) for f in units]) - n = len(units) - for variable in FAMILY_FLAGS: - flags = sim.calculate(variable, YEAR) - for i in range(n): - # The generator's construction, checked against the model. - assert not flags[offsets[i + 1] - 1], (variable, units[i]) - for variable in INCOME_TESTS: - values = sim.calculate(variable, YEAR) - for i in range(n): - assert abs(values[i] - values[n + i]) < 0.01, (variable, units[i]) + for would_claim_uc in (None, False): + sim = Simulation(situation=situation(units + without, would_claim_uc)) + offsets = np.cumsum([0] + [len(f) for f in units]) + n = len(units) + for variable in FAMILY_FLAGS: + flags = sim.calculate(variable, YEAR) + for i in range(n): + # The generator's construction, checked against the model. + assert not flags[offsets[i + 1] - 1], (variable, units[i]) + for variable in INCOME_TESTS: + values = sim.calculate(variable, YEAR) + for i in range(n): + assert abs(values[i] - values[n + i]) < 0.01, ( + variable, + would_claim_uc, + units[i], + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py index da8034ccf0..6119abf2e1 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py @@ -7,18 +7,20 @@ class housing_benefit_applicable_income(Variable): label = "relevant income for Housing Benefit means test" documentation = ( "Income taken into account in the Housing Benefit means test. It is " - "nil for a family in receipt of Income Support, income-based " + "nil for a family on Universal Credit, Income Support, income-based " "Jobseeker's Allowance or income-related Employment and Support " - "Allowance, whose whole income is disregarded, and for a pension-age " - "family with a positive guarantee credit (the guarantee credit " - "passport). Where the Pension Credit award is savings credit only, it " - "is the Secretary of State's assessment of income plus the savings " - "credit payable, less childcare charges and the earnings disregards. " - "Otherwise it is the family's income under the Housing Benefit rules." + "Allowance (housing_benefit_on_passporting_benefit), whose whole " + "income is disregarded, and for a pension-age family with a positive " + "guarantee credit (the guarantee credit passport). Where the Pension " + "Credit award is savings credit only, it is the Secretary of State's " + "assessment of income plus the savings credit payable, less childcare " + "charges and the earnings disregards. Otherwise it is the family's " + "income under the Housing Benefit rules." ) reference = ( "https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4", "https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", "https://www.legislation.gov.uk/uksi/2006/213/regulation/5", "https://www.legislation.gov.uk/uksi/2006/214/regulation/26", "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", @@ -122,22 +124,22 @@ def formula(benunit, period, parameters): benunit("guarantee_credit", period) > 0 ) # SI 2006/213 Sch 5 para 4 (NI: SR 2006/405 Sch 6 para 4) disregards - # "the whole of his income" where a claimant is on income support, an - # income-based jobseeker's allowance or an income-related employment - # and support allowance. Para 5 does the same where the claimant's - # partner in a joint-claim couple is on income-based JSA. The model - # holds these awards for the benefit unit and cannot tell which member - # claims Housing Benefit (a couple choose, reg 82(1)), so it applies - # the disregard whichever member is on the benefit. There is no age - # condition: SI 2006/213 reg 5(1)(b) (NI: SR 2006/405 reg 5(1)(b)) - # applies these regulations to a claimant over the qualifying age for - # State Pension Credit whose partner is on one of these benefits, so a - # mixed-age couple whose younger member is on income-related ESA is - # covered. The universal credit limb is left out: the model never pays - # Housing Benefit and Universal Credit to the same family - # (housing_benefit_eligible), and Universal Credit depends on Housing - # Benefit through the benefit cap. - on_income_related_benefit = benunit( - "in_receipt_of_income_support_jsa_ib_or_esa_ir", period + # "the whole of his income" where a claimant is on universal credit, + # income support, an income-based jobseeker's allowance or an + # income-related employment and support allowance. Para 5 does the + # same where the claimant's partner in a joint-claim couple is on + # income-based JSA. The model holds these awards for the benefit unit + # and cannot tell which member claims Housing Benefit (a couple + # choose, reg 82(1)), so it applies the disregard whichever member is + # on the benefit. There is no age condition: SI 2006/213 reg 5(1)(b) + # (NI: SR 2006/405 reg 5(1)(b)) applies these regulations to a + # claimant over the qualifying age for State Pension Credit whose + # partner is on one of these benefits, so a mixed-age couple whose + # younger member is on income-related ESA or Universal Credit is + # covered. Universal Credit is read before the benefit cap + # (housing_benefit_on_passporting_benefit), which avoids a circular + # dependency through the cap. + on_passporting_benefit = benunit( + "housing_benefit_on_passporting_benefit", period ) - return where(guarantee_credit | on_income_related_benefit, 0, applicable_income) + return where(guarantee_credit | on_passporting_benefit, 0, applicable_income) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.py index ba2414d9c2..a7600bf518 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.py @@ -14,16 +14,16 @@ class housing_benefit_applicable_income_disregard(Variable): "also capped at net earnings. The additional earnings disregard of " "£17.10 is added where a work condition is met and net earnings at " "least equal the other disregards (including that one), the childcare " - "charges deducted and £17.10. A claimant who, or whose partner, is on " - "Income Support, " - "income-based Jobseeker's Allowance or income-related Employment and " - "Support Allowance has all earnings disregarded, at any age: the " - "working-age Regulations then apply (SI 2006/213 reg 5(1)(b)). The " + "charges deducted and £17.10. A family on Universal Credit, Income " + "Support, income-based Jobseeker's Allowance or income-related " + "Employment and Support Allowance " + "(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 " "disregard (Sch 4 para 10A), which replaces paras 3 to 10 but not " - "para 18. Nor is the universal credit limb of para 12: the model does " - "not pay Housing Benefit to a family on Universal Credit." + "para 18." ) definition_period = YEAR unit = GBP @@ -32,6 +32,8 @@ class housing_benefit_applicable_income_disregard(Variable): "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", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/5/paragraph/12", "https://www.legislation.gov.uk/uksi/2026/978/regulation/2", "https://www.legislation.gov.uk/nisr/2026/157/regulation/2", ) @@ -79,16 +81,18 @@ def formula(benunit, period, parameters): additional_amount, 0, ) - # Working age Sch 4 para 12. The working-age Regulations apply at any + # Working age Sch 4 para 12 (NI: SR 2006/405 Sch 5 para 12): "Where a + # claimant is on universal credit, income support, an income-based + # jobseeker's allowance or an income-related employment and support + # allowance, his earnings." The working-age Regulations apply at any # age where the claimant or partner is on one of these benefits (SI # 2006/213 reg 5(1)(b); SI 2006/214 reg 5(2)), so there is no age - # condition. Families on Universal Credit cannot receive Housing - # Benefit in the model. - on_income_related_benefit = ( - add(benunit, period, ["income_support", "jsa_income", "esa_income"]) > 0 + # condition. + on_passporting_benefit = benunit( + "housing_benefit_on_passporting_benefit", period ) return where( - on_income_related_benefit, + on_passporting_benefit, net_earnings, standard + accommodation + additional, ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py index 69a6c23fbe..59dd042318 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py @@ -15,10 +15,11 @@ class housing_benefit_assessable_capital(Variable): "partner (is_claimant_or_partner): a dependant's capital is not the " "claimant's. Where the Pension Credit award is savings credit only, the " "Pension Credit assessment of capital is used instead. It is nil for a " - "family in receipt of Income Support, income-based Jobseeker's " - "Allowance or income-related Employment and Support Allowance, and for " - "a pension-age family with a positive guarantee credit (the guarantee " - "credit passport)." + "family on Universal Credit, Income Support, income-based Jobseeker's " + "Allowance or income-related Employment and Support Allowance " + "(housing_benefit_on_passporting_benefit), and for a pension-age " + "family with a positive guarantee credit (the guarantee credit " + "passport)." ) definition_period = YEAR unit = GBP @@ -27,6 +28,7 @@ class housing_benefit_assessable_capital(Variable): "https://www.legislation.gov.uk/uksi/2006/213/regulation/25", "https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5", "https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", ) @@ -79,17 +81,17 @@ def formula(benunit, period, parameters): benunit("guarantee_credit", period) > 0 ) # SI 2006/213 Sch 6 para 5 (NI: SR 2006/405 Sch 7 para 5) disregards - # "the whole of his capital" where a claimant is on income support, an - # income-based jobseeker's allowance or an income-related employment - # and support allowance (para 6: a joint-claim partner on income-based - # JSA). With no capital the tariff income is nil and the capital limit - # is met. See housing_benefit_applicable_income for the age and - # universal credit points. - on_income_related_benefit = benunit( - "in_receipt_of_income_support_jsa_ib_or_esa_ir", period + # "the whole of his capital" where a claimant is on universal credit, + # income support, an income-based jobseeker's allowance or an + # income-related employment and support allowance (para 6: a + # joint-claim partner on income-based JSA). With no capital the tariff + # income is nil and the capital limit is met. See + # housing_benefit_applicable_income for the age and benefit cap points. + on_passporting_benefit = benunit( + "housing_benefit_on_passporting_benefit", period ) return where( - guarantee_credit | on_income_related_benefit, + guarantee_credit | on_passporting_benefit, 0, max_(0, capital), ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_on_passporting_benefit.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_on_passporting_benefit.py new file mode 100644 index 0000000000..b0b3a3edc8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_on_passporting_benefit.py @@ -0,0 +1,65 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_on_passporting_benefit(Variable): + label = "on a benefit that passports the Housing Benefit means test" + documentation = ( + "Whether this benefit unit is on Universal Credit, Income Support, " + "income-based Jobseeker's Allowance or income-related Employment and " + "Support Allowance, which disregards the whole of its earnings, other " + "income and capital in the Housing Benefit means test. Income Support, " + "income-based JSA and income-related ESA count when a positive amount " + "is paid (in_receipt_of_income_support_jsa_ib_or_esa_ir). A person is " + "on Universal Credit on any day they are entitled to it, whether it is " + "in payment or not (SI 2006/213 and SR 2006/405 reg 2(3B)). The model " + "reads that as Universal Credit above nil before the benefit cap and " + "deductions (is_uc_entitled), for a family that claims it " + "(would_claim_uc), so a Universal Credit award that the cap or " + "deductions reduce to nil still counts. The model tests the year " + "rather than each day, and both members of a joint claim are on " + "Universal Credit. There is no age condition: the working-age " + "regulations apply to a claimant over the qualifying age for State " + "Pension Credit whose partner is on one of these benefits (reg " + "5(1)(b)), and the model's Universal Credit needs a claimant or " + "partner under the qualifying age for State Pension Credit in any " + "case (is_uc_eligible). The " + "universal credit limb applies from 28 October " + "2013 in Great Britain and 8 May 2018 in Northern Ireland " + "(gov.dwp.housing_benefit.means_test.universal_credit_passport)." + ) + entity = BenUnit + definition_period = YEAR + value_type = bool + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/2", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/5/paragraph/12", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5", + ) + + def formula(benunit, period, parameters): + p = parameters( + period + ).gov.dwp.housing_benefit.means_test.universal_credit_passport + country = benunit.household("country", period) + # Great Britain's date applies everywhere but Northern Ireland, + # including an unknown country. + universal_credit_limb = where( + country == country.possible_values.NORTHERN_IRELAND, + p.northern_ireland, + p.great_britain, + ) + # Universal Credit before the benefit cap and deductions: Universal + # Credit depends on Housing Benefit through the benefit cap + # (benefit_cap_reduction), so reading the amount paid + # (universal_credit) here would be circular. Before the cap is also + # the law's reading: entitlement counts whether or not it is paid. + on_universal_credit = benunit("is_uc_entitled", period) & universal_credit_limb + on_legacy_benefit = benunit( + "in_receipt_of_income_support_jsa_ib_or_esa_ir", period + ) + return on_universal_credit | on_legacy_benefit