diff --git a/changelog.d/1914.fixed.md b/changelog.d/1914.fixed.md new file mode 100644 index 0000000000..3f184fc988 --- /dev/null +++ b/changelog.d/1914.fixed.md @@ -0,0 +1 @@ +Income-related ESA ends for the claimant and partner of a family that claims Universal Credit, as the claim brings its abolition into force (Welfare Reform Act 2012 s.33(1)(b); SI 2013/983 art. 4), so it is no longer paid alongside Universal Credit (#1914). diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml index aac4fec6c6..87009a36b1 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml @@ -9,6 +9,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant @@ -32,6 +33,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant @@ -51,6 +53,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant @@ -71,6 +74,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant @@ -91,6 +95,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant @@ -135,6 +140,7 @@ benunits: claimant_benunit: members: claimant + would_claim_uc: false unrelated_benunit: members: unrelated_adult households: @@ -158,8 +164,10 @@ benunits: benunit_1: members: claimant_1 + would_claim_uc: false benunit_2: members: claimant_2 + would_claim_uc: false households: household: members: [claimant_1, claimant_2] @@ -182,6 +190,7 @@ benunit: members: [claimant, child] would_claim_IS: true + would_claim_uc: false households: household: members: [claimant, child] @@ -202,6 +211,7 @@ benunits: benunit: members: claimant + would_claim_uc: false households: household: members: claimant diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_remunerative_work.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_remunerative_work.yaml index c57c401bbf..eacc7e084d 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_remunerative_work.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_remunerative_work.yaml @@ -40,6 +40,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -63,6 +64,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -88,6 +90,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -112,6 +115,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -135,6 +139,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -159,6 +164,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -181,6 +187,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -205,6 +212,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -226,6 +234,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -248,6 +257,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -275,6 +285,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -299,6 +310,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -320,6 +332,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -348,6 +361,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -383,6 +397,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -410,6 +425,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -433,6 +449,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -458,6 +475,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -483,6 +501,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -514,6 +533,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -540,6 +560,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -571,6 +592,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -596,6 +618,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -620,6 +643,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -646,6 +670,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -678,6 +703,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -703,6 +729,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -734,6 +761,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -760,6 +788,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -791,6 +820,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -818,6 +848,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -843,6 +874,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -868,6 +900,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -899,6 +932,7 @@ benunits: couple: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -924,6 +958,7 @@ benunits: couple: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -949,6 +984,7 @@ benunits: couple: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -975,6 +1011,7 @@ benunits: couple: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -1000,6 +1037,7 @@ benunits: couple: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -1027,6 +1065,7 @@ benunits: couple: members: [first, second] + would_claim_uc: false households: household: members: [first, second] @@ -1053,6 +1092,7 @@ benunits: couple: members: [first, second] + would_claim_uc: false households: household: members: [first, second] @@ -1107,6 +1147,7 @@ benunits: benunit: members: [claimant, lodger] + would_claim_uc: false households: household: members: [claimant, lodger] @@ -1134,6 +1175,7 @@ benunits: benunit: members: [claimant, lodger] + would_claim_uc: false households: household: members: [claimant, lodger] @@ -1167,6 +1209,7 @@ benunits: benunit: members: [claimant, lodger] + would_claim_uc: false households: household: members: [claimant, lodger] @@ -1237,6 +1280,7 @@ couple: members: [carer, partner] income_support_assessable_capital: 0 + would_claim_uc: false households: household: members: [carer, partner] @@ -1268,6 +1312,7 @@ unit: members: [claimant, partner, outside] esa_income_assessable_capital: 0 + would_claim_uc: false households: household: members: [claimant, partner, outside] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_universal_credit_claim.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_universal_credit_claim.yaml new file mode 100644 index 0000000000..efddac0f27 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_universal_credit_claim.yaml @@ -0,0 +1,166 @@ +# Income-related ESA ends when the family claims Universal Credit. +# A claim for Universal Credit brings the abolition of income-related ESA +# (Welfare Reform Act 2012 s.33(1)(b)) into force for the claimant's old style +# ESA award from the first day of the period claimed for, whether or not +# Universal Credit is awarded (SI 2013/983 art. 4(1), (2)(a), (3)(a) and (9); +# Northern Ireland: Welfare Reform (NI) Order 2015 art. 39(1)(b) and SR +# 2017/190 art. 6). The two-week run-on (SI 2019/1152 reg. 5) is not modelled +# in an annual model. A member who is neither the claimant nor the partner +# claims in their own right and is not part of the family's claim. +# No case has capital, so no tariff income: the award is the reported amount. + +- name: Case 1, a single claimant who claims Universal Credit loses income-related ESA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + benunits: + benunit: + members: [person1] + would_claim_uc: true + households: + household: + members: [person1] + output: + claims_universal_credit: true + esa_income_report_closed: true + esa_income_eligible: false + # The UC claim ends the award: 0, not the 5_000 reported. + esa_income: 0 + claimant_or_partner_esa_income: 0 + is_on_income_related_esa: false + +- name: Case 2, the same claimant without a Universal Credit claim keeps income-related ESA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + benunits: + benunit: + members: [person1] + would_claim_uc: false + households: + household: + members: [person1] + output: + claims_universal_credit: false + esa_income_report_closed: false + esa_income_eligible: true + # No claim, no tariff income: the reported 5_000. + esa_income: 5_000 + claimant_or_partner_esa_income: 5_000 + is_on_income_related_esa: true + +- name: Case 3, a Universal Credit claim ends income-related ESA even when no Universal Credit is awarded. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + private_pension_income: 40_000 + benunits: + benunit: + members: [person1] + would_claim_uc: true + households: + household: + members: [person1] + output: + claims_universal_credit: true + # £40,000 of pension income is UC unearned income above the £4,801.68 + # 2025-26 standard allowance (12 x £400.14), so nothing is awarded. + universal_credit: 0 + esa_income_report_closed: true + # The claim still ends the old style award (art. 4(9) of SI 2013/983). + esa_income: 0 + claimant_or_partner_esa_income: 0 + +- name: Case 4, the couple's Universal Credit claim leaves a non-dependent adult's own income-related ESA. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + person2: + age: 38 + is_claimant_or_partner: true + person3: + age: 30 + is_claimant_or_partner: false + current_education: NOT_IN_EDUCATION + esa_income_reported: 2_000 + benunits: + benunit: + members: [person1, person2, person3] + would_claim_uc: true + households: + household: + members: [person1, person2, person3] + output: + claims_universal_credit: true + esa_income_report_closed: [true, true, false] + # Only person3's own claim is left, and person3 does not work. + esa_income_eligible: true + # 2_000, person3's own award, not 5_000 + 2_000. + esa_income: 2_000 + claimant_or_partner_esa_income: 0 + is_on_income_related_esa: [false, false, true] + +- name: Case 5, the gate applies in 2027, after income-related ESA's 1 July 2026 abolition date. + period: 2027 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + benunits: + benunit: + members: [person1] + would_claim_uc: true + households: + household: + members: [person1] + output: + claims_universal_credit: true + esa_income_report_closed: true + esa_income: 0 + claimant_or_partner_esa_income: 0 + +- name: Case 6, a Universal Credit claim ends income-related ESA in Northern Ireland. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 40 + is_claimant_or_partner: true + esa_income_reported: 5_000 + benunits: + benunit: + members: [person1] + would_claim_uc: true + households: + household: + members: [person1] + region: NORTHERN_IRELAND + output: + claims_universal_credit: true + esa_income_report_closed: true + esa_income: 0 + claimant_or_partner_esa_income: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/legacy_capital.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/legacy_capital.yaml index beed6513c8..1c37c4c5c4 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/legacy_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/legacy_capital.yaml @@ -64,6 +64,7 @@ benunits: claimant_benunit: members: [claimant] + would_claim_uc: false unrelated_benunit: members: [unrelated_claimant] households: diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_claimant_partner_gates.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_claimant_partner_gates.yaml index 1dc8fa0c6b..5e3e9191f1 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_claimant_partner_gates.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_claimant_partner_gates.yaml @@ -519,6 +519,7 @@ members: [carer, partner] income_support_assessable_capital: 0 esa_income_assessable_capital: 0 + would_claim_uc: false output: esa_income: 3_000 income_support_eligible: false @@ -542,6 +543,7 @@ income_support_assessable_capital: 0 # Above the £16,000 ESA capital limit (ESA Regs 2008 reg 110). esa_income_assessable_capital: 20_000 + would_claim_uc: false output: esa_income: 0 income_support_eligible: true @@ -582,6 +584,7 @@ members: [carer] income_support_assessable_capital: 0 esa_income: 0 + would_claim_uc: false output: # The model pays no income-related ESA, so none bars Income Support. income_support_eligible: true diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/claimant_or_partner_awards.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/claimant_or_partner_awards.yaml index 06af3598f5..82cb89df67 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/claimant_or_partner_awards.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/claimant_or_partner_awards.yaml @@ -19,6 +19,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -41,6 +42,7 @@ benunits: benunit: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] @@ -89,6 +91,7 @@ benunits: benunit: members: [claimant, other] + would_claim_uc: false households: household: members: [claimant, other] @@ -111,6 +114,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -155,6 +159,7 @@ benunit: members: [claimant] esa_income: 0 + would_claim_uc: false households: household: members: [claimant] @@ -362,6 +367,7 @@ benunit: members: [claimant] esa_income: 200 + would_claim_uc: false households: household: members: [claimant] @@ -385,6 +391,7 @@ benunit: members: [claimant] esa_income: 0 + would_claim_uc: false households: household: members: [claimant] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/council_tax_reduction_passports.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/council_tax_reduction_passports.yaml index 88a4f16cfa..e36da6ed71 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/council_tax_reduction_passports.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/council_tax_reduction_passports.yaml @@ -36,6 +36,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -187,6 +188,7 @@ nondep_unit: members: [nondep, other] universal_credit: 0 + would_claim_uc: false households: household: members: [applicant, nondep, other] @@ -217,6 +219,7 @@ nondep_unit: members: [payee, partner] universal_credit: 0 + would_claim_uc: false households: household: members: [applicant, payee, partner] @@ -254,6 +257,7 @@ nondep_unit: members: [payee, partner] universal_credit: 0 + would_claim_uc: false households: household: members: [applicant, payee, partner] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/income_support_take_up_and_person_awards.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/income_support_take_up_and_person_awards.yaml index 9a9b4e688b..09d946e58f 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/income_support_take_up_and_person_awards.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/income_support_take_up_and_person_awards.yaml @@ -107,6 +107,7 @@ benunits: benunit: members: [claimant, partner, other] + would_claim_uc: false households: household: members: [claimant, partner, other] @@ -148,6 +149,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/means_test_income.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/means_test_income.yaml index 8e4bb2be1a..3b5ed5f49c 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/means_test_income.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/means_test_income.yaml @@ -118,6 +118,7 @@ benunit: members: [claimant, other] universal_credit: 0 + would_claim_uc: false households: household: members: [claimant, other] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/mixed_age_couple_pension_credit_saving.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/mixed_age_couple_pension_credit_saving.yaml index 93921ebd58..5e3e43c563 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/mixed_age_couple_pension_credit_saving.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/mixed_age_couple_pension_credit_saving.yaml @@ -78,6 +78,7 @@ benunit: members: [older, younger] is_mixed_age_couple: true + would_claim_uc: false households: household: members: [older, younger] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/passports.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/passports.yaml index cb78e220ce..63c07bf301 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/passports.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/passports.yaml @@ -45,6 +45,7 @@ benunits: benunit: members: [claimant] + would_claim_uc: false households: household: members: [claimant] @@ -153,6 +154,7 @@ child_tax_credit: 0 working_tax_credit: 0 pension_credit: 0 + would_claim_uc: false households: household: members: [parent, child, other] @@ -272,6 +274,7 @@ meets_child_tax_credit_criteria_for_targeted_childcare_entitlement: false working_tax_credit_run_on: false extended_childcare_entitlement_eligible: false + would_claim_uc: false households: household: members: [parent, child, other] @@ -382,6 +385,7 @@ benunit: members: [claimant, other] working_tax_credit: 0 + would_claim_uc: false households: household: members: [claimant, other] @@ -413,6 +417,7 @@ benunits: benunit: members: [parent, student] + would_claim_uc: false households: household: members: [parent, student] @@ -459,6 +464,7 @@ benunits: benunit: members: [student, partner] + would_claim_uc: false households: household: members: [student, partner] @@ -483,6 +489,7 @@ benunits: benunit: members: [student, partner] + would_claim_uc: false households: household: members: [student, partner] diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/pension_credit_earnings_disregard.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/pension_credit_earnings_disregard.yaml index bca7da11ad..417c6041ab 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/pension_credit_earnings_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/legacy_award_readers/pension_credit_earnings_disregard.yaml @@ -85,6 +85,7 @@ benunits: benunit: members: [claimant, partner] + would_claim_uc: false households: household: members: [claimant, partner] diff --git a/policyengine_uk/tests/policy/baseline/gov/dfe/bursary_fund_16_to_19/bursary_fund_16_to_19.yaml b/policyengine_uk/tests/policy/baseline/gov/dfe/bursary_fund_16_to_19/bursary_fund_16_to_19.yaml index 33600f00ac..0cf3e91122 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dfe/bursary_fund_16_to_19/bursary_fund_16_to_19.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dfe/bursary_fund_16_to_19/bursary_fund_16_to_19.yaml @@ -239,6 +239,7 @@ benunits: benunit: members: ["student"] + would_claim_uc: false households: household: members: ["student"] 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 fed93729ca..5f5f0b671d 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 @@ -308,6 +308,7 @@ benunits: parent: members: parent + would_claim_uc: false adult_child: members: adult_child households: diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/universal_credit/person_legacy_benefits_closed.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/universal_credit/person_legacy_benefits_closed.yaml index 2f4f43bbfb..352e12a1be 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/universal_credit/person_legacy_benefits_closed.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/universal_credit/person_legacy_benefits_closed.yaml @@ -25,7 +25,8 @@ "claimant", "partner", "outside" - ] + ], + "would_claim_uc": false } }, "households": { diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/winter_fuel_payment/relevant_benefit_receipt.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/winter_fuel_payment/relevant_benefit_receipt.yaml index 220b4bbcd5..bfd3411b3e 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/winter_fuel_payment/relevant_benefit_receipt.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/winter_fuel_payment/relevant_benefit_receipt.yaml @@ -1184,6 +1184,7 @@ jsa_income: 0 income_support: 0 universal_credit: 0 + would_claim_uc: false households: household: members: [pension_credit_payee, partner] diff --git a/policyengine_uk/tests/test_benefit_cap_specified_benefits_properties.py b/policyengine_uk/tests/test_benefit_cap_specified_benefits_properties.py index 5b173020fe..f65edc3e71 100644 --- a/policyengine_uk/tests/test_benefit_cap_specified_benefits_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_specified_benefits_properties.py @@ -4,7 +4,9 @@ - the claimant or partner receives ESA that includes the support component (75F(1)(a); 83(1)(a)), industrial injuries benefit, attendance allowance - or an armed forces compensation payment (75F(1)(b)-(d); 83(1)(b)-(e)); + or an armed forces compensation payment (75F(1)(b)-(d); 83(1)(b)-(e)). A + Universal Credit claim ends the couple's income-related ESA (SI 2013/983 + art. 4), so a claiming family can count only contributory ESA; - the claimant, partner or a child or young person they are responsible for receives disability living allowance (75F(1)(e); 83(1)(f)); - the claimant, partner or a young person they are responsible for receives @@ -279,8 +281,14 @@ def reference_specified_benefit(members, benunit_inputs, scheme): young_roles = ("young_person", "sixteen") if scheme == "uc" else ("young_person",) young_persons = [m for m in members if m["_role"] in young_roles] children = [m for m in members if m["_role"] == "child"] - # No capital, so the couple's income-related award is their reports. - couple_award = any(m["esa_income_reported"] > 0 for m in claimants) + # No capital, so the couple's income-related award is their reports, + # unless the family claims Universal Credit: the claim ends it (SI + # 2013/983 art. 4; esa_income_report_closed). would_claim_uc defaults to + # true. + claims_uc = benunit_inputs.get("would_claim_uc", True) + couple_award = not claims_uc and any( + m["esa_income_reported"] > 0 for m in claimants + ) def support_component(m): # Supplied, or assumed for anyone with their own allowance. @@ -398,9 +406,12 @@ def reference_cap(members): def capped_family(scheme): """30,000 of the scheme's award before the cap and none of the other's; the other family-level capped benefits are nil, so the capped total is - the award plus whatever the claimant's and partner's own benefits add.""" + the award plus whatever the claimant's and partner's own benefits add. + The family claims Universal Credit exactly when it is on it, so the + couple's income-related ESA continues only on Housing Benefit.""" return { **CAPPED_FAMILY, + "would_claim_uc": scheme == "uc", "universal_credit_pre_benefit_cap": 30_000 if scheme == "uc" else 0, "housing_benefit_pre_benefit_cap": 30_000 if scheme == "hb" else 0, # This supplied award exercises the cap independently of take-up; diff --git a/policyengine_uk/tests/test_claimant_or_partner_awards_entered_directly.py b/policyengine_uk/tests/test_claimant_or_partner_awards_entered_directly.py index 8a1104b6c1..39c805137f 100644 --- a/policyengine_uk/tests/test_claimant_or_partner_awards_entered_directly.py +++ b/policyengine_uk/tests/test_claimant_or_partner_awards_entered_directly.py @@ -46,7 +46,11 @@ def family(award): reported: {YEAR: 3_000}, }, }, - "benunits": {"family": {"members": members}}, + # Not claiming Universal Credit, which would end the claimant's + # income-related ESA (esa_income_report_closed). + "benunits": { + "family": {"members": members, "would_claim_uc": {YEAR: False}} + }, "households": {"home": {"members": members}}, } ) @@ -154,7 +158,11 @@ def test_the_raw_reported_total_is_read_through_the_reports(award): reported: {YEAR: 3_000}, }, }, - "benunits": {"family": {"members": members}}, + # Not claiming Universal Credit, which would end the partner's + # income-related ESA (esa_income_report_closed). + "benunits": { + "family": {"members": members, "would_claim_uc": {YEAR: False}} + }, "households": {"home": {"members": members, "savings": {YEAR: 10_000}}}, } ) diff --git a/policyengine_uk/tests/test_disable_simulated_benefits_benefit_cap.py b/policyengine_uk/tests/test_disable_simulated_benefits_benefit_cap.py index cf8dbee648..3647f78d50 100644 --- a/policyengine_uk/tests/test_disable_simulated_benefits_benefit_cap.py +++ b/policyengine_uk/tests/test_disable_simulated_benefits_benefit_cap.py @@ -234,7 +234,11 @@ def test_a_couple_that_is_not_the_claimant_and_partner_reads_the_stored_award(): "claimant": {"age": 40, "esa_income_reported": 3_000}, "partner": {"age": 38, "esa_income_reported": 2_000}, }, - "benunits": {"couple": {"members": ["claimant", "partner"]}}, + # Not claiming Universal Credit, which would end the couple's + # income-related ESA (esa_income_report_closed). + "benunits": { + "couple": {"members": ["claimant", "partner"], "would_claim_uc": False} + }, "households": {"home": {"members": ["claimant", "partner"]}}, } ) diff --git a/policyengine_uk/tests/test_esa_income_universal_credit_claim_properties.py b/policyengine_uk/tests/test_esa_income_universal_credit_claim_properties.py new file mode 100644 index 0000000000..6fc6e412da --- /dev/null +++ b/policyengine_uk/tests/test_esa_income_universal_credit_claim_properties.py @@ -0,0 +1,203 @@ +"""Property-based tests for the end of income-related ESA on a Universal +Credit claim (#1914). + +A claim for Universal Credit brings the abolition of income-related ESA +(Welfare Reform Act 2012 s.33(1)(b)) into force for the claimant's old style +ESA award, whether or not Universal Credit is awarded (SI 2013/983 art. 4(1), +(2)(a), (3)(a) and (9); NI: SR 2017/190 art. 6). The claim is the claimant's +and partner's. A member who is neither, such as a non-dependent adult, claims +income-related ESA in their own right and is not part of it. + +Invariants, for any generated population of working-age families in 2025 +and 2027 (either side of income-related ESA's 1 July 2026 abolition date, +which the model does not yet apply) with no other legacy benefit, so none is +moved off legacy benefits: + +1. Exclusive: a family that claims Universal Credit pays its claimant and + partner no income-related ESA (claimant_or_partner_esa_income), and + neither of them is on it (is_on_income_related_esa). So Universal Credit + and the claimant's or partner's income-related ESA are never both paid. + Without a claim the gate is inert: esa_income_report_closed is + person_legacy_benefits_closed. +2. Differential: claiming Universal Credit gives the same income-related ESA + outcomes (esa_income, claimant_or_partner_esa_income, esa_income_eligible + and each member's is_on_income_related_esa) as not claiming with the + claimant's and partner's reports removed. Another member's own award is + what it would be if the couple had never reported one. + +Intended: claiming Universal Credit can raise esa_income. While the claimant +or partner reports an award, the benefit unit's screen tests only them, and +another member's report is paid or not with their claim +(esa_income_eligible). Once the claim ends the couple's award, that member is +screened on their own claim alone, as invariant 2 says. +""" + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +pytestmark = pytest.mark.usefixtures("cloned_uk_tax_benefit_system") + +YEARS = (2025, 2027) +PROPERTY_SETTINGS = settings( + max_examples=10, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +WORKING_AGE = st.integers(25, 60) +# "other" is an adult who is neither the claimant, the partner nor a young +# person they are responsible for, so they claim in their own right. +SHAPES = { + "single": ["claimant"], + "couple": ["claimant", "partner"], + "lone_parent": ["claimant", "child"], + "single_with_other": ["claimant", "other"], + "couple_with_other": ["claimant", "partner", "other"], +} +REPORT = st.sampled_from([0.0, 2_000.0, 6_000.0]) +BENUNIT_OUTPUTS = [ + "esa_income", + "claimant_or_partner_esa_income", + "esa_income_eligible", + "claims_universal_credit", + "universal_credit", +] +PERSON_OUTPUTS = [ + "is_on_income_related_esa", + "is_claimant_or_partner", + "esa_income_report_closed", + "person_legacy_benefits_closed", +] + + +@st.composite +def families(draw): + roles = SHAPES[draw(st.sampled_from(sorted(SHAPES)))] + members = [] + for role in roles: + members.append( + dict( + role=role, + age=draw(st.integers(0, 15) if role == "child" else WORKING_AGE), + esa_income_reported=0.0 if role == "child" else draw(REPORT), + employment_income=( + 0.0 + if role == "child" + else draw(st.sampled_from([0.0, 0.0, 4_000.0, 20_000.0])) + ), + weekly_hours=0.0 + if role == "child" + else draw(st.sampled_from([0, 10, 30])), + ) + ) + return dict( + members=members, + # Around the £6,000 tariff threshold and £16,000 limit. + savings=draw(st.sampled_from([0.0, 7_000.0, 20_000.0])), + would_claim_uc=draw(st.booleans()), + ) + + +def every_year(value): + return {year: value for year in YEARS} + + +def situation(units, would_claim_uc=None, drop_couple_reports=False): + people, benunits, households = {}, {}, {} + for i, unit in enumerate(units): + names = [] + for j, member in enumerate(unit["members"]): + name = f"p{i}_{j}" + couple = member["role"] in ("claimant", "partner") + report = member["esa_income_reported"] + if drop_couple_reports and couple: + report = 0.0 + # Set every input for every member, or it stops being an input + # for the rest of the simulation. + people[name] = { + "age": every_year(member["age"]), + "is_claimant_or_partner": every_year(couple), + "current_education": every_year("NOT_IN_EDUCATION"), + "esa_income_reported": every_year(report), + "employment_income": every_year(member["employment_income"]), + "weekly_hours": every_year(member["weekly_hours"]), + } + names.append(name) + claims = unit["would_claim_uc"] if would_claim_uc is None else would_claim_uc + benunits[f"b{i}"] = { + "members": names, + "would_claim_uc": every_year(claims), + "claims_all_entitled_benefits": every_year(False), + } + households[f"h{i}"] = { + "members": names, + "savings": every_year(unit["savings"]), + } + return {"people": people, "benunits": benunits, "households": households} + + +def calculate(units, **kwargs): + sim = Simulation(situation=situation(units, **kwargs)) + return { + year: { + v: np.asarray(sim.calculate(v, year)) + for v in BENUNIT_OUTPUTS + PERSON_OUTPUTS + } + for year in YEARS + } + + +def members_of(units): + """Each person's benefit unit index, in simulation order.""" + return np.array([i for i, unit in enumerate(units) for _ in unit["members"]]) + + +@PROPERTY_SETTINGS +@given(st.lists(families(), min_size=1, max_size=12)) +def test_a_universal_credit_claim_ends_the_couples_income_related_esa(units): + values = calculate(units) + benunit = members_of(units) + for year in YEARS: + v = values[year] + claims = v["claims_universal_credit"].astype(bool) + # Nothing here moves a family off legacy benefits, so the claim is + # would_claim_uc. + assert list(claims) == [unit["would_claim_uc"] for unit in units] + assert np.all(v["claimant_or_partner_esa_income"][claims] == 0), year + assert not np.any( + v["is_on_income_related_esa"].astype(bool) + & v["is_claimant_or_partner"].astype(bool) + & claims[benunit] + ), year + paid_uc = v["universal_credit"] > 0 + assert not np.any(paid_uc & (v["claimant_or_partner_esa_income"] > 0)), year + not_claiming = ~claims[benunit] + assert np.array_equal( + v["esa_income_report_closed"][not_claiming], + v["person_legacy_benefits_closed"][not_claiming], + ), year + + +@PROPERTY_SETTINGS +@given(st.lists(families(), min_size=1, max_size=12)) +def test_a_claim_is_the_couple_reporting_no_income_related_esa(units): + claiming = calculate(units, would_claim_uc=True) + without_couple_reports = calculate( + units, would_claim_uc=False, drop_couple_reports=True + ) + for year in YEARS: + for name in [ + "esa_income", + "claimant_or_partner_esa_income", + "esa_income_eligible", + "is_on_income_related_esa", + ]: + assert np.allclose( + claiming[year][name].astype(float), + without_couple_reports[year][name].astype(float), + atol=0.01, + ), (year, name) diff --git a/policyengine_uk/tests/test_income_support_eligibility_properties.py b/policyengine_uk/tests/test_income_support_eligibility_properties.py index 232ec21431..cb3319414a 100644 --- a/policyengine_uk/tests/test_income_support_eligibility_properties.py +++ b/policyengine_uk/tests/test_income_support_eligibility_properties.py @@ -308,7 +308,9 @@ def situation(units, capital_as_savings, esa_income, jsa_income): people[name] = {k: {YEAR: v} for k, v in inputs.items()} people[name]["is_claimant_or_partner"] = {YEAR: claimant_or_partner} names.append(name) - benunits[f"b{i}"] = {"members": names} + # Legacy claimants: a Universal Credit claim would end the couple's + # income-related ESA (esa_income_report_closed). + benunits[f"b{i}"] = {"members": names, "would_claim_uc": {YEAR: False}} households[f"h{i}"] = {"members": names} if capital_as_savings: households[f"h{i}"]["savings"] = {YEAR: capital} diff --git a/policyengine_uk/tests/test_income_support_esa_entered_directly.py b/policyengine_uk/tests/test_income_support_esa_entered_directly.py index ce9b42862f..d3433a7052 100644 --- a/policyengine_uk/tests/test_income_support_esa_entered_directly.py +++ b/policyengine_uk/tests/test_income_support_esa_entered_directly.py @@ -44,11 +44,14 @@ def simulation(people, benunit=None): return Simulation( situation={ "people": people, + # Legacy claimants: a Universal Credit claim would end the + # carer's income-related ESA (esa_income_report_closed). "benunits": { "b": { "members": names, "income_support_assessable_capital": {YEAR: 0}, "esa_income_assessable_capital": {YEAR: 0}, + "would_claim_uc": {YEAR: False}, **(benunit or {}), } }, diff --git a/policyengine_uk/tests/test_income_support_gate_reads_claimant_or_partner_awards.py b/policyengine_uk/tests/test_income_support_gate_reads_claimant_or_partner_awards.py index b14da3de7b..24894a7fb4 100644 --- a/policyengine_uk/tests/test_income_support_gate_reads_claimant_or_partner_awards.py +++ b/policyengine_uk/tests/test_income_support_gate_reads_claimant_or_partner_awards.py @@ -270,11 +270,14 @@ def simulation(families, entered=None): name = f"p{i}_{j}" people[name] = {k: {YEAR: v} for k, v in inputs.items()} names.append(name) + # Legacy claimants: a Universal Credit claim would end the couple's + # income-related ESA (esa_income_report_closed). benunits[f"b{i}"] = { "members": names, "income_support_assessable_capital": {YEAR: capital}, "esa_income_assessable_capital": {YEAR: capital}, "jsa_income_assessable_capital": {YEAR: capital}, + "would_claim_uc": {YEAR: False}, } for award, values in (entered or {}).items(): benunits[f"b{i}"][award] = {YEAR: values[i]} diff --git a/policyengine_uk/tests/test_legacy_award_readers_properties.py b/policyengine_uk/tests/test_legacy_award_readers_properties.py index 455f4cfe35..a0a5632e9f 100644 --- a/policyengine_uk/tests/test_legacy_award_readers_properties.py +++ b/policyengine_uk/tests/test_legacy_award_readers_properties.py @@ -298,10 +298,13 @@ def situation(units, year=YEAR, benunit_inputs=None): names.append(name) # claims_all_entitled_benefits sums reports across the whole # simulation, so fix the take-up mode per benefit unit: the variants - # must not share it. + # must not share it. The families are on legacy awards and do not + # claim Universal Credit, which would end the couple's income-related + # ESA (esa_income_report_closed). benunits[f"b{i}"] = { "members": names, "claims_all_entitled_benefits": {year: False}, + "would_claim_uc": {year: False}, **{k: {year: v} for k, v in (benunit_inputs or {}).items()}, } households[f"h{i}"] = { @@ -960,6 +963,7 @@ def test_other_members_esa_never_changes_non_dependant_exemption(drawn): benunits[f"nondep_unit_{tag}"] = { "members": unit, "universal_credit": {year: 0}, + "would_claim_uc": {year: False}, } households[f"h_{tag}"] = { "members": names + unit, @@ -1023,7 +1027,7 @@ def test_claimant_and_partner_awards_count_in_full_as_their_ctr_income(): award adds exactly its amount. """ ctr = "council_tax_reduction_applicable_income" - no_uc = {"universal_credit": 0} + no_uc = {"universal_credit": 0, "would_claim_uc": False} claimant_esa = {"claimant": {**CLAIMANT, "esa_income_reported": 5_000}} assert np.isclose( _difference(ctr, {"claimant": CLAIMANT}, claimant_esa, no_uc), 5_000 @@ -1102,7 +1106,7 @@ def _claimant_and_other(other_report): } return { "people": people, - "benunits": {"b": {"members": list(people)}}, + "benunits": {"b": {"members": list(people), "would_claim_uc": {YEAR: False}}}, "households": {"h": {"members": list(people)}}, } @@ -1158,12 +1162,14 @@ def test_late_zero_entry_overrides_the_claimants_reports(): def _situation(people, year=YEAR): + # Not claiming Universal Credit, which would end the claimant's + # income-related ESA (esa_income_report_closed). names = list(people) return { "people": { n: {k: {year: v} for k, v in inputs.items()} for n, inputs in people.items() }, - "benunits": {"b": {"members": names}}, + "benunits": {"b": {"members": names, "would_claim_uc": {year: False}}}, "households": {"h": {"members": names}}, } @@ -1289,6 +1295,7 @@ def member(age, role, report, works): "non_dependant_unit": { "members": ["claimant", "other"], "universal_credit": {year: 0}, + "would_claim_uc": {year: False}, }, }, "households": { diff --git a/policyengine_uk/tests/test_legacy_award_work_properties.py b/policyengine_uk/tests/test_legacy_award_work_properties.py index 1779a07305..3cb5d833d2 100644 --- a/policyengine_uk/tests/test_legacy_award_work_properties.py +++ b/policyengine_uk/tests/test_legacy_award_work_properties.py @@ -151,10 +151,13 @@ def situation(units, year): people[name]["is_claimant_or_partner"] = {year: claimant_or_partner} people[name]["is_parent"] = {year: claimant_or_partner and bool(children)} names.append(name) + # Legacy claimants: a Universal Credit claim would end the couple's + # income-related ESA (esa_income_report_closed). benunits[f"b{i}"] = { "members": names, "esa_income_assessable_capital": {year: capital}, "jsa_income_assessable_capital": {year: capital}, + "would_claim_uc": {year: False}, } households[f"h{i}"] = {"members": names} return {"people": people, "benunits": benunits, "households": households} diff --git a/policyengine_uk/tests/test_legacy_closure_scope.py b/policyengine_uk/tests/test_legacy_closure_scope.py index 4126a21ddc..e3f4428e40 100644 --- a/policyengine_uk/tests/test_legacy_closure_scope.py +++ b/policyengine_uk/tests/test_legacy_closure_scope.py @@ -36,11 +36,15 @@ def household(year, claimant=None, partner=None, outside=None, child=False): name: {key: {str(year): value} for key, value in inputs.items()} for name, inputs in members.items() }, + # The family does not claim Universal Credit of its own accord: that + # claim would end the couple's income-related ESA + # (esa_income_report_closed). "benunits": { "unit": { "members": list(members), "esa_income_assessable_capital": {str(year): 0}, "jsa_income_assessable_capital": {str(year): 0}, + "would_claim_uc": {str(year): False}, } }, "households": {"household": {"members": list(members)}}, diff --git a/policyengine_uk/tests/test_winter_heating_payment_properties.py b/policyengine_uk/tests/test_winter_heating_payment_properties.py index 2639d8881b..66b165de44 100644 --- a/policyengine_uk/tests/test_winter_heating_payment_properties.py +++ b/policyengine_uk/tests/test_winter_heating_payment_properties.py @@ -208,6 +208,10 @@ def situation(drawn, year): variable: {year: AWARD if unit["award"] == key else 0} for key, variable in AWARD_INPUTS.items() }, + # The family claims Universal Credit only when it is on it: a + # claim would end the couple's income-related ESA + # (esa_income_report_closed). + "would_claim_uc": {year: unit["award"] == "UC"}, } benunits[f"h{h}_b{u}"] = benunit hh[f"h{h}"] = {"members": names, "country": {year: household["country"]}} diff --git a/policyengine_uk/utils/benefit_unit.py b/policyengine_uk/utils/benefit_unit.py index 2df7693ab5..330a9ade55 100644 --- a/policyengine_uk/utils/benefit_unit.py +++ b/policyengine_uk/utils/benefit_unit.py @@ -6,6 +6,15 @@ # each other are the same, and an award within half a penny of zero is none. HALF_PENNY = 0.005 +# For each award award_of_members reads, the person-level variable saying the +# award on a member's report has ended. Its formula leaves those reports out: +# income-related ESA also ends for the claimant and partner of a family that +# claims Universal Credit (esa_income_report_closed). +REPORT_CLOSED = { + "esa_income": "esa_income_report_closed", + "jsa_income": "person_legacy_benefits_closed", +} + def add_for_members(benunit, period, variables, members): """Sum variables over the benefit-unit members a means test counts. @@ -82,7 +91,7 @@ def award_of_members(benunit, period, award, report, award_on_reports, members): members_reported = benunit.sum(reported * members) # Formula awards omit reports whose own award has closed. Keep the raw # totals above for disable_simulated_benefits and direct-value provenance. - open_reported = reported * ~person("person_legacy_benefits_closed", period) + open_reported = reported * ~person(REPORT_CLOSED[award], period) award_on_all_reports = award_on_reports(benunit, period, benunit.sum(open_reported)) award_on_members_reports = award_on_reports( benunit, period, benunit.sum(open_reported * members) diff --git a/policyengine_uk/variables/gov/dwp/esa_income.py b/policyengine_uk/variables/gov/dwp/esa_income.py index 7b723bf4c6..e382b53e47 100644 --- a/policyengine_uk/variables/gov/dwp/esa_income.py +++ b/policyengine_uk/variables/gov/dwp/esa_income.py @@ -16,7 +16,10 @@ class esa_income(Variable): label = "ESA (income-based)" documentation = ( "Reported income-related ESA screened through bounded capital and " - "remunerative work tests (esa_income_eligible). " + "remunerative work tests (esa_income_eligible). Reports whose award " + "has ended are left out (esa_income_report_closed): the owner's " + "legacy benefits have closed, or the owner is the claimant or " + "partner of a family that claims Universal Credit. " "This is not a full entitlement model." ) definition_period = YEAR @@ -26,6 +29,6 @@ def formula(benunit, period, parameters): person = benunit.members reported_award = benunit.sum( person("esa_income_reported", period) - * ~person("person_legacy_benefits_closed", period) + * ~person("esa_income_report_closed", period) ) return income_related_esa_award(benunit, period, reported_award) diff --git a/policyengine_uk/variables/gov/dwp/esa_income_eligible.py b/policyengine_uk/variables/gov/dwp/esa_income_eligible.py index c071f77373..690416d60e 100644 --- a/policyengine_uk/variables/gov/dwp/esa_income_eligible.py +++ b/policyengine_uk/variables/gov/dwp/esa_income_eligible.py @@ -26,9 +26,10 @@ class esa_income_eligible(Variable): "in it, so when the claimant or partner reports, another member's " "report is paid or not with their claim. Whether that member is on " "the award themselves (is_on_income_related_esa) is tested on their " - "own claim. Reports whose owner has closed legacy benefits are left " - "out before choosing candidates (person_legacy_benefits_closed). " - "This is not a full " + "own claim. Reports whose award has ended are left out before " + "choosing candidates (esa_income_report_closed): the owner's legacy " + "benefits have closed, or the owner is the claimant or partner of a " + "family that claims Universal Credit. This is not a full " "entitlement model." ) definition_period = YEAR @@ -45,7 +46,7 @@ def formula(benunit, period, parameters): person = benunit.members capital = benunit("esa_income_assessable_capital", period) reports_award = (person("esa_income_reported", period) > 0) & ~person( - "person_legacy_benefits_closed", period + "esa_income_report_closed", period ) claimant_or_partner = person("is_claimant_or_partner", period) # The candidate claimants: the claimant or partner who reports the diff --git a/policyengine_uk/variables/gov/dwp/esa_income_report_closed.py b/policyengine_uk/variables/gov/dwp/esa_income_report_closed.py new file mode 100644 index 0000000000..dd087317c8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_income_report_closed.py @@ -0,0 +1,48 @@ +from policyengine_uk.model_api import * + + +class esa_income_report_closed(Variable): + value_type = bool + entity = Person + label = "Income-related ESA award on this person's report has ended" + documentation = ( + "Whether the income-related ESA award on this person's report has " + "ended, so the model leaves the report out of esa_income, " + "esa_income_eligible and the claimant's or partner's award " + "(claimant_or_partner_esa_income). It ends when the person's legacy " + "benefits close (person_legacy_benefits_closed), or when the person " + "is the claimant or partner of a family that claims Universal Credit " + "(claims_universal_credit). A claim for Universal Credit brings the " + "abolition of income-related ESA (Welfare Reform Act 2012 s.33(1)(b)) " + "into force for the claimant's old style ESA award from the first day " + "of the period claimed for, whether or not Universal Credit is " + "awarded (SI 2013/983 art. 4(1), (2)(a), (3)(a) and (9), and the later " + "commencement orders that extended it to further postcode districts; " + "in Northern Ireland, Welfare Reform (Northern Ireland) Order 2015 " + "art. 39(1)(b) and SR 2017/190 art. 6(1) to (3) and (6)). For claims " + "from 22 July 2020 the award runs on for two weeks after that day (SI " + "2019/1152 reg. 5), which this annual model does not represent. A " + "contributory allowance in the award continues as new style ESA " + "(esa_contrib). A member who is neither the claimant nor the partner, " + "such as a non-dependent adult, claims in their own right and is not " + "part of the family's Universal Credit claim, so the claim does not " + "end their award. The model applies this in every year and area: the " + "postcode districts named in the commencement orders are not " + "modelled." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/ukpga/2012/5/section/33", + "https://www.legislation.gov.uk/uksi/2013/983/article/4", + "https://www.legislation.gov.uk/uksi/2019/1152/regulation/5", + "https://www.legislation.gov.uk/uksi/2025/1148/article/3A", + "https://www.legislation.gov.uk/nisi/2015/2006/article/39", + "https://www.legislation.gov.uk/nisr/2017/190/article/6", + "https://www.legislation.gov.uk/nisr/2025/176/article/3A", + ) + + def formula(person, period, parameters): + claims_uc = person.benunit("claims_universal_credit", period) + return person("person_legacy_benefits_closed", period) | ( + person("is_claimant_or_partner", period) & claims_uc + ) diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/claims_universal_credit.py b/policyengine_uk/variables/gov/dwp/universal_credit/claims_universal_credit.py index 21a1bdc84f..952acc87e0 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/claims_universal_credit.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/claims_universal_credit.py @@ -10,17 +10,19 @@ class claims_universal_credit(Variable): "anyway (would_claim_uc), or it claims when DWP moves it off its " "legacy benefits (claims_uc_at_legacy_closure). Universal Credit is " "paid only to claiming families. A claim ends the family's Housing " - "Benefit continuing award and Child Tax Credit. Once DWP moves a " - "family off legacy benefits (legacy_benefits_closed) all its legacy " - "awards end; for other claimants the overlap of Universal Credit " - "with Working Tax Credit, Income Support, income-related ESA and " - "income-based JSA is not modelled, nor is Housing Benefit for " - "specified or temporary accommodation." + "Benefit continuing award and Child Tax Credit, and the claimant's " + "and partner's income-related ESA (esa_income_report_closed). Once " + "DWP moves a family off legacy benefits (legacy_benefits_closed) all " + "its legacy awards end; for other claimants the overlap of Universal " + "Credit with Working Tax Credit, Income Support and income-based JSA " + "is not modelled, nor is Housing Benefit for specified or temporary " + "accommodation." ) definition_period = YEAR reference = ( "https://www.legislation.gov.uk/uksi/2014/1230/regulation/8", "https://www.legislation.gov.uk/uksi/2014/1230/regulation/46", + "https://www.legislation.gov.uk/uksi/2013/983/article/4", ) def formula(benunit, period, parameters):