From 77bc05a773e6de1567d3650ddce4103c907b0a5c Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:49:43 +0400 Subject: [PATCH 1/3] Fix Housing Benefit capital threshold history and age references --- changelog.d/2197.fixed.md | 1 + .../allowances/age_threshold/older.yaml | 12 ++- .../allowances/age_threshold/younger.yaml | 13 ++- .../pension_age/tariff_income/threshold.yaml | 23 ++++- .../test_housing_benefit_parameter_history.py | 96 +++++++++++++++++++ 5 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 changelog.d/2197.fixed.md create mode 100644 policyengine_uk/tests/test_housing_benefit_parameter_history.py diff --git a/changelog.d/2197.fixed.md b/changelog.d/2197.fixed.md new file mode 100644 index 0000000000..7d50653911 --- /dev/null +++ b/changelog.d/2197.fixed.md @@ -0,0 +1 @@ +- Corrected the written pre-November-2009 pension-age Housing Benefit capital threshold and allowance age source references, without changing supported 2015-onward threshold values. diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/older.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/older.yaml index 9b1ea6b20f..d55b7e986a 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/older.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/older.yaml @@ -1,11 +1,15 @@ -description: A higher Houseing Benefit allowance amount is provided for filers over this age threshold. +description: >- + Inclusive age threshold for a single claimant's higher working-age Housing + Benefit personal allowance, subject to statutory exceptions. metadata: label: Housing benefit allowance older age threshold period: year unit: year - reference: - - title: The Housing Benefit Regulations 2006 sec. 74 - href: https://www.legislation.gov.uk/uksi/2006/213/made/data.pdf#page=73 + reference: + - title: The Housing Benefit Regulations 2006 Schedule 3 Part 1 paragraph 1, as made + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3/part/1/made + - title: The Housing Benefit Regulations (Northern Ireland) 2006 Schedule 4 Part I paragraph 1 + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/4 values: 2019-04-01: 25 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/younger.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/younger.yaml index 31c6ce9904..5aa0b2f30d 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/younger.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/younger.yaml @@ -1,11 +1,16 @@ -description: A lower Housing Benefit allowance amount is provided if both members of a couple are below this age threshold. +description: >- + Inclusive age threshold for the higher working-age Housing Benefit personal + allowance for a lone parent or a couple with at least one member at this age, + subject to statutory exceptions. metadata: label: Housing benefit allowance younger age threshold period: year unit: year - reference: - - title: The Housing Benefit Regulations 2006 sec. 74 - href: https://www.legislation.gov.uk/uksi/2006/213/made/data.pdf#page=73 + reference: + - title: The Housing Benefit Regulations 2006 Schedule 3 Part 1 paragraph 1, as made + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3/part/1/made + - title: The Housing Benefit Regulations (Northern Ireland) 2006 Schedule 4 Part I paragraph 1 + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/4 values: 2019-04-01: 18 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/pension_age/tariff_income/threshold.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/pension_age/tariff_income/threshold.yaml index df97be0015..a209c92ee5 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/pension_age/tariff_income/threshold.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/pension_age/tariff_income/threshold.yaml @@ -1,4 +1,6 @@ -description: Standard pension-age Housing Benefit tariff income threshold. +description: >- + Ordinary pension-age Housing Benefit tariff income threshold, excluding the + higher threshold for specified accommodation before 2 November 2009. metadata: label: Pension-age Housing Benefit tariff income threshold period: year @@ -6,5 +8,22 @@ metadata: reference: - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 29(2) href: https://www.legislation.gov.uk/uksi/2006/214/regulation/29 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 reg. 27(2) + href: https://www.legislation.gov.uk/nisr/2006/406/regulation/27 values: - 2006-04-10: 10000 + 2006-04-10: + value: 6_000 + metadata: + reference: + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 29(2)(b), as made + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/29/made + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations (Northern Ireland) 2006 reg. 27(2)(b), as made + href: https://www.legislation.gov.uk/nisr/2006/406/regulation/27/made + 2009-11-02: + value: 10_000 + metadata: + reference: + - title: The Social Security (Deemed Income from Capital) Regulations 2009 regs. 1 and 5 + href: https://www.legislation.gov.uk/uksi/2009/1676/made + - title: The Social Security (Deemed Income from Capital) Regulations (Northern Ireland) 2009 regs. 1 and 3 + href: https://www.legislation.gov.uk/nisr/2009/262/made diff --git a/policyengine_uk/tests/test_housing_benefit_parameter_history.py b/policyengine_uk/tests/test_housing_benefit_parameter_history.py new file mode 100644 index 0000000000..5b5c874632 --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_parameter_history.py @@ -0,0 +1,96 @@ +"""Externally sourced Housing Benefit threshold history and citation checks.""" + +from pathlib import Path + +import pytest +from policyengine_core.parameters import ParameterNode + +from policyengine_uk.system import system + + +@pytest.fixture(scope="module") +def written_housing_benefit_parameters(): + """Read statutory dates before the model's fiscal-year conversion.""" + directory = ( + Path(__file__).parents[1] / "parameters" / "gov" / "dwp" / "housing_benefit" + ) + return ParameterNode(directory_path=str(directory)) + + +@pytest.mark.parametrize( + "date, expected", + [ + # SI 2006/214 reg 29(2)(b), outside its accommodation exception. + ("2006-04-10", 6_000), + ("2008-04-30", 6_000), + ("2009-11-01", 6_000), + # SI 2009/1676 regs 1 and 5; NI SR 2009/262 regs 1 and 3. + ("2009-11-02", 10_000), + ("2009-11-03", 10_000), + ("2015-04-30", 10_000), + ("2026-04-30", 10_000), + ], +) +def test_written_standard_pension_capital_threshold( + written_housing_benefit_parameters, date, expected +): + threshold = written_housing_benefit_parameters.means_test.capital.pension_age.tariff_income.threshold + assert threshold(date) == expected + + +@pytest.mark.parametrize("year", [2015, 2025, 2026]) +def test_supported_model_year_thresholds_are_unchanged(year): + """The historical correction must not alter supported-year thresholds.""" + capital = system.parameters(str(year)).gov.dwp.housing_benefit.means_test.capital + assert capital.pension_age.tariff_income.threshold == 10_000 + assert capital.working_age.tariff_income.threshold == 6_000 + + +@pytest.mark.parametrize("year", [2015, 2019, 2026]) +def test_allowance_age_constants_remain_available_in_supported_years(year): + """Existing package backdating supplies the age constants before 2019.""" + ages = system.parameters(str(year)).gov.dwp.housing_benefit.allowances.age_threshold + # SI 2006/213 Sch 3 Part 1 para 1; NI SR 2006/405 Sch 4 Part I. + assert ages.older == 25 + assert ages.younger == 18 + + +@pytest.mark.parametrize("name", ["older", "younger"]) +def test_allowance_age_references_identify_the_allowance_schedules( + written_housing_benefit_parameters, name +): + age = getattr(written_housing_benefit_parameters.allowances.age_threshold, name) + references = {reference["href"] for reference in age.metadata["reference"]} + assert references == { + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/part/1/made", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + } + + +@pytest.mark.parametrize( + "date, expected_references", + [ + ( + "2006-04-10", + { + "https://www.legislation.gov.uk/uksi/2006/214/regulation/29/made", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/27/made", + }, + ), + ( + "2009-11-02", + { + "https://www.legislation.gov.uk/uksi/2009/1676/made", + "https://www.legislation.gov.uk/nisr/2009/262/made", + }, + ), + ], +) +def test_pension_capital_values_have_dated_gb_and_ni_sources( + written_housing_benefit_parameters, date, expected_references +): + threshold = written_housing_benefit_parameters.means_test.capital.pension_age.tariff_income.threshold + values = {value.instant_str: value for value in threshold.values_list} + assert date in values + references = {reference["href"] for reference in values[date].metadata["reference"]} + assert references == expected_references From 5f9c96b7b2dd0e549475a46e6f15d3a3ca572930 Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Fri, 9 Oct 2026 00:14:06 +0400 Subject: [PATCH 2/3] Fix issues from review: Housing Benefit calculation gaps --- changelog.d/2197.fixed.md | 5 +- .../engineering/housing-benefit-assessment.md | 196 ++++ .../permitted_work/former_weeks_limit.yaml | 9 + .../permitted_work/higher_limit_hours.yaml | 9 + .../dwp/ESA/permitted_work/lower_limit.yaml | 9 + .../permitted_work/ordinary_hours_limit.yaml | 9 + .../gov/dwp/ESA/permitted_work/rounding.yaml | 9 + .../permitted_work/weeks_limit_applies.yaml | 12 + .../age_threshold/former_pension_age.yaml | 9 + .../dwp/housing_benefit/allowances/child.yaml | 34 + .../allowances/child_limit/count.yaml | 19 + .../child_limit/schedule/gb_pension_age.yaml | 22 + .../child_limit/schedule/gb_working_age.yaml | 22 + .../child_limit/schedule/ni_pension_age.yaml | 22 + .../child_limit/schedule/ni_working_age.yaml | 22 + .../allowances/couple/aged.yaml | 39 +- .../couple/pension_age_under_65.yaml | 34 + .../allowances/disabled_child_premium.yaml | 79 ++ .../allowances/enhanced_child_premium.yaml | 79 ++ .../allowances/family_premium/ordinary.yaml | 31 + .../family_premium/protected_lone_parent.yaml | 11 + .../schedule/gb_open_to_new_claims.yaml | 10 + .../schedule/ni_open_to_new_claims.yaml | 10 + .../allowances/lone_parent/aged.yaml | 39 +- .../lone_parent/pension_age_under_65.yaml | 34 + .../under_65_category_applies.yaml | 13 + .../allowances/single/aged.yaml | 39 +- .../single/pension_age_under_65.yaml | 34 + .../blindness_run_on_weeks.yaml | 12 + .../capital/disregards/arrears_weeks.yaml | 19 + .../carer_reassessment_commencement.yaml | 19 + .../capital/disregards/injury_weeks.yaml | 19 + .../disregards/large_error_payment.yaml | 19 + .../large_error_payment_earliest_receipt.yaml | 19 + .../capital/disregards/temporary_weeks.yaml | 19 + .../means_test/capital/sources.yaml | 14 +- .../means_test/childcare/incapacity_days.yaml | 9 + .../means_test/childcare/lcw_link_days.yaml | 9 + .../childcare/old_incapacity_link_days.yaml | 9 + .../childcare/out_of_school_min_age.yaml | 9 + .../childcare/pension_incapacity_age.yaml | 9 + .../means_test/childcare/sickness_weeks.yaml | 9 + .../childcare/weekly_maximum/one_child.yaml | 14 + .../weekly_maximum/two_or_more_children.yaml | 14 + .../means_test/childcare/work_hours.yaml | 9 + .../income_disregard/incapacity_days.yaml | 9 + .../income_disregard/incapacity_days_ill.yaml | 9 + .../protection_break_weeks.yaml | 9 + .../means_test/income_disregard/special.yaml | 9 + .../additional_exceptions.yaml | 43 + .../non_dep_deduction/amount.yaml | 72 +- policyengine_uk/programs.yaml | 4 +- ...t_applicable_income_childcare_element.yaml | 570 ++++++++--- .../housing_benefit_applicable_amount.yaml | 106 ++- .../test_housing_benefit_additional_rules.py | 885 ++++++++++++++++++ ...ousing_benefit_non_dep_additional_rules.py | 355 +++++++ .../test_housing_benefit_parameter_history.py | 63 ++ policyengine_uk/utils/housing_benefit.py | 27 + .../utils/housing_benefit_capital.py | 150 +++ .../utils/housing_benefit_non_dependants.py | 142 +++ policyengine_uk/utils/net_earnings.py | 34 + .../gov/dwp/esa_assessment_phase_ended.py | 14 + .../gov/dwp/esa_assessment_phase_exception.py | 14 + .../variables/gov/dwp/esa_claim_made.py | 14 + .../variables/gov/dwp/esa_converted_award.py | 14 + .../variables/gov/dwp/esa_main_phase.py | 31 + .../variables/gov/dwp/esa_support_group.py | 14 + .../dwp/esa_work_related_activity_group.py | 14 + ...fit_applicable_income_childcare_element.py | 42 +- ...ing_benefit_applicable_income_disregard.py | 80 +- .../housing_benefit_net_earnings.py | 74 +- ...ousing_benefit_permitted_work_disregard.py | 32 + .../housing_benefit_person_net_earnings.py | 49 + ...nefit_pre_additional_earnings_disregard.py | 43 + ...sing_benefit_savings_credit_only_income.py | 77 +- ...ing_benefit_standard_earnings_disregard.py | 112 +++ ...dditional_earnings_disregard_conditions.py | 39 +- .../housing_benefit/carer_premium_run_on.py | 14 + ..._limited_capability_for_work_determined.py | 14 + .../housing_benefit_applicable_amount.py | 64 +- .../housing_benefit_assessable_capital.py | 45 +- .../housing_benefit_assessment_date.py | 18 + ..._benefit_capital_arrears_official_error.py | 15 + ...ousing_benefit_capital_arrears_received.py | 18 + ...g_benefit_capital_arrears_total_payment.py | 17 + ...housing_benefit_capital_business_active.py | 15 + ...housing_benefit_capital_business_assets.py | 17 + ...housing_benefit_capital_business_ceased.py | 18 + ...benefit_capital_business_disposal_steps.py | 15 + ..._benefit_capital_business_extension_end.py | 18 + ...fit_capital_business_illness_and_return.py | 15 + ...t_capital_carer_reassessment_provenance.py | 15 + ...fit_capital_carer_reassessment_received.py | 18 + ...fit_capital_carer_reassessment_retained.py | 17 + ...sing_benefit_capital_esa_error_received.py | 18 + ...benefit_capital_esa_error_total_payment.py | 17 + ...fit_capital_esa_official_error_retained.py | 17 + ...enefit_capital_home_funds_extension_end.py | 18 + ...ing_benefit_capital_home_funds_received.py | 18 + ...ing_benefit_capital_home_funds_retained.py | 17 + ...t_capital_injury_first_payment_received.py | 18 + ...benefit_capital_injury_payment_is_first.py | 15 + ...benefit_capital_injury_payment_retained.py | 17 + .../housing_benefit_capital_injury_trust.py | 17 + ...using_benefit_capital_premises_category.py | 25 + ..._benefit_capital_premises_extension_end.py | 18 + ...ing_benefit_capital_premises_first_step.py | 18 + ..._benefit_capital_premises_intended_home.py | 13 + ...nefit_capital_premises_reasonable_steps.py | 13 + ...capital_property_occupier_incapacitated.py | 13 + ...tal_property_occupier_is_former_partner.py | 13 + ...apital_property_occupier_is_lone_parent.py | 13 + ...t_capital_property_occupier_is_relative.py | 13 + ...l_property_occupier_over_qualifying_age.py | 13 + ...capital_property_relationship_estranged.py | 13 + ...fit_capital_qualifying_arrears_retained.py | 17 + ...efit_capital_relative_occupied_premises.py | 17 + ...fit_capital_repairs_funds_extension_end.py | 18 + ..._benefit_capital_repairs_funds_received.py | 18 + ..._benefit_capital_repairs_funds_retained.py | 17 + ...sing_benefit_capital_temporary_premises.py | 17 + .../housing_benefit_child_allowance.py | 70 ++ ...using_benefit_child_benefit_after_death.py | 15 + ...it_child_count_at_two_child_limit_start.py | 17 + ..._child_disability_payment_or_suspension.py | 15 + ...using_benefit_child_disability_premiums.py | 59 ++ ...hanced_disability_payment_or_suspension.py | 15 + ...hild_in_family_at_two_child_limit_start.py | 17 + ...it_childcare_blind_certification_ceased.py | 17 + .../housing_benefit_childcare_charges_paid.py | 15 + ..._childcare_compulsory_education_charges.py | 15 + ...childcare_disability_benefit_in_payment.py | 14 + ...isability_payment_suspended_in_hospital.py | 14 + ...housing_benefit_childcare_in_child_home.py | 14 + ...housing_benefit_childcare_incapacitated.py | 64 ++ ...ldcare_incapacity_but_for_determination.py | 15 + ...dcare_listed_incapacity_benefit_payable.py | 15 + ...using_benefit_childcare_paid_to_partner.py | 14 + ...ng_benefit_childcare_parental_leave_end.py | 17 + ..._benefit_childcare_parental_leave_start.py | 17 + ...sing_benefit_childcare_parental_pay_end.py | 17 + ...benefit_childcare_parental_pay_entitled.py | 14 + .../housing_benefit_childcare_provider.py | 30 + ..._benefit_childcare_provider_is_relative.py | 14 + ...ousing_benefit_childcare_sickness_start.py | 17 + ...using_benefit_childcare_treated_as_work.py | 72 ++ ...g_benefit_childcare_work_before_absence.py | 14 + ...ousing_benefit_childcare_work_condition.py | 32 + ...housing_benefit_childcare_wtc_award_end.py | 17 + ...fit_childcare_wtc_in_payment_at_pay_end.py | 14 + .../housing_benefit_continuous_award_end.py | 18 + .../housing_benefit_continuous_award_start.py | 18 + ...housing_benefit_ctc_child_element_count.py | 17 + ...fit_disabled_child_premium_before_death.py | 15 + ...fit_enhanced_child_premium_before_death.py | 15 + ...nefit_entitled_at_two_child_limit_start.py | 17 + .../housing_benefit_family_premium.py | 58 ++ ...amily_premium_entitled_before_abolition.py | 15 + ...mily_premium_family_condition_continued.py | 15 + ...amily_premium_new_claim_since_abolition.py | 15 + ...t_hospital_suspended_incapacity_benefit.py | 14 + ...g_benefit_income_support_for_incapacity.py | 14 + ...ousing_benefit_invalid_vehicle_provided.py | 14 + ...e_parent_family_premium_1998_protection.py | 15 + ...t_new_claim_since_two_child_limit_start.py | 17 + ...t_ni_additional_occupation_net_earnings.py | 15 + ...housing_benefit_owned_household_capital.py | 17 + ...g_benefit_owned_household_capital_known.py | 15 + .../housing_benefit_paid_work_expected.py | 14 + ...benefit_pension_age_disregarded_capital.py | 21 + ...on_credit_earnings_disregard_assessment.py | 31 + ...it_pension_credit_net_income_assessment.py | 22 + ...it_pension_special_disregard_conditions.py | 70 ++ .../housing_benefit_permitted_work_limit.py | 52 + ...it_protected_special_earnings_disregard.py | 14 + ...sing_benefit_qualifying_childcare_costs.py | 69 ++ .../housing_benefit_remunerative_work.py | 22 + ...special_disregard_max_award_break_weeks.py | 14 + ...al_disregard_max_employment_break_weeks.py | 14 + ...nefit_specified_occupation_net_earnings.py | 15 + ...benefit_working_age_disregarded_capital.py | 21 + .../incapacity_benefit_is_long_term.py | 14 + ...acity_benefit_is_short_term_higher_rate.py | 15 + ...pacity_benefit_is_short_term_lower_rate.py | 14 + .../incapacity_for_work_days.py | 14 + .../incapacity_for_work_gap_days.py | 14 + .../incapacity_shortened_duration_rule.py | 14 + .../housing_benefit/is_hospital_inpatient.py | 14 + .../is_housing_benefit_claimant.py | 18 + .../gov/dwp/housing_benefit/is_in_prison.py | 14 + .../limited_capability_for_work_days.py | 14 + .../limited_capability_for_work_gap_days.py | 14 + .../housing_benefit/mobility_supplement.py | 15 + .../housing_benefit_benefit_week_start.py | 15 + ...t_individual_non_dep_deduction_eligible.py | 6 +- .../housing_benefit_non_dep_absent.py | 15 + ...ng_benefit_non_dep_additional_exception.py | 44 + ...custody_excludes_mental_health_hospital.py | 15 + .../housing_benefit_non_dep_deductions.py | 45 +- ...using_benefit_non_dep_full_time_student.py | 23 + ...ousing_benefit_non_dep_increase_history.py | 16 + ...g_benefit_non_dep_linked_inpatient_days.py | 15 + ...ing_benefit_non_dep_military_operations.py | 15 + ...g_benefit_non_dep_normal_home_elsewhere.py | 15 + ...housing_benefit_non_dep_period_of_study.py | 20 + ...housing_benefit_non_dep_summer_vacation.py | 17 + ...enefit_non_dep_youth_training_allowance.py | 15 + ..._children_for_housing_benefit_childcare.py | 33 +- .../permitted_work_authority_approved.py | 14 + ...tted_work_former_restart_conditions_met.py | 14 + .../permitted_work_medically_supervised.py | 14 + .../permitted_work_net_earnings.py | 15 + .../permitted_work_supported.py | 14 + .../permitted_work_weekly_hours.py | 14 + .../housing_benefit/permitted_work_weeks.py | 14 + ...ing_tax_credit_30_hour_element_in_award.py | 14 + ..._tax_credit_disability_element_in_award.py | 14 + .../gov/dwp/lifetime_isa_countable_capital.py | 20 +- ...time_isa_medical_evidence_received_date.py | 12 + ...ifetime_isa_qualifying_medical_evidence.py | 10 + 220 files changed, 6587 insertions(+), 483 deletions(-) create mode 100644 docs/engineering/housing-benefit-assessment.md create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/former_weeks_limit.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/higher_limit_hours.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/lower_limit.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/ordinary_hours_limit.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/rounding.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/ESA/permitted_work/weeks_limit_applies.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/former_pension_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/count.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_pension_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_working_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_pension_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_working_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/pension_age_under_65.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/disabled_child_premium.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/enhanced_child_premium.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/ordinary.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/protected_lone_parent.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/gb_open_to_new_claims.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/ni_open_to_new_claims.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/pension_age_under_65.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_history/under_65_category_applies.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/pension_age_under_65.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/blindness_run_on_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/arrears_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/carer_reassessment_commencement.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/injury_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment_earliest_receipt.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/temporary_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/incapacity_days.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/lcw_link_days.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/old_incapacity_link_days.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/out_of_school_min_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/pension_incapacity_age.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/sickness_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/one_child.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/two_or_more_children.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/work_hours.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days_ill.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/protection_break_weeks.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/special.yaml create mode 100644 policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/additional_exceptions.yaml create mode 100644 policyengine_uk/tests/test_housing_benefit_additional_rules.py create mode 100644 policyengine_uk/tests/test_housing_benefit_non_dep_additional_rules.py create mode 100644 policyengine_uk/utils/housing_benefit.py create mode 100644 policyengine_uk/utils/housing_benefit_capital.py create mode 100644 policyengine_uk/utils/housing_benefit_non_dependants.py create mode 100644 policyengine_uk/utils/net_earnings.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_assessment_phase_ended.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_assessment_phase_exception.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_claim_made.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_converted_award.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_main_phase.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_support_group.py create mode 100644 policyengine_uk/variables/gov/dwp/esa_work_related_activity_group.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_permitted_work_disregard.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_person_net_earnings.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_pre_additional_earnings_disregard.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_standard_earnings_disregard.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/carer_premium_run_on.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/esa_limited_capability_for_work_determined.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessment_date.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_official_error.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_total_payment.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_active.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_assets.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_ceased.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_disposal_steps.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_extension_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_illness_and_return.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_provenance.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_total_payment.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_official_error_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_extension_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_first_payment_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_is_first.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_trust.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_category.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_extension_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_first_step.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_intended_home.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_reasonable_steps.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_incapacitated.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_former_partner.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_lone_parent.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_relative.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_over_qualifying_age.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_relationship_estranged.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_qualifying_arrears_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_relative_occupied_premises.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_extension_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_received.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_retained.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_temporary_premises.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_allowance.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_benefit_after_death.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_count_at_two_child_limit_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_payment_or_suspension.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_premiums.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_enhanced_disability_payment_or_suspension.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_in_family_at_two_child_limit_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_blind_certification_ceased.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_charges_paid.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_compulsory_education_charges.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_benefit_in_payment.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_payment_suspended_in_hospital.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_in_child_home.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacitated.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacity_but_for_determination.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_listed_incapacity_benefit_payable.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_paid_to_partner.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_entitled.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider_is_relative.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_sickness_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_treated_as_work.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_before_absence.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_condition.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_award_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_in_payment_at_pay_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_end.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ctc_child_element_count.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_disabled_child_premium_before_death.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_enhanced_child_premium_before_death.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_entitled_at_two_child_limit_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_entitled_before_abolition.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_family_condition_continued.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_new_claim_since_abolition.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_hospital_suspended_incapacity_benefit.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_income_support_for_incapacity.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_invalid_vehicle_provided.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_lone_parent_family_premium_1998_protection.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_new_claim_since_two_child_limit_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ni_additional_occupation_net_earnings.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital_known.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_paid_work_expected.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_age_disregarded_capital.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_earnings_disregard_assessment.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_net_income_assessment.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_special_disregard_conditions.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_permitted_work_limit.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_protected_special_earnings_disregard.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_qualifying_childcare_costs.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_remunerative_work.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_award_break_weeks.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_employment_break_weeks.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_specified_occupation_net_earnings.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_working_age_disregarded_capital.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_long_term.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_higher_rate.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_lower_rate.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_days.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_gap_days.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_shortened_duration_rule.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/is_hospital_inpatient.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/is_housing_benefit_claimant.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/is_in_prison.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_days.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_gap_days.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/mobility_supplement.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_benefit_week_start.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_absent.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_additional_exception.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_custody_excludes_mental_health_hospital.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_full_time_student.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_increase_history.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_linked_inpatient_days.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_military_operations.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_normal_home_elsewhere.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_period_of_study.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_summer_vacation.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_youth_training_allowance.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_authority_approved.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_former_restart_conditions_met.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_medically_supervised.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_net_earnings.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_supported.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weekly_hours.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weeks.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_30_hour_element_in_award.py create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_disability_element_in_award.py create mode 100644 policyengine_uk/variables/input/lifetime_isa_medical_evidence_received_date.py create mode 100644 policyengine_uk/variables/input/lifetime_isa_qualifying_medical_evidence.py diff --git a/changelog.d/2197.fixed.md b/changelog.d/2197.fixed.md index 7d50653911..f9144e1399 100644 --- a/changelog.d/2197.fixed.md +++ b/changelog.d/2197.fixed.md @@ -1 +1,4 @@ -- Corrected the written pre-November-2009 pension-age Housing Benefit capital threshold and allowance age source references, without changing supported 2015-onward threshold values. +- Corrected Housing Benefit historical allowances and non-dependant scales, and the pre-November-2009 pension-age capital threshold. +- Added child applicable amounts, protected family and child-disability premiums, and the claimant-specific ESA age exception. +- Corrected childcare qualification and income limits, special/permitted-work earnings disregards, capital exclusions and ownership treatment, and the LISA medical exception. +- Added remaining non-dependant exceptions and claimant-specific pension-age postponement, with government references and focused regression tests. diff --git a/docs/engineering/housing-benefit-assessment.md b/docs/engineering/housing-benefit-assessment.md new file mode 100644 index 0000000000..e196553721 --- /dev/null +++ b/docs/engineering/housing-benefit-assessment.md @@ -0,0 +1,196 @@ +# Housing Benefit assessment facts and timing + +Housing Benefit calculations use individual policy parameters and the existing +person, benefit-unit and household entities. Additional facts are needed where +annual income, age and household wealth cannot establish statutory eligibility. +These inputs do not change a claimant's circumstances automatically. + +## Annual amounts and dated facts + +Weekly amounts become annual amounts using the model's 52-week convention. +Ordinary parameters retain the model's 30 April fiscal-year sampling. Preserved +Boolean schedules and `fiscal_year_segments` handle the December 2018 removal +of the under-65 allowance, the two-child restriction and its removal, and +jurisdiction-specific family-premium abolition. Those calculations hold supplied +family facts fixed and apply the rule separately in each segment before averaging. +They do not multiply a Boolean input by an assumed share of a year. + +`housing_benefit_assessment_date` defaults to 6 October, matching annual age +inputs. It is the date for reported childcare status, retained capital and pending +non-dependant changes. The resulting point-in-time weekly calculation is +annualised; it is not a reconstruction of every week's actual award. Supply +different dates and factual inputs to examine individual assessments. Do not +interpret the date as a guarantee that policy remains unchanged afterwards. + +## Applicable amounts + +Child personal allowances use the legacy-benefit child/young-person definition. +During the historical two-child restriction, actual Child Tax Credit individual +element counts can permit more children even if the resulting tax-credit payment +is zero. Continuing-claim protection requires the initial award/count, the +individual children still in the family, and no subsequent new claim. + +The family premium is separate. After its GB or NI abolition date, it requires +pre-abolition HB entitlement with a child/young person, a continuously qualifying +family and no new claim. The old higher lone-parent premium requires continuing +April 1998 statutory protection, not just current lone-parent status. + +Disabled-child and enhanced-child premiums require listed disability awards, +specified hospital suspensions, blindness or the prescribed post-death Child +Benefit continuation. A general disability indicator is insufficient. These +premiums are not restricted to the first two child personal allowances. Adult +premiums remain in the existing shared premium variables; the HB child additions +do not change Council Tax Reduction or Income Support. + +The main-phase ESA age exception tests the claimant personally. A partner's +main-phase award does not on its own satisfy that exception. + +## Childcare + +Report qualifying charges on each child using +`housing_benefit_childcare_charges_paid`, with the HB-specific provider category +and excluded education/partner/relative-care facts. Unknown provider status +does not establish qualification. The aggregate adult `childcare_expenses` +input alone does not identify the children or provider and is not substituted +for these facts. + +Work treatment covers actual or expected paid work, specified sickness/credit +periods after preceding remunerative work, and statutory paid parental leave +with its relevant end dates. Couples need the corresponding partner work, +incapacity, inpatient or custody facts. Child age ends on the relevant first +Monday in September, with actual dates of birth used where supplied. + +The capped qualifying charge can offset net earnings after the pre-additional +earnings disregard, plus actual WTC/CTC income, but not unrelated unearned +income. The separate pre-additional calculation avoids a circular dependency. +HB has its own fixed £175/£300 weekly childcare caps, independent of reforms to +the tax-credit parameters. + +## Earnings + +The £20 special disregard is not a flat allowance for everyone described as +disabled or a carer. Working-age and pension-age grounds differ. Specified +occupation and carer earnings have their own couple aggregation and top-up +rules. Permitted work requires the actual qualifying benefit/credits, authority +acceptance, work category, weekly hours and earnings; couples share one limit. +The higher limit follows the highest adult minimum-wage rate with the statutory +rounding, not the claimant's age-specific minimum wage. + +For savings-credit-only HB, use the Secretary of State's net-income assessment +and the earnings disregard already included in it. Supply +`housing_benefit_pension_credit_net_income_assessment` and +`housing_benefit_pension_credit_earnings_disregard_assessment` together when +those figures are known. Only permitted HB modifications are deducted: the +full PC and HB disregards must not both be subtracted. + +The fallback reads the model's Pension Credit income. Its disregard adapter +uses `pension_credit_earnings_disregard` when that separate component is +installed; otherwise it returns zero, matching the deduction actually made +by the existing PC-income formula. PR #2019 owns that upstream correction. +Without it or an actual supplied assessment, the PC estimate retains that +known limitation. HB does not introduce a second PC calculation. + +## Capital + +Retained capital is a stock, not annual benefit income. Category amounts must +already be included in the capital sources being assessed and be disjoint. +Dates and payment provenance matter: ordinary Carer's Allowance arrears are +not the July 2026 Independent Review reassessment payment. + +The implemented categories cover those reassessment payments, qualifying +injury payments/trusts, listed benefit arrears and official-error payments, +specified home/repair funds, business assets and qualifying temporary or +relative-occupied premises. Working-age 26/52-week rules and pension-age +calendar-year rules remain distinct. Authority-accepted longer periods must +be supplied where the provision permits them. These inputs do not represent +every historic compensation/support scheme listed in the capital schedules. + +Remove excluded funds from shared household sources before the claimant/partner +allocation proxy. Where actual ownership is known, set +`housing_benefit_owned_household_capital_known` and +`housing_benefit_owned_household_capital` to the combined claimant/partner +interest in the configured household sources, excluding separately counted +LISAs. A known zero replaces the proxy. Remove only those claimants' own +exclusions in this path. Asset-level ownership and valuation records should +determine this amount; an equal household-adult share is only a fallback. + +The LISA medical exception requires the account manager to have received +written registered-practitioner evidence of expected life below one year. +Prospective first-home eligibility alone is not unrestricted surrender: +the statutory withdrawal is a restricted conveyancer transaction. + +## Non-dependants + +Normal home elsewhere and youth-training inputs record the exact statutory +conditions. Income-related ESA under age 25 is exempt only outside the support +and work-related activity groups; a zero cash component is insufficient. +Hospital, custody and military-operation exemptions require current absence. +`housing_benefit_non_dep_linked_inpatient_days` must be prepared from admissions: +sum inpatient days only, link gaps at most 28 days, and restart after longer +gaps. Mental-health hospital detention is not the specified custody category. + +Full-time students are exempt during study even when working. Working-age +summer-vacation students are exempt only when not in remunerative work, +unless the claimant-specific pensionable-age exception applies. NI pension-age +student rules retain their age-65 condition. Education enrolment is a fallback +for full-time status; override it for part-time courses. + +Pension-age increases use claimant-specific award history. The existing core +entities cannot store a claimant/non-dependant relationship directly, so +`housing_benefit_non_dep_increase_history` accepts sparse, validated JSON +records on each claimant's benefit unit. This is an explicit data interface, +not an existing standard entity or a generic exemption input: + +```json +[ + { + "person_id": "adult_child", + "previous_weekly_deduction": 20.4, + "last_effective_date": "2025-04-07", + "increases": [ + {"date": "2026-08-01", "kind": "circumstances"} + ] + } +] +``` + +Record every pending increase after the current continuous award began or the +last effective change, whichever is later. Use the amount actually still +applied before the pending increases, before rent-share allocation. Account +for ordinary uprating and immediate reductions in that previous amount. +Event kinds are `arrival`, `circumstances` and `uprating`; only the first two +start the postponement. Arrival during an existing award normally has a +previous deduction of zero. An existing resident when a new claim starts +does not establish a deferred arrival. + +The first qualifying increase for the same person determines the 26-week +date, rounded forward to this claim's benefit-week start. Later increases do +not restart it. Reductions and exemptions apply immediately. Different +claimants can supply different histories for the same person. Missing history +means no evidenced postponement, not a fabricated recent arrival. + +## Data and remaining coverage + +These factual inputs default to zero/false or an unknown future date. Existing +datasets are not silently populated with inferred historical awards, payment +provenance, provider qualifications or claimant-specific change records. +Population results will use available data and documented fallbacks until +upstream materialisers supply those fields. + +Later pension-age cohort routing, other published rate corrections, general +non-dependant income/couple rules, within-family deductions, award attribution, +and more detailed asset valuation are separate model changes. Do not describe +the model as a complete reconstruction of every HB provision or pre-2015 award. + +## Government sources + +- [GB working-age HB Regulations](https://www.legislation.gov.uk/uksi/2006/213). +- [GB pension-age HB Regulations](https://www.legislation.gov.uk/uksi/2006/214). +- [NI working-age HB Regulations](https://www.legislation.gov.uk/nisr/2006/405). +- [NI pension-age HB Regulations](https://www.legislation.gov.uk/nisr/2006/406). +- [Pension Credit earnings disregards](https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI). +- [2026 GB carers' reassessment exclusion](https://www.legislation.gov.uk/uksi/2026/681). +- [2026 NI counterpart](https://www.legislation.gov.uk/nisr/2026/146). +- [LISA medical withdrawal exception](https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/4). + +The relevant parameters and variables also carry their own source references. diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/former_weeks_limit.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/former_weeks_limit.yaml new file mode 100644 index 0000000000..bef6d07f2f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/former_weeks_limit.yaml @@ -0,0 +1,9 @@ +description: Former ordinary higher-limit permitted-work duration limit +values: + 2015-04-01: 52 +metadata: + unit: week + label: former ordinary higher-limit permitted-work duration limit + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/higher_limit_hours.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/higher_limit_hours.yaml new file mode 100644 index 0000000000..27b64ddd67 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/higher_limit_hours.yaml @@ -0,0 +1,9 @@ +description: Minimum-wage hours used to calculate the higher permitted-work earnings limit +values: + 2015-04-01: 16 +metadata: + unit: hour + label: minimum-wage hours used to calculate the higher permitted-work earnings limit + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/lower_limit.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/lower_limit.yaml new file mode 100644 index 0000000000..2cb1d9751b --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/lower_limit.yaml @@ -0,0 +1,9 @@ +description: Lower permitted-work weekly earnings limit +values: + 2015-04-01: 20 +metadata: + unit: currency-GBP + label: lower permitted-work weekly earnings limit + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/ordinary_hours_limit.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/ordinary_hours_limit.yaml new file mode 100644 index 0000000000..888cb71c55 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/ordinary_hours_limit.yaml @@ -0,0 +1,9 @@ +description: Exclusive weekly hours limit for ordinary higher-limit permitted work +values: + 2015-04-01: 16 +metadata: + unit: hour + label: exclusive weekly hours limit for ordinary higher-limit permitted work + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/rounding.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/rounding.yaml new file mode 100644 index 0000000000..86245137dd --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/rounding.yaml @@ -0,0 +1,9 @@ +description: Permitted-work limit upward rounding increment +values: + 2015-04-01: 0.5 +metadata: + unit: currency-GBP + label: permitted-work limit upward rounding increment + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2008/794/regulation/45 diff --git a/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/weeks_limit_applies.yaml b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/weeks_limit_applies.yaml new file mode 100644 index 0000000000..30220df549 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/ESA/permitted_work/weeks_limit_applies.yaml @@ -0,0 +1,12 @@ +description: Whether the former ordinary higher-limit permitted-work 52-week restriction applies. +values: + 2015-04-01: true + 2017-04-03: false +metadata: + unit: bool + label: former permitted-work duration restriction applies + reference: + - title: Removal of the ESA permitted-work 52-week restriction + href: https://www.legislation.gov.uk/uksi/2017/205/regulation/3/made + - title: Northern Ireland matching removal from 3 April 2017 + href: https://www.legislation.gov.uk/nisr/2017/50/regulation/3/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/former_pension_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/former_pension_age.yaml new file mode 100644 index 0000000000..ab3d289fce --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/age_threshold/former_pension_age.yaml @@ -0,0 +1,9 @@ +description: Age boundary for the former lower pension-age Housing Benefit allowance category. +values: + 2015-04-01: 65 +metadata: + unit: year + label: housing benefit former pension-age allowance boundary + reference: + - title: Housing Benefit pension-age Regulations 2006, Schedule 3 paragraph 1 as in 2015 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2015-04-06 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child.yaml new file mode 100644 index 0000000000..1b9622ea47 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child.yaml @@ -0,0 +1,34 @@ +description: Weekly Housing Benefit personal allowance for each qualifying child or young person, distinct from premiums. +values: + 2015-04-01: 66.9 + 2020-04-01: 68.27 + 2021-04-01: 68.6 + 2022-04-01: 70.8 + 2023-04-01: 77.78 + 2024-04-01: 83.24 + 2025-04-01: 84.66 + 2026-04-01: 87.88 +metadata: + unit: currency-GBP + label: housing benefit child personal allowance + period: week + uprating: gov.benefit_uprating_cpi + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/2 + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/uksi/2015/457/article/18/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2020/234/article/24/made + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/uksi/2021/162/article/24/made + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2022/292/article/24/made + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/uksi/2023/316/article/24/made + - title: Housing Benefit statutory rule 7 + href: https://www.legislation.gov.uk/uksi/2024/242/article/23/made + - title: Housing Benefit statutory rule 8 + href: https://www.legislation.gov.uk/uksi/2025/295/article/23/made + - title: Housing Benefit statutory rule 9 + href: https://www.legislation.gov.uk/uksi/2026/148/article/23/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/count.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/count.yaml new file mode 100644 index 0000000000..e7683d0372 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/count.yaml @@ -0,0 +1,19 @@ +description: Ordinary maximum number of child personal allowances while the Housing Benefit child restriction applies. +values: + 2015-04-01: 2 +metadata: + unit: child + label: housing benefit ordinary child allowance limit + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/376/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/79/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2024/611/regulation/6 + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/nisr/2024/119/regulation/5 + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2026/316/regulation/2 + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/nisr/2026/68/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_pension_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_pension_age.yaml new file mode 100644 index 0000000000..1dffedd6a1 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_pension_age.yaml @@ -0,0 +1,22 @@ +description: Whether the Housing Benefit two-child personal-allowance restriction applies under this regulation set. +values: + 2015-04-01: false + 2017-04-06: true + 2024-06-08: false +metadata: + unit: bool + label: housing benefit gb pension age child limit applies + preserve_calendar_dates: true + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/376/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/79/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2024/611/regulation/6 + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/nisr/2024/119/regulation/5 + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2026/316/regulation/2 + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/nisr/2026/68/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_working_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_working_age.yaml new file mode 100644 index 0000000000..213446a6bf --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/gb_working_age.yaml @@ -0,0 +1,22 @@ +description: Whether the Housing Benefit two-child personal-allowance restriction applies under this regulation set. +values: + 2015-04-01: false + 2017-04-06: true + 2026-04-06: false +metadata: + unit: bool + label: housing benefit gb working age child limit applies + preserve_calendar_dates: true + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/376/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/79/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2024/611/regulation/6 + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/nisr/2024/119/regulation/5 + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2026/316/regulation/2 + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/nisr/2026/68/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_pension_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_pension_age.yaml new file mode 100644 index 0000000000..a72cf14421 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_pension_age.yaml @@ -0,0 +1,22 @@ +description: Whether the Housing Benefit two-child personal-allowance restriction applies under this regulation set. +values: + 2015-04-01: false + 2017-05-11: true + 2024-06-08: false +metadata: + unit: bool + label: housing benefit ni pension age child limit applies + preserve_calendar_dates: true + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/376/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/79/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2024/611/regulation/6 + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/nisr/2024/119/regulation/5 + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2026/316/regulation/2 + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/nisr/2026/68/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_working_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_working_age.yaml new file mode 100644 index 0000000000..021f6b175c --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/child_limit/schedule/ni_working_age.yaml @@ -0,0 +1,22 @@ +description: Whether the Housing Benefit two-child personal-allowance restriction applies under this regulation set. +values: + 2015-04-01: false + 2017-05-11: true + 2026-04-06: false +metadata: + unit: bool + label: housing benefit ni working age child limit applies + preserve_calendar_dates: true + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/376/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/79/made + - title: Housing Benefit statutory rule 3 + href: https://www.legislation.gov.uk/uksi/2024/611/regulation/6 + - title: Housing Benefit statutory rule 4 + href: https://www.legislation.gov.uk/nisr/2024/119/regulation/5 + - title: Housing Benefit statutory rule 5 + href: https://www.legislation.gov.uk/uksi/2026/316/regulation/2 + - title: Housing Benefit statutory rule 6 + href: https://www.legislation.gov.uk/nisr/2026/68/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged.yaml index 12cf678445..95669def57 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/aged.yaml @@ -1,6 +1,35 @@ description: The following couple personal allowance is provided under the Housing Benefit if at least one member is over the state pension age threshold. values: - 2015-04-01: 270.6 + 2015-04-01: + value: 248.3 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2015 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + 2016-04-01: + value: 252.3 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2016 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + 2017-04-01: + value: 258.15 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2017 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + 2018-04-01: + value: 263.8 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2018 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + 2019-04-01: + value: 270.6 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2019 + href: https://www.legislation.gov.uk/uksi/2019/480/schedule/6/made 2021-04-01: 286.05 2022-04-06: 294.9 2023-04-01: 324.7 @@ -14,6 +43,14 @@ metadata: label: Housing benefit aged couple personal allowance uprating: gov.benefit_uprating_cpi reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made - title: The Housing Benefit Regulations 2006 Schedule 3 sec. 1 href: https://www.legislation.gov.uk/uksi/2006/213/data.pdf#page=212 - title: Benefit and pension rates 2024 to 2025 - Policy paper diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/pension_age_under_65.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/pension_age_under_65.yaml new file mode 100644 index 0000000000..e4781e409b --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/couple/pension_age_under_65.yaml @@ -0,0 +1,34 @@ +description: Weekly pension-age Housing Benefit personal allowance where neither claimant nor partner has attained age 65, before the category was removed on 6 December 2018. +values: + 2015-04-01: 230.85 + 2016-04-01: 237.55 + 2017-04-01: 243.25 + 2018-04-01: 248.8 + 2018-12-06: 0 +metadata: + period: week + unit: currency-GBP + label: housing benefit couple pension-age allowance below 65 + reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made + - title: Pension-age Housing Benefit Regulations 2006, Schedule 3, former paragraph 1 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2015-04-06 + - title: Social Security Benefits Up-rating Order 2015, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + - title: Social Security Benefits Up-rating Regulations 2016, regulation 6 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + - title: Social Security Benefits Up-rating Order 2017, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + - title: Social Security Benefits Up-rating Order 2018, Schedule 6 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + - title: Removal of the under-65 category from 6 December 2018 + href: https://www.legislation.gov.uk/uksi/2017/1187/regulation/7/made + - title: Northern Ireland matching removal of the under-65 category + href: https://www.legislation.gov.uk/nisr/2017/242/regulation/7/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/disabled_child_premium.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/disabled_child_premium.yaml new file mode 100644 index 0000000000..add9eb49f6 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/disabled_child_premium.yaml @@ -0,0 +1,79 @@ +description: Weekly Housing Benefit disabled child premium, separately for each qualifying child or young person. +values: + 2015-04-01: + value: 60.06 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2015, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/6/made + 2017-04-01: + value: 60.9 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2017, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/6/made + 2018-04-01: + value: 62.86 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2018, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/5/made + 2019-04-01: + value: 64.19 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2019, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2019/480/schedule/5/made + 2020-04-01: + value: 65.52 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2020, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2020/234/schedule/5/made + 2021-04-01: + value: 65.94 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2021, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2021/162/schedule/5/made + 2022-04-01: + value: 68.04 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2022, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2022/292/schedule/5/made + 2023-04-01: + value: 74.69 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2023, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2023/316/schedule/5/made + 2024-04-01: + value: 80.01 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2024, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2024/242/schedule/5/made + 2025-04-01: + value: 81.37 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2025, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2025/295/schedule/5/made + 2026-04-01: + value: 84.46 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2026, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2026/148/schedule/5/made +metadata: + unit: currency-GBP + period: week + uprating: gov.benefit_uprating_cpi + reference: + - title: Housing Benefit Regulations 2006, Schedule 3 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3 + - title: Pension-age Housing Benefit Regulations 2006, Schedule 3 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: Northern Ireland Housing Benefit premiums 2026 + href: https://www.legislation.gov.uk/nisr/2026/59/schedule/5/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/enhanced_child_premium.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/enhanced_child_premium.yaml new file mode 100644 index 0000000000..9ec6a83505 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/enhanced_child_premium.yaml @@ -0,0 +1,79 @@ +description: Weekly Housing Benefit enhanced child premium, separately for each qualifying child or young person. +values: + 2015-04-01: + value: 24.43 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2015, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/6/made + 2017-04-01: + value: 24.78 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2017, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/6/made + 2018-04-01: + value: 25.48 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2018, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/5/made + 2019-04-01: + value: 26.04 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2019, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2019/480/schedule/5/made + 2020-04-01: + value: 26.6 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2020, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2020/234/schedule/5/made + 2021-04-01: + value: 26.67 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2021, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2021/162/schedule/5/made + 2022-04-01: + value: 27.44 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2022, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2022/292/schedule/5/made + 2023-04-01: + value: 30.17 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2023, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2023/316/schedule/5/made + 2024-04-01: + value: 32.2 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2024, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2024/242/schedule/5/made + 2025-04-01: + value: 32.75 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2025, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2025/295/schedule/5/made + 2026-04-01: + value: 33.99 + metadata: + reference: + - title: Social Security Benefits Up-rating Order 2026, Housing Benefit premiums + href: https://www.legislation.gov.uk/uksi/2026/148/schedule/5/made +metadata: + unit: currency-GBP + period: week + uprating: gov.benefit_uprating_cpi + reference: + - title: Housing Benefit Regulations 2006, Schedule 3 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3 + - title: Pension-age Housing Benefit Regulations 2006, Schedule 3 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 + - title: Northern Ireland Housing Benefit premiums 2026 + href: https://www.legislation.gov.uk/nisr/2026/59/schedule/5/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/ordinary.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/ordinary.yaml new file mode 100644 index 0000000000..6ee61f7417 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/ordinary.yaml @@ -0,0 +1,31 @@ +description: Weekly ordinary Housing Benefit family premium, where abolition protection applies. +values: + 2015-04-01: 17.45 + 2020-04-01: 17.6 + 2021-04-01: 17.65 + 2022-04-01: 17.85 + 2023-04-01: 18.53 + 2024-04-01: 19.15 + 2025-04-01: 19.48 + 2026-04-01: 20.22 +metadata: + unit: currency-GBP + period: week + uprating: gov.benefit_uprating_cpi + reference: + - title: Social Security Benefits Up-rating Order 2015, family premium + href: https://www.legislation.gov.uk/uksi/2015/457/article/18/made + - title: Social Security Benefits Up-rating Order 2020, family premium + href: https://www.legislation.gov.uk/uksi/2020/234/article/25/made + - title: Social Security Benefits Up-rating Order 2021, family premium + href: https://www.legislation.gov.uk/uksi/2021/162/article/25/made + - title: Social Security Benefits Up-rating Order 2022, family premium + href: https://www.legislation.gov.uk/uksi/2022/292/article/25/made + - title: Social Security Benefits Up-rating Order 2023, family premium + href: https://www.legislation.gov.uk/uksi/2023/316/article/25/made + - title: Social Security Benefits Up-rating Order 2024, family premium + href: https://www.legislation.gov.uk/uksi/2024/242/article/24/made + - title: Social Security Benefits Up-rating Order 2025, family premium + href: https://www.legislation.gov.uk/uksi/2025/295/article/24/made + - title: Social Security Benefits Up-rating Order 2026, family premium + href: https://www.legislation.gov.uk/uksi/2026/148/article/24/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/protected_lone_parent.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/protected_lone_parent.yaml new file mode 100644 index 0000000000..5c8c722e60 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/protected_lone_parent.yaml @@ -0,0 +1,11 @@ +description: Weekly working-age Housing Benefit family premium for lone parents with continuing April 1998 protection. +values: + 2015-04-01: 22.2 +metadata: + unit: currency-GBP + period: week + reference: + - title: Housing Benefit Regulations 2006, Schedule 3 paragraph 3 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/3 + - title: Social Security Benefits Up-rating Order 2026, article 23(7) + href: https://www.legislation.gov.uk/uksi/2026/148/article/23/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/gb_open_to_new_claims.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/gb_open_to_new_claims.yaml new file mode 100644 index 0000000000..5607ad2b71 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/gb_open_to_new_claims.yaml @@ -0,0 +1,10 @@ +description: Housing Benefit family premium is available without abolition protection in Great Britain. +values: + 2006-04-01: true + 2016-05-01: false +metadata: + unit: bool + preserve_calendar_dates: true + reference: + - title: Housing Benefit family premium abolition and transitional protection + href: https://www.legislation.gov.uk/uksi/2015/1857/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/ni_open_to_new_claims.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/ni_open_to_new_claims.yaml new file mode 100644 index 0000000000..6a2c7205db --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/family_premium/schedule/ni_open_to_new_claims.yaml @@ -0,0 +1,10 @@ +description: Housing Benefit family premium is available without abolition protection in Northern Ireland. +values: + 2006-04-01: true + 2016-09-05: false +metadata: + unit: bool + preserve_calendar_dates: true + reference: + - title: Housing Benefit family premium abolition and transitional protection + href: https://www.legislation.gov.uk/nisr/2016/310/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged.yaml index 0292f05a7c..edb0e06ca5 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/aged.yaml @@ -1,7 +1,36 @@ description: Personal allowance for Housing Benefit for a lone parent over State Pension age. values: - 2015-04-01: 181 + 2015-04-01: + value: 166.05 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2015 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + 2016-04-01: + value: 168.7 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2016 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + 2017-04-01: + value: 172.55 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2017 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + 2018-04-01: + value: 176.4 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2018 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + 2019-04-01: + value: 181 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2019 + href: https://www.legislation.gov.uk/uksi/2019/480/schedule/6/made 2021-04-01: 191.15 2022-04-06: 197.1 2023-04-01: 217 @@ -15,6 +44,14 @@ metadata: label: Housing benefit lone parent aged personal allowance uprating: gov.benefit_uprating_cpi reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made - title: The Housing Benefit Regulations 2006 Schedule 3 sec. 1 href: https://www.legislation.gov.uk/uksi/2006/213/data.pdf#page=212 - title: Benefit and pension rates 2024 to 2025 - Policy paper diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/pension_age_under_65.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/pension_age_under_65.yaml new file mode 100644 index 0000000000..4340d40c64 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/lone_parent/pension_age_under_65.yaml @@ -0,0 +1,34 @@ +description: Weekly pension-age Housing Benefit personal allowance where neither claimant nor partner has attained age 65, before the category was removed on 6 December 2018. +values: + 2015-04-01: 151.2 + 2016-04-01: 155.6 + 2017-04-01: 159.35 + 2018-04-01: 163 + 2018-12-06: 0 +metadata: + period: week + unit: currency-GBP + label: housing benefit lone parent pension-age allowance below 65 + reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made + - title: Pension-age Housing Benefit Regulations 2006, Schedule 3, former paragraph 1 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2015-04-06 + - title: Social Security Benefits Up-rating Order 2015, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + - title: Social Security Benefits Up-rating Regulations 2016, regulation 6 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + - title: Social Security Benefits Up-rating Order 2017, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + - title: Social Security Benefits Up-rating Order 2018, Schedule 6 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + - title: Removal of the under-65 category from 6 December 2018 + href: https://www.legislation.gov.uk/uksi/2017/1187/regulation/7/made + - title: Northern Ireland matching removal of the under-65 category + href: https://www.legislation.gov.uk/nisr/2017/242/regulation/7/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_history/under_65_category_applies.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_history/under_65_category_applies.yaml new file mode 100644 index 0000000000..d12a8eb636 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/pension_age_history/under_65_category_applies.yaml @@ -0,0 +1,13 @@ +description: Whether the former pension-age allowance category for claimants under 65 remains in legislation. +values: + 2015-04-01: true + 2018-12-06: false +metadata: + unit: bool + label: housing benefit former under-65 pension category applies + preserve_calendar_dates: true + reference: + - title: Housing Benefit statutory rule 1 + href: https://www.legislation.gov.uk/uksi/2017/1187/regulation/7/made + - title: Housing Benefit statutory rule 2 + href: https://www.legislation.gov.uk/nisr/2017/242/regulation/7/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged.yaml index c3bf99f4ba..860323eda9 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/aged.yaml @@ -1,6 +1,35 @@ description: The following personal allowance amount is provided to single filers over the pension age under the Housing Benefit. values: - 2015-04-01: 181 + 2015-04-01: + value: 166.05 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2015 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + 2016-04-01: + value: 168.7 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2016 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + 2017-04-01: + value: 172.55 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2017 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + 2018-04-01: + value: 176.4 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2018 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + 2019-04-01: + value: 181 + metadata: + reference: + - title: Enacted pension-age Housing Benefit allowances for 2019 + href: https://www.legislation.gov.uk/uksi/2019/480/schedule/6/made 2021-04-01: 191.15 2022-04-06: 197.1 2023-04-01: 217 @@ -14,6 +43,14 @@ metadata: label: Housing benefit single aged personal allowance uprating: gov.benefit_uprating_cpi reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made - title: The Housing Benefit Regulations 2006 Schedule 3 sec. 1 href: https://www.legislation.gov.uk/uksi/2006/213/data.pdf#page=212 - title: Benefit and pension rates 2024 to 2025 - Policy paper diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/pension_age_under_65.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/pension_age_under_65.yaml new file mode 100644 index 0000000000..4409b5feff --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/allowances/single/pension_age_under_65.yaml @@ -0,0 +1,34 @@ +description: Weekly pension-age Housing Benefit personal allowance where neither claimant nor partner has attained age 65, before the category was removed on 6 December 2018. +values: + 2015-04-01: 151.2 + 2016-04-01: 155.6 + 2017-04-01: 159.35 + 2018-04-01: 163 + 2018-12-06: 0 +metadata: + period: week + unit: currency-GBP + label: housing benefit single pension-age allowance below 65 + reference: + - title: Northern Ireland pension-age Housing Benefit allowances 2015 + href: https://www.legislation.gov.uk/nisr/2015/124/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2016 + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Northern Ireland pension-age Housing Benefit allowances 2017 + href: https://www.legislation.gov.uk/nisr/2017/56/schedule/7/made + - title: Northern Ireland pension-age Housing Benefit allowances 2018 + href: https://www.legislation.gov.uk/nisr/2018/58/schedule/6/made + - title: Pension-age Housing Benefit Regulations 2006, Schedule 3, former paragraph 1 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/2015-04-06 + - title: Social Security Benefits Up-rating Order 2015, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2015/457/schedule/7/made + - title: Social Security Benefits Up-rating Regulations 2016, regulation 6 + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + - title: Social Security Benefits Up-rating Order 2017, Schedule 7 + href: https://www.legislation.gov.uk/uksi/2017/260/schedule/7/made + - title: Social Security Benefits Up-rating Order 2018, Schedule 6 + href: https://www.legislation.gov.uk/uksi/2018/281/schedule/6/made + - title: Removal of the under-65 category from 6 December 2018 + href: https://www.legislation.gov.uk/uksi/2017/1187/regulation/7/made + - title: Northern Ireland matching removal of the under-65 category + href: https://www.legislation.gov.uk/nisr/2017/242/regulation/7/made diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/blindness_run_on_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/blindness_run_on_weeks.yaml new file mode 100644 index 0000000000..72aad588ac --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/blindness_run_on_weeks.yaml @@ -0,0 +1,12 @@ +description: Period for which a person who regains sight remains treated as blind for Housing Benefit premium and childcare conditions. +values: + 2006-04-01: 28 +metadata: + unit: week + reference: + - title: Housing Benefit Regulations 2006, Schedule 3 paragraph 13(2) + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/13 + - title: Housing Benefit childcare, regulation 28(10)(b) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 + - title: Pension-age Housing Benefit, Schedule 3 paragraph 6(5) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/6 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/arrears_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/arrears_weeks.yaml new file mode 100644 index 0000000000..5684a12a65 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/arrears_weeks.yaml @@ -0,0 +1,19 @@ +description: Working-age qualifying arrears capital exclusion period. +values: + 2015-04-01: 52 +metadata: + unit: week + label: housing benefit working-age qualifying arrears capital exclusion period + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/carer_reassessment_commencement.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/carer_reassessment_commencement.yaml new file mode 100644 index 0000000000..72811dd4b1 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/carer_reassessment_commencement.yaml @@ -0,0 +1,19 @@ +description: Commencement of the specific Carer's Allowance reassessment capital exclusion. +values: + 2015-04-01: 20260716 +metadata: + unit: date + label: housing benefit commencement of the specific carer's allowance reassessment capital exclusion + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/injury_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/injury_weeks.yaml new file mode 100644 index 0000000000..544306a6ef --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/injury_weeks.yaml @@ -0,0 +1,19 @@ +description: Working-age first personal-injury payment exclusion period. +values: + 2015-04-01: 52 +metadata: + unit: week + label: housing benefit working-age first personal-injury payment exclusion period + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment.yaml new file mode 100644 index 0000000000..ff58953936 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment.yaml @@ -0,0 +1,19 @@ +description: Minimum relevant error payment for continuing-award capital exclusion. +values: + 2015-04-01: 5000 +metadata: + unit: currency-GBP + label: housing benefit minimum relevant error payment for continuing-award capital exclusion + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment_earliest_receipt.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment_earliest_receipt.yaml new file mode 100644 index 0000000000..6c58ec9060 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/large_error_payment_earliest_receipt.yaml @@ -0,0 +1,19 @@ +description: Earliest payment date for the continuing-award large-error exclusion. +values: + 2015-04-01: 20011014 +metadata: + unit: date + label: housing benefit earliest payment date for the continuing-award large-error exclusion + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/temporary_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/temporary_weeks.yaml new file mode 100644 index 0000000000..52b3a51e62 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/disregards/temporary_weeks.yaml @@ -0,0 +1,19 @@ +description: Ordinary temporary home or business capital exclusion period. +values: + 2015-04-01: 26 +metadata: + unit: week + label: housing benefit ordinary temporary home or business capital exclusion period + reference: + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2006/406/schedule/7 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/uksi/2026/681 + - title: Housing Benefit capital exclusion legislation + href: https://www.legislation.gov.uk/nisr/2026/146 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sources.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sources.yaml index e313576158..c38f24a20d 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sources.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/capital/sources.yaml @@ -15,10 +15,12 @@ description: > pension-age regulations and paragraphs 32 and 33 of Schedule 7 to the Northern Ireland regulations make the same disregard). Datasets built before private pension wealth was split out of `corporate_wealth` still carry it - inside that countable bucket. Other Schedule 6 disregards within these broad - asset classes are not yet split out separately. Because the - dataset only provides household-level capital stocks, the model allocates - them across benunits using an adult-share proxy. + inside that countable bucket. Category-specific retained capital exclusions + are removed before allocation, where their payment, purpose, date and + statutory qualification facts are supplied. Not every historic compensation + scheme in Schedule 6 has a separate input. Known claimant/partner capital, + including a reported zero, replaces the household proxy rather than adding + to it. Otherwise household stocks are allocated by claimant/partner counts. metadata: label: Housing Benefit countable capital sources period: year @@ -34,8 +36,8 @@ metadata: href: https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/32 - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 reg. 44(1) href: https://www.legislation.gov.uk/uksi/2006/214/regulation/44 - - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 Schedule 6 para. 1 - href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6/paragraph/1 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 Schedule 6 para. 26 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6/paragraph/26 - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 Schedule 6 para. 24 href: https://www.legislation.gov.uk/uksi/2006/214/schedule/6/paragraph/24 values: diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/incapacity_days.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/incapacity_days.yaml new file mode 100644 index 0000000000..00cb4e618f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/incapacity_days.yaml @@ -0,0 +1,9 @@ +description: Linked incapacity days for Housing Benefit childcare +values: + 2015-04-01: 196 +metadata: + unit: day + label: linked incapacity days for housing benefit childcare + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/lcw_link_days.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/lcw_link_days.yaml new file mode 100644 index 0000000000..7ef7041961 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/lcw_link_days.yaml @@ -0,0 +1,9 @@ +description: Maximum break linking ESA limited-capability periods +values: + 2015-04-01: 84 +metadata: + unit: day + label: maximum break linking esa limited-capability periods + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/old_incapacity_link_days.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/old_incapacity_link_days.yaml new file mode 100644 index 0000000000..b525c2b1f5 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/old_incapacity_link_days.yaml @@ -0,0 +1,9 @@ +description: Maximum break linking old incapacity periods +values: + 2015-04-01: 56 +metadata: + unit: day + label: maximum break linking old incapacity periods + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/out_of_school_min_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/out_of_school_min_age.yaml new file mode 100644 index 0000000000..db12d19ef1 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/out_of_school_min_age.yaml @@ -0,0 +1,9 @@ +description: Minimum age for the school or local authority out-of-hours childcare route +values: + 2015-04-01: 8 +metadata: + unit: year + label: minimum age for the school or local authority out-of-hours childcare route + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/pension_incapacity_age.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/pension_incapacity_age.yaml new file mode 100644 index 0000000000..0ea8ff77d3 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/pension_incapacity_age.yaml @@ -0,0 +1,9 @@ +description: Pension-age childcare partner incapacity age +values: + 2015-04-01: 80 +metadata: + unit: year + label: pension-age childcare partner incapacity age + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/31 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/sickness_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/sickness_weeks.yaml new file mode 100644 index 0000000000..beb95ec67f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/sickness_weeks.yaml @@ -0,0 +1,9 @@ +description: Maximum sick absence treated as work for Housing Benefit childcare +values: + 2015-04-01: 28 +metadata: + unit: week + label: maximum sick absence treated as work for housing benefit childcare + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/28 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/one_child.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/one_child.yaml new file mode 100644 index 0000000000..90bb6c8bea --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/one_child.yaml @@ -0,0 +1,14 @@ +description: Maximum weekly relevant Housing Benefit childcare charges for one child. +values: + 2015-04-01: 175 +metadata: + unit: currency-GBP + period: week + label: housing benefit childcare maximum for one child + reference: + - title: Housing Benefit Regulations 2006, regulation 27(3) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/27 + - title: Pension-age Housing Benefit Regulations 2006, regulation 30(3) + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/30 + - title: Northern Ireland Housing Benefit Regulations, regulation 24(3) + href: https://www.legislation.gov.uk/nisr/2006/405/regulation/24 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/two_or_more_children.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/two_or_more_children.yaml new file mode 100644 index 0000000000..38349324c4 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/weekly_maximum/two_or_more_children.yaml @@ -0,0 +1,14 @@ +description: Maximum weekly relevant Housing Benefit childcare charges for two or more children. +values: + 2015-04-01: 300 +metadata: + unit: currency-GBP + period: week + label: housing benefit childcare maximum for two or more children + reference: + - title: Housing Benefit Regulations 2006, regulation 27(3) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/27 + - title: Pension-age Housing Benefit Regulations 2006, regulation 30(3) + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/30 + - title: Northern Ireland Housing Benefit Regulations, regulation 24(3) + href: https://www.legislation.gov.uk/nisr/2006/405/regulation/24 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/work_hours.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/work_hours.yaml new file mode 100644 index 0000000000..cfafcc7c7f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/childcare/work_hours.yaml @@ -0,0 +1,9 @@ +description: Weekly remunerative work hours for Housing Benefit childcare +values: + 2015-04-01: 16 +metadata: + unit: hour + label: weekly remunerative work hours for housing benefit childcare + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/6 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days.yaml new file mode 100644 index 0000000000..1585d909f6 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days.yaml @@ -0,0 +1,9 @@ +description: Old incapacity duration for pension-age special earnings disregard +values: + 2015-04-01: 364 +metadata: + unit: day + label: old incapacity duration for pension-age special earnings disregard + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days_ill.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days_ill.yaml new file mode 100644 index 0000000000..bdaa38f1d2 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/incapacity_days_ill.yaml @@ -0,0 +1,9 @@ +description: Old incapacity duration for an ill claimant under the statutory shortened route +values: + 2015-04-01: 196 +metadata: + unit: day + label: old incapacity duration for an ill claimant under the statutory shortened route + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/protection_break_weeks.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/protection_break_weeks.yaml new file mode 100644 index 0000000000..95cad0fbfd --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/protection_break_weeks.yaml @@ -0,0 +1,9 @@ +description: Maximum break preserving the pension-age special earnings disregard +values: + 2015-04-01: 8 +metadata: + unit: week + label: maximum break preserving the pension-age special earnings disregard + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/special.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/special.yaml new file mode 100644 index 0000000000..49f7972136 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/means_test/income_disregard/special.yaml @@ -0,0 +1,9 @@ +description: Weekly special Housing Benefit earnings disregard +values: + 2015-04-01: 20 +metadata: + unit: currency-GBP + label: weekly special housing benefit earnings disregard + reference: + - title: Housing Benefit statutory conditions + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/4 diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/additional_exceptions.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/additional_exceptions.yaml new file mode 100644 index 0000000000..7e616e6de7 --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/additional_exceptions.yaml @@ -0,0 +1,43 @@ +description: Housing Benefit additional non-dependant exception thresholds and pension-age postponement. +metadata: + reference: + - title: Housing Benefit Regulations 2006, regulation 74(7)-(8) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/74 + - title: Housing Benefit (State Pension Credit) Regulations 2006, regulation 59(10)-(13) + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/59 + - title: Northern Ireland pension-age Housing Benefit Regulations 2006, regulation 57 + href: https://www.legislation.gov.uk/nisr/2006/406/regulation/57 +hospital_weeks: + description: Minimum linked inpatient duration, exceeded before the non-dependant absence exemption applies. + values: + 2006-04-01: 52 + metadata: + unit: week +assessment_phase_age: + description: Age below which income-related ESA outside the support and work-related activity groups exempts a non-dependant. + values: + 2006-04-01: 25 + metadata: + unit: year +former_pension_age: + description: Former claimant or partner age condition for pension-age non-dependant student exemptions and postponement, retained for Northern Ireland students. + values: + 2006-04-01: 65 + metadata: + unit: year +age_condition_removed: + description: Date the age-65 condition ended for GB pension-age student exemptions and GB and NI pension-age postponement, encoded YYYYMMDD. + values: + 2006-04-01: 20181206 + metadata: + reference: + - title: Social Security (Equalisation of State Pension Age) Regulations 2017, regulation 7 + href: https://www.legislation.gov.uk/uksi/2017/1187/regulation/7 + - title: Social Security (Equalisation of State Pension Age) Regulations (Northern Ireland) 2017, regulation 7 + href: https://www.legislation.gov.uk/nisr/2017/242/regulation/7 +postponement_weeks: + description: Pension-age Housing Benefit postponement of a qualifying non-dependant deduction increase. + values: + 2006-04-01: 26 + metadata: + unit: week diff --git a/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/amount.yaml b/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/amount.yaml index ab7e2b2695..d06dc02c7f 100644 --- a/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/amount.yaml +++ b/policyengine_uk/parameters/gov/dwp/housing_benefit/non_dep_deduction/amount.yaml @@ -2,74 +2,110 @@ description: The following amount is provided for individuals under the Housing brackets: - threshold: - 2018-06-18: 0 + 2015-04-01: 0 + 2016-04-01: 0 + 2017-04-01: 0 + 2018-04-01: 0 amount: - 2018-06-18: 15.25 + 2015-04-01: 14.55 + 2016-04-01: 14.65 + 2017-04-01: 14.8 + 2018-04-01: 15.25 2021-04-01: 15.95 2022-04-01: 16.45 2023-04-01: 18.1 2024-04-01: 19.3 2026-04-01: 20.4 - threshold: - 2018-06-18: 139 + 2015-04-01: 129 + 2016-04-01: 133 + 2017-04-01: 136 + 2018-04-01: 139 2021-04-01: 154 2023-04-01: 162 2024-04-01: 176 2026-04-01: 192 amount: - 2018-06-18: 35 + 2015-04-01: 33.4 + 2016-04-01: 33.65 + 2017-04-01: 34 + 2018-04-01: 35 2021-04-01: 36.65 2022-04-01: 37.8 2023-04-01: 41.6 2024-04-01: 44.4 2026-04-01: 46.85 - threshold: - 2018-06-18: 204 + 2015-04-01: 189 + 2016-04-01: 195 + 2017-04-01: 200 + 2018-04-01: 204 2021-04-01: 224 2023-04-01: 236 2024-04-01: 256 2026-04-01: 279 amount: - 2018-06-18: 48.05 + 2015-04-01: 45.85 + 2016-04-01: 46.2 + 2017-04-01: 46.65 + 2018-04-01: 48.05 2021-04-01: 50.3 2022-04-01: 51.85 2023-04-01: 57.1 2024-04-01: 60.95 2026-04-01: 64.35 - threshold: - 2018-06-18: 265 + 2015-04-01: 246 + 2016-04-01: 253 + 2017-04-01: 259 + 2018-04-01: 265 2021-04-01: 292 2023-04-01: 308 2024-04-01: 334 2026-04-01: 365 amount: - 2018-06-18: 78.65 + 2015-04-01: 75.05 + 2016-04-01: 75.6 + 2017-04-01: 76.35 + 2018-04-01: 78.65 2021-04-01: 82.3 2022-04-01: 84.85 2023-04-01: 93.4 2024-04-01: 99.65 2026-04-01: 105.2 - threshold: - 2018-06-18: 354 + 2015-04-01: 328 + 2016-04-01: 338 + 2017-04-01: 346 + 2018-04-01: 354 2021-04-01: 389 2023-04-01: 410 2024-04-01: 445 2026-04-01: 485 amount: - 2018-06-18: 89.55 + 2015-04-01: 85.45 + 2016-04-01: 86.1 + 2017-04-01: 86.95 + 2018-04-01: 89.55 2021-04-01: 93.7 2022-04-01: 96.6 2023-04-01: 106.35 2024-04-01: 113.5 2026-04-01: 119.85 - threshold: - 2018-06-18: 439 + 2015-04-01: 408 + 2016-04-01: 420 + 2017-04-01: 430 + 2018-04-01: 439 2021-04-01: 484 2023-04-01: 511 2024-04-01: 554 2026-04-01: 605 amount: - 2018-06-18: 98.3 + 2015-04-01: 93.8 + 2016-04-01: 94.5 + 2017-04-01: 95.45 + 2018-04-01: 98.3 2021-04-01: 102.85 2022-04-01: 106.05 2023-04-01: 116.75 @@ -85,5 +121,17 @@ metadata: threshold_unit: currency-GBP type: single_amount reference: + - title: Enacted 2015 non-dependant bands and amounts + href: https://www.legislation.gov.uk/uksi/2015/457/article/18/made + - title: Northern Ireland 2015 non-dependant bands and amounts + href: https://www.legislation.gov.uk/nisr/2015/124/article/20/made + - title: Enacted 2016 non-dependant bands and amounts + href: https://www.legislation.gov.uk/uksi/2016/242/regulation/6/made + - title: Northern Ireland 2016 matching bands and amounts + href: https://www.legislation.gov.uk/nisr/2016/110/regulation/6/made + - title: Enacted 2017 non-dependant bands and amounts + href: https://www.legislation.gov.uk/uksi/2017/260/article/23/made + - title: Northern Ireland 2017 matching bands and amounts + href: https://www.legislation.gov.uk/nisr/2017/56/article/23/made - title: The Housing Benefit Regulations 2006 sec. 74 href: https://www.legislation.gov.uk/uksi/2006/213/regulation/74/2024-04-01 diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index 702098c804..9e43e26c85 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -224,12 +224,12 @@ programs: full_name: Housing Benefit category: Benefits agency: DWP - status: complete + status: partial coverage: UK variable: housing_benefit parameter_prefix: gov.dwp.housing_benefit verified_start_year: 2022 - notes: Legacy benefit being replaced by Universal Credit + notes: Legacy benefit being replaced by Universal Credit; special childcare, capital and award-history rules require factual inputs, and some historical/cohort and non-dependant provisions remain incomplete. See docs/engineering/housing-benefit-assessment.md. - id: income_support name: Income Support diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml index 411dd36183..2cd90c738e 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml @@ -1,242 +1,558 @@ -- name: One child, capped - period: 2025 - absolute_error_margin: 0.01 +# HB Regs 2006 regs 27–28 / pension regs 30–31: qualifying costs and deduction limits. +- name: One qualifying child capped at statutory 175 per week + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 10000 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 1 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 1 - housing_benefit_applicable_income_childcare_element: 9000 + housing_benefit_applicable_income_childcare_element: 9100 -- name: Two child, capped - period: 2025 - absolute_error_margin: 0.01 +- name: Two qualifying children capped at statutory 300 per week + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 10000 - child0: - age: 8 - child1: + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 10000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + sibling: + age: 8 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 10000 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: - benunit: - members: [claimant, child0, child1] + family: + members: [claimant, child, sibling] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 2 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 2 - housing_benefit_applicable_income_childcare_element: 10000 + housing_benefit_applicable_income_childcare_element: 15600 + +- name: Unpaid sibling does not increase one-child cap + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 10000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + sibling: + age: 8 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 0 + housing_benefit_childcare_provider: REGISTERED_APPROVED + benunits: + family: + members: [claimant, child, sibling] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 9100 -- name: No children - period: 2025 - absolute_error_margin: 0.01 +- name: Unknown provider does not qualify + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 30000 + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: UNREGISTERED benunits: - benunit: - members: [claimant] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 0 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 -- name: Non-disabled child aged 15 remains within annual age approximation - period: 2025 - absolute_error_margin: 0.01 +- name: Non-relative care in child home qualifies without registration + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 15 + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: NON_RELATIVE_HOME_CARE + housing_benefit_childcare_in_child_home: true benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 1 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 1 - housing_benefit_applicable_income_childcare_element: 9000 + housing_benefit_applicable_income_childcare_element: 5000 -- name: Non-disabled young person aged 16 no longer counts - period: 2025 - absolute_error_margin: 0.01 +- name: Relative care wholly in child home excluded + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 16 + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + housing_benefit_childcare_in_child_home: true + housing_benefit_childcare_provider_is_relative: true benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 0 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 -- name: Non-disabled young person aged 17 no longer counts - period: 2025 - absolute_error_margin: 0.01 +- name: Relative registered care outside child home allowed + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 17 + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + housing_benefit_childcare_provider_is_relative: true benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 5000 + +- name: Payment to partner excluded + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + housing_benefit_childcare_paid_to_partner: true + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 0 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 -- name: Disabled young person aged 16 counts - period: 2025 - absolute_error_margin: 0.01 +- name: Compulsory education portion excluded + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 16 - is_disabled_for_benefits: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + housing_benefit_childcare_compulsory_education_charges: 1500 benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 1 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 1 - housing_benefit_applicable_income_childcare_element: 9000 + housing_benefit_applicable_income_childcare_element: 3500 -- name: Blind young person aged 16 counts - period: 2025 - absolute_error_margin: 0.01 +- name: Lone parent below 16 hours fails work condition + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 16 - is_blind: true + is_claimant_or_partner: true + weekly_hours: 15 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 1 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 1 - housing_benefit_applicable_income_childcare_element: 9000 + housing_benefit_applicable_income_childcare_element: 0 -- name: Disabled young person aged 17 no longer counts - period: 2025 - absolute_error_margin: 0.01 +- name: Childcare cannot reduce unearned income + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9000 - child0: - age: 17 - is_disabled_for_benefits: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: - benunit: - members: [claimant, child0] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 1000 + housing_benefit_pre_additional_earnings_disregard: 260 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 740 + +- name: Tax credits can cover remaining childcare + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 1000 + housing_benefit_pre_additional_earnings_disregard: 260 + working_tax_credit: 2000 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 2740 + +- name: Zero earnings and no tax credits cannot deduct childcare + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 10 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 0 + housing_benefit_pre_additional_earnings_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 0 + +- name: Birthday before September loses standard childcare at first Monday + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 15 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20110801 + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 0 relevant children the deduction is min(cost, weekly cap * 52). num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 -- name: One relevant child and an older young person use the one-child cap - period: 2025 - absolute_error_margin: 0.01 +- name: Birthday after September retains childcare until following September + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 30_000 + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true child: - age: 10 - young_person: - age: 17 + age: 15 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20111001 benunits: - benunit: - members: [claimant, child, young_person] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: num_relevant_children_for_housing_benefit_childcare: 1 - # Reg 27(3) selects the one-child cap: min(30,000, 312.0555942 * 52). - # The existing uprated WTC cap is retained; its difference from the - # statutory HB cap of 175/week is outside this classification change. - housing_benefit_applicable_income_childcare_element: 16_226.8908984 + housing_benefit_applicable_income_childcare_element: 5000 -- name: Under-18 claimant is not their own relevant child - period: 2025 +- name: Disabled child has extended September endpoint + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: - age: 17 - childcare_expenses: 9_000 + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 16 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20100801 + housing_benefit_childcare_disability_benefit_in_payment: true benunits: - benunit: - members: [claimant] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 output: - # 0 dependants implies 0 childcare cap (HB reg 27(3)). num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 -- name: Disabled 16-year-old outside education and training is not a relevant young person - period: 2025 +- name: Disabled child before September endpoint qualifies + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 9_000 - young_person: + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: age: 16 - is_disabled_for_benefits: true - is_in_non_advanced_education: false - is_in_approved_training: false + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20101001 + housing_benefit_childcare_disability_benefit_in_payment: true benunits: - benunit: - members: [claimant, young_person] + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 5000 + +- name: First Monday is inclusive end of eligibility + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 15 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20110801 + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 + housing_benefit_assessment_date: 2026-09-07 output: - # HB reg 28(6) requires a child of the family, including a qualifying - # young person; the disability age extension does not create that status. num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 + +- name: Day before first Monday remains eligible + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + is_claimant_or_partner: true + weekly_hours: 16 + housing_benefit_paid_work_expected: true + child: + age: 15 + is_claimant_or_partner: false + housing_benefit_childcare_charges_paid: 5000 + housing_benefit_childcare_provider: REGISTERED_APPROVED + date_of_birth: 20110801 + benunits: + family: + members: [claimant, child] + housing_benefit_pension_age_regulations_apply: false + housing_benefit_net_earnings: 20000 + housing_benefit_pre_additional_earnings_disregard: 1300 + working_tax_credit: 0 + child_tax_credit: 0 + housing_benefit_assessment_date: 2026-09-06 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + housing_benefit_applicable_income_childcare_element: 5000 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_applicable_amount.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_applicable_amount.yaml index eeea8a6e58..3910862f28 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_applicable_amount.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_applicable_amount.yaml @@ -1,117 +1,143 @@ -- name: Single person, older amount - period: 2025 - absolute_error_margin: 100 +# GB SI 2026/148 Sch 4: adult amounts and child amount 87.88/week. +- name: Single older + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 25 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true benunits: - benunit: + family: members: [claimant] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 90.5 * 52 + housing_benefit_applicable_amount: 4968.60 -- name: Single person, younger amount - period: 2025 - absolute_error_margin: 100 +- name: Single younger + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 23 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true benunits: - benunit: + family: members: [claimant] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 71.7 * 52 + housing_benefit_applicable_amount: 3933.80 -- name: Lone parent, younger amount - period: 2025 - absolute_error_margin: 100 +- name: Lone parent younger plus child allowance + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 17 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true is_parent: true child: age: 1 - is_SP_age: false + is_claimant_or_partner: false benunits: - benunit: + family: members: [claimant, child] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 71.7 * 52 + housing_benefit_applicable_amount: 8503.56 -- name: Lone parent, older amount - period: 2025 - absolute_error_margin: 100 +- name: Lone parent older plus child allowance + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 18 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true is_parent: true child: age: 1 - is_SP_age: false + is_claimant_or_partner: false benunits: - benunit: + family: members: [claimant, child] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 90.5 * 52 + housing_benefit_applicable_amount: 9538.36 -- name: Couple, older amount - period: 2025 - absolute_error_margin: 200 +- name: Couple older + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 18 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true partner: age: 18 - is_SP_age: false is_claimant_or_partner: true benunits: - benunit: + family: members: [claimant, partner] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 142.25 * 52 + housing_benefit_applicable_amount: 7807.80 -- name: Couple, younger amount - period: 2025 - absolute_error_margin: 100 +- name: Couple younger + period: 2026 + absolute_error_margin: 0.02 input: people: claimant: age: 17 - is_SP_age: false is_claimant_or_partner: true + is_housing_benefit_claimant: true partner: age: 17 - is_SP_age: false is_claimant_or_partner: true benunits: - benunit: + family: members: [claimant, partner] housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false benefits_premiums: 0 output: - housing_benefit_applicable_amount: 108.3 * 52 + housing_benefit_applicable_amount: 5946.20 + +- name: Single under 25 main-phase ESA uses older rate + period: 2026 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 23 + is_claimant_or_partner: true + is_housing_benefit_claimant: true + esa_claim_made: true + esa_assessment_phase_ended: true + esa_support_group: true + benunits: + family: + members: [claimant] + housing_benefit_eligible: true + housing_benefit_pension_age_regulations_apply: false + benefits_premiums: 0 + output: + housing_benefit_applicable_amount: 4968.60 diff --git a/policyengine_uk/tests/test_housing_benefit_additional_rules.py b/policyengine_uk/tests/test_housing_benefit_additional_rules.py new file mode 100644 index 0000000000..9e821329af --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_additional_rules.py @@ -0,0 +1,885 @@ +"""Housing Benefit additional-rule regressions from the operative legislation. + +Capital: SI 2006/213 Sch 6, SI 2006/214 Sch 6, SI 2026/681 and SR 2026/146. +Earnings: SI 2006/213 Sch 4, SI 2006/214 Sch 4, SPC Regs 2002 Sch VI. +Cases use small situations only: no external datasets or generated populations. +""" + +import numpy as np +import pytest + +from policyengine_uk import Simulation +from policyengine_uk.utils.housing_benefit_capital import year_after + + +def family_simulation( + *, year=2026, people=None, family=None, household=None, reform=None +): + people = people or {"claimant": {"age": 40, "is_claimant_or_partner": True}} + defaults = { + "housing_benefit_pension_age_regulations_apply": False, + "housing_benefit_on_passporting_benefit": False, + "in_receipt_of_guarantee_credit": False, + "in_receipt_of_savings_credit_only": False, + "would_claim_uc": False, + "working_tax_credit": 0, + "child_tax_credit": 0, + } + defaults.update(family or {}) + situation = { + "people": { + name: {key: {str(year): value} for key, value in values.items()} + for name, values in people.items() + }, + "benunits": { + "family": { + "members": list(people), + **{key: {str(year): value} for key, value in defaults.items()}, + } + }, + "households": { + "household": { + "members": list(people), + **{key: {str(year): value} for key, value in (household or {}).items()}, + } + }, + } + return Simulation(situation=situation, reform=reform) + + +@pytest.mark.parametrize( + "date,provenance,expected", + [ + ("2026-07-15", True, 12_000), + ("2026-07-16", True, 2_000), + ("2026-10-06", False, 12_000), + ], +) +@pytest.mark.parametrize("country", ["ENGLAND", "NORTHERN_IRELAND"]) +def test_carer_reassessment_commencement_and_provenance( + date, provenance, expected, country +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_carer_reassessment_retained": 10_000, + "housing_benefit_capital_carer_reassessment_received": "2026-07-01", + "housing_benefit_capital_carer_reassessment_provenance": provenance, + } + }, + family={"housing_benefit_assessment_date": date}, + household={"savings": 12_000, "country": country}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "known,owned,expected", [(False, 0, 12_000), (True, 0, 0), (True, 3_000, 3_000)] +) +def test_known_capital_including_zero_replaces_proxy(known, owned, expected): + simulation = family_simulation( + family={ + "housing_benefit_owned_household_capital_known": known, + "housing_benefit_owned_household_capital": owned, + }, + household={"savings": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "pension,first,received,expected", + [ + (False, True, "2025-10-08", 2_000), + (False, True, "2025-10-06", 12_000), + (False, False, "2026-01-01", 12_000), + (True, False, "2020-01-01", 2_000), + ], +) +def test_personal_injury_direct_payment_rules(pension, first, received, expected): + simulation = family_simulation( + people={ + "claimant": { + "age": 70 if pension else 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_injury_payment_retained": 10_000, + "housing_benefit_capital_injury_first_payment_received": received, + "housing_benefit_capital_injury_payment_is_first": first, + } + }, + family={"housing_benefit_pension_age_regulations_apply": pension}, + household={"savings": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +def test_pension_calendar_year_is_not_52_weeks(): + dates = np.array(["2023-03-01", "2024-02-29", "2024-10-06"], dtype="datetime64[D]") + assert list(year_after(dates).astype(str)) == [ + "2024-03-01", + "2025-02-28", + "2025-10-06", + ] + + +@pytest.mark.parametrize( + "payment,official,award_start,expected", + [ + (5_000, True, "2024-01-01", 7_000), + (4_999, True, "2024-01-01", 12_000), + (5_000, False, "2024-01-01", 12_000), + (5_000, True, "2026-01-01", 12_000), + ], +) +def test_large_error_arrears_require_threshold_and_continuing_award( + payment, official, award_start, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_qualifying_arrears_retained": 5_000, + "housing_benefit_capital_arrears_total_payment": payment, + "housing_benefit_capital_arrears_received": "2024-05-01", + "housing_benefit_capital_arrears_official_error": official, + } + }, + family={"housing_benefit_continuous_award_start": award_start}, + household={"savings": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "supervised,hours,weekly_earnings,approved,limit", + [ + (False, 15.99, 203.50, True, 203.50), + (False, 16, 203.50, True, 0), + (True, 16, 203.50, True, 203.50), + (True, 10, 203.51, True, 0), + (False, 20, 20, True, 20), + (False, 10, 100, False, 0), + ], +) +def test_permitted_work_limits_and_factual_conditions( + supervised, hours, weekly_earnings, approved, limit +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "esa_contrib": 1_000, + "permitted_work_authority_approved": approved, + "permitted_work_net_earnings": weekly_earnings, + "permitted_work_weekly_hours": hours, + "permitted_work_supported": supervised, + } + } + ) + assert simulation.calculate("housing_benefit_permitted_work_limit", 2026)[ + 0 + ] == pytest.approx(limit) + + +def test_permitted_work_couple_shares_one_limit_and_caps_other_ordinary_earnings(): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 90 * 52, + "esa_contrib": 1_000, + "permitted_work_authority_approved": True, + "permitted_work_net_earnings": 90, + "permitted_work_weekly_hours": 10, + }, + "partner": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 100 * 52, + }, + } + ) + assert ( + simulation.calculate("housing_benefit_standard_earnings_disregard", 2026)[0] + == 110 * 52 + ) + + +def test_working_age_carer_with_low_earnings_does_not_get_flat_twenty(): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 4 * 52, + "is_entitled_to_carer_benefit": True, + }, + "partner": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 40 * 52, + }, + } + ) + assert ( + simulation.calculate("housing_benefit_standard_earnings_disregard", 2026)[0] + == 14 * 52 + ) + + +@pytest.mark.parametrize( + "evidence,date,expected", + [ + (False, "2026-01-01", 7_500), + (True, "2026-10-07", 7_500), + (True, "2026-10-06", 10_000), + ], +) +def test_lisa_requires_provider_held_qualifying_evidence_received( + evidence, date, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "lifetime_isa_balance": 10_000, + "lifetime_isa_qualifying_medical_evidence": evidence, + "lifetime_isa_medical_evidence_received_date": date, + } + } + ) + assert simulation.calculate("lifetime_isa_countable_capital", 2026)[0] == expected + + +def children(number, **facts): + return { + "claimant": {"age": 40, "is_claimant_or_partner": True}, + **{ + f"child_{index}": { + "age": 5 + index, + "is_claimant_or_partner": False, + "is_child_or_young_person_for_legacy_benefits": True, + **facts, + } + for index in range(number) + }, + } + + +@pytest.mark.parametrize( + "year,pension,country,count,expected_children", + [ + (2016, False, "ENGLAND", 3, 3), + (2020, False, "ENGLAND", 3, 2), + (2020, True, "NORTHERN_IRELAND", 3, 2), + (2025, True, "ENGLAND", 3, 3), + (2025, False, "NORTHERN_IRELAND", 3, 2), + (2026, False, "ENGLAND", 3, 3), + ], +) +def test_child_allowance_history_and_two_child_limit( + year, pension, country, count, expected_children +): + simulation = family_simulation( + year=year, + people=children(count), + family={"housing_benefit_pension_age_regulations_apply": pension}, + household={"country": country}, + ) + rate = simulation.tax_benefit_system.parameters( + str(year) + ).gov.dwp.housing_benefit.allowances.child + assert simulation.calculate("housing_benefit_child_allowance", year)[ + 0 + ] == pytest.approx(expected_children * rate * 52, abs=0.01) + + +@pytest.mark.parametrize( + "new_claim,ctc_elements,continuing_children,expected_children", + [ + (False, 0, 3, 3), + (True, 0, 3, 2), + (False, 0, 2, 2), + (False, 4, 2, 4), + (True, 3, 0, 3), + ], +) +def test_only_continuing_children_or_actual_ctc_award_protect_larger_families( + new_claim, ctc_elements, continuing_children, expected_children +): + people = children(4) + for index in range(continuing_children): + people[f"child_{index}"][ + "housing_benefit_child_in_family_at_two_child_limit_start" + ] = True + simulation = family_simulation( + year=2020, + people=people, + family={ + "housing_benefit_entitled_at_two_child_limit_start": True, + "housing_benefit_child_count_at_two_child_limit_start": 3, + "housing_benefit_new_claim_since_two_child_limit_start": new_claim, + "housing_benefit_ctc_child_element_count": ctc_elements, + "child_tax_credit": 0, + }, + ) + assert simulation.calculate("housing_benefit_child_allowance", 2020)[ + 0 + ] == pytest.approx(expected_children * 68.27 * 52, abs=0.01) + + +@pytest.mark.parametrize( + "pension,age,expected", + [ + (True, 64, (163 * 244 / 365 + 176.4 * 121 / 365) * 52), + (True, 65, 176.4 * 52), + (False, 64, 73.1 * 52), + ], +) +def test_2018_under_65_category_ends_within_the_fiscal_year(pension, age, expected): + simulation = family_simulation( + year=2018, + people={"claimant": {"age": age, "is_claimant_or_partner": True}}, + family={ + "housing_benefit_eligible": True, + "housing_benefit_pension_age_regulations_apply": pension, + "benefits_premiums": 0, + }, + ) + assert simulation.calculate("housing_benefit_applicable_amount", 2018)[ + 0 + ] == pytest.approx(expected, abs=0.02) + + +@pytest.mark.parametrize( + "protected,continuing,new_claim,pension,old_lone,weekly", + [ + (False, False, False, False, False, 0), + (True, True, False, False, False, 20.22), + (True, False, False, False, False, 0), + (True, True, True, False, False, 0), + (True, True, False, False, True, 22.2), + (True, True, False, True, True, 20.22), + ], +) +def test_family_premium_requires_actual_abolition_and_lone_parent_protection( + protected, continuing, new_claim, pension, old_lone, weekly +): + simulation = family_simulation( + people=children(1), + family={ + "housing_benefit_family_premium_entitled_before_abolition": protected, + "housing_benefit_family_premium_family_condition_continued": continuing, + "housing_benefit_family_premium_new_claim_since_abolition": new_claim, + "housing_benefit_lone_parent_family_premium_1998_protection": old_lone, + "housing_benefit_pension_age_regulations_apply": pension, + }, + ) + assert simulation.calculate("housing_benefit_family_premium", 2026)[ + 0 + ] == pytest.approx(weekly * 52, abs=0.01) + + +@pytest.mark.parametrize("pension", [False, True]) +@pytest.mark.parametrize( + "child_facts,weekly", + [ + ({"is_disabled_for_benefits": True, "dla": 0, "pip": 0}, 0), + ({"dla": 100, "dla_sc_category": "MIDDLE"}, 84.46), + ({"dla": 100, "dla_sc_category": "HIGHER"}, 84.46 + 33.99), + ( + {"housing_benefit_child_enhanced_disability_payment_or_suspension": True}, + 84.46 + 33.99, + ), + ({"is_blind": True}, 84.46), + ( + { + "is_child_or_young_person_for_legacy_benefits": False, + "housing_benefit_child_benefit_after_death": True, + "housing_benefit_disabled_child_premium_before_death": True, + }, + 84.46, + ), + ], +) +def test_child_premiums_are_separate_and_require_statutory_award_facts( + pension, child_facts, weekly +): + simulation = family_simulation( + people=children(1, **child_facts), + family={"housing_benefit_pension_age_regulations_apply": pension}, + ) + assert simulation.calculate("housing_benefit_child_disability_premiums", 2026)[ + 0 + ] == pytest.approx(weekly * 52, abs=0.01) + + +@pytest.mark.parametrize( + "childcare,expected_weekly", [(70, 20), (62.9, 37.1), (60, 37.1)] +) +def test_additional_earnings_disregard_coverage_includes_childcare( + childcare, expected_weekly +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 100 * 52, + } + }, + family={ + "disability_premium": 100, + "housing_benefit_applicable_income_childcare_element": childcare * 52, + "meets_housing_benefit_additional_earnings_disregard_conditions": True, + }, + ) + assert simulation.calculate("housing_benefit_applicable_income_disregard", 2026)[ + 0 + ] == pytest.approx(expected_weekly * 52, abs=0.01) + + +def test_savings_credit_only_retains_pc_disregard_and_does_not_deduct_it_twice(): + simulation = family_simulation( + people={ + "claimant": { + "age": 80, + "is_claimant_or_partner": True, + "housing_benefit_person_net_earnings": 100 * 52, + } + }, + family={ + "housing_benefit_pension_age_regulations_apply": True, + "in_receipt_of_savings_credit_only": True, + "housing_benefit_pension_credit_net_income_assessment": 10_000, + "pension_credit": 500, + "housing_benefit_pension_credit_earnings_disregard_assessment": 5 * 52, + "housing_benefit_standard_earnings_disregard": 20 * 52, + "housing_benefit_applicable_income_childcare_element": 0, + "meets_housing_benefit_additional_earnings_disregard_conditions": False, + }, + ) + assert ( + simulation.calculate("housing_benefit_applicable_income_disregard", 2026)[0] + == 5 * 52 + ) + assert ( + simulation.calculate("housing_benefit_savings_credit_only_income", 2026)[0] + == 10_500 + ) + + +def test_housing_benefit_reform_does_not_change_reported_pc_assessment(): + people = { + "claimant": { + "age": 70, + "is_claimant_or_partner": True, + "employment_income": 10, + "self_employment_income": 0, + "employment_benefits": 0, + "total_income": 10, + "income_tax": 0, + "ni_class_1_employee": 0, + "ni_class_2": 0, + "ni_class_4": 0, + "pension_contributions": 10, + } + } + assessment = { + "housing_benefit_pension_credit_earnings_disregard_assessment": 5, + "housing_benefit_pension_credit_net_income_assessment": 100, + } + baseline = family_simulation(people=people, family=assessment) + reformed = family_simulation( + people=people, + family=assessment, + reform={ + "gov.dwp.housing_benefit.means_test.pension_contribution_deduction_rate": { + "2026": 0 + } + }, + ) + assert baseline.calculate("housing_benefit_person_net_earnings", 2026)[0] == 5 + assert reformed.calculate("housing_benefit_person_net_earnings", 2026)[0] == 10 + for simulation in (baseline, reformed): + assert ( + simulation.calculate( + "housing_benefit_pension_credit_earnings_disregard_assessment", 2026 + )[0] + == 5 + ) + assert ( + simulation.calculate( + "housing_benefit_pension_credit_net_income_assessment", 2026 + )[0] + == 100 + ) + + +@pytest.mark.parametrize( + "pension,received,extension,expected", + [ + (False, "2026-04-08", "9999-01-01", 2_000), + (False, "2026-04-07", "9999-01-01", 12_000), + (False, "2026-01-01", "2026-10-06", 2_000), + (True, "2025-10-07", "9999-01-01", 2_000), + (True, "2025-10-06", "2027-01-01", 12_000), + ], +) +def test_home_funds_have_regime_specific_durations( + pension, received, extension, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 70 if pension else 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_home_funds_retained": 10_000, + "housing_benefit_capital_home_funds_received": received, + "housing_benefit_capital_home_funds_extension_end": extension, + } + }, + family={"housing_benefit_pension_age_regulations_apply": pension}, + household={"savings": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "facts,expected", + [ + ({"housing_benefit_capital_business_active": True}, 2_000), + ( + { + "housing_benefit_capital_business_ceased": "2025-01-01", + "housing_benefit_capital_business_disposal_steps": True, + "housing_benefit_capital_business_extension_end": "2026-10-06", + }, + 2_000, + ), + ( + { + "housing_benefit_capital_business_ceased": "2025-01-01", + "housing_benefit_capital_business_disposal_steps": False, + "housing_benefit_capital_business_extension_end": "2026-10-06", + }, + 12_000, + ), + ({"housing_benefit_capital_business_illness_and_return": True}, 2_000), + ], +) +def test_business_assets_require_active_business_disposal_or_illness_conditions( + facts, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_business_assets": 10_000, + **facts, + } + }, + family={"housing_benefit_continuous_award_start": "2026-05-01"}, + household={"corporate_wealth": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "category,intended,steps,expected", + [ + ("ACQUIRED_HOME", True, False, 2_000), + ("ACQUIRED_HOME", False, False, 12_000), + ("SALE", False, True, 2_000), + ("SALE", False, False, 12_000), + ("LEGAL_POSSESSION", True, True, 2_000), + ("ESSENTIAL_REPAIRS", False, True, 12_000), + ], +) +def test_temporary_premises_categories_require_their_own_purpose_and_steps( + category, intended, steps, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_temporary_premises": 10_000, + "housing_benefit_capital_premises_category": category, + "housing_benefit_capital_premises_intended_home": intended, + "housing_benefit_capital_premises_reasonable_steps": steps, + "housing_benefit_capital_premises_first_step": "2026-05-01", + } + }, + household={"other_residential_property_value": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "relative,old,incapacitated,expected", + [ + (True, True, False, 2_000), + (True, False, True, 2_000), + (True, False, False, 12_000), + (False, True, True, 12_000), + ], +) +def test_relative_occupied_premises_not_every_second_home( + relative, old, incapacitated, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "housing_benefit_capital_relative_occupied_premises": 10_000, + "housing_benefit_capital_property_occupier_is_relative": relative, + "housing_benefit_capital_property_occupier_over_qualifying_age": old, + "housing_benefit_capital_property_occupier_incapacitated": incapacitated, + } + }, + household={"other_residential_property_value": 12_000}, + ) + assert ( + simulation.calculate("housing_benefit_assessable_capital", 2026)[0] == expected + ) + + +def test_excluded_personal_capital_is_removed_before_proxy_allocation(): + situation = { + "people": { + "first": { + "age": {2026: 40}, + "is_claimant_or_partner": {2026: True}, + "housing_benefit_capital_injury_trust": {2026: 10_000}, + }, + "second": {"age": {2026: 40}, "is_claimant_or_partner": {2026: True}}, + }, + "benunits": { + name: { + "members": [person], + "housing_benefit_pension_age_regulations_apply": {2026: False}, + "housing_benefit_on_passporting_benefit": {2026: False}, + "in_receipt_of_guarantee_credit": {2026: False}, + } + for name, person in [("first_family", "first"), ("second_family", "second")] + }, + "households": { + "home": {"members": ["first", "second"], "savings": {2026: 12_000}} + }, + } + simulation = Simulation(situation=situation) + np.testing.assert_allclose( + simulation.calculate("housing_benefit_assessable_capital", 2026), [1_000, 1_000] + ) + situation["benunits"]["second_family"].update( + { + "housing_benefit_owned_household_capital_known": {2026: True}, + "housing_benefit_owned_household_capital": {2026: 4_000}, + } + ) + owned = Simulation(situation=situation) + np.testing.assert_allclose( + owned.calculate("housing_benefit_assessable_capital", 2026), [1_000, 4_000] + ) + + +@pytest.mark.parametrize( + "sick_start,previous_work,expected", + [ + ("2026-03-25", True, True), + ("2026-03-24", True, False), + ("2026-03-25", False, False), + ], +) +def test_childcare_sickness_treatment_requires_preceding_work_and_first_28_weeks( + sick_start, previous_work, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "weekly_hours": 0, + "housing_benefit_childcare_work_before_absence": previous_work, + "housing_benefit_childcare_sickness_start": sick_start, + "statutory_sick_pay": 1_000, + } + } + ) + assert ( + bool(simulation.calculate("housing_benefit_childcare_treated_as_work", 2026)[0]) + is expected + ) + + +@pytest.mark.parametrize( + "partner_facts,expected", + [ + ({"weekly_hours": 16, "employment_income": 1_000}, True), + ({"weekly_hours": 0, "is_hospital_inpatient": True}, True), + ({"weekly_hours": 0, "is_in_prison": True}, True), + ( + {"weekly_hours": 0, "is_disabled_for_benefits": True, "dla": 0, "pip": 0}, + False, + ), + ({"weekly_hours": 0, "dla": 1_000}, True), + ], +) +def test_couple_childcare_work_condition_requires_partner_work_or_listed_incapacity( + partner_facts, expected +): + simulation = family_simulation( + people={ + "claimant": { + "age": 40, + "is_claimant_or_partner": True, + "weekly_hours": 16, + "employment_income": 1_000, + }, + "partner": {"age": 40, "is_claimant_or_partner": True, **partner_facts}, + }, + family={"disability_premium": 0}, + ) + assert ( + bool(simulation.calculate("housing_benefit_childcare_work_condition", 2026)[0]) + is expected + ) + + +def test_claimant_wr_ag_status_alone_establishes_esa_age_exception(): + simulation = family_simulation( + people={ + "claimant": { + "age": 22, + "is_claimant_or_partner": True, + "is_housing_benefit_claimant": True, + "esa_work_related_activity_group": True, + "esa_claim_made": False, + "esa_assessment_phase_ended": False, + } + }, + family={"housing_benefit_eligible": True, "benefits_premiums": 0}, + ) + assert simulation.calculate("housing_benefit_applicable_amount", 2026)[ + 0 + ] == pytest.approx(95.55 * 52, abs=0.01) + + +@pytest.mark.parametrize( + "country,open_days", [("ENGLAND", 25), ("NORTHERN_IRELAND", 152)] +) +def test_family_premium_abolition_uses_the_jurisdiction_specific_fiscal_year_date( + country, open_days +): + simulation = family_simulation( + year=2016, people=children(1), household={"country": country} + ) + assert simulation.calculate("housing_benefit_family_premium", 2016)[ + 0 + ] == pytest.approx(17.45 * 52 * open_days / 365, abs=0.01) + + +def test_disabled_child_premiums_are_not_limited_to_two_child_personal_allowances(): + simulation = family_simulation( + year=2020, people=children(3, dla=1_000, dla_sc_category="HIGHER") + ) + assert simulation.calculate("housing_benefit_child_allowance", 2020)[ + 0 + ] == pytest.approx(2 * 68.27 * 52, abs=0.01) + assert simulation.calculate("housing_benefit_child_disability_premiums", 2020)[ + 0 + ] == pytest.approx(3 * (65.52 + 26.60) * 52, abs=0.01) + + +def test_explicit_child_allowance_reform_remains_authoritative(): + simulation = family_simulation( + people=children(3), + reform={ + "gov.dwp.housing_benefit.allowances.child": {"2026": 100}, + }, + ) + assert ( + simulation.calculate("housing_benefit_child_allowance", 2026)[0] == 3 * 100 * 52 + ) + + +@pytest.mark.parametrize( + "facts,expected", + [ + ({"incapacity_benefit": 1_000}, False), + ( + { + "incapacity_benefit": 1_000, + "incapacity_benefit_is_short_term_lower_rate": True, + }, + False, + ), + ( + { + "incapacity_benefit": 1_000, + "incapacity_benefit_is_short_term_higher_rate": True, + }, + True, + ), + ({"housing_benefit_childcare_listed_incapacity_benefit_payable": True}, True), + ({"housing_benefit_childcare_incapacity_but_for_determination": True}, True), + ], +) +def test_childcare_incapatity_requires_positive_rate_or_statutory_condition( + facts, expected +): + simulation = family_simulation( + people={"claimant": {"age": 40, "is_claimant_or_partner": True, **facts}}, + family={"disability_premium": 0}, + ) + assert ( + bool(simulation.calculate("housing_benefit_childcare_incapacitated", 2026)[0]) + is expected + ) + + +def test_pc_assessment_adapter_uses_the_separately_installed_pc_component(): + from policyengine_core.reforms import Reform + from policyengine_uk.model_api import BenUnit, Variable, YEAR + + class pension_credit_earnings_disregard(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + label = "Test Pension Credit earnings disregard" + + def formula(benunit, period, parameters): + return np.full(benunit.count, 260.0) + + class WithPensionCreditComponent(Reform): + def apply(self): + self.add_variable(pension_credit_earnings_disregard) + + without = family_simulation() + with_component = family_simulation(reform=WithPensionCreditComponent) + name = "housing_benefit_pension_credit_earnings_disregard_assessment" + assert without.calculate(name, 2026)[0] == 0 + assert with_component.calculate(name, 2026)[0] == 260 diff --git a/policyengine_uk/tests/test_housing_benefit_non_dep_additional_rules.py b/policyengine_uk/tests/test_housing_benefit_non_dep_additional_rules.py new file mode 100644 index 0000000000..6f8c315030 --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_non_dep_additional_rules.py @@ -0,0 +1,355 @@ +"""HB reg 74 / SPC reg 55 and SPC reg 59: factual exception and change cases.""" + +import json + +import numpy as np +import pytest + +from policyengine_uk import Simulation + + +def non_dep_simulation( + *, + year=2026, + claimant=None, + non_dep=None, + family=None, + country="ENGLAND", + other_claim=None, +): + claimant_values = {"age": 70, "is_claimant_or_partner": True} + claimant_values.update(claimant or {}) + non_dep_values = { + "age": 30, + "is_claimant_or_partner": True, + "is_non_dependant_of_household_head": True, + "household_benefits_individual_non_dep_deduction": 40 * 52, + "housing_benefit_non_dep_full_time_student": False, + } + non_dep_values.update(non_dep or {}) + claim = { + "housing_benefit_pension_age_regulations_apply": True, + "housing_benefit_assessment_date": "2026-10-06", + "housing_benefit_continuous_award_start": "2020-01-01", + "benunit_is_rent_liable": True, + "share_of_household_rent": 1, + } + claim.update(family or {}) + people = {"claimant": claimant_values, "non_dep": non_dep_values} + families = { + "claim": {"members": ["claimant"], **claim}, + "non_dep_family": { + "members": ["non_dep"], + "benunit_is_rent_liable": False, + "share_of_household_rent": 0, + "housing_benefit_pension_age_regulations_apply": False, + }, + } + if other_claim: + people["other_claimant"] = {"age": 40, "is_claimant_or_partner": True} + families["other_claim"] = { + "members": ["other_claimant"], + "benunit_is_rent_liable": True, + "housing_benefit_pension_age_regulations_apply": False, + "share_of_household_rent": 0.5, + **other_claim, + } + families["claim"]["share_of_household_rent"] = 0.5 + situation = { + "people": { + name: {key: {str(year): value} for key, value in values.items()} + for name, values in people.items() + }, + "benunits": { + name: { + key: value if key == "members" else {str(year): value} + for key, value in values.items() + } + for name, values in families.items() + }, + "households": { + "home": {"members": list(people), "country": {str(year): country}} + }, + } + return Simulation(situation=situation) + + +def history(*events, previous=20, last="2020-01-01", person_id="non_dep"): + return json.dumps( + [ + { + "person_id": person_id, + "previous_weekly_deduction": previous, + "last_effective_date": last, + "increases": [{"date": day, "kind": kind} for day, kind in events], + } + ] + ) + + +@pytest.mark.parametrize( + "facts,exempt", + [ + ({"housing_benefit_non_dep_normal_home_elsewhere": True}, True), + ({"housing_benefit_non_dep_youth_training_allowance": True}, True), + ( + { + "age": 24, + "esa_income_reported": 1000, + "esa_support_group": False, + "esa_work_related_activity_group": False, + }, + True, + ), + ( + { + "age": 24, + "esa_income_reported": 1000, + "esa_work_related_activity_group": True, + }, + False, + ), + ({"age": 24, "esa_income_reported": 1000, "esa_support_group": True}, False), + ({"age": 25, "esa_income_reported": 1000}, False), + ( + { + "housing_benefit_non_dep_absent": True, + "is_hospital_inpatient": True, + "housing_benefit_non_dep_linked_inpatient_days": 364, + }, + False, + ), + ( + { + "housing_benefit_non_dep_absent": True, + "is_hospital_inpatient": True, + "housing_benefit_non_dep_linked_inpatient_days": 365, + }, + True, + ), + ( + { + "housing_benefit_non_dep_absent": False, + "is_hospital_inpatient": True, + "housing_benefit_non_dep_linked_inpatient_days": 365, + }, + False, + ), + ( + { + "housing_benefit_non_dep_absent": True, + "is_in_prison": True, + "housing_benefit_non_dep_custody_excludes_mental_health_hospital": True, + }, + True, + ), + ( + { + "housing_benefit_non_dep_absent": True, + "is_in_prison": True, + "housing_benefit_non_dep_custody_excludes_mental_health_hospital": False, + }, + False, + ), + ( + { + "housing_benefit_non_dep_absent": True, + "housing_benefit_non_dep_military_operations": True, + }, + True, + ), + ( + { + "housing_benefit_non_dep_absent": False, + "housing_benefit_non_dep_military_operations": True, + }, + False, + ), + ], +) +def test_additional_exception_facts(facts, exempt): + simulation = non_dep_simulation(non_dep=facts) + assert ( + bool( + simulation.calculate("housing_benefit_non_dep_additional_exception", 2026)[ + 1 + ] + ) + is exempt + ) + assert ( + bool( + simulation.calculate( + "housing_benefit_individual_non_dep_deduction_eligible", 2026 + )[1] + ) + is not exempt + ) + + +@pytest.mark.parametrize( + "pension,summer,study,works,expected", + [ + (False, False, True, True, 0), + (False, True, False, False, 0), + (False, True, False, True, 40 * 52), + (True, True, False, True, 0), + ], +) +def test_student_study_summer_work_and_pension_rules( + pension, summer, study, works, expected +): + simulation = non_dep_simulation( + claimant={"age": 70 if pension else 40, "is_SP_age": pension}, + family={"housing_benefit_pension_age_regulations_apply": pension}, + non_dep={ + "housing_benefit_non_dep_full_time_student": True, + "housing_benefit_non_dep_period_of_study": study, + "housing_benefit_non_dep_summer_vacation": summer, + "housing_benefit_remunerative_work": works, + }, + ) + assert ( + simulation.calculate("housing_benefit_non_dep_deductions", 2026)[0] == expected + ) + + +@pytest.mark.parametrize( + "country,age,expected", + [ + ("ENGLAND", 64, 0), + ("NORTHERN_IRELAND", 64, 40 * 52), + ("NORTHERN_IRELAND", 65, 0), + ], +) +def test_pension_student_ni_retains_age_65_condition(country, age, expected): + simulation = non_dep_simulation( + country=country, + claimant={"age": age}, + non_dep={ + "housing_benefit_non_dep_full_time_student": True, + "housing_benefit_non_dep_period_of_study": False, + "housing_benefit_non_dep_summer_vacation": True, + "housing_benefit_remunerative_work": True, + }, + ) + assert ( + simulation.calculate("housing_benefit_non_dep_deductions", 2026)[0] == expected + ) + + +def test_unrelated_pensioner_does_not_exempt_other_claimant_student(): + simulation = non_dep_simulation( + non_dep={ + "housing_benefit_non_dep_full_time_student": True, + "housing_benefit_non_dep_period_of_study": False, + "housing_benefit_non_dep_summer_vacation": True, + "housing_benefit_remunerative_work": True, + }, + other_claim={"housing_benefit_pension_age_regulations_apply": False}, + ) + np.testing.assert_allclose( + simulation.calculate("housing_benefit_non_dep_deductions", 2026), + [0, 0, 20 * 52], + ) + + +@pytest.mark.parametrize( + "date,expected", [("2026-10-11", 20 * 52), ("2026-10-12", 40 * 52)] +) +@pytest.mark.parametrize("country", ["ENGLAND", "NORTHERN_IRELAND"]) +def test_pension_increase_postponed_and_rounded_to_monday(date, expected, country): + simulation = non_dep_simulation( + country=country, + family={ + "housing_benefit_assessment_date": date, + "housing_benefit_non_dep_increase_history": history( + ("2026-04-08", "circumstances") + ), + }, + ) + assert ( + simulation.calculate("housing_benefit_non_dep_deductions", 2026)[0] == expected + ) + + +def test_second_increase_does_not_restart_clock(): + simulation = non_dep_simulation( + family={ + "housing_benefit_assessment_date": "2026-10-12", + "housing_benefit_non_dep_increase_history": history( + ("2026-04-08", "circumstances"), ("2026-08-01", "circumstances") + ), + } + ) + assert ( + simulation.calculate("housing_benefit_non_dep_deductions", 2026)[0] == 40 * 52 + ) + + +@pytest.mark.parametrize( + "events,previous,award_start,current,expected", + [ + ([("2026-08-01", "arrival")], 0, "2020-01-01", 40, 0), + ([("2026-04-01", "uprating")], 20, "2020-01-01", 40, 40), + ([("2026-01-01", "arrival")], 0, "2026-05-01", 40, 40), + ([("2026-08-01", "circumstances")], 40, "2020-01-01", 20, 20), + ([("2026-08-01", "circumstances")], 20, "2020-01-01", 0, 0), + ], +) +def test_arrival_uprating_initial_claim_reductions_and_exemptions( + events, previous, award_start, current, expected +): + simulation = non_dep_simulation( + non_dep={"household_benefits_individual_non_dep_deduction": current * 52}, + family={ + "housing_benefit_continuous_award_start": award_start, + "housing_benefit_non_dep_increase_history": history( + *events, previous=previous + ), + }, + ) + assert ( + simulation.calculate("housing_benefit_non_dep_deductions", 2026)[0] + == expected * 52 + ) + + +def test_postponement_is_claim_specific_before_rent_allocation(): + simulation = non_dep_simulation( + family={ + "housing_benefit_non_dep_increase_history": history( + ("2026-08-01", "arrival"), previous=0 + ) + }, + other_claim={ + "housing_benefit_pension_age_regulations_apply": True, + "housing_benefit_continuous_award_start": "2026-09-01", + "housing_benefit_non_dep_increase_history": history( + ("2026-08-01", "arrival"), previous=0 + ), + }, + ) + np.testing.assert_allclose( + simulation.calculate("housing_benefit_non_dep_deductions", 2026), + [0, 0, 20 * 52], + ) + + +@pytest.mark.parametrize( + "bad", + [ + "not JSON", + "{}", + '[{"person_id":"non_dep"}]', + history(("2026-08-01", "circumstances"), previous=-1), + history(("2026-08-01", "unknown")), + history(("2026-08-01", "arrival"), person_id="missing"), + ], +) +def test_invalid_postponement_history_is_not_silently_accepted(bad): + simulation = non_dep_simulation( + family={"housing_benefit_non_dep_increase_history": bad} + ) + with pytest.raises(ValueError): + simulation.calculate("housing_benefit_non_dep_deductions", 2026) diff --git a/policyengine_uk/tests/test_housing_benefit_parameter_history.py b/policyengine_uk/tests/test_housing_benefit_parameter_history.py index 5b5c874632..0e3350e111 100644 --- a/policyengine_uk/tests/test_housing_benefit_parameter_history.py +++ b/policyengine_uk/tests/test_housing_benefit_parameter_history.py @@ -94,3 +94,66 @@ def test_pension_capital_values_have_dated_gb_and_ni_sources( assert date in values references = {reference["href"] for reference in values[date].metadata["reference"]} assert references == expected_references + + +@pytest.mark.parametrize( + "year,single,couple,under_65_single,under_65_couple", + [ + # Original annual Orders/Adjustment Regulations, GB and NI. + (2015, 166.05, 248.30, 151.20, 230.85), + (2016, 168.70, 252.30, 155.60, 237.55), + (2017, 172.55, 258.15, 159.35, 243.25), + (2018, 176.40, 263.80, 163.00, 248.80), + ], +) +def test_original_pension_allowance_history( + written_housing_benefit_parameters, + year, + single, + couple, + under_65_single, + under_65_couple, +): + allowances = written_housing_benefit_parameters.allowances + date = f"{year}-04-30" + for name in ("single", "lone_parent"): + assert getattr(allowances, name).aged(date) == single + assert getattr(allowances, name).pension_age_under_65(date) == under_65_single + assert allowances.couple.aged(date) == couple + assert allowances.couple.pension_age_under_65(date) == under_65_couple + + +def test_under_65_category_removed_on_statutory_date( + written_housing_benefit_parameters, +): + category = written_housing_benefit_parameters.allowances.pension_age_history.under_65_category_applies + assert category("2018-12-05") + assert not category("2018-12-06") + + +@pytest.mark.parametrize( + "year,thresholds,amounts", + [ + ( + 2015, + [0, 129, 189, 246, 328, 408], + [14.55, 33.40, 45.85, 75.05, 85.45, 93.80], + ), + ( + 2016, + [0, 133, 195, 253, 338, 420], + [14.65, 33.65, 46.20, 75.60, 86.10, 94.50], + ), + ( + 2017, + [0, 136, 200, 259, 346, 430], + [14.80, 34.00, 46.65, 76.35, 86.95, 95.45], + ), + ], +) +def test_original_non_dependant_scale_history( + written_housing_benefit_parameters, year, thresholds, amounts +): + scale = written_housing_benefit_parameters.non_dep_deduction.amount(f"{year}-04-30") + assert list(scale.thresholds) == thresholds + assert list(scale.amounts) == amounts diff --git a/policyengine_uk/utils/housing_benefit.py b/policyengine_uk/utils/housing_benefit.py new file mode 100644 index 0000000000..58d98cd51f --- /dev/null +++ b/policyengine_uk/utils/housing_benefit.py @@ -0,0 +1,27 @@ +"""Date operations shared by Housing Benefit stock/status rules.""" + +import numpy as np + + +def calendar_dates(yyyymmdd): + """Convert existing validated YYYYMMDD date values to calendar-day arrays.""" + values = np.asarray(yyyymmdd, dtype=np.int64) + months = (12 * (values // 10000 - 1970) + values // 100 % 100 - 1).astype( + "datetime64[M]" + ) + return months.astype("datetime64[D]") + (values % 100 - 1).astype("timedelta64[D]") + + +def september_first_monday(birth_date, birthday_age): + """The first Monday in September following the specified birthday.""" + born = np.asarray(birth_date, dtype=np.int64) + year = born // 10000 + birthday_age + birthday = calendar_dates(year * 10000 + born % 10000) + september = (12 * (year - 1970) + 8).astype("datetime64[M]").astype("datetime64[D]") + # 1 January 1970 was Thursday (weekday 3, Monday 0). + monday = september + ((-september.astype(np.int64) - 3) % 7).astype( + "timedelta64[D]" + ) + year = year + (monday <= birthday) + september = (12 * (year - 1970) + 8).astype("datetime64[M]").astype("datetime64[D]") + return september + ((-september.astype(np.int64) - 3) % 7).astype("timedelta64[D]") diff --git a/policyengine_uk/utils/housing_benefit_capital.py b/policyengine_uk/utils/housing_benefit_capital.py new file mode 100644 index 0000000000..95a66ec376 --- /dev/null +++ b/policyengine_uk/utils/housing_benefit_capital.py @@ -0,0 +1,150 @@ +"""Category-specific Housing Benefit capital exclusions, using retained stocks.""" + +import numpy as np + +from policyengine_uk.utils.housing_benefit import calendar_dates + + +_UNKNOWN = np.datetime64("9999-01-01") + + +def year_after(dates): + """One calendar year, retaining the day or the final day of February.""" + month = dates.astype("datetime64[M]") + day = (dates - month.astype("datetime64[D]")).astype(int) + next_month = month + np.timedelta64(12, "M") + return np.minimum( + next_month.astype("datetime64[D]") + day.astype("timedelta64[D]"), + (next_month + np.timedelta64(1, "M")).astype("datetime64[D]") + - np.timedelta64(1, "D"), + ) + + +def within_days(now, start, days, extension=None): + """A statutory period beginning on receipt; extensions require a known date.""" + normal = now < start + np.timedelta64(int(days), "D") + longer = False if extension is None else (extension < _UNKNOWN) & (now <= extension) + return (now >= start) & (normal | longer) + + +def disregarded_capital(person, period, parameters, pension): + """Keep working-age and pension-age exclusions separate for shared stocks.""" + p = parameters(period).gov.dwp.housing_benefit.means_test.capital.disregards + now = person.benunit("housing_benefit_assessment_date", period) + + def amount(name): + return np.maximum(person("housing_benefit_capital_" + name, period), 0) + + def fact(name): + return person("housing_benefit_capital_" + name, period) + + start = person.benunit("housing_benefit_continuous_award_start", period) + end = person.benunit("housing_benefit_continuous_award_end", period) + ordinary_days = p.temporary_weeks * 7 + commencement = calendar_dates(p.carer_reassessment_commencement) + refund = ( + amount("carer_reassessment_retained") + * fact("carer_reassessment_provenance") + * (now >= commencement) + * (fact("carer_reassessment_received") <= now) + ) + injury_date = fact("injury_first_payment_received") + injury_active = ( + (now >= injury_date) + if pension + else ( + fact("injury_payment_is_first") + & within_days(now, injury_date, p.injury_weeks * 7) + ) + ) + injury = amount("injury_trust") + amount("injury_payment_retained") * injury_active + arrears_date = fact("arrears_received") + ordinary_arrears = ( + (now >= arrears_date) & (now < year_after(arrears_date)) + if pension + else within_days(now, arrears_date, p.arrears_weeks * 7) + ) + continuous = (arrears_date >= start) & (now >= arrears_date) & (now <= end) + if not pension: + continuous &= arrears_date >= calendar_dates( + p.large_error_payment_earliest_receipt + ) + large_error = ( + continuous + & fact("arrears_official_error") + & (amount("arrears_total_payment") >= p.large_error_payment) + ) + arrears = amount("qualifying_arrears_retained") * (ordinary_arrears | large_error) + esa_date = fact("esa_error_received") + esa_ordinary = ( + (now >= esa_date) & (now < year_after(esa_date)) + if pension + else within_days(now, esa_date, p.arrears_weeks * 7) + ) + esa_large = ( + (amount("esa_error_total_payment") >= p.large_error_payment) + & (esa_date >= start) + & (now >= esa_date) + & (now <= end) + ) + arrears += amount("esa_official_error_retained") * (esa_ordinary | esa_large) + earmarked = 0 + for category in ("home", "repairs"): + received = fact(category + "_funds_received") + active = ( + (now >= received) & (now < year_after(received)) + if pension + else within_days( + now, received, ordinary_days, fact(category + "_funds_extension_end") + ) + ) + earmarked += amount(category + "_funds_retained") * active + business_extension = fact("business_extension_end") + disposal = ( + fact("business_disposal_steps") + & (fact("business_ceased") <= now) + & (business_extension < _UNKNOWN) + & (now <= business_extension) + ) + illness = fact("business_illness_and_return") & within_days( + now, start, ordinary_days, business_extension + ) + business = amount("business_assets") * ( + fact("business_active") | disposal | illness + ) + category = fact("premises_category") + types = category.possible_values + intended = fact("premises_intended_home") + steps = fact("premises_reasonable_steps") + ordinary_premises = ( + ((category == types.ACQUIRED_HOME) & intended) + | ((category == types.SALE) & steps) + | ( + ( + (category == types.LEGAL_POSSESSION) + | (category == types.ESSENTIAL_REPAIRS) + ) + & intended + & steps + ) + ) + temporary = ordinary_premises & within_days( + now, fact("premises_first_step"), ordinary_days, fact("premises_extension_end") + ) + estranged = category == types.FORMER_HOME_ESTRANGEMENT + former_lone = fact("property_occupier_is_former_partner") & fact( + "property_occupier_is_lone_parent" + ) + temporary |= estranged & ( + within_days(now, fact("premises_first_step"), ordinary_days) | former_lone + ) + premises = amount("temporary_premises") * temporary + relative = fact("property_occupier_is_relative") & ( + fact("property_occupier_over_qualifying_age") + | fact("property_occupier_incapacitated") + ) + former = fact("property_occupier_is_former_partner") & ~fact( + "property_relationship_estranged" + ) + relatives = amount("relative_occupied_premises") * (relative | former) + return refund + injury + arrears + earmarked + business + premises + relatives diff --git a/policyengine_uk/utils/housing_benefit_non_dependants.py b/policyengine_uk/utils/housing_benefit_non_dependants.py new file mode 100644 index 0000000000..d47ff001d2 --- /dev/null +++ b/policyengine_uk/utils/housing_benefit_non_dependants.py @@ -0,0 +1,142 @@ +"""Claimant-specific Housing Benefit non-dependant change histories. + +The input is factual award history, not a user-selected exemption. Core's +existing person/family/household entities have no claimant/non-dependant +relationship entity, so the sparse relationship records are JSON strings on +each claimant's benefit unit. Parsing is separate from the date/amount rule. +""" + +import json +from datetime import date + +import numpy as np + + +def _day(value): + if not isinstance(value, str): + raise ValueError("Non-dependant history dates must be ISO calendar dates") + try: + return np.datetime64(date.fromisoformat(value), "D") + except ValueError as error: + raise ValueError( + "Non-dependant history dates must be ISO calendar dates" + ) from error + + +def postponed_non_dep_increases( + benunit, period, current_deductions, full_student_exemption, student, applies, weeks +): + """Return only positive increases still postponed, before rent allocation. + + SI 2006/214 reg 59(10)-(13); SR 2006/406 reg 57(12)-(15). + First qualifying increase starts the clock. An uprating is not an arrival + or a change in the person's circumstances. Existing deductions, decreases + and exemptions remain effective. + """ + person = benunit.members + histories = benunit("housing_benefit_non_dep_increase_history", period) + now = benunit("housing_benefit_assessment_date", period) + award_start = benunit("housing_benefit_continuous_award_start", period) + weekdays = benunit("housing_benefit_benefit_week_start", period) + if np.any((weekdays < 0) | (weekdays > 6)): + raise ValueError("Housing Benefit benefit-week weekday must be 0 through 6") + person_indices = { + str(identifier): index for index, identifier in enumerate(person.ids) + } + household_of_person = person.household.members_entity_id + household_of_claim = benunit.max(household_of_person) + claim_indices, indices, previous_amounts, last_dates = [], [], [], [] + event_records, event_dates, event_kinds = [], [], [] + for claim, encoded in enumerate(histories): + if not applies[claim] or encoded in ("", "[]"): + continue + try: + records = json.loads(encoded) + except (ValueError, TypeError) as error: + raise ValueError( + "Housing Benefit non-dependant history must be a JSON array" + ) from error + if not isinstance(records, list): + raise ValueError( + "Housing Benefit non-dependant history must be a JSON array" + ) + seen = set() + for record in records: + if not isinstance(record, dict) or set(record) != { + "person_id", + "previous_weekly_deduction", + "last_effective_date", + "increases", + }: + raise ValueError( + "Non-dependant history has missing or unexpected fields" + ) + identifier = record["person_id"] + if ( + not isinstance(identifier, str) + or identifier not in person_indices + or identifier in seen + ): + raise ValueError( + "Non-dependant history needs unique existing person IDs" + ) + seen.add(identifier) + index = person_indices[identifier] + if household_of_person[index] != household_of_claim[claim]: + raise ValueError( + "Non-dependant history person must be in the claimant's household" + ) + previous = record["previous_weekly_deduction"] + if ( + isinstance(previous, bool) + or not isinstance(previous, (int, float)) + or not np.isfinite(previous) + or previous < 0 + ): + raise ValueError( + "Previous non-dependant deduction must be a finite nonnegative weekly amount" + ) + last = _day(record["last_effective_date"]) + events = record["increases"] + if not isinstance(events, list): + raise ValueError( + "Non-dependant increases must be an array of dated events" + ) + record_index = len(claim_indices) + claim_indices.append(claim) + indices.append(index) + previous_amounts.append(previous) + last_dates.append(last) + for event in events: + if not isinstance(event, dict) or set(event) != {"date", "kind"}: + raise ValueError("Each non-dependant increase needs date and kind") + event_date = _day(event["date"]) + if event["kind"] not in ("arrival", "circumstances", "uprating"): + raise ValueError("Unknown non-dependant increase kind") + event_records.append(record_index) + event_dates.append(event_date) + event_kinds.append(event["kind"] != "uprating") + # The loops above only decode and validate sparse relationship records. + # Apply the policy rule to arrays, including multiple claims per person. + claims = np.asarray(claim_indices, dtype=int) + people = np.asarray(indices, dtype=int) + records = np.asarray(event_records, dtype=int) + dates = np.asarray(event_dates, dtype="datetime64[D]") + last = np.asarray(last_dates, dtype="datetime64[D]") + since = np.maximum(award_start[claims], last) + valid = ( + np.asarray(event_kinds, dtype=bool) + & (dates > since[records]) + & (dates <= now[claims[records]]) + ) + first = np.full(len(claims), "9999-01-01", dtype="datetime64[D]") + np.minimum.at(first, records[valid], dates[valid]) + due = first + np.timedelta64(int(weeks * 7), "D") + weekday = (due - np.datetime64("1970-01-05", "D")).astype(int) % 7 + due += ((weekdays[claims] - weekday) % 7).astype("timedelta64[D]") + current = np.where( + full_student_exemption[claims] & student[people], 0, current_deductions[people] + ) + pending = (first < np.datetime64("9999-01-01")) & (now[claims] < due) + difference = np.maximum(0, current - np.asarray(previous_amounts) * 52) * pending + return np.bincount(claims, weights=difference, minlength=benunit.count) diff --git a/policyengine_uk/utils/net_earnings.py b/policyengine_uk/utils/net_earnings.py new file mode 100644 index 0000000000..82ea50af54 --- /dev/null +++ b/policyengine_uk/utils/net_earnings.py @@ -0,0 +1,34 @@ +"""The existing individual earnings/tax-attribution convention, with a rate +provided by the calling benefit rather than borrowed from another program. +""" + +import numpy as np + + +def net_earnings(person, period, pension_deduction_rate): + employment = person("employment_income", period) + self_employment = person("self_employment_income", period) + statutory_pay = person("employment_benefits", period) + gross = np.maximum(employment, 0) + np.maximum(self_employment, 0) + statutory_pay + income_before_losses = person("total_income", period) + statutory_pay + system = person.simulation.tax_benefit_system + for component in system.get_variable("total_income").adds: + income_before_losses += np.maximum(-person(component, period), 0) + share = np.divide( + gross, + income_before_losses, + out=np.zeros_like(gross), + where=income_before_losses > 0, + ) + tax = person("income_tax", period) * np.minimum(share, 1) + ni = sum( + person(name, period) + for name in ("ni_class_1_employee", "ni_class_2", "ni_class_4") + ) + return np.maximum( + gross + - tax + - ni + - person("pension_contributions", period) * pension_deduction_rate, + 0, + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_assessment_phase_ended.py b/policyengine_uk/variables/gov/dwp/esa_assessment_phase_ended.py new file mode 100644 index 0000000000..a1376468d5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_assessment_phase_ended.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_assessment_phase_ended(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa assessment phase ended" + documentation = "The person's statutory ESA assessment phase has ended. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_assessment_phase_exception.py b/policyengine_uk/variables/gov/dwp/esa_assessment_phase_exception.py new file mode 100644 index 0000000000..09ae77dbd3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_assessment_phase_exception.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_assessment_phase_exception(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa assessment phase exception" + documentation = "ESA regulation 7 applies to the person, waiving assessment-phase completion before the support component. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_claim_made.py b/policyengine_uk/variables/gov/dwp/esa_claim_made.py new file mode 100644 index 0000000000..d3e2212e2a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_claim_made.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_claim_made(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa claim made" + documentation = "The person has made a claim for Employment and Support Allowance. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_converted_award.py b/policyengine_uk/variables/gov/dwp/esa_converted_award.py new file mode 100644 index 0000000000..d69ca2c753 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_converted_award.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_converted_award(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa converted award" + documentation = "The person is entitled to converted ESA, including entitlement prevented solely by the contributory ESA duration limit. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_main_phase.py b/policyengine_uk/variables/gov/dwp/esa_main_phase.py new file mode 100644 index 0000000000..d1d8396243 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_main_phase.py @@ -0,0 +1,31 @@ +from policyengine_uk.model_api import * + + +class esa_main_phase(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "ESA main-phase conditions satisfied" + documentation = "Determined ESA work-related activity/support status after assessment, its statutory exception, or a converted award. Payment alone does not establish this state." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) + + def formula(person, period, parameters): + assessment_complete = person("esa_assessment_phase_ended", period) | person( + "esa_assessment_phase_exception", period + ) + claimed_or_credits = person("esa_claim_made", period) | person( + "receives_limited_capability_for_work_credits", period + ) + return ( + person("esa_converted_award", period) + | person("esa_work_related_activity_group", period) + | ( + claimed_or_credits + & person("esa_support_group", period) + & assessment_complete + ) + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_support_group.py b/policyengine_uk/variables/gov/dwp/esa_support_group.py new file mode 100644 index 0000000000..fb9661eb03 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_support_group.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_support_group(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa support group" + documentation = "The Secretary of State has determined that this person has, or is treated as having, limited capability for work-related activity for ESA. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/esa_work_related_activity_group.py b/policyengine_uk/variables/gov/dwp/esa_work_related_activity_group.py new file mode 100644 index 0000000000..9970254103 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/esa_work_related_activity_group.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_work_related_activity_group(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa work related activity group" + documentation = "The Secretary of State has determined that this person belongs to the ESA work-related activity group. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/21", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py index aa7dd6bd65..687e5b84ea 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py @@ -4,26 +4,36 @@ class housing_benefit_applicable_income_childcare_element(Variable): value_type = float entity = BenUnit - label = "Housing Benefit applicable income childcare element" definition_period = YEAR unit = GBP - reference = "https://www.legislation.gov.uk/uksi/2006/213/regulation/27" + label = "Housing Benefit deductible childcare charges" + documentation = "Qualifying per-child childcare, subject to the work condition, own statutory caps and the remaining-earnings plus actual-tax-credit restriction. It cannot reduce pensions, capital tariff or other unearned income. The pre-additional earnings disregard prevents a dependency cycle while preserving the additional-disregard coverage test." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/27", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/30", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/24", + ) def formula(benunit, period, parameters): - p = parameters(period).gov.dwp.tax_credits.working_tax_credit.elements - relevant_children = benunit( - "num_relevant_children_for_housing_benefit_childcare", period + p = parameters( + period + ).gov.dwp.housing_benefit.means_test.childcare.weekly_maximum + count = benunit("num_relevant_children_for_housing_benefit_childcare", period) + cap = ( + where(count == 1, p.one_child, where(count > 1, p.two_or_more_children, 0)) + * WEEKS_IN_YEAR ) - childcare_amount_1 = (relevant_children == 1) * p.childcare_1 - childcare_amount_2 = (relevant_children > 1) * p.childcare_2 - max_weekly_childcare_amount = childcare_amount_1 + childcare_amount_2 - # Assuming that no children leads to no childcare element - capped_max_childcare_amount = where( - relevant_children == 0, 0, max_weekly_childcare_amount + charges = benunit.sum( + benunit.members("housing_benefit_qualifying_childcare_costs", period) ) - max_childcare_amount = capped_max_childcare_amount * WEEKS_IN_YEAR - childcare_expenses = add(benunit, period, ["childcare_expenses"]) - return min_( - max_childcare_amount, - childcare_expenses, + qualifying = min_(max_(charges, 0), cap) + earnings = benunit("housing_benefit_net_earnings", period) + base = benunit("housing_benefit_pre_additional_earnings_disregard", period) + available_tax_credits = max_( + add(benunit, period, ["working_tax_credit", "child_tax_credit"]), 0 + ) + deductible = min_(qualifying, max_(earnings - base, 0) + available_tax_credits) + return where( + benunit("housing_benefit_childcare_work_condition", period), deductible, 0 ) 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 a7600bf518..ae9a7e8d24 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 @@ -4,95 +4,41 @@ class housing_benefit_applicable_income_disregard(Variable): value_type = float entity = BenUnit - label = "Housing Benefit applicable income disregards" - documentation = ( - "Sums disregarded from the claimant's and partner's net earnings. " - "A lone parent has £25 a week, a couple £10 and anyone else £5, " - "capped at net earnings. From 5 October 2026 the working-age " - "Regulations add the specified or temporary accommodation disregard " - "(housing_benefit_specified_or_temporary_accommodation_disregard), " - "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 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." - ) definition_period = YEAR unit = GBP + label = "Housing Benefit earnings disregards" + documentation = "Ordinary, special, permitted-work and accommodation earnings disregards, plus the additional earnings amount when its work and coverage conditions hold. The coverage comparison includes earnings-limited childcare. Savings-credit-only cases retain Pension Credit grounds. Passported earnings are disregarded in full." reference = ( "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", "https://www.legislation.gov.uk/nisr/2006/405/schedule/5", "https://www.legislation.gov.uk/nisr/2006/406/schedule/5", - "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", ) def formula(benunit, period, parameters): p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard - net_earnings = benunit("housing_benefit_net_earnings", period) - # Working age Sch 4 paras 4, 7 and 10; pension age Sch 4 paras 2 and 7. - weekly_amount = select( - [benunit("is_lone_parent", period), benunit("is_couple", period)], - [p.lone_parent, p.couple], - default=p.single, - ) - standard = min_(weekly_amount * WEEKS_IN_YEAR, net_earnings) - # Working age Sch 4 para 18 (NI Sch 5 para 18), from 5 October 2026: - # specified or temporary accommodation. It applies alongside paras 3 - # to 10A, none of which excludes it, and takes the earnings they - # leave. - accommodation = min_( - benunit( - "housing_benefit_specified_or_temporary_accommodation_disregard", - period, - ), - net_earnings - standard, - ) - # Working age Sch 4 para 17; pension age Sch 4 para 9. - additional_amount = p.worker * WEEKS_IN_YEAR + earnings = benunit("housing_benefit_net_earnings", period) + base = benunit("housing_benefit_pre_additional_earnings_disregard", period) childcare = benunit( "housing_benefit_applicable_income_childcare_element", period ) - # "Equal or exceed", compared in pence: net earnings are float32, so - # exactly £1,149.20 is held as £1,149.19995, and an exact comparison - # with the total fails at equality. From 5 October 2026 the total - # includes the para 18 amount (para 17(3)(a), "paragraphs 3 to 10A - # and 18"); it is zero under the pension-age para 9(3)(a). - covers_additional = np.round(net_earnings.astype(float), 2) >= np.round( - (standard + accommodation + childcare + additional_amount).astype(float), - 2, + amount = p.worker * WEEKS_IN_YEAR + # Compare in pence: exact equality can otherwise fail in float32. + covers = np.round(earnings.astype(float), 2) >= np.round( + (base + childcare + amount).astype(float), 2 ) additional = where( benunit( "meets_housing_benefit_additional_earnings_disregard_conditions", period ) - & covers_additional, - additional_amount, + & covers, + amount, 0, ) - # 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. - on_passporting_benefit = benunit( - "housing_benefit_on_passporting_benefit", period - ) return where( - on_passporting_benefit, - net_earnings, - standard + accommodation + additional, + benunit("housing_benefit_on_passporting_benefit", period), + earnings, + base + additional, ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_net_earnings.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_net_earnings.py index 8f8d97ac9a..5b660de5cb 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_net_earnings.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_net_earnings.py @@ -5,83 +5,17 @@ class housing_benefit_net_earnings(Variable): value_type = float entity = BenUnit label = "Housing Benefit net earnings" - documentation = ( - "Net earnings of the claimant and partner, from which the Housing " - "Benefit earnings disregards are taken. For each person: employment " - "income plus self-employment profit (each floored at zero, as a loss " - "in one employment is not set against another) plus statutory sick " - "and maternity pay (regulation 35(1)(i); pension age regulation " - "35(1)(h)), less income tax, " - "Class 1, 2 and 4 National Insurance, and half of pension " - "contributions, floored at zero. For an employee the regulations " - "deduct the income tax deducted from the earnings (regulation 36(3); " - "pension age regulation 36(2)); for the self-employed, a notional " - "basic-rate tax on the profit alone less personal reliefs (regulation " - "39(1); pension age regulation 40(1)). PolicyEngine attributes a " - "person's income tax to earnings in proportion to their share of the " - "person's total income plus statutory pay, before any negative income " - "component. " - "For employment income that is a lower bound " - "on the tax on the earnings taxed as the top slice of income; for " - "self-employment profit alongside other income it can exceed the " - "notional tax. It is exact for an employee whose earnings are their " - "only taxable income, and whenever no income tax is due. The earnings " - "of a child or young person are not the claimant's (regulation 25(3); " - "pension age regulation 23(3)), so only the claimant's and partner's " - "count (is_claimant_or_partner)." - ) + documentation = "Net earnings calculated for each claimant and partner before aggregation. Dependants' earnings do not count; individual calculation preserves the special and permitted-work couple allocation rules." definition_period = YEAR unit = GBP reference = ( - "https://www.legislation.gov.uk/uksi/2006/213/regulation/35", "https://www.legislation.gov.uk/uksi/2006/213/regulation/36", - "https://www.legislation.gov.uk/uksi/2006/213/regulation/38", - "https://www.legislation.gov.uk/uksi/2006/213/regulation/39", - "https://www.legislation.gov.uk/uksi/2006/214/regulation/35", "https://www.legislation.gov.uk/uksi/2006/214/regulation/36", - "https://www.legislation.gov.uk/uksi/2006/214/regulation/39", - "https://www.legislation.gov.uk/uksi/2006/214/regulation/40", ) def formula(benunit, period, parameters): - p = parameters(period).gov.dwp.housing_benefit.means_test person = benunit.members - employment_income = person("employment_income", period) - self_employment_income = person("self_employment_income", period) - # Statutory sick and maternity pay are earnings (reg 35(1)(i); pension - # age reg 35(1)(h)). The model taxes them as employment income - # (employment_benefits) but leaves them out of total_income. - statutory_pay = person("employment_benefits", period) - earnings = ( - max_(employment_income, 0) + max_(self_employment_income, 0) + statutory_pay - ) - # Income tax is attributed by the earnings' share of total income, - # with statutory pay added and before any negative component (a - # loss), so that a loss set against other income does not drop or - # inflate the share of tax on these earnings. - income_before_losses = person("total_income", period) + statutory_pay - system = person.simulation.tax_benefit_system - for component in system.get_variable("total_income").adds: - income_before_losses += max_(-person(component, period), 0) - earnings_share = np.divide( - earnings, - income_before_losses, - out=np.zeros_like(earnings), - where=income_before_losses > 0, - ) - income_tax = person("income_tax", period) * min_(earnings_share, 1) - national_insurance = add( - person, period, ["ni_class_1_employee", "ni_class_2", "ni_class_4"] - ) - pension_contributions = ( - person("pension_contributions", period) - * p.pension_contribution_deduction_rate - ) - net_earnings = max_( - earnings - income_tax - national_insurance - pension_contributions, - 0, + return benunit.sum( + person("housing_benefit_person_net_earnings", period) + * person("is_claimant_or_partner", period) ) - # The claimant and partner: a child's or young person's earnings are - # not the claimant's (reg 25(3); pension age reg 23(3)). - claimant_or_partner = person("is_claimant_or_partner", period) - return benunit.sum(net_earnings * claimant_or_partner) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_permitted_work_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_permitted_work_disregard.py new file mode 100644 index 0000000000..6f08bf1af8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_permitted_work_disregard.py @@ -0,0 +1,32 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_permitted_work_disregard(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Housing Benefit permitted-work earnings disregard" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/10A", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5A", + ) + + def formula(benunit, period, parameters): + person = benunit.members + p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard + adult = person("is_claimant_or_partner", period) + earnings = person("housing_benefit_person_net_earnings", period) * adult + limits = person("housing_benefit_permitted_work_limit", period) * adult + exempt = limits > 0 + amount = benunit.max(limits) * WEEKS_IN_YEAR + contributions = benunit.sum( + where(exempt, earnings, min_(earnings, p.special * WEEKS_IN_YEAR)) + ) + permitted = min_(amount, contributions) + lone_parent = where( + benunit("is_lone_parent", period), + min_(benunit.sum(earnings), p.lone_parent * WEEKS_IN_YEAR), + 0, + ) + return where(benunit.any(exempt), max_(permitted, lone_parent), 0) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_person_net_earnings.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_person_net_earnings.py new file mode 100644 index 0000000000..de3ccff2e6 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_person_net_earnings.py @@ -0,0 +1,49 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.net_earnings import net_earnings + + +class housing_benefit_person_net_earnings(Variable): + value_type = float + entity = Person + label = "Housing Benefit net earnings of an individual" + documentation = ( + "Net earnings of the claimant and partner, from which the Housing " + "Benefit earnings disregards are taken. For each person: employment " + "income plus self-employment profit (each floored at zero, as a loss " + "in one employment is not set against another) plus statutory sick " + "and maternity pay (regulation 35(1)(i); pension age regulation " + "35(1)(h)), less income tax, " + "Class 1, 2 and 4 National Insurance, and half of pension " + "contributions, floored at zero. For an employee the regulations " + "deduct the income tax deducted from the earnings (regulation 36(3); " + "pension age regulation 36(2)); for the self-employed, a notional " + "basic-rate tax on the profit alone less personal reliefs (regulation " + "39(1); pension age regulation 40(1)). PolicyEngine attributes a " + "person's income tax to earnings in proportion to their share of the " + "person's total income plus statutory pay, before any negative income " + "component. " + "For employment income that is a lower bound " + "on the tax on the earnings taxed as the top slice of income; for " + "self-employment profit alongside other income it can exceed the " + "notional tax. It is exact for an employee whose earnings are their " + "only taxable income, and whenever no income tax is due. The earnings " + "of a child or young person are not the claimant's (regulation 25(3); " + "pension age regulation 23(3)), so only the claimant's and partner's " + "count (is_claimant_or_partner)." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/35", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/36", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/38", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/39", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/35", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/36", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/39", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/40", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test + return net_earnings(person, period, p.pension_contribution_deduction_rate) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_pre_additional_earnings_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_pre_additional_earnings_disregard.py new file mode 100644 index 0000000000..25b80a8953 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_pre_additional_earnings_disregard.py @@ -0,0 +1,43 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_pre_additional_earnings_disregard(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = ( + "Housing Benefit earnings disregard excluding the additional earnings amount" + ) + documentation = "Ordinary/special/permitted-work and accommodation disregards before the additional earnings amount. This intermediate avoids a circular dependency with the earnings-limited childcare deduction. Savings-credit-only cases retain PC grounds, with only the permitted higher lone-parent/exempt-work modifications." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/27", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/17", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + ) + + def formula(benunit, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard + earnings = benunit("housing_benefit_net_earnings", period) + standard = benunit("housing_benefit_standard_earnings_disregard", period) + accommodation = min_( + max_(earnings - standard, 0), + benunit( + "housing_benefit_specified_or_temporary_accommodation_disregard", period + ), + ) + pc = benunit( + "housing_benefit_pension_credit_earnings_disregard_assessment", period + ) + lone = where( + benunit("is_lone_parent", period), + min_(earnings, p.lone_parent * WEEKS_IN_YEAR), + 0, + ) + sc_only = benunit( + "housing_benefit_pension_age_regulations_apply", period + ) & benunit("in_receipt_of_savings_credit_only", period) + sc_base = max_( + pc, max_(lone, benunit("housing_benefit_permitted_work_disregard", period)) + ) + return where(sc_only, sc_base, standard + accommodation) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py index 74fb57f8e4..bde0d9cd2d 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py @@ -4,82 +4,27 @@ class housing_benefit_savings_credit_only_income(Variable): value_type = float entity = BenUnit - label = ( - "Housing Benefit income where the Pension Credit award is savings credit only" - ) - documentation = ( - "Income for the Housing Benefit means test of a claimant who, or whose " - "partner, has a Pension Credit award of savings credit only. The " - "authority takes the Secretary of State's assessment of net income for " - "that award and modifies it only for the listed items. Modelled: the " - "savings credit payable is added, and childcare charges and the " - "Housing Benefit earnings disregards are deducted. Pension Credit " - "income in the model disregards no earnings, whereas the Secretary of " - "State's figure is after the Pension Credit disregards (£20 for a lone " - "parent, £5 single or £10 couple otherwise). Deducting the Housing " - "Benefit disregards (£25 for a lone parent, £5 or £10 otherwise, and " - "the additional £17.10) therefore gives that figure less the higher " - "Housing Benefit amounts the regulation allows: £5 more for a lone " - "parent, and the additional disregard. This holds while neither " - "programme's £20 disregards for disabled people, carers and some " - "occupations are modelled; for those earners the Secretary of State's " - "figure is after £20, so the omission changes the income assessed, the " - "savings credit payable and possibly whether the award is savings " - "credit only. Childcare charges are deducted as in the general " - "route, without the work condition or the cap at earnings. Housing " - "Benefit's own income and tariff income rules do not apply to the " - "Secretary of State's figure, which already counts Pension Credit " - "deemed income from capital. Not modelled: the " - "maintenance disregards (neither income definition counts " - "maintenance), the exempt work disregard, the income and capital of a " - "partner treated as a household member but not in the Pension Credit " - "assessment, income of a non-dependant treated as the claimant's, and " - "war pensions (Great Britain: local schemes under section 134(8) of " - "the Social Security Administration Act 1992; Northern Ireland: war " - "pension income above £10 disregarded under Schedule 6 paragraph 1); " - "the model has no war pension income." - ) definition_period = YEAR unit = GBP + label = "Housing Benefit income for a savings-credit-only Pension Credit award" + documentation = "Use the Pension Credit net-income assessment, with savings credit payable added and only the modifications permitted by regulation 27. The PC assessment already includes its Schedule VI earnings disregard; deduct only the additional HB amount, not both complete disregards. No HB capital tariff or general HB disability-disregard grounds replace the PC assessment. Specific partner/non-dependant attribution and war-pension inputs remain governed by their separate provisions." reference = ( "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", - "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", - "https://www.legislation.gov.uk/nisr/2006/406/schedule/5", "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", ) def formula(benunit, period, parameters): - # SI 2006/214 reg 27(1) and (3) (NI: SR 2006/406 reg 25): the - # Secretary of State's assessment of net income for the award. - pension_credit_income = benunit("pension_credit_income", period) - # Reg 27(4)(a): the savings credit payable. A savings-credit-only - # award pays only the savings credit, so this is the Pension Credit - # paid (under the Pension Credit freeze, the frozen amount). - savings_credit_payable = benunit("pension_credit", period) - # Reg 27(4)(b): childcare charges taken into account under reg - # 30(1)(c), here as the general route deducts them; the reg 31 work - # condition and the reg 30(1)(c) cap at earnings are not modelled. + pc_income = benunit( + "housing_benefit_pension_credit_net_income_assessment", period + ) + savings_credit = benunit("pension_credit", period) childcare = benunit( "housing_benefit_applicable_income_childcare_element", period ) - # Reg 27(4)(c)(i) (Sch 4 para 2: £25 for a lone parent, against SPC - # Regs 2002 Sch VI para 1's £20) and (d) (Sch 4 para 9(1), the - # additional £17.10; the para 5A exempt work disregard is not - # modelled). NI: reg 25(4)(c)(i) and (d), Sch 5 paras 2 and 9(1). - # The model's Pension Credit income applies no Sch VI disregard, so - # deducting the whole Housing Benefit disregard also takes off the Sch - # VI amounts already inside the Secretary of State's figure: £20 for a - # lone parent (para 1) and £5 or £10 otherwise (para 5), which match - # Sch 4 paras 2 and 7 but for the lone parent's extra £5. Neither - # schedule's £20 disregards (Sch VI paras 2 to 4; Sch 4 paras 3 to 5) - # are modelled. If Sch 4 paras 3 to 5 are added to the disregard - # variable, this route needs the Sch VI grounds instead, as reg 27(4) - # does not let Housing Benefit's own £20 grounds replace them. - # Reg 27(5): Housing Benefit's own income rules, including tariff - # income from capital, do not apply to the Secretary of State's figure. - disregard = benunit("housing_benefit_applicable_income_disregard", period) - return max_( - 0, - pension_credit_income + savings_credit_payable - childcare - disregard, + pc_disregard = benunit( + "housing_benefit_pension_credit_earnings_disregard_assessment", period ) + hb_disregard = benunit("housing_benefit_applicable_income_disregard", period) + modification = max_(hb_disregard - pc_disregard, 0) + return max_(pc_income + savings_credit - childcare - modification, 0) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_standard_earnings_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_standard_earnings_disregard.py new file mode 100644 index 0000000000..1860978df5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_standard_earnings_disregard.py @@ -0,0 +1,112 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_standard_earnings_disregard(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = ( + "Housing Benefit earnings disregard before accommodation and additional amounts" + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/5", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/5", + ) + + def formula(benunit, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard + person = benunit.members + adult = person("is_claimant_or_partner", period) + earnings = person("housing_benefit_person_net_earnings", period) * adult + total = benunit.sum(earnings) + special = p.special * WEEKS_IN_YEAR + couple = benunit("is_couple", period) + lone_parent = benunit("is_lone_parent", period) + ordinary_limit = where(couple, p.couple, p.single) * WEEKS_IN_YEAR + ordinary = min_(total, ordinary_limit) + carer = adult & ( + person("is_entitled_to_carer_benefit", period) + | person("carer_premium_run_on", period) + ) + country = person.household("country", period) + ni = country == country.possible_values.NORTHERN_IRELAND + occupation = min_( + earnings, + max_( + 0, + person("housing_benefit_specified_occupation_net_earnings", period) + + ni + * person( + "housing_benefit_ni_additional_occupation_net_earnings", period + ), + ), + ) + other_earnings = benunit.project(benunit.sum(earnings)) - earnings + other_carer_or_occupation = ( + benunit.project(benunit.sum(carer)) - carer > 0 + ) | (benunit.project(benunit.sum(occupation)) - occupation > 0) + carer_candidate = min_( + special, + earnings + + where( + other_carer_or_occupation, + other_earnings, + min_(other_earnings, p.couple * WEEKS_IN_YEAR), + ), + ) + working_carer = benunit.max(where(carer, carer_candidate, 0)) + # Paragraphs 8–9: restrict own ordinary-job top-up; a partner in a + # specified occupation can contribute earnings under paragraph 8(2)(a). + own_top_up = benunit.project(ordinary_limit) + occupation_candidate = min_( + special, + occupation + + min_(max_(earnings - occupation, 0), own_top_up) + + where( + benunit.project(benunit.sum(occupation)) - occupation > 0, + other_earnings, + min_(other_earnings, p.couple * WEEKS_IN_YEAR), + ), + ) + working_occupation = benunit.max(where(occupation > 0, occupation_candidate, 0)) + disability = ( + (benunit("disability_premium", period) > 0) + | (benunit("severe_disability_premium", period) > 0) + | benunit.any( + adult + & ( + person("esa_support_group", period) + | person("esa_work_related_activity_group", period) + ) + ) + ) + working = select( + [disability, benunit.any(carer), benunit.sum(occupation) > 0], + [min_(total, special), working_carer, working_occupation], + default=ordinary, + ) + pension_disability = benunit.any( + adult + & person("housing_benefit_pension_special_disregard_conditions", period) + ) + pension = select( + [pension_disability | (benunit.sum(occupation) > 0), benunit.any(carer)], + [min_(total, special), min_(special, benunit.sum(earnings * carer))], + default=ordinary, + ) + standard = where( + benunit("housing_benefit_pension_age_regulations_apply", period), + pension, + working, + ) + standard = where( + lone_parent, min_(total, p.lone_parent * WEEKS_IN_YEAR), standard + ) + permitted = benunit("housing_benefit_permitted_work_disregard", period) + has_permitted = benunit.any( + adult & (person("housing_benefit_permitted_work_limit", period) > 0) + ) + return where(has_permitted, permitted, standard) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.py index c62844633d..7e439e0f4d 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.py @@ -13,14 +13,11 @@ class meets_housing_benefit_additional_earnings_disregard_conditions(Variable): "least 30 hours a week; a couple with a child or young person, or a " "lone parent, with someone working at least 16 hours; or a disabled " "claimant or partner working at least 16 hours. Disability uses the " - "input the model uses for the disability premium. Membership of the " - "work-related activity group and the support component are not " - "modelled. Nor is the Working Tax Credit 30 hour element route " - "(paragraph 17(2)(a) and 9(2)(a)); beyond the routes above it covers " - "only a couple whose 30-hour worker is under 25 and whose partner is " - "aged at least 60 and works 16 hours, and a disability that meets the " - "Working Tax Credit test but not the disability premium one, and no " - "tax credit can be claimed for 2025-26 onwards. The 50 plus element " + "input the model uses for the disability premium together with " + "determined ESA work-related activity and support-group status. " + "Pension-age claims use their own Schedule 4 disability conditions. " + "An actual Working Tax Credit 30-hour-element award is a separate " + "route (paragraph 17(2)(a) and 9(2)(a)). The 50 plus element " "route (paragraph 17(2)(c) and 9(2)(c)) ended with the element on 6 " "April 2012. The net earnings test is applied in " "housing_benefit_applicable_income_disregard. Only the claimant's and " @@ -41,8 +38,11 @@ def formula(benunit, period, parameters): person = benunit.members claimant_or_partner = person("is_claimant_or_partner", period) hours = person("weekly_hours", period) - works_hours = claimant_or_partner & (hours >= p.worker_hours) - works_lower_hours = claimant_or_partner & (hours >= p.worker_hours_lower) + remunerative = person("housing_benefit_remunerative_work", period) + works_hours = claimant_or_partner & remunerative & (hours >= p.worker_hours) + works_lower_hours = ( + claimant_or_partner & remunerative & (hours >= p.worker_hours_lower) + ) # Para 17(2)(b)(i) and 9(2)(b)(i): one person meets both tests. aged_worker = benunit.any(works_hours & (person("age", period) >= p.worker_age)) # Para 17(2)(b)(ii)-(iii) and 9(2)(b)(ii)-(iii). @@ -54,7 +54,20 @@ def formula(benunit, period, parameters): ) family_worker = family_with_child & benunit.any(works_lower_hours) # Para 17(2)(b)(iv)-(v) and 9(2)(b)(iv): the disabled person works. - disabled_worker = benunit.any( - works_lower_hours & person("is_disabled_for_benefits", period) + working_age_disability = ( + person("is_disabled_for_benefits", period) + | person("esa_work_related_activity_group", period) + | person("esa_support_group", period) + ) + disability = where( + person.benunit("housing_benefit_pension_age_regulations_apply", period), + person("housing_benefit_pension_special_disregard_conditions", period), + working_age_disability, + ) + disabled_worker = benunit.any(works_lower_hours & disability) + return ( + aged_worker + | family_worker + | disabled_worker + | benunit("working_tax_credit_30_hour_element_in_award", period) ) - return aged_worker | family_worker | disabled_worker diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/carer_premium_run_on.py b/policyengine_uk/variables/gov/dwp/housing_benefit/carer_premium_run_on.py new file mode 100644 index 0000000000..58b0cb351a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/carer_premium_run_on.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class carer_premium_run_on(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "carer premium run on" + documentation = "A carer premium continues in respect of this person under its statutory run-on rule after their carer-benefit entitlement ended. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/esa_limited_capability_for_work_determined.py b/policyengine_uk/variables/gov/dwp/housing_benefit/esa_limited_capability_for_work_determined.py new file mode 100644 index 0000000000..40a776b74a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/esa_limited_capability_for_work_determined.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class esa_limited_capability_for_work_determined(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "esa limited capability for work determined" + documentation = "Secretary of State has determined that the person has, or is treated as having, limited capability for work for ESA. This is not the separate Universal Credit status." + reference = ( + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py index cba43eaafe..54ce909b40 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_applicable_amount.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.excise import fiscal_year_segments class housing_benefit_applicable_amount(Variable): @@ -11,6 +12,9 @@ class housing_benefit_applicable_amount(Variable): reference = ( "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/1A", + "https://www.legislation.gov.uk/uksi/2017/1187/regulation/7/made", + "https://www.legislation.gov.uk/nisr/2017/242/regulation/7/made", ) def formula(benunit, period, parameters): @@ -24,32 +28,46 @@ def formula(benunit, period, parameters): eldest_age = benunit("eldest_claimant_or_partner_age", period) older_age_threshold = p.age_threshold.older younger_age_threshold = p.age_threshold.younger - u_18 = eldest_age < younger_age_threshold - u_25 = eldest_age < older_age_threshold - o_25 = (eldest_age >= older_age_threshold) & ~pension_age_regulations - o_18 = (eldest_age >= younger_age_threshold) * ~pension_age_regulations + # Schedule 3 paragraph 1A tests the claimant personally, not a partner. + person = benunit.members + esa_exception = benunit.any( + person("is_housing_benefit_claimant", period) + & person("esa_main_phase", period) + ) + older_single = (eldest_age >= older_age_threshold) | esa_exception + older_family = (eldest_age >= younger_age_threshold) | esa_exception single = benunit("is_single_person", period) couple = benunit("is_couple", period) lone_parent = benunit("is_lone_parent", period) - single_personal_allowance = ( - u_25 * p.single.younger - + o_25 * p.single.older - + pension_age_regulations * p.single.aged - ) - couple_personal_allowance = ( - u_18 * p.couple.younger - + o_18 * p.couple.older - + pension_age_regulations * p.couple.aged - ) - lone_parent_personal_allowance = ( - u_18 * p.lone_parent.younger - + o_18 * p.lone_parent.older - + pension_age_regulations * p.lone_parent.aged + working_age = ( + single * where(older_single, p.single.older, p.single.younger) + + couple * where(older_family, p.couple.older, p.couple.younger) + + lone_parent + * where(older_family, p.lone_parent.older, p.lone_parent.younger) ) + pension_age = 0 + for rules, share in fiscal_year_segments( + parameters.gov.dwp.housing_benefit.allowances.pension_age_history, + period.start.year, + ): + lower = rules.under_65_category_applies & ( + eldest_age < p.age_threshold.former_pension_age + ) + pension_age += share * ( + single * where(lower, p.single.pension_age_under_65, p.single.aged) + + couple * where(lower, p.couple.pension_age_under_65, p.couple.aged) + + lone_parent + * where(lower, p.lone_parent.pension_age_under_65, p.lone_parent.aged) + ) personal_allowance = ( - single * single_personal_allowance - + couple * couple_personal_allowance - + lone_parent * lone_parent_personal_allowance - ) * WEEKS_IN_YEAR + where(pension_age_regulations, pension_age, working_age) * WEEKS_IN_YEAR + ) premiums = benunit("benefits_premiums", period) - return personal_allowance + premiums + children = benunit("housing_benefit_child_allowance", period) + return ( + personal_allowance + + children + + premiums + + benunit("housing_benefit_family_premium", period) + + benunit("housing_benefit_child_disability_premiums", period) + ) 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 2af26611c4..9b997ee142 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 @@ -10,7 +10,10 @@ class housing_benefit_assessable_capital(Variable): "Household sources are allocated across benunits in proportion to their " "claimants and partners, a PolicyEngine convention because household " "capital data cannot identify ownership; children and young persons add " - "no weight. Person-level sources, such as a Lifetime ISA, count only for " + "no weight. Supplied category-specific retained exclusions are removed " + "before this allocation. A known claimant/partner owned amount, " + "including zero, instead replaces the household proxy, less only " + "their own qualifying exclusions. Person-level sources, such as a Lifetime ISA, count only for " "the holder's own benunit, and only when the holder is its claimant or " "partner (is_claimant_or_partner): a dependant's capital is not the " "claimant's. Where the Pension Credit award is savings credit only, the " @@ -43,6 +46,21 @@ def formula(benunit, period, parameters): ) p = parameters(period).gov.dwp.housing_benefit.means_test.capital household_capital = sum(household(source, period) for source in p.sources) + working_exclusions = person( + "housing_benefit_working_age_disregarded_capital", period + ) + pension_exclusions = person( + "housing_benefit_pension_age_disregarded_capital", period + ) + # Remove retained excluded funds before allocating a shared household + # stock. Subtracting them after allocation would charge another family + # for part of the holder's excluded money. + household_exclusions = where( + pension_age_regulations, + benunit.max(person.household.sum(pension_exclusions)), + benunit.max(person.household.sum(working_exclusions)), + ) + household_capital = max_(household_capital - household_exclusions, 0) claimant_or_partner = person("is_claimant_or_partner", period) person_capital = sum( benunit.sum(person(source, period) * claimant_or_partner) @@ -72,10 +90,33 @@ def formula(benunit, period, parameters): savings_credit_only = pension_age_regulations & benunit( "in_receipt_of_savings_credit_only", period ) + owned_exclusions = benunit.sum( + where( + person.benunit("housing_benefit_pension_age_regulations_apply", period), + pension_exclusions, + working_exclusions, + ) + * claimant_or_partner + ) + known_owned_capital = max_( + benunit("housing_benefit_owned_household_capital", period) + - owned_exclusions, + 0, + ) + # A known zero replaces the proxy just as a positive supplied value + # does. Person-level LISA capital is added once, in either path. + ordinary_capital = ( + where( + benunit("housing_benefit_owned_household_capital_known", period), + known_owned_capital, + household_capital_proxy, + ) + + person_capital + ) capital = where( savings_credit_only, benunit("pension_credit_assessable_capital", period), - household_capital_proxy + person_capital, + ordinary_capital, ) # Guarantee Credit passport: SI 2006/214 reg 26 (NI: SR 2006/406 # reg 24) disregards the whole of the capital and income of a diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessment_date.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessment_date.py new file mode 100644 index 0000000000..544e0f8840 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessment_date.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_assessment_date(Variable): + value_type = date + entity = BenUnit + definition_period = YEAR + label = "Housing Benefit date for factual status and retained capital" + documentation = "Point-in-time assessment date for supplied status, duration and retained-capital facts. Defaults to 6 October, consistently with UK annual age inputs. This is a stock/status convention, not a prediction that policy remains unchanged. Annual awards hold these facts fixed unless a formula explicitly segments a policy change. Supply a different assessment date when known." + + def formula(benunit, period, parameters): + return np.full( + benunit.nb_persons().shape, + f"{period.start.year}-10-06", + dtype="datetime64[D]", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_official_error.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_official_error.py new file mode 100644 index 0000000000..5f14c13de1 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_official_error.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_arrears_official_error(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital arrears official error" + documentation = "The listed arrears payment rectifies official error or an error on a point of law. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_received.py new file mode 100644 index 0000000000..60a499a3ba --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_arrears_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital arrears received" + documentation = "Receipt date of the relevant arrears payment. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_total_payment.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_total_payment.py new file mode 100644 index 0000000000..6a3ce01ed5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_arrears_total_payment.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_arrears_total_payment(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital arrears total payment" + documentation = "Total relevant arrears/compensation payment before expenditure, for the statutory large-error-payment threshold. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_active.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_active.py new file mode 100644 index 0000000000..e71a8c33eb --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_active.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_active(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital business active" + documentation = "The person is carrying on the trade/business to which the supplied assets belong. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_assets.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_assets.py new file mode 100644 index 0000000000..73e11b20eb --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_assets.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_assets(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital business assets" + documentation = "Value of assets belonging to and used in the person's own trade/business, not portfolio shares. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_ceased.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_ceased.py new file mode 100644 index 0000000000..2cfb9d2f2b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_ceased.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_ceased(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital business ceased" + documentation = "Date the person ceased the trade/business. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_disposal_steps.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_disposal_steps.py new file mode 100644 index 0000000000..80a0435a98 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_disposal_steps.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_disposal_steps(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital business disposal steps" + documentation = "Reasonable steps are being taken to dispose of the former business assets. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_extension_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_extension_end.py new file mode 100644 index 0000000000..56139046aa --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_extension_end.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_extension_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital business extension end" + documentation = "Authority-accepted final day of the reasonable business-asset disposal period (including its initial period), or of an extension beyond the normal temporary-illness period. An unknown date does not establish reasonable ongoing disposal. Unobserved facts default to an unknown future date." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_illness_and_return.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_illness_and_return.py new file mode 100644 index 0000000000..3c84d27c9f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_business_illness_and_return.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_business_illness_and_return(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital business illness and return" + documentation = "The person ceased work because of disease/disability and intends to resume the same business. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_provenance.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_provenance.py new file mode 100644 index 0000000000..2030901da2 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_provenance.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_carer_reassessment_provenance(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital carer reassessment provenance" + documentation = "The Secretary of State (GB) or Department (NI) made this CA recalculation payment consequent on that Independent Review; ordinary CA arrears do not satisfy this fact. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_received.py new file mode 100644 index 0000000000..a0fd940cd7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_carer_reassessment_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital carer reassessment received" + documentation = "Receipt date of that statutory reassessment payment. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_retained.py new file mode 100644 index 0000000000..2edaf5efa6 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_carer_reassessment_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_carer_reassessment_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital carer reassessment retained" + documentation = "Retained amount of the specific Carer's Allowance recalculation payment consequent on the Independent Review dated 21 July 2025. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_received.py new file mode 100644 index 0000000000..85790a1169 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_esa_error_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital esa error received" + documentation = "Receipt date of the paragraph 9A contributory ESA error payment. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_total_payment.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_total_payment.py new file mode 100644 index 0000000000..942dbb0001 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_error_total_payment.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_esa_error_total_payment(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital esa error total payment" + documentation = "Total paragraph 9A contributory ESA error payment before expenditure. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_official_error_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_official_error_retained.py new file mode 100644 index 0000000000..10bab62645 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_esa_official_error_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_esa_official_error_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital esa official error retained" + documentation = "Retained payment rectifying an official error preventing or delaying contributory ESA assessment, under working-age Schedule 6 paragraph 9A. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_extension_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_extension_end.py new file mode 100644 index 0000000000..22b13cd995 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_extension_end.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_home_funds_extension_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital home funds extension end" + documentation = "Authority-accepted final day of a reasonable longer period to use home funds. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_received.py new file mode 100644 index 0000000000..579e115d06 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_home_funds_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital home funds received" + documentation = "Receipt date of the retained funds earmarked for a home. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_retained.py new file mode 100644 index 0000000000..9ad3720f26 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_home_funds_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_home_funds_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital home funds retained" + documentation = "Retained sale proceeds/acquisition loan or grant intended for another home, satisfying the applicable schedule's specified-use condition. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_first_payment_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_first_payment_received.py new file mode 100644 index 0000000000..0da4b3b722 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_first_payment_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_injury_first_payment_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital injury first payment received" + documentation = "Date on which any payment for this injury was first received. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_is_first.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_is_first.py new file mode 100644 index 0000000000..b399c6d89a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_is_first.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_injury_payment_is_first(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital injury payment is first" + documentation = "The retained direct payment is the first payment in consequence of this injury, not a subsequent payment. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_retained.py new file mode 100644 index 0000000000..36d4e1a2f8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_payment_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_injury_payment_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital injury payment retained" + documentation = "Personal-injury payment remaining in possession as money, excluding trust distributions and amounts used to purchase another asset. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_trust.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_trust.py new file mode 100644 index 0000000000..2b1d06b0ef --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_injury_trust.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_injury_trust(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital injury trust" + documentation = "Capital administered in a qualifying personal-injury trust or court arrangement for the claimant/partner, separately from retained direct compensation. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_category.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_category.py new file mode 100644 index 0000000000..eb2377b1a4 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_category.py @@ -0,0 +1,25 @@ +from policyengine_uk.model_api import * + + +class HousingBenefitPremisesCategory(Enum): + NONE = "No temporary property category" + ACQUIRED_HOME = "Acquired premises intended as home" + SALE = "Premises being disposed of" + LEGAL_POSSESSION = "Premises subject to steps for legal possession" + ESSENTIAL_REPAIRS = "Premises requiring essential repairs before occupation" + FORMER_HOME_ESTRANGEMENT = ( + "Former home left following estrangement/divorce/dissolution" + ) + + +class housing_benefit_capital_premises_category(Variable): + value_type = Enum + possible_values = HousingBenefitPremisesCategory + default_value = HousingBenefitPremisesCategory.NONE + entity = Person + definition_period = YEAR + label = "Temporary Housing Benefit property capital category" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_extension_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_extension_end.py new file mode 100644 index 0000000000..518f81a504 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_extension_end.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_premises_extension_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital premises extension end" + documentation = "Authority-accepted extension end for the selected premises rule where that provision permits an extension. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_first_step.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_first_step.py new file mode 100644 index 0000000000..ddcbc9ef8a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_first_step.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_premises_first_step(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital premises first step" + documentation = "First acquisition, sale, legal-possession or essential-repair step starting the selected statutory 26-week premises disregard. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_intended_home.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_intended_home.py new file mode 100644 index 0000000000..de77ceb32f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_intended_home.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_premises_intended_home(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital premises intended home" + documentation = "The claimant intends to occupy the supplied acquired/possession/repair premises as their home. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_reasonable_steps.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_reasonable_steps.py new file mode 100644 index 0000000000..0c98f7a0aa --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_premises_reasonable_steps.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_premises_reasonable_steps(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital premises reasonable steps" + documentation = "The claimant is currently taking reasonable sale, legal-possession or essential-repair steps for the selected premises category. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_incapacitated.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_incapacitated.py new file mode 100644 index 0000000000..51799a24f1 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_incapacitated.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_occupier_incapacitated(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property occupier incapacitated" + documentation = "That occupier is incapacitated under the applicable capital rule. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_former_partner.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_former_partner.py new file mode 100644 index 0000000000..b101eb683b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_former_partner.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_occupier_is_former_partner(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property occupier is former partner" + documentation = "The occupier is the claimant's former partner. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_lone_parent.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_lone_parent.py new file mode 100644 index 0000000000..d32823c3d5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_lone_parent.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_occupier_is_lone_parent(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property occupier is lone parent" + documentation = "That former partner occupies the property as home and is a lone parent. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_relative.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_relative.py new file mode 100644 index 0000000000..aa39e66002 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_is_relative.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_occupier_is_relative(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property occupier is relative" + documentation = "The occupier of the supplied other property is a relative within the applicable capital schedule's family relationship rule. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_over_qualifying_age.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_over_qualifying_age.py new file mode 100644 index 0000000000..66781f2114 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_occupier_over_qualifying_age.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_occupier_over_qualifying_age(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property occupier over qualifying age" + documentation = "That occupier has attained the qualifying age for State Pension Credit. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_relationship_estranged.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_relationship_estranged.py new file mode 100644 index 0000000000..f5153b4673 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_property_relationship_estranged.py @@ -0,0 +1,13 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_property_relationship_estranged(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit capital property relationship estranged" + documentation = "The former-partner relationship ended by estrangement/divorce/dissolution. False unless supplied; refers to the occupier of this capital owner's property, who may live outside the modelled household." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_qualifying_arrears_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_qualifying_arrears_retained.py new file mode 100644 index 0000000000..ad31b591be --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_qualifying_arrears_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_qualifying_arrears_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital qualifying arrears retained" + documentation = "Retained arrears/concessionary payment of the benefit types expressly listed in the applicable HB capital schedule, not ordinary annual benefit income. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_relative_occupied_premises.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_relative_occupied_premises.py new file mode 100644 index 0000000000..767a9daffb --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_relative_occupied_premises.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_relative_occupied_premises(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital relative occupied premises" + documentation = "Value of premises occupied as a home by a qualifying relative of the claimant/partner who has attained the prescribed age or is incapacitated, or by the former partner as a lone parent. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_extension_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_extension_end.py new file mode 100644 index 0000000000..c6dcbc4247 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_extension_end.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_repairs_funds_extension_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital repairs funds extension end" + documentation = "Authority-accepted final day of a reasonable longer period to use repair funds. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_received.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_received.py new file mode 100644 index 0000000000..1e69000c71 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_received.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_capital_repairs_funds_received(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit capital repairs funds received" + documentation = "Receipt date of the retained essential-repair funds. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_retained.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_retained.py new file mode 100644 index 0000000000..79cd1f601c --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_repairs_funds_retained.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_repairs_funds_retained(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital repairs funds retained" + documentation = "Retained loan, grant or insurance funds specifically for essential repairs/alterations to the home under the applicable schedule. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_temporary_premises.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_temporary_premises.py new file mode 100644 index 0000000000..3e502de549 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_capital_temporary_premises.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_capital_temporary_premises(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit capital temporary premises" + documentation = "Claimant/partner interest in premises being acquired, possessed, repaired or disposed of to satisfy an explicitly selected temporary property disregard, excluding the main home already omitted from sources. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_allowance.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_allowance.py new file mode 100644 index 0000000000..1bd1c573e5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_allowance.py @@ -0,0 +1,70 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.excise import fiscal_year_segments + + +class housing_benefit_child_allowance(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Housing Benefit child personal allowances" + documentation = "Child personal allowances, with actual CTC-award and continuing-child transitional protection during the two-child restriction. Missing award/history facts default to no exception, not an inferred award. Jurisdiction-specific changes are day-weighted over the fiscal year, holding supplied family facts fixed." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/22", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/22", + ) + + def formula(benunit, period, parameters): + person = benunit.members + p = parameters(period).gov.dwp.housing_benefit.allowances + child = person("is_child_or_young_person_for_legacy_benefits", period) + count = benunit.sum(child) + protected = benunit.sum( + child + & person("housing_benefit_child_in_family_at_two_child_limit_start", period) + ) + continuing_claim = ( + benunit("housing_benefit_entitled_at_two_child_limit_start", period) + & ( + benunit("housing_benefit_child_count_at_two_child_limit_start", period) + > p.child_limit.count + ) + & ~benunit("housing_benefit_new_claim_since_two_child_limit_start", period) + ) + protected_count = where(continuing_claim, protected, 0) + restricted_count = min_( + count, + max_( + p.child_limit.count, + max_( + protected_count, + max_(0, benunit("housing_benefit_ctc_child_element_count", period)), + ), + ), + ) + country = benunit.household("country", period) + ni = country == country.possible_values.NORTHERN_IRELAND + pension = benunit("housing_benefit_pension_age_regulations_apply", period) + total = 0 + for rules, share in fiscal_year_segments( + parameters.gov.dwp.housing_benefit.allowances.child_limit.schedule, + period.start.year, + ): + applies = where( + ni, + where(pension, rules.ni_pension_age, rules.ni_working_age), + where(pension, rules.gb_pension_age, rules.gb_working_age), + ) + total += ( + where(applies, restricted_count, count) + * p.child + * WEEKS_IN_YEAR + * share + ) + return total diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_benefit_after_death.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_benefit_after_death.py new file mode 100644 index 0000000000..004ce3e39a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_benefit_after_death.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_benefit_after_death(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit child benefit after death" + documentation = "Claimant or partner remains entitled to Child Benefit in respect of this child/young person after death under section 145A, within its prescribed period." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_count_at_two_child_limit_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_count_at_two_child_limit_start.py new file mode 100644 index 0000000000..1d9984af9b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_count_at_two_child_limit_start.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_count_at_two_child_limit_start(Variable): + value_type = int + entity = BenUnit + definition_period = YEAR + label = "housing benefit child count at two child limit start" + documentation = "Number of children/young persons for whom the claimant was responsible immediately before the 2017 restriction. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_payment_or_suspension.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_payment_or_suspension.py new file mode 100644 index 0000000000..03f798b3a7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_payment_or_suspension.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_disability_payment_or_suspension(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit child disability payment or suspension" + documentation = "Listed Scottish child/young-person disability payment is payable, or a listed DLA/PIP/Scottish award is suspended solely for hospital treatment while the child remains in the family. This is an actual award fact, not general disability." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_premiums.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_premiums.py new file mode 100644 index 0000000000..2afa76b882 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_disability_premiums.py @@ -0,0 +1,59 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_disability_premiums(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Housing Benefit disabled-child and enhanced-child premiums" + documentation = "Both premiums are additional to child personal allowances and adult premiums. They are not subject to the historical two-child personal-allowance limit. Actual listed benefit awards, hospital suspension, blindness and statutory post-death Child Benefit continuation establish the separate conditions; a general disability indicator does not." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/15", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/16", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/7", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/8", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/4", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/4", + ) + + def formula(benunit, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.allowances + person = benunit.members + child = person("is_child_or_young_person_for_legacy_benefits", period) + listed = ( + add(person, period, ["dla", "pip", "armed_forces_independence_payment"]) > 0 + ) + suspended_or_scottish = person( + "housing_benefit_child_disability_payment_or_suspension", period + ) + ceased = person("housing_benefit_childcare_blind_certification_ceased", period) + now = person.benunit("housing_benefit_assessment_date", period) + weeks = parameters(period).gov.dwp.housing_benefit.blindness_run_on_weeks + blind = person("is_blind", period) | ( + (now >= ceased) & (now < ceased + np.timedelta64(int(weeks * 7), "D")) + ) + disabled = child & (listed | suspended_or_scottish | blind) + dla = person("dla_sc_category", period) + pip = person("pip_dl_category", period) + enhanced = child & ( + ((dla == dla.possible_values.HIGHER) & (person("dla", period) > 0)) + | ((pip == pip.possible_values.ENHANCED) & (person("pip", period) > 0)) + | (person("armed_forces_independence_payment", period) > 0) + | person( + "housing_benefit_child_enhanced_disability_payment_or_suspension", + period, + ) + ) + after_death = person("housing_benefit_child_benefit_after_death", period) + disabled |= enhanced + disabled |= after_death & person( + "housing_benefit_disabled_child_premium_before_death", period + ) + enhanced |= after_death & person( + "housing_benefit_enhanced_child_premium_before_death", period + ) + return WEEKS_IN_YEAR * ( + benunit.sum(disabled) * p.disabled_child_premium + + benunit.sum(enhanced) * p.enhanced_child_premium + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_enhanced_disability_payment_or_suspension.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_enhanced_disability_payment_or_suspension.py new file mode 100644 index 0000000000..78c4820007 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_enhanced_disability_payment_or_suspension.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_enhanced_disability_payment_or_suspension(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit child enhanced disability payment or suspension" + documentation = "Listed Scottish highest-care/enhanced-daily-living payment is payable, or a listed highest-care/enhanced-daily-living award is suspended solely for hospital treatment. This records the higher statutory benefit rate, not general severe disability." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_in_family_at_two_child_limit_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_in_family_at_two_child_limit_start.py new file mode 100644 index 0000000000..cfce6332a2 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_child_in_family_at_two_child_limit_start.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_child_in_family_at_two_child_limit_start(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit child in family at two child limit start" + documentation = "This current family child was an individual for whom the claimant was responsible immediately before the jurisdiction's 2017 child-limit cutoff. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_blind_certification_ceased.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_blind_certification_ceased.py new file mode 100644 index 0000000000..349ba781ca --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_blind_certification_ceased.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_blind_certification_ceased(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare blind certification ceased" + documentation = "Date on which the child ceased to be certified severely sight impaired/blind. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_charges_paid.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_charges_paid.py new file mode 100644 index 0000000000..1997d968fa --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_charges_paid.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_charges_paid(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit childcare charges paid" + documentation = "Annual charges paid by the claimant/partner in respect of this child, not spending by the child. Provide per-child amounts rather than reallocating aggregate adult childcare consumption. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_compulsory_education_charges.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_compulsory_education_charges.py new file mode 100644 index 0000000000..be6e0bc842 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_compulsory_education_charges.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_compulsory_education_charges(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit childcare compulsory education charges" + documentation = "Part of the per-child charges that pays for compulsory education, which is excluded. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_benefit_in_payment.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_benefit_in_payment.py new file mode 100644 index 0000000000..585c483611 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_benefit_in_payment.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_disability_benefit_in_payment(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare disability benefit in payment" + documentation = "A prescribed disability benefit, including the Scottish equivalents listed in regulation 28(13), is payable for the child. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_payment_suspended_in_hospital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_payment_suspended_in_hospital.py new file mode 100644 index 0000000000..551637cdab --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_disability_payment_suspended_in_hospital.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_disability_payment_suspended_in_hospital(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare disability payment suspended in hospital" + documentation = "A prescribed disability benefit was payable but is suspended solely because the child is a hospital inpatient. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_in_child_home.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_in_child_home.py new file mode 100644 index 0000000000..a404d37996 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_in_child_home.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_in_child_home(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare in child home" + documentation = "The care is provided wholly or mainly in this child's home. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacitated.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacitated.py new file mode 100644 index 0000000000..7caf805ed3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacitated.py @@ -0,0 +1,64 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_incapacitated(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Partner incapacity conditions for Housing Benefit childcare" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.childcare + benefits = ( + add( + person, + period, + [ + "attendance_allowance", + "dla", + "pip", + "armed_forces_independence_payment", + "sda", + ], + ) + > 0 + ) + ib = (person("incapacity_benefit", period) > 0) & ( + person("incapacity_benefit_is_long_term", period) + | person("incapacity_benefit_is_short_term_higher_rate", period) + ) + old_duration = ( + person("incapacity_for_work_days", period) >= p.incapacity_days + ) & ( + person("incapacity_for_work_gap_days", period) <= p.old_incapacity_link_days + ) + lcw_duration = ( + person("limited_capability_for_work_days", period) >= p.incapacity_days + ) & (person("limited_capability_for_work_gap_days", period) <= p.lcw_link_days) + premium = person("is_disabled_for_benefits", period) & ( + person.benunit("disability_premium", period) > 0 + ) + pension_age = person.benunit( + "housing_benefit_pension_age_regulations_apply", period + ) & (person("age", period) >= p.pension_incapacity_age) + return ( + benefits + | ib + | old_duration + | lcw_duration + | premium + | pension_age + | person("esa_main_phase", period) + | person( + "housing_benefit_childcare_listed_incapacity_benefit_payable", period + ) + | person( + "housing_benefit_childcare_incapacity_but_for_determination", period + ) + | person("housing_benefit_hospital_suspended_incapacity_benefit", period) + | person("housing_benefit_invalid_vehicle_provided", period) + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacity_but_for_determination.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacity_but_for_determination.py new file mode 100644 index 0000000000..25b8ee1105 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_incapacity_but_for_determination.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_incapacity_but_for_determination(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare incapacity but for determination" + documentation = "The partner would meet the specified disability-premium/support-component/WRAG condition but for a statutory determination treating the person as capable of work or not having limited capability, under HB regulation 28(11)(b) or (ba)." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/29", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_listed_incapacity_benefit_payable.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_listed_incapacity_benefit_payable.py new file mode 100644 index 0000000000..2603ad50bb --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_listed_incapacity_benefit_payable.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_listed_incapacity_benefit_payable(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare listed incapacity benefit payable" + documentation = "A pension, allowance or payment expressly listed by HB regulation 28(11)(d) / pension-age regulation 31 is payable in respect of this partner, including the listed Scottish disability payments, section 104 disablement-pension increase or analogous war/industrial-injury increase. Does not mean any disability-related payment." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/29", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_paid_to_partner.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_paid_to_partner.py new file mode 100644 index 0000000000..381017debe --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_paid_to_partner.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_paid_to_partner(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare paid to partner" + documentation = "The claimant pays their partner, or the partner pays the claimant, for this child's care. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_end.py new file mode 100644 index 0000000000..1dbff67bc0 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_end.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_parental_leave_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare parental leave end" + documentation = "Last day of that prescribed statutory parental leave. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_start.py new file mode 100644 index 0000000000..b734a4b407 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_leave_start.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_parental_leave_start(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare parental leave start" + documentation = "First day of prescribed maternity, paternity, adoption, shared-parental, bereavement or neonatal leave. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_end.py new file mode 100644 index 0000000000..75b9a5884d --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_end.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_parental_pay_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare parental pay end" + documentation = "Last day of entitlement to the prescribed statutory parental payment, maternity allowance or qualifying support. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_entitled.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_entitled.py new file mode 100644 index 0000000000..0db1f44e9b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_parental_pay_entitled.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_parental_pay_entitled(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare parental pay entitled" + documentation = "The person is entitled to one of the statutory payments or qualifying support expressly listed in regulation 28(14). Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider.py new file mode 100644 index 0000000000..dfd218a3ac --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider.py @@ -0,0 +1,30 @@ +from policyengine_uk.model_api import * + + +class HousingBenefitChildcareProvider(Enum): + UNREGISTERED = "Unregistered or unknown provider" + REGISTERED_APPROVED = ( + "Registered or approved under the applicable jurisdiction's prescribed scheme" + ) + EXEMPT_SCHOOL = "School or establishment expressly exempt from registration" + SCHOOL_LOCAL_AUTHORITY_OUT_OF_HOURS = "School or local authority out-of-hours route" + FOSTER_KINSHIP_OTHER_CHILD = "Foster or kinship carer caring for a different child" + DOMICILIARY_WORKER = "Prescribed domiciliary care worker" + NON_RELATIVE_HOME_CARE = ( + "Non-relative providing care wholly or mainly in the child's home" + ) + + +class housing_benefit_childcare_provider(Variable): + value_type = Enum + possible_values = HousingBenefitChildcareProvider + default_value = HousingBenefitChildcareProvider.UNREGISTERED + entity = Person + definition_period = YEAR + label = "Housing Benefit provider caring for this child" + documentation = "Statutory registration/approval or provider category for the care charged in respect of this child. The registered/exempt categories require the applicable GB or NI provision, not registration in another country. Other exclusion facts are tested separately. Unknown care does not automatically qualify." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider_is_relative.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider_is_relative.py new file mode 100644 index 0000000000..462ca1fbb1 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_provider_is_relative.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_provider_is_relative(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare provider is relative" + documentation = "The provider is a relative of this child within the statutory definition. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_sickness_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_sickness_start.py new file mode 100644 index 0000000000..dc5aa76ff7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_sickness_start.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_sickness_start(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare sickness start" + documentation = "First day of the sickness benefit or incapacity/LCW credits period after remunerative work. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_treated_as_work.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_treated_as_work.py new file mode 100644 index 0000000000..6b5f892566 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_treated_as_work.py @@ -0,0 +1,72 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_treated_as_work(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "In remunerative work or qualifying absence for Housing Benefit childcare" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/6", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.childcare + paid = ( + add(person, period, ["employment_income", "self_employment_income"]) > 0 + ) | person("housing_benefit_paid_work_expected", period) + works = (person("weekly_hours", period) >= p.work_hours) & paid + before = person("housing_benefit_childcare_work_before_absence", period) + assessment = person.benunit("housing_benefit_assessment_date", period) + sick_start = person("housing_benefit_childcare_sickness_start", period) + sick_days = (assessment - sick_start).astype("timedelta64[D]").astype(int) + short_ib = (person("incapacity_benefit", period) > 0) & person( + "incapacity_benefit_is_short_term_lower_rate", period + ) + sick_payment = ( + ( + add( + person, + period, + ["statutory_sick_pay", "esa_contrib", "esa_income_reported"], + ) + > 0 + ) + | short_ib + | ( + (person.benunit("income_support", period) > 0) + & person("housing_benefit_income_support_for_incapacity", period) + ) + | person("receives_limited_capability_for_work_credits", period) + ) + sick = ( + before + & sick_payment + & (sick_days >= 0) + & (sick_days < p.sickness_weeks * 7) + ) + leave_start = person("housing_benefit_childcare_parental_leave_start", period) + leave_end = person("housing_benefit_childcare_parental_leave_end", period) + pay_end = person("housing_benefit_childcare_parental_pay_end", period) + continued = person( + "housing_benefit_childcare_wtc_in_payment_at_pay_end", period + ) + end = min_( + leave_end, + where( + continued, + person("housing_benefit_childcare_wtc_award_end", period), + pay_end, + ), + ) + statutory_pay = person( + "housing_benefit_childcare_parental_pay_entitled", period + ) | ( + add(person, period, ["statutory_maternity_pay", "maternity_allowance"]) > 0 + ) + leave = ( + before & statutory_pay & (assessment >= leave_start) & (assessment <= end) + ) + return works | sick | leave diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_before_absence.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_before_absence.py new file mode 100644 index 0000000000..6bd044def5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_before_absence.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_work_before_absence(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare work before absence" + documentation = "The person was in remunerative work immediately before the sickness period or in the week before statutory parental leave. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_condition.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_condition.py new file mode 100644 index 0000000000..3b0af948e5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_work_condition.py @@ -0,0 +1,32 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_work_condition(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "Housing Benefit childcare work condition" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) + + def formula(benunit, period, parameters): + person = benunit.members + adult = person("is_claimant_or_partner", period) + works = person("housing_benefit_childcare_treated_as_work", period) + cannot_care = ( + person("housing_benefit_childcare_incapacitated", period) + | person("is_hospital_inpatient", period) + | person("is_in_prison", period) + ) + working_adults = benunit.sum(adult & works) + couple_qualifies = benunit.all(~adult | works | cannot_care) & ( + working_adults > 0 + ) + return where( + benunit("is_couple", period), + couple_qualifies, + benunit("is_lone_parent", period) & (working_adults > 0), + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_award_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_award_end.py new file mode 100644 index 0000000000..358e82e6b6 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_award_end.py @@ -0,0 +1,17 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_wtc_award_end(Variable): + value_type = date + entity = Person + definition_period = YEAR + label = "housing benefit childcare wtc award end" + documentation = "Last day of that WTC childcare-element award, where the element was payable at parental-pay cessation. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_in_payment_at_pay_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_in_payment_at_pay_end.py new file mode 100644 index 0000000000..5d7b5df7bf --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_childcare_wtc_in_payment_at_pay_end.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_childcare_wtc_in_payment_at_pay_end(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit childcare wtc in payment at pay end" + documentation = "The WTC childcare element was in payment on the statutory parental-pay entitlement end date. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_end.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_end.py new file mode 100644 index 0000000000..a846359136 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_end.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_continuous_award_end(Variable): + value_type = date + entity = BenUnit + definition_period = YEAR + label = "housing benefit continuous award end" + documentation = "Last day of that uninterrupted HB award sequence; leave unknown/future for an ongoing award only when its start is supplied. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_start.py new file mode 100644 index 0000000000..aebf96fe9c --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_continuous_award_start.py @@ -0,0 +1,18 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class housing_benefit_continuous_award_start(Variable): + value_type = date + entity = BenUnit + definition_period = YEAR + label = "housing benefit continuous award start" + documentation = "First day of the current uninterrupted sequence of HB awards for the claimant/partner. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + default_value = date(9999, 1, 1) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ctc_child_element_count.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ctc_child_element_count.py new file mode 100644 index 0000000000..ac729be2f4 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ctc_child_element_count.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_ctc_child_element_count(Variable): + value_type = int + entity = BenUnit + definition_period = YEAR + label = "housing benefit ctc child element count" + documentation = "Number of current family children whose individual elements were included in an actual CTC award, including a zero-payable award. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_disabled_child_premium_before_death.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_disabled_child_premium_before_death.py new file mode 100644 index 0000000000..e29e5e9855 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_disabled_child_premium_before_death.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_disabled_child_premium_before_death(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit disabled child premium before death" + documentation = "A disabled child premium was included in the claimant's applicable amount immediately before this child's death, or ceased solely because of that death." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_enhanced_child_premium_before_death.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_enhanced_child_premium_before_death.py new file mode 100644 index 0000000000..bd2a247786 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_enhanced_child_premium_before_death.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_enhanced_child_premium_before_death(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit enhanced child premium before death" + documentation = "Enhanced child premium conditions were satisfied immediately before death and ceased because of death." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_entitled_at_two_child_limit_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_entitled_at_two_child_limit_start.py new file mode 100644 index 0000000000..6fca66200a --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_entitled_at_two_child_limit_start.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_entitled_at_two_child_limit_start(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit entitled at two child limit start" + documentation = "The claimant was entitled to HB immediately before the jurisdiction's 2017 two-child restriction began. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium.py new file mode 100644 index 0000000000..7163dcf0d1 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium.py @@ -0,0 +1,58 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.excise import fiscal_year_segments + + +class housing_benefit_family_premium(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Housing Benefit family premium" + documentation = "Separate from each child's personal allowance. Post-abolition entitlement requires the jurisdiction-specific pre-abolition award/family facts, continuing family condition and no new claim. The higher old lone-parent amount applies only to working-age claims with continuing 1998 protection." + reference = ( + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/3", + ) + + def formula(benunit, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.allowances.family_premium + person = benunit.members + has_child = benunit.any( + person("is_child_or_young_person_for_legacy_benefits", period) + ) + protected = ( + benunit("housing_benefit_family_premium_entitled_before_abolition", period) + & benunit( + "housing_benefit_family_premium_family_condition_continued", period + ) + & ~benunit( + "housing_benefit_family_premium_new_claim_since_abolition", period + ) + ) + higher = ( + ~benunit("housing_benefit_pension_age_regulations_apply", period) + & benunit("is_lone_parent", period) + & benunit( + "housing_benefit_lone_parent_family_premium_1998_protection", period + ) + ) + amount = where(higher, p.protected_lone_parent, p.ordinary) * WEEKS_IN_YEAR + country = benunit.household("country", period) + ni = country == country.possible_values.NORTHERN_IRELAND + total = 0 + for rules, share in fiscal_year_segments( + parameters.gov.dwp.housing_benefit.allowances.family_premium.schedule, + period.start.year, + ): + total += ( + has_child + * ( + where(ni, rules.ni_open_to_new_claims, rules.gb_open_to_new_claims) + | protected + ) + * amount + * share + ) + return total diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_entitled_before_abolition.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_entitled_before_abolition.py new file mode 100644 index 0000000000..c1bf2743ca --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_entitled_before_abolition.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_family_premium_entitled_before_abolition(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit family premium entitled before abolition" + documentation = "Claimant was entitled to HB and had a child or young person in the family on 30 April 2016 (GB) or 4 September 2016 (NI)." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_family_condition_continued.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_family_condition_continued.py new file mode 100644 index 0000000000..7f582875f3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_family_condition_continued.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_family_premium_family_condition_continued(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit family premium family condition continued" + documentation = "Since the applicable family-premium abolition date, the claimant's family has continuously included a child or young person; changing which child qualifies does not itself end protection." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_new_claim_since_abolition.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_new_claim_since_abolition.py new file mode 100644 index 0000000000..242087bcab --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_family_premium_new_claim_since_abolition.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_family_premium_new_claim_since_abolition(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit family premium new claim since abolition" + documentation = "A new Housing Benefit claim has been made since the applicable family-premium abolition date; this ends transitional protection." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_hospital_suspended_incapacity_benefit.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_hospital_suspended_incapacity_benefit.py new file mode 100644 index 0000000000..aa20bf8b5f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_hospital_suspended_incapacity_benefit.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_hospital_suspended_incapacity_benefit(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit hospital suspended incapacity benefit" + documentation = "A prescribed incapacity/disability award ceased to be payable solely because of hospital admission under regulation 28(11)(e)-(ec). Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_income_support_for_incapacity.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_income_support_for_incapacity.py new file mode 100644 index 0000000000..0284d151df --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_income_support_for_incapacity.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_income_support_for_incapacity(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit income support for incapacity" + documentation = "The person's Income Support award is on the prescribed incapacity ground. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_invalid_vehicle_provided.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_invalid_vehicle_provided.py new file mode 100644 index 0000000000..329bbde494 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_invalid_vehicle_provided.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_invalid_vehicle_provided(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit invalid vehicle provided" + documentation = "The prescribed NHS/Scottish/NI authority has provided the person an invalid carriage or vehicle under regulation 28(11)(g). Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_lone_parent_family_premium_1998_protection.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_lone_parent_family_premium_1998_protection.py new file mode 100644 index 0000000000..c18f0e04a7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_lone_parent_family_premium_1998_protection.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_lone_parent_family_premium_1998_protection(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit lone parent family premium 1998 protection" + documentation = "Award records establish continuing Schedule 3 paragraph 3(3)-(5) protection: HB/qualifying CTB entitlement from 5 April 1998 including permitted rent-free periods; continuous lone-parent status; required income-support/JSA/ESA receipt or nonreceipt continuity; and no disqualifying disability premium or ESA component. This is not ordinary lone-parent status." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3", + "https://www.legislation.gov.uk/uksi/2015/1857/made", + "https://www.legislation.gov.uk/nisr/2016/310/made", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_new_claim_since_two_child_limit_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_new_claim_since_two_child_limit_start.py new file mode 100644 index 0000000000..1d49a4016f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_new_claim_since_two_child_limit_start.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_new_claim_since_two_child_limit_start(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit new claim since two child limit start" + documentation = "A new Housing Benefit claim has been made since the jurisdiction's 2017 child-limit cutoff. Not inferred from benefit amounts; supply when known." + reference = ( + "https://www.legislation.gov.uk/uksi/2017/376/made", + "https://www.legislation.gov.uk/nisr/2017/79/made", + "https://www.legislation.gov.uk/uksi/2024/611/regulation/6", + "https://www.legislation.gov.uk/nisr/2024/119/regulation/5", + "https://www.legislation.gov.uk/uksi/2026/316/regulation/2", + "https://www.legislation.gov.uk/nisr/2026/68/regulation/2", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ni_additional_occupation_net_earnings.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ni_additional_occupation_net_earnings.py new file mode 100644 index 0000000000..858ca48328 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_ni_additional_occupation_net_earnings.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_ni_additional_occupation_net_earnings(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit ni additional occupation net earnings" + documentation = "Net earnings from additional Northern Ireland prescribed part-time army/PSNI reserve or trainee employments, included only for a Northern Ireland claim. Defaults to zero/false when the factual history is not supplied." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital.py new file mode 100644 index 0000000000..94f3254825 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_owned_household_capital(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + label = "housing benefit owned household capital" + documentation = "Claimant/partner beneficial share of valued capital in the configured household sources, excluding person-level LISA capital. Include only their legal beneficial shares, applying joint-owner counts including owners outside the household; exclude dependants' holdings. This replaces the household proxy when known, rather than adding to it. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + unit = GBP + quantity_type = STOCK + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital_known.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital_known.py new file mode 100644 index 0000000000..0803b802c4 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_owned_household_capital_known.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_owned_household_capital_known(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "housing benefit owned household capital known" + documentation = "Whether the combined claimant/partner beneficial interest in the configured household capital sources is known, including a known zero. Unobserved facts default to zero/false or an unknown future date. Amounts must be included in the capital sources being assessed and must not overlap other category amounts." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/nisr/2006/405/schedule/7", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/7", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_paid_work_expected.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_paid_work_expected.py new file mode 100644 index 0000000000..c911a62d04 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_paid_work_expected.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_paid_work_expected(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit paid work expected" + documentation = "The person's current work is for remuneration expected to be paid even if no earnings have yet been received. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_age_disregarded_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_age_disregarded_capital.py new file mode 100644 index 0000000000..3d44eefff3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_age_disregarded_capital.py @@ -0,0 +1,21 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.housing_benefit_capital import disregarded_capital + + +class housing_benefit_pension_age_disregarded_capital(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = GBP + quantity_type = STOCK + label = "pension age Housing Benefit capital exclusions within supplied assets" + documentation = "Category-specific retained capital exclusions. Inputs must be present in the assessed sources, disjoint, and supported by their statutory provenance/date/occupation/business facts. This does not infer those facts from broad survey balances or implement every separately listed historic compensation scheme." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/uksi/2026/681", + "https://www.legislation.gov.uk/nisr/2026/146", + ) + + def formula(person, period, parameters): + return disregarded_capital(person, period, parameters, True) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_earnings_disregard_assessment.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_earnings_disregard_assessment.py new file mode 100644 index 0000000000..cbb7dea3ad --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_earnings_disregard_assessment.py @@ -0,0 +1,31 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_pension_credit_earnings_disregard_assessment(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Earnings disregard already included in the Pension Credit assessment" + documentation = ( + "Earnings deduction already made in the supplied Pension Credit " + "net-income assessment, not an additional HB deduction. Override " + "with the actual assessed amount when supplying that assessment. " + "The fallback reads the model's pension_credit_earnings_disregard " + "when that component is installed (PR #2019); otherwise it is zero " + "because the existing model PC-income formula makes no such deduction. " + "This explicit compatibility path avoids duplicating that separate PR." + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) + + def formula(benunit, period, parameters): + # Structural compatibility, not a branch on household values. + if ( + "pension_credit_earnings_disregard" + in benunit.simulation.tax_benefit_system.variables + ): + return benunit("pension_credit_earnings_disregard", period) + return np.zeros(benunit.count) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_net_income_assessment.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_net_income_assessment.py new file mode 100644 index 0000000000..e430240c80 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_credit_net_income_assessment.py @@ -0,0 +1,22 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_pension_credit_net_income_assessment(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Pension Credit net-income assessment supplied for Housing Benefit" + documentation = ( + "Secretary of State's net-income assessment for a savings-credit-only " + "award. Supply the actual assessment when known. The fallback is the " + "model's pension_credit_income, retaining that program's coverage " + "and limitations rather than implementing Pension Credit again in HB." + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", + ) + + def formula(benunit, period, parameters): + return benunit("pension_credit_income", period) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_special_disregard_conditions.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_special_disregard_conditions.py new file mode 100644 index 0000000000..113a56d3c9 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_pension_special_disregard_conditions.py @@ -0,0 +1,70 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_pension_special_disregard_conditions(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Pension-age Housing Benefit disability/protection earnings-disregard conditions" + reference = "https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5" + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.income_disregard + benefits = ( + add( + person, + period, + [ + "attendance_allowance", + "dla", + "pip", + "armed_forces_independence_payment", + "sda", + "mobility_supplement", + ], + ) + > 0 + ) + long_incapacity = (person("incapacity_benefit", period) > 0) & person( + "incapacity_benefit_is_long_term", period + ) + duration = where( + person("incapacity_shortened_duration_rule", period), + p.incapacity_days_ill, + p.incapacity_days, + ) + old_incapacity = person("incapacity_for_work_days", period) >= duration + protected = ( + person("housing_benefit_protected_special_earnings_disregard", period) + & ( + person( + "housing_benefit_special_disregard_max_award_break_weeks", period + ) + <= p.protection_break_weeks + ) + & ( + person( + "housing_benefit_special_disregard_max_employment_break_weeks", + period, + ) + <= p.protection_break_weeks + ) + ) + assessed_lcw = ( + person("esa_limited_capability_for_work_determined", period) + | person("esa_support_group", period) + | person("esa_work_related_activity_group", period) + ) & ( + person("esa_assessment_phase_ended", period) + | person("esa_assessment_phase_exception", period) + ) + return ( + benefits + | long_incapacity + | person("is_blind", period) + | person("esa_main_phase", period) + | assessed_lcw + | person("working_tax_credit_disability_element_in_award", period) + | old_incapacity + | protected + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_permitted_work_limit.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_permitted_work_limit.py new file mode 100644 index 0000000000..06d50556ea --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_permitted_work_limit.py @@ -0,0 +1,52 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_permitted_work_limit(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = GBP + label = "Weekly Housing Benefit permitted-work disregard limit" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/10A", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4/paragraph/5A", + "https://www.legislation.gov.uk/uksi/2008/794/regulation/45", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.ESA.permitted_work + wage = parameters(period).gov.hmrc.minimum_wage.non_apprentice + higher = ( + np.ceil(wage.amounts[-1] * p.higher_limit_hours / p.rounding) * p.rounding + ) + earnings = max_(person("permitted_work_net_earnings", period), 0) + receipt = ( + add( + person, + period, + ["esa_contrib", "incapacity_benefit", "sda"], + ) + > 0 + ) | person("receives_limited_capability_for_work_credits", period) + supervised = person("permitted_work_supported", period) | person( + "permitted_work_medically_supervised", period + ) + former_period = ( + not_(p.weeks_limit_applies) + | person("esa_support_group", period) + | ( + (person("permitted_work_weeks", period) <= p.former_weeks_limit) + & person("permitted_work_former_restart_conditions_met", period) + ) + ) + ordinary = ( + person("permitted_work_weekly_hours", period) < p.ordinary_hours_limit + ) & former_period + limit = where( + (earnings <= higher) & (supervised | ordinary), + higher, + where(earnings <= p.lower_limit, p.lower_limit, 0), + ) + return where( + receipt & person("permitted_work_authority_approved", period), limit, 0 + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_protected_special_earnings_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_protected_special_earnings_disregard.py new file mode 100644 index 0000000000..9db0036ed2 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_protected_special_earnings_disregard.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_protected_special_earnings_disregard(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit protected special earnings disregard" + documentation = "The person had a £20 HB earnings disregard within eight weeks before reaching Pension Credit qualifying age and continued employment after that award. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_qualifying_childcare_costs.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_qualifying_childcare_costs.py new file mode 100644 index 0000000000..88715db805 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_qualifying_childcare_costs.py @@ -0,0 +1,69 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.dates import birth_day +from policyengine_uk.utils.housing_benefit import september_first_monday + + +class housing_benefit_qualifying_childcare_costs(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = GBP + label = "Qualifying Housing Benefit childcare charges for this child" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.childcare + born = birth_day(person, period) + assessment = person.benunit("housing_benefit_assessment_date", period) + disabled = ( + ( + add(person, period, ["dla", "pip", "armed_forces_independence_payment"]) + > 0 + ) + | person("housing_benefit_childcare_disability_benefit_in_payment", period) + | person( + "housing_benefit_childcare_disability_payment_suspended_in_hospital", + period, + ) + | person("is_blind", period) + ) + ceased = person("housing_benefit_childcare_blind_certification_ceased", period) + standard_end = september_first_monday(born, p.child_age_limit.standard - 1) + disabled_end = september_first_monday(born, p.child_age_limit.disabled - 1) + blind_weeks = parameters(period).gov.dwp.housing_benefit.blindness_run_on_weeks + recent_blind = ( + (ceased >= standard_end - np.timedelta64(int(blind_weeks * 7), "D")) + & (ceased < disabled_end) + & (ceased <= assessment) + ) + age_end = where(disabled | recent_blind, disabled_end, standard_end) + child = person("is_child_or_young_person_for_legacy_benefits", period) + provider = person("housing_benefit_childcare_provider", period) + types = provider.possible_values + home = person("housing_benefit_childcare_in_child_home", period) + relative = person("housing_benefit_childcare_provider_is_relative", period) + ordinary_provider = ( + (provider == types.REGISTERED_APPROVED) + | (provider == types.EXEMPT_SCHOOL) + | (provider == types.FOSTER_KINSHIP_OTHER_CHILD) + | (provider == types.DOMICILIARY_WORKER) + ) + school_route = (provider == types.SCHOOL_LOCAL_AUTHORITY_OUT_OF_HOURS) & ( + person("age", period) >= p.out_of_school_min_age + ) + home_route = (provider == types.NON_RELATIVE_HOME_CARE) & home & ~relative + provider_qualifies = ( + (ordinary_provider | school_route | home_route) + & ~(relative & home) + & ~person("housing_benefit_childcare_paid_to_partner", period) + ) + charges = max_( + person("housing_benefit_childcare_charges_paid", period) + - person("housing_benefit_childcare_compulsory_education_charges", period), + 0, + ) + return where(child & (assessment < age_end) & provider_qualifies, charges, 0) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_remunerative_work.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_remunerative_work.py new file mode 100644 index 0000000000..6de74ae1a5 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_remunerative_work.py @@ -0,0 +1,22 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_remunerative_work(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep remunerative work" + documentation = "Remunerative work under HB regulation 6: normally at least 16 hours a week, for payment or expected payment. Override the earnings/hours fallback for statutory exceptions and averaged or irregular hours." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.housing_benefit.means_test.childcare + paid = ( + add(person, period, ["employment_income", "self_employment_income"]) > 0 + ) | person("housing_benefit_paid_work_expected", period) + return (person("weekly_hours", period) >= p.work_hours) & paid diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_award_break_weeks.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_award_break_weeks.py new file mode 100644 index 0000000000..268fc482b8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_award_break_weeks.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_special_disregard_max_award_break_weeks(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit special disregard max award break weeks" + documentation = "Longest break in HB entitlement since the qualifying protected award, in weeks. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_employment_break_weeks.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_employment_break_weeks.py new file mode 100644 index 0000000000..ccc648cefa --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_special_disregard_max_employment_break_weeks.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_special_disregard_max_employment_break_weeks(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit special disregard max employment break weeks" + documentation = "Longest break in employment since the qualifying protected award, in weeks. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_specified_occupation_net_earnings.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_specified_occupation_net_earnings.py new file mode 100644 index 0000000000..df2860b596 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_specified_occupation_net_earnings.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_specified_occupation_net_earnings(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "housing benefit specified occupation net earnings" + documentation = "Net earnings from the part-time firefighting, auxiliary coast rescue, part-time lifeboat and prescribed reserve-force employments listed in the applicable HB schedule; not other earnings. Defaults to zero/false when the factual history is not supplied." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_working_age_disregarded_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_working_age_disregarded_capital.py new file mode 100644 index 0000000000..4b645964f7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_working_age_disregarded_capital.py @@ -0,0 +1,21 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.housing_benefit_capital import disregarded_capital + + +class housing_benefit_working_age_disregarded_capital(Variable): + value_type = float + entity = Person + definition_period = YEAR + unit = GBP + quantity_type = STOCK + label = "working age Housing Benefit capital exclusions within supplied assets" + documentation = "Category-specific retained capital exclusions. Inputs must be present in the assessed sources, disjoint, and supported by their statutory provenance/date/occupation/business facts. This does not infer those facts from broad survey balances or implement every separately listed historic compensation scheme." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/6", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/6", + "https://www.legislation.gov.uk/uksi/2026/681", + "https://www.legislation.gov.uk/nisr/2026/146", + ) + + def formula(person, period, parameters): + return disregarded_capital(person, period, parameters, False) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_long_term.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_long_term.py new file mode 100644 index 0000000000..774b7cc034 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_long_term.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class incapacity_benefit_is_long_term(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "incapacity benefit is long term" + documentation = "The person's reported Incapacity Benefit is the long-term rate, rather than a short-term award. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_higher_rate.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_higher_rate.py new file mode 100644 index 0000000000..ffb8556c06 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_higher_rate.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class incapacity_benefit_is_short_term_higher_rate(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "incapacity benefit is short term higher rate" + documentation = "Incapacity Benefit is actually payable at its short-term higher rate. A positive IB amount with unknown rate must not be treated as higher rate merely because the lower-rate flag is false." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/29", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_lower_rate.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_lower_rate.py new file mode 100644 index 0000000000..f9097ec47b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_benefit_is_short_term_lower_rate.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class incapacity_benefit_is_short_term_lower_rate(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "incapacity benefit is short term lower rate" + documentation = "The person's reported Incapacity Benefit is the short-term lower rate. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_days.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_days.py new file mode 100644 index 0000000000..bb4308f813 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_days.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class incapacity_for_work_days(Variable): + value_type = int + entity = Person + definition_period = YEAR + label = "incapacity for work days" + documentation = "Duration of the person's current legally linked incapacity-for-work period, with only breaks permitted by the relevant rule included. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_gap_days.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_gap_days.py new file mode 100644 index 0000000000..8008195127 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_for_work_gap_days.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class incapacity_for_work_gap_days(Variable): + value_type = int + entity = Person + definition_period = YEAR + label = "incapacity for work gap days" + documentation = "Longest intervening break in the supplied linked incapacity periods. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_shortened_duration_rule.py b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_shortened_duration_rule.py new file mode 100644 index 0000000000..7b69d3cf8f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/incapacity_shortened_duration_rule.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class incapacity_shortened_duration_rule(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "incapacity shortened duration rule" + documentation = "The claimant meets the statutory serious-illness definition for the 196-day rather than 364-day old incapacity disregard route. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/is_hospital_inpatient.py b/policyengine_uk/variables/gov/dwp/housing_benefit/is_hospital_inpatient.py new file mode 100644 index 0000000000..c05d73460e --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/is_hospital_inpatient.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class is_hospital_inpatient(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "is hospital inpatient" + documentation = "The person currently receives inpatient hospital treatment. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/is_housing_benefit_claimant.py b/policyengine_uk/variables/gov/dwp/housing_benefit/is_housing_benefit_claimant.py new file mode 100644 index 0000000000..2762f66a14 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/is_housing_benefit_claimant.py @@ -0,0 +1,18 @@ +from policyengine_uk.model_api import * + + +class is_housing_benefit_claimant(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Housing Benefit claimant" + documentation = "Identifies the person making the Housing Benefit claim. Defaults to the benefit-unit head among claimant/partner members, or their eldest member; supply explicitly when the partner claims. This is not inferred from ESA receipt." + reference = "https://www.legislation.gov.uk/uksi/2006/213/regulation/82" + + def formula(person, period, parameters): + adults = person("is_claimant_or_partner", period) + heads = adults & person("is_benunit_head", period) + pool = where(person.benunit.any(heads), heads, adults) + return pool & ( + person.get_rank(person.benunit, -person("age", period), condition=pool) == 0 + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/is_in_prison.py b/policyengine_uk/variables/gov/dwp/housing_benefit/is_in_prison.py new file mode 100644 index 0000000000..7bcb47bd39 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/is_in_prison.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class is_in_prison(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "is in prison" + documentation = "The person is detained pending trial/sentence or serving a court sentence, excluding statutory mental-health hospital detention. Supply the factual value when known; otherwise zero/false or an unobserved future date is used." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_days.py b/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_days.py new file mode 100644 index 0000000000..a4fd59a5ed --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_days.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class limited_capability_for_work_days(Variable): + value_type = int + entity = Person + definition_period = YEAR + label = "limited capability for work days" + documentation = "Duration of the person's current legally linked ESA limited-capability-for-work period. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_gap_days.py b/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_gap_days.py new file mode 100644 index 0000000000..1aa40c201b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/limited_capability_for_work_gap_days.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class limited_capability_for_work_gap_days(Variable): + value_type = int + entity = Person + definition_period = YEAR + label = "limited capability for work gap days" + documentation = "Longest intervening break in the supplied linked limited-capability periods. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/mobility_supplement.py b/policyengine_uk/variables/gov/dwp/housing_benefit/mobility_supplement.py new file mode 100644 index 0000000000..fb04d0f746 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/mobility_supplement.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class mobility_supplement(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "mobility supplement" + documentation = "Reported war-disablement/personal-injury mobility supplement under the provisions listed in pension-age HB Schedule 4 paragraph 5. Defaults to zero/false when the factual history is not supplied." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_benefit_week_start.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_benefit_week_start.py new file mode 100644 index 0000000000..9aa6329134 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_benefit_week_start.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_benefit_week_start(Variable): + value_type = int + entity = BenUnit + definition_period = YEAR + label = "housing benefit benefit week start" + documentation = "Weekday on which this claimant's benefit week begins, Monday=0 through Sunday=6. Defaults to Monday; affects only rounding the statutory 26-week postponement." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_individual_non_dep_deduction_eligible.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_individual_non_dep_deduction_eligible.py index 37ea75a311..290561f012 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_individual_non_dep_deduction_eligible.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_individual_non_dep_deduction_eligible.py @@ -11,4 +11,8 @@ def formula(person, period, parameters): rent_liable = person.benunit("benunit_is_rent_liable", period) p = parameters(period).gov.dwp.housing_benefit.non_dep_deduction age_eligible = person("age", period) >= p.age_threshold - return age_eligible & ~rent_liable + return ( + age_eligible + & ~rent_liable + & ~person("housing_benefit_non_dep_additional_exception", period) + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_absent.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_absent.py new file mode 100644 index 0000000000..78a80c3792 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_absent.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_absent(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep absent" + documentation = "Not currently residing with the claimant. Used with current hospital, custody or military-operation facts, not a past absence." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_additional_exception.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_additional_exception.py new file mode 100644 index 0000000000..0dcbf8bfb9 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_additional_exception.py @@ -0,0 +1,44 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_additional_exception(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Additional Housing Benefit non-dependant exemption" + documentation = "Normal home elsewhere, specified youth training, under-25 income-related ESA outside the support/WRAG groups, and qualifying hospital, custody or military-operation absence. Student and postponed-increase rules are applied separately for each claimant." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) + + def formula(person, period, parameters): + p = parameters( + period + ).gov.dwp.housing_benefit.non_dep_deduction.additional_exceptions + esa = ( + (person("age", period) < p.assessment_phase_age) + & (person("esa_income_reported", period) > 0) + & ~person("esa_support_group", period) + & ~person("esa_work_related_activity_group", period) + ) + hospital = person("is_hospital_inpatient", period) & ( + person("housing_benefit_non_dep_linked_inpatient_days", period) + > p.hospital_weeks * 7 + ) + custody = person("is_in_prison", period) & person( + "housing_benefit_non_dep_custody_excludes_mental_health_hospital", period + ) + absence = person("housing_benefit_non_dep_absent", period) & ( + hospital + | custody + | person("housing_benefit_non_dep_military_operations", period) + ) + return ( + person("housing_benefit_non_dep_normal_home_elsewhere", period) + | person("housing_benefit_non_dep_youth_training_allowance", period) + | esa + | absence + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_custody_excludes_mental_health_hospital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_custody_excludes_mental_health_hospital.py new file mode 100644 index 0000000000..a57d22a5a3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_custody_excludes_mental_health_hospital.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_custody_excludes_mental_health_hospital(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep custody excludes mental health hospital" + documentation = "Current custody is pending trial, pending sentence after conviction, or under a court sentence, and is not statutory mental-health hospital detention. Used with is_in_prison and current absence." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_deductions.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_deductions.py index e5e9e3a933..0f851c79d7 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_deductions.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_deductions.py @@ -1,4 +1,8 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.housing_benefit import calendar_dates +from policyengine_uk.utils.housing_benefit_non_dependants import ( + postponed_non_dep_increases, +) class housing_benefit_non_dep_deductions(Variable): @@ -11,6 +15,10 @@ class housing_benefit_non_dep_deductions(Variable): "https://www.legislation.gov.uk/uksi/2006/213/regulation/3", "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/59", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/57", ) def formula(benunit, period, parameters): @@ -26,5 +34,40 @@ def formula(benunit, period, parameters): deductions = person( "household_benefits_individual_non_dep_deduction", period ) * person("is_non_dependant_of_household_head", period) + # Study-period and non-working summer students are exempt for every + # claimant. Pension-age / age-65 exceptions depend on this claimant, + # not on whether any unrelated pensioner lives in the household. + student = person("housing_benefit_non_dep_full_time_student", period) + study = person("housing_benefit_non_dep_period_of_study", period) + summer = person("housing_benefit_non_dep_summer_vacation", period) + works = person("housing_benefit_remunerative_work", period) + deductions *= ~(student & (study | (summer & ~works))) + p = parameters( + period + ).gov.dwp.housing_benefit.non_dep_deduction.additional_exceptions + adult = person("is_claimant_or_partner", period) + age_65 = benunit.any(adult & (person("age", period) >= p.former_pension_age)) + state_pension_age = benunit.any(adult & person("is_SP_age", period)) + pension = benunit("housing_benefit_pension_age_regulations_apply", period) + country = benunit.household("country", period) + ni = country == country.possible_values.NORTHERN_IRELAND + after_age_change = benunit( + "housing_benefit_assessment_date", period + ) >= calendar_dates(p.age_condition_removed) + full_exemption = where( + pension, where(ni | ~after_age_change, age_65, True), state_pension_age + ) + total = benunit.max(person.household.sum(deductions)) + all_students = benunit.max(person.household.sum(deductions * student)) + total -= full_exemption * all_students + postponed = postponed_non_dep_increases( + benunit, + period, + deductions, + full_exemption, + student, + pension & (after_age_change | age_65), + p.postponement_weeks, + ) share = benunit("share_of_household_rent", period) - return share * benunit.max(person.household.sum(deductions)) + return share * max_(total - postponed, 0) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_full_time_student.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_full_time_student.py new file mode 100644 index 0000000000..3a2fec130c --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_full_time_student.py @@ -0,0 +1,23 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.household.demographic.highest_education import ( + EducationType, +) + + +class housing_benefit_non_dep_full_time_student(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Full-time student for Housing Benefit non-dependant rules" + documentation = "Full-time course status. The fallback uses the model's education enrolment and higher-education inputs, as the existing local-benefit rules do; explicitly override it for part-time courses. This fact alone does not exempt a working student during summer vacation." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) + + def formula(person, period, parameters): + return ( + person("current_education", period) != EducationType.NOT_IN_EDUCATION + ) | person("in_HE", period) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_increase_history.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_increase_history.py new file mode 100644 index 0000000000..6b6aed7854 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_increase_history.py @@ -0,0 +1,16 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_increase_history(Variable): + value_type = str + entity = BenUnit + definition_period = YEAR + label = "housing benefit non dep increase history" + documentation = "JSON array of claimant-specific pending non-dependant increases. Each record identifies person_id, previous_weekly_deduction (before rent-share allocation), last_effective_date and increases [{date, kind}], where kind is arrival, circumstances or uprating. Include every pending increase since the current continuous award began or the last effective change, whichever is later. previous_weekly_deduction is the amount actually applied immediately before these increases, including ordinary uprating and immediate reductions. Empty history means no evidenced postponement; it does not assert that every resident recently arrived. See docs/engineering/housing-benefit-assessment.md." + default_value = "[]" + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_linked_inpatient_days.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_linked_inpatient_days.py new file mode 100644 index 0000000000..cb0aee5fc1 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_linked_inpatient_days.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_linked_inpatient_days(Variable): + value_type = int + entity = Person + definition_period = YEAR + label = "housing benefit non dep linked inpatient days" + documentation = "Days actually spent as an inpatient in the current linked series of admissions. Sum admission days only, excluding intervening days; restart the series after any gap exceeding 28 days. Must be supplied from admission/discharge records, not elapsed time since the first admission." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_military_operations.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_military_operations.py new file mode 100644 index 0000000000..6d0eace651 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_military_operations.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_military_operations(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep military operations" + documentation = "Currently away on military operations; ordinary military service or training does not qualify." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_normal_home_elsewhere.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_normal_home_elsewhere.py new file mode 100644 index 0000000000..0323632d4f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_normal_home_elsewhere.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_normal_home_elsewhere(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep normal home elsewhere" + documentation = "The authority considers this person's normal home elsewhere, despite residence with the claimant." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_period_of_study.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_period_of_study.py new file mode 100644 index 0000000000..cda7edbc69 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_period_of_study.py @@ -0,0 +1,20 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_period_of_study(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Non-dependant is in a Housing Benefit statutory period of study" + documentation = "Period of study as defined by the relevant HB student regulations. In the absence of more precise course dates, an enrolled full-time student outside a reported summer vacation is treated as studying. Override for other periods outside the statutory course dates." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) + + def formula(person, period, parameters): + return person("housing_benefit_non_dep_full_time_student", period) & ~person( + "housing_benefit_non_dep_summer_vacation", period + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_summer_vacation.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_summer_vacation.py new file mode 100644 index 0000000000..6048c9e0e7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_summer_vacation.py @@ -0,0 +1,17 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_summer_vacation(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep summer vacation" + documentation = ( + "Currently in a recognised summer vacation appropriate to the full-time course." + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_youth_training_allowance.py b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_youth_training_allowance.py new file mode 100644 index 0000000000..84ee903024 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/non_dep_deduction/housing_benefit_non_dep_youth_training_allowance.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_non_dep_youth_training_allowance(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "housing benefit non dep youth training allowance" + documentation = "Receives the training allowance specified by the relevant GB or NI Housing Benefit non-dependant regulation; ordinary training or an apprenticeship is insufficient." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/55", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/72", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/53", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/num_relevant_children_for_housing_benefit_childcare.py b/policyengine_uk/variables/gov/dwp/housing_benefit/num_relevant_children_for_housing_benefit_childcare.py index b678bac9f0..039b7496a6 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/num_relevant_children_for_housing_benefit_childcare.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/num_relevant_children_for_housing_benefit_childcare.py @@ -2,37 +2,14 @@ class num_relevant_children_for_housing_benefit_childcare(Variable): - """Children whose ages permit relevant Housing Benefit childcare charges. - - Regulation 28(6) ends eligibility on the day before the first Monday - in September after the fifteenth birthday (sixteenth if disabled). - Annual integer ages approximate this with exclusive limits of 16 and - 17. The legacy-benefit family definition excludes claimants/partners. - Per-child charges are unobserved, so eligible children stand in for - children in respect of whom charges are paid under regulation 27(3). - Disability uses the existing benefits-disability input or blindness; - historic certification and suspended-payment cases are unobserved. - """ - value_type = int entity = BenUnit - label = "Relevant children for Housing Benefit childcare charges" definition_period = YEAR - reference = ( - "https://www.legislation.gov.uk/uksi/2006/213/regulation/27", - "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", - ) + label = "Children with qualifying paid Housing Benefit childcare" + documentation = "Counts only children with positive qualifying per-child charges. An older sibling or child with no paid qualifying care cannot increase the one-child cap. Provider and exact September age conditions are applied to each child's charges." + reference = "https://www.legislation.gov.uk/uksi/2006/213/regulation/27" def formula(benunit, period, parameters): - person = benunit.members - p = parameters( - period - ).gov.dwp.housing_benefit.means_test.childcare.child_age_limit - child_or_young_person = person( - "is_child_or_young_person_for_legacy_benefits", period - ) - disabled = person("is_disabled_for_benefits", period) | person( - "is_blind", period + return benunit.sum( + benunit.members("housing_benefit_qualifying_childcare_costs", period) > 0 ) - age_limit = where(disabled, p.disabled, p.standard) - return benunit.sum(child_or_young_person & (person("age", period) < age_limit)) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_authority_approved.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_authority_approved.py new file mode 100644 index 0000000000..ca590f358d --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_authority_approved.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_authority_approved(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "permitted work authority approved" + documentation = "The competent authority has accepted that this person is undertaking work of a prescribed exempt-work kind. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_former_restart_conditions_met.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_former_restart_conditions_met.py new file mode 100644 index 0000000000..ece793571b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_former_restart_conditions_met.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_former_restart_conditions_met(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "permitted work former restart conditions met" + documentation = "The pre-April-2017 statutory conditions allowing this higher-limit work period to start/restart have been satisfied. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_medically_supervised.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_medically_supervised.py new file mode 100644 index 0000000000..9d4abeef7b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_medically_supervised.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_medically_supervised(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "permitted work medically supervised" + documentation = "The exempt work is part of prescribed medically supervised treatment as a hospital inpatient or regular outpatient. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_net_earnings.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_net_earnings.py new file mode 100644 index 0000000000..1e60124db6 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_net_earnings.py @@ -0,0 +1,15 @@ +from policyengine_uk.model_api import * + + +class permitted_work_net_earnings(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "permitted work net earnings" + documentation = "Weekly earnings from the particular work assessed as exempt, calculated under the relevant ESA/incapacity rules. Other jobs are excluded from this input. Defaults to zero/false when the factual history is not supplied." + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_supported.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_supported.py new file mode 100644 index 0000000000..bf637ed8ba --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_supported.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_supported(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "permitted work supported" + documentation = "The exempt work is supervised by the prescribed public/local authority or qualifying voluntary/community-interest organisation worker. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weekly_hours.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weekly_hours.py new file mode 100644 index 0000000000..5b86a61b2f --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weekly_hours.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_weekly_hours(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "permitted work weekly hours" + documentation = "Average weekly hours in the work assessed as exempt, excluding separate other work. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weeks.py b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weeks.py new file mode 100644 index 0000000000..b00f249f09 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/permitted_work_weeks.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class permitted_work_weeks(Variable): + value_type = float + entity = Person + definition_period = YEAR + label = "permitted work weeks" + documentation = "Weeks in the current ordinary higher-limit permitted-work period under the former 52-week restriction. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_30_hour_element_in_award.py b/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_30_hour_element_in_award.py new file mode 100644 index 0000000000..55fd10d871 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_30_hour_element_in_award.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class working_tax_credit_30_hour_element_in_award(Variable): + value_type = bool + entity = BenUnit + definition_period = YEAR + label = "working tax credit 30 hour element in award" + documentation = "An actual Working Tax Credit award includes the 30-hour element under regulation 20(1)(c), for the claimant or partner. This is not inferred from age or a zero annual tax-credit payment." + reference = ( + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3", + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_disability_element_in_award.py b/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_disability_element_in_award.py new file mode 100644 index 0000000000..8174d63348 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/working_tax_credit_disability_element_in_award.py @@ -0,0 +1,14 @@ +from policyengine_uk.model_api import * + + +class working_tax_credit_disability_element_in_award(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "working tax credit disability element in award" + documentation = "A disability/severe-disability element is included in the person's actual Working Tax Credit award. Defaults to zero/false when the factual history is not supplied." + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) diff --git a/policyengine_uk/variables/gov/dwp/lifetime_isa_countable_capital.py b/policyengine_uk/variables/gov/dwp/lifetime_isa_countable_capital.py index 6daf2817c3..c7d399d013 100644 --- a/policyengine_uk/variables/gov/dwp/lifetime_isa_countable_capital.py +++ b/policyengine_uk/variables/gov/dwp/lifetime_isa_countable_capital.py @@ -8,23 +8,33 @@ class lifetime_isa_countable_capital(Variable): "withdrawal charge below the charge-free age, and the whole balance " "from that age. Every means test values capital at its current market " "or surrender value, and DWP guidance counts a Lifetime ISA at 75% of " - "its value under 60 and in full from 60. Not modelled: the " - "charge-free withdrawals towards a first home or with a terminal " - "illness." + "its value under 60 and in full from 60. Qualifying written medical " + "evidence received by the account manager also removes the charge. " + "Evidence is assessed at the annual age date, 6 October. Prospective " + "first-home eligibility does not remove the charge from unrestricted " + "surrender: the purchase exception requires a qualifying transaction " + "and direct payment to a conveyancer." ) entity = Person definition_period = YEAR value_type = float unit = GBP quantity_type = STOCK - reference = [ + reference = ( "https://www.legislation.gov.uk/uksi/2013/376/regulation/49", "https://assets.publishing.service.gov.uk/media/693ace15c72b0f8ccf33d609/adm-ch-H1.pdf#page=56", "https://www.legislation.gov.uk/uksi/1998/1870/schedule", - ] + "https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/4", + "https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/6", + ) def formula(person, period, parameters): p = parameters(period).gov.hmrc.isa.lifetime balance = person("lifetime_isa_balance", period) charge_free = person("age", period) >= p.charge_free_age + medical = person("lifetime_isa_qualifying_medical_evidence", period) & ( + person("lifetime_isa_medical_evidence_received_date", period) + <= np.datetime64(f"{period.start.year}-10-06") + ) + charge_free = charge_free | medical return where(charge_free, balance, balance * (1 - p.withdrawal_charge)) diff --git a/policyengine_uk/variables/input/lifetime_isa_medical_evidence_received_date.py b/policyengine_uk/variables/input/lifetime_isa_medical_evidence_received_date.py new file mode 100644 index 0000000000..76ab595c46 --- /dev/null +++ b/policyengine_uk/variables/input/lifetime_isa_medical_evidence_received_date.py @@ -0,0 +1,12 @@ +from datetime import date + +from policyengine_uk.model_api import * + + +class lifetime_isa_medical_evidence_received_date(Variable): + value_type = date + entity = Person + definition_period = YEAR + default_value = date(9999, 1, 1) + label = "Date Lifetime ISA manager received qualifying medical evidence" + reference = "https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/4" diff --git a/policyengine_uk/variables/input/lifetime_isa_qualifying_medical_evidence.py b/policyengine_uk/variables/input/lifetime_isa_qualifying_medical_evidence.py new file mode 100644 index 0000000000..bb4585273e --- /dev/null +++ b/policyengine_uk/variables/input/lifetime_isa_qualifying_medical_evidence.py @@ -0,0 +1,10 @@ +from policyengine_uk.model_api import * + + +class lifetime_isa_qualifying_medical_evidence(Variable): + value_type = bool + entity = Person + definition_period = YEAR + label = "Lifetime ISA manager holds qualifying medical evidence" + documentation = "The account manager has received written evidence from a registered medical practitioner that the investor is expected to live for less than one year. A diagnosis or general disability alone does not qualify. False unless supplied." + reference = "https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/4" From 3321a0a8a22551832ebfe4e0b4cc4a698676a5df Mon Sep 17 00:00:00 2001 From: Anthony Volk <14987227+anth-volk@users.noreply.github.com> Date: Fri, 9 Oct 2026 01:15:05 +0400 Subject: [PATCH 3/3] Fix issues from review: Housing Benefit CI regressions --- changelog.d/2197.fixed.md | 1 + .../engineering/housing-benefit-assessment.md | 12 + .../personal_allowance/history/england.yaml | 11 + .../personal_allowance/history/scotland.yaml | 13 + .../personal_allowance/under_65_age.yaml | 13 + .../personal_allowance/under_65_couple.yaml | 46 ++ .../personal_allowance/under_65_single.yaml | 46 ++ .../under_65_wales_scheme_applies.yaml | 12 + ...g_benefit_applicable_income_disregard.yaml | 27 +- ..._or_temporary_accommodation_disregard.yaml | 3 +- ...itional_earnings_disregard_conditions.yaml | 50 ++ .../housing_benefit_savings_credit_only.yaml | 3 +- .../legacy_claimant_relationships.yaml | 16 +- ...ousing_benefit_pension_age_means_test.yaml | 12 +- .../state_pension_credit_qualifying_age.yaml | 10 +- ...duction_historical_personal_allowance.yaml | 551 ++++++++++++++++++ ...eduction_pensioner_earnings_disregard.yaml | 27 + ...council_tax_reduction_applicable_amount.py | 44 +- 18 files changed, 865 insertions(+), 32 deletions(-) create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/england.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/scotland.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_age.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_couple.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_single.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_wales_scheme_applies.yaml create mode 100644 policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_historical_personal_allowance.yaml diff --git a/changelog.d/2197.fixed.md b/changelog.d/2197.fixed.md index f9144e1399..254979665c 100644 --- a/changelog.d/2197.fixed.md +++ b/changelog.d/2197.fixed.md @@ -2,3 +2,4 @@ - Added child applicable amounts, protected family and child-disability premiums, and the claimant-specific ESA age exception. - Corrected childcare qualification and income limits, special/permitted-work earnings disregards, capital exclusions and ownership treatment, and the LISA medical exception. - Added remaining non-dependant exceptions and claimant-specific pension-age postponement, with government references and focused regression tests. +- Corrected connected Council Tax Reduction historical under-65 pensioner routing and updated existing regression tests for the changed Housing Benefit rules. diff --git a/docs/engineering/housing-benefit-assessment.md b/docs/engineering/housing-benefit-assessment.md index e196553721..71f06c4df1 100644 --- a/docs/engineering/housing-benefit-assessment.md +++ b/docs/engineering/housing-benefit-assessment.md @@ -45,6 +45,15 @@ do not change Council Tax Reduction or Income Support. The main-phase ESA age exception tests the claimant personally. A partner's main-phase award does not on its own satisfy that exception. +The connected Council Tax Reduction calculation also needs the former +under-65 pensioner personal allowance. Its category dates are separate from +HB: England removed it on 6 December 2018, Scotland on 1 February 2021 and +Wales for schemes from 1 April 2022. Separate referenced CTR rates and Boolean +schedules preserve those differences. The existing higher-age allowance +parameters remain shared; HB's new child additions are not imported into CTR. +The Welsh replacement applies by annual scheme year; it does not change the +last five days of the model's previous 6-April fiscal year. + ## Childcare Report qualifying charges on each child using @@ -192,5 +201,8 @@ the model as a complete reconstruction of every HB provision or pre-2015 award. - [2026 GB carers' reassessment exclusion](https://www.legislation.gov.uk/uksi/2026/681). - [2026 NI counterpart](https://www.legislation.gov.uk/nisr/2026/146). - [LISA medical withdrawal exception](https://www.legislation.gov.uk/uksi/1998/1870/schedule/paragraph/4). +- [England CTR historical pensioner table](https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2018-04-01). +- [Scotland CTR removal of the under-65 category](https://www.legislation.gov.uk/ssi/2020/413/regulation/13/made). +- [Wales CTR replacement pensioner table](https://www.legislation.gov.uk/wsi/2022/51/regulation/5/made). The relevant parameters and variables also carry their own source references. diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/england.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/england.yaml new file mode 100644 index 0000000000..62579e79bf --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/england.yaml @@ -0,0 +1,11 @@ +description: Whether England's pensioner Council Tax Reduction table retains its separate under-65 personal allowance. +values: + 2015-04-01: true + 2018-12-06: false +metadata: + unit: bool + label: England former CTR pensioner under-65 category applies + preserve_calendar_dates: true + reference: + - title: Prescribed pensioner personal allowances, Schedule 2 paragraph 1, Tables 1 and 2 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2018-04-01 diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/scotland.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/scotland.yaml new file mode 100644 index 0000000000..842e1126d4 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/history/scotland.yaml @@ -0,0 +1,13 @@ +description: Whether Scotland's pensioner Council Tax Reduction table retains its separate under-65 personal allowance. +values: + 2015-04-01: true + 2021-02-01: false +metadata: + unit: bool + label: Scotland former CTR pensioner under-65 category applies + preserve_calendar_dates: true + reference: + - title: Council Tax Reduction (Scotland) Amendment (No. 4) Regulations 2020, commencement + href: https://www.legislation.gov.uk/ssi/2020/413/regulation/1/made + - title: Removal of the under-65 category + href: https://www.legislation.gov.uk/ssi/2020/413/regulation/13/made diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_age.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_age.yaml new file mode 100644 index 0000000000..d53da2c4fd --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_age.yaml @@ -0,0 +1,13 @@ +description: Age below which the former Council Tax Reduction pensioner personal allowance category applies. +values: + 2015-04-01: 65 +metadata: + unit: year + label: former CTR pensioner allowance age boundary + reference: + - title: England pensioner personal allowances, Schedule 2 paragraph 1 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2016-04-01 + - title: Wales pensioner personal allowances, Schedule 2 paragraph 1 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2016-04-30 + - title: Scotland pensioner personal allowances, Schedule 1 paragraph 2 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2016-04-30 diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_couple.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_couple.yaml new file mode 100644 index 0000000000..7d289ebf57 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_couple.yaml @@ -0,0 +1,46 @@ +description: Weekly Council Tax Reduction pensioner personal allowance for a couple both aged under 65 while the former category exists in the applicable national table. +metadata: + unit: currency-GBP + period: week + label: CTR pensioner under-65 couple personal allowance + breakdown: country + reference: + - title: England prescribed pensioner personal allowances, 2015 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2015-04-01 + - title: England prescribed pensioner personal allowances, 2016 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2016-04-01 + - title: England prescribed pensioner personal allowances, 2017 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2017-04-01 + - title: England prescribed pensioner personal allowances, 2018 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2018-04-01 + - title: Scotland pensioner personal allowances, including retained under-65 rates in 2020 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2020-04-30 + - title: Wales pensioner personal allowances, 2019 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2019-04-01 + - title: Wales pensioner personal allowances, 2020 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2020-04-01 + - title: Wales pensioner personal allowances, 2021 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2021-04-01 +ENGLAND: + 2015-04-01: 230.85 + 2016-04-01: 237.55 + 2017-04-01: 243.25 + 2018-04-01: 248.8 +SCOTLAND: + 2015-04-01: 230.85 + 2016-04-01: 237.55 + 2017-04-01: 243.25 + 2018-04-01: 248.8 + 2019-04-01: 255.25 +WALES: + 2015-04-01: 230.85 + 2016-04-01: 237.55 + 2017-04-01: 243.25 + 2018-04-01: 248.8 + 2019-04-01: 255.25 + 2020-04-01: 265.2 + 2021-04-01: 270.3 +NORTHERN_IRELAND: + 2015-04-01: 0 +UNKNOWN: + 2015-04-01: 0 diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_single.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_single.yaml new file mode 100644 index 0000000000..8848d309de --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_single.yaml @@ -0,0 +1,46 @@ +description: Weekly Council Tax Reduction pensioner personal allowance for a single applicant or lone parent aged under 65 while the former category exists in the applicable national table. +metadata: + unit: currency-GBP + period: week + label: CTR pensioner under-65 single or lone-parent personal allowance + breakdown: country + reference: + - title: England prescribed pensioner personal allowances, 2015 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2015-04-01 + - title: England prescribed pensioner personal allowances, 2016 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2016-04-01 + - title: England prescribed pensioner personal allowances, 2017 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2017-04-01 + - title: England prescribed pensioner personal allowances, 2018 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2018-04-01 + - title: Scotland pensioner personal allowances, including retained under-65 rates in 2020 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2020-04-30 + - title: Wales pensioner personal allowances, 2019 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2019-04-01 + - title: Wales pensioner personal allowances, 2020 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2020-04-01 + - title: Wales pensioner personal allowances, 2021 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2021-04-01 +ENGLAND: + 2015-04-01: 151.2 + 2016-04-01: 155.6 + 2017-04-01: 159.35 + 2018-04-01: 163 +SCOTLAND: + 2015-04-01: 151.2 + 2016-04-01: 155.6 + 2017-04-01: 159.35 + 2018-04-01: 163 + 2019-04-01: 167.25 +WALES: + 2015-04-01: 151.2 + 2016-04-01: 155.6 + 2017-04-01: 159.35 + 2018-04-01: 163 + 2019-04-01: 167.25 + 2020-04-01: 173.8 + 2021-04-01: 177.1 +NORTHERN_IRELAND: + 2015-04-01: 0 +UNKNOWN: + 2015-04-01: 0 diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_wales_scheme_applies.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_wales_scheme_applies.yaml new file mode 100644 index 0000000000..97d3208ff4 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/pensioners/personal_allowance/under_65_wales_scheme_applies.yaml @@ -0,0 +1,12 @@ +description: Whether the Welsh pensioner Council Tax Reduction scheme for the model year retains its separate under-65 personal allowance. +values: + 2015-04-01: true + 2022-04-01: false +metadata: + unit: bool + label: Wales former CTR pensioner under-65 category applies + reference: + - title: Application to schemes for financial years beginning from 1 April 2022 + href: https://www.legislation.gov.uk/wsi/2022/51/regulation/1/made + - title: Replacement pensioner personal allowance table + href: https://www.legislation.gov.uk/wsi/2022/51/regulation/5/made 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 7cf5e90192..8e2f3d155e 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 @@ -355,17 +355,19 @@ age: 30 employment_income: 5_200 # £100 a week weekly_hours: 16 - childcare_expenses: 4_160 # £80 a week child: age: 5 + housing_benefit_childcare_charges_paid: 4_160 + housing_benefit_childcare_provider: REGISTERED_APPROVED 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. - # £5,200 < £1,300 + £4,160 + £889.20 = £6,349.20, so only £25 a week. - housing_benefit_applicable_income_childcare_element: 4_160 + # SI 2006/213 reg 27(1)(c): no tax credits, so childcare is capped + # at earnings after the £25 disregard: £5,200 - £1,300 = £3,900. + # £5,200 < £1,300 + £3,900 + £889.20, so no additional disregard. + housing_benefit_applicable_income_childcare_element: 3_900 housing_benefit_applicable_income_disregard: 1_300 - name: Lone parent whose earnings cover the disregards and childcare gets the additional disregard @@ -377,9 +379,10 @@ age: 30 employment_income: 5_200 # £100 a week weekly_hours: 16 - childcare_expenses: 1_040 # £20 a week child: age: 5 + housing_benefit_childcare_charges_paid: 1_040 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: benunit: would_claim_uc: false # not on Universal Credit, which passports the means test @@ -430,7 +433,7 @@ # One member must work 30 hours; hours are not added across the couple. housing_benefit_applicable_income_disregard: 520 # £10 × 52 -- name: Disabled single person working 20 hours gets £5 plus the additional disregard (model limitation; the law gives £20 plus it) +- name: Disabled single person working 20 hours gets £20 plus the additional disregard period: 2026 absolute_error_margin: 0.01 input: @@ -448,15 +451,9 @@ # Para 17(2)(b)(iv)(aa): a single claimant with the disability premium # working 16 hours or more meets the condition. meets_housing_benefit_additional_earnings_disregard_conditions: true - # KNOWN LIMITATION: the law gives £1,929.20. Intended model limitation. - # In law the same disability premium brings in - # the £20 disregard in place of £5: Sch 4 para 3(2), "This paragraph - # applies where the claimant's applicable amount includes an amount by - # way of the disability premium". The law gives (£20 + £17.10) × 52 = - # £1,929.20 (£8,000 ≥ £1,040 + £889.20). The £20 disregards are out of - # scope for this change and tracked as a follow-up; until then the model - # gives (£5 + £17.10) × 52. - housing_benefit_applicable_income_disregard: 1_149.20 + # SI 2006/213 Sch 4 para 3(2): the actual disability premium gives + # the £20 ordinary disregard. (£20 + £17.10) * 52 = £1,929.20. + housing_benefit_applicable_income_disregard: 1_929.20 - name: Working-age claimant on Income Support has all earnings disregarded period: 2026 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 d6027e8a89..e44530df08 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 @@ -680,9 +680,10 @@ age: 30 employment_income: 7_800 # £150 a week weekly_hours: 16 - childcare_expenses: 2_080 # £40 a week child: age: 5 + housing_benefit_childcare_charges_paid: 2_080 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: benunit: would_claim_uc: false # not on Universal Credit, which passports the means test diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.yaml index a44009535b..41215a657e 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/meets_housing_benefit_additional_earnings_disregard_conditions.yaml @@ -9,6 +9,7 @@ person: age: 25 weekly_hours: 30 + employment_income: 8_000 benunits: benunit: members: [person] @@ -22,6 +23,7 @@ person: age: 24 weekly_hours: 40 + employment_income: 8_000 benunits: benunit: members: [person] @@ -37,6 +39,7 @@ partner: age: 24 weekly_hours: 30 + employment_income: 8_000 benunits: benunit: members: [claimant, partner] @@ -51,6 +54,7 @@ parent: age: 20 weekly_hours: 16 + employment_income: 8_000 child: age: 2 benunits: @@ -66,6 +70,7 @@ parent: age: 30 weekly_hours: 15 + employment_income: 8_000 child: age: 2 benunits: @@ -83,6 +88,7 @@ partner: age: 22 weekly_hours: 16 + employment_income: 8_000 child: age: 1 benunits: @@ -98,9 +104,11 @@ claimant: age: 40 weekly_hours: 20 + employment_income: 8_000 partner: age: 40 weekly_hours: 20 + employment_income: 8_000 benunits: benunit: members: [claimant, partner] @@ -116,6 +124,7 @@ partner: age: 40 weekly_hours: 16 + employment_income: 8_000 is_disabled_for_benefits: true benunits: benunit: @@ -130,6 +139,7 @@ claimant: age: 40 weekly_hours: 16 + employment_income: 8_000 partner: age: 40 is_disabled_for_benefits: true @@ -147,8 +157,48 @@ person: age: 70 weekly_hours: 30 + employment_income: 8_000 benunits: benunit: members: [person] output: meets_housing_benefit_additional_earnings_disregard_conditions: true + +- name: Case 11, unpaid 30-hour work does not satisfy the remunerative-work condition. + period: 2026 + input: + age: 30 + weekly_hours: 30 + employment_income: 0 + self_employment_income: 0 + housing_benefit_paid_work_expected: false + output: + meets_housing_benefit_additional_earnings_disregard_conditions: false + +- name: Case 12, expected payment can establish remunerative work before earnings arrive. + period: 2026 + input: + age: 30 + weekly_hours: 30 + employment_income: 0 + housing_benefit_paid_work_expected: true + output: + meets_housing_benefit_additional_earnings_disregard_conditions: true + housing_benefit_applicable_income_disregard: 0 + +- name: Case 13, a lone parent's unpaid 16-hour work does not satisfy the condition. + period: 2026 + input: + people: + person1: + age: 30 + weekly_hours: 16 + employment_income: 0 + housing_benefit_paid_work_expected: false + person2: + age: 5 + benunits: + benunit: + members: [person1, person2] + output: + meets_housing_benefit_additional_earnings_disregard_conditions: false diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml index bc8af60aad..2bc66fa99d 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml @@ -203,7 +203,8 @@ hours_worked: 1_040 person2: age: 8 - childcare_expenses: 2_600 + housing_benefit_childcare_charges_paid: 2_600 + housing_benefit_childcare_provider: REGISTERED_APPROVED benunits: benunit: members: [person1, person2] 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 e30e13c8b2..3003a65328 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 @@ -28,7 +28,9 @@ benefits_premiums: 0 output: # HB Sch 3 para 1: the applicable weekly model rate is 92.04; *52. - housing_benefit_applicable_amount: 4786.08 + # SI 2006/213 Sch 3 para 2: add the child's £84.66 * 52. + housing_benefit_child_allowance: 4_402.32 + housing_benefit_applicable_amount: 9_188.40 # CTR retains the existing shared HB allowance parameters. council_tax_reduction_applicable_amount: 4786.08 # HB Sch 4 paras 4/7/10: 25 * 52, with no hours disregard. @@ -68,7 +70,9 @@ benefits_premiums: 0 output: # HB Sch 3 para 1: the applicable weekly model rate is 144.67; *52. - housing_benefit_applicable_amount: 7522.84 + # SI 2006/213 Sch 3 para 2: add the child's £84.66 * 52. + housing_benefit_child_allowance: 4_402.32 + housing_benefit_applicable_amount: 11_925.16 # CTR retains the existing shared HB allowance parameters. council_tax_reduction_applicable_amount: 7522.84 # HB Sch 4 paras 4/7/10: 10 * 52, with no hours disregard. @@ -168,7 +172,9 @@ benefits_premiums: 0 output: # HB Sch 3 para 1: the applicable weekly model rate is 72.92; *52. - housing_benefit_applicable_amount: 3791.84 + # SI 2006/213 Sch 3 para 2: add the child's £84.66 * 52. + housing_benefit_child_allowance: 4_402.32 + housing_benefit_applicable_amount: 8_194.16 # CTR retains the existing shared HB allowance parameters. council_tax_reduction_applicable_amount: 3791.84 # HB Sch 4 paras 4/7/10: 25 * 52, with no hours disregard. @@ -228,6 +234,8 @@ output: # HB Sch 3 para 1(2): the claimant is under 18, even if responsible # for an older qualifying young person. Younger rate 72.92 * 52. - housing_benefit_applicable_amount: 3_791.84 + # SI 2006/213 Sch 3 para 2: add the child's £84.66 * 52. + housing_benefit_child_allowance: 4_402.32 + housing_benefit_applicable_amount: 8_194.16 # The shared CTR allowance calculation also uses only claimant/partner ages. council_tax_reduction_applicable_amount: 3_791.84 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_pension_age_means_test.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_pension_age_means_test.yaml index 4e721cbe6b..07509615dc 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_pension_age_means_test.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/housing_benefit_pension_age_means_test.yaml @@ -54,6 +54,7 @@ guarantee_credit: 0 households: household: + country: ENGLAND members: [claimant] rent: 6_240 tenure_type: RENT_FROM_COUNCIL @@ -64,8 +65,9 @@ housing_benefit_pension_age_regulations_apply: true council_tax_reduction_pensioner: true benefits_premiums: 0 - housing_benefit_applicable_amount: 9_412 - council_tax_reduction_applicable_amount: 9_412 + # 2017 under-65 pensioner category: £159.35 * 52. + housing_benefit_applicable_amount: 8_286.20 + council_tax_reduction_applicable_amount: 8_286.20 - name: Synthetic component routing does not apply the pension-age guarantee-credit passport under working-age flags # This fixes the scheme flags and income components to test their consumers; @@ -142,12 +144,14 @@ housing_benefit_applicable_income_childcare_element: 0 households: household: + country: ENGLAND members: [claimant] savings: 12_000 output: has_attained_state_pension_credit_qualifying_age: true - housing_benefit_applicable_amount: 9_412 - council_tax_reduction_applicable_amount: 9_412 + # 2017 under-65 pensioner category: £159.35 * 52. + housing_benefit_applicable_amount: 8_286.20 + council_tax_reduction_applicable_amount: 8_286.20 housing_benefit_assessable_capital: 0 housing_benefit_tariff_income: 0 housing_benefit_applicable_income: 0 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/state_pension_credit_qualifying_age.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/state_pension_credit_qualifying_age.yaml index e993dfbfb0..16e4c05d9c 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/state_pension_credit_qualifying_age.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/state_pension_credit_qualifying_age.yaml @@ -327,8 +327,9 @@ - name: Case 14, the pension-age Housing Benefit and CTR personal allowance applies from the qualifying age. # Born 6 April 1952, over the qualifying age in 2016-17, so the pension-age - # regulations (SI 2006/214) apply. The model's single pension-age rate for - # 2016-17 is 181 a week: 181 x 52 = 9,412. No premiums apply. + # regulations (SI 2006/214) apply. The former under-65 category is + # £155.60 * 52 = £8,091.20 (SI 2016/242 reg 6; England CTR Sch 2). + # No premiums apply. period: 2016 absolute_error_margin: 0.01 input: @@ -342,12 +343,13 @@ members: [person1] households: household: + country: ENGLAND members: [person1] tenure_type: RENT_FROM_COUNCIL output: benefits_premiums: 0 - housing_benefit_applicable_amount: 9_412 - council_tax_reduction_applicable_amount: 9_412 + housing_benefit_applicable_amount: 8_091.20 + council_tax_reduction_applicable_amount: 8_091.20 - name: Case 15, below the qualifying age the working-age allowance for a single person aged 25 or over applies. # Born 6 September 1953, under the qualifying age in 2017-18: 73.10 a week, diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_historical_personal_allowance.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_historical_personal_allowance.yaml new file mode 100644 index 0000000000..61c16a0d49 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_historical_personal_allowance.yaml @@ -0,0 +1,551 @@ +# Historical CTR personal-allowance table component tests. +# The pensioner flag is supplied to isolate the table from age eligibility; +# synthetic under-65 inputs after December 2018 are not real new claims. +# England: SI 2012/2885 Sch 2 para 1 (dated 2016-04-01 and 2018-04-01). +# Scotland: SSI 2012/319 Sch 1 para 2; SSI 2020/413 regs 1 and 13. +# Wales: WSI 2013/3029 Sch 2 para 1; WSI 2022/51 regs 1(3) and 5. +# Rates use 30 April; dated category changes use fiscal-year segments. +# Higher rates remain the existing shared HB parameters. The Scotland 2020 +# case supplies its enacted higher rate to isolate this category correction +# from the separate older-rate corrections owned by PR #1925. + +- name: Case 1, ENGLAND personal allowance for ages 64 in 2016. + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: ENGLAND + output: + # £155.6 per week * 52. + council_tax_reduction_applicable_amount: 8091.20 + housing_benefit_applicable_amount: 0 + +- name: Case 2, ENGLAND personal allowance for ages 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: ENGLAND + output: + # £159.35 per week * 52. + council_tax_reduction_applicable_amount: 8286.20 + housing_benefit_applicable_amount: 0 + +- name: Case 3, ENGLAND personal allowance for ages 64 and 63 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + person2: + age: 63 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: ENGLAND + output: + # £243.25 per week * 52. + council_tax_reduction_applicable_amount: 12649.00 + housing_benefit_applicable_amount: 0 + +- name: Case 4, ENGLAND personal allowance for ages 65 and 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + person2: + age: 64 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: ENGLAND + output: + # £258.15 per week * 52. + council_tax_reduction_applicable_amount: 13423.80 + housing_benefit_applicable_amount: 0 + +- name: Case 5, SCOTLAND personal allowance for ages 64 in 2016. + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # £155.6 per week * 52. + council_tax_reduction_applicable_amount: 8091.20 + housing_benefit_applicable_amount: 0 + +- name: Case 6, SCOTLAND personal allowance for ages 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # £159.35 per week * 52. + council_tax_reduction_applicable_amount: 8286.20 + housing_benefit_applicable_amount: 0 + +- name: Case 7, SCOTLAND personal allowance for ages 64 and 63 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + person2: + age: 63 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: SCOTLAND + output: + # £243.25 per week * 52. + council_tax_reduction_applicable_amount: 12649.00 + housing_benefit_applicable_amount: 0 + +- name: Case 8, SCOTLAND personal allowance for ages 65 and 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + person2: + age: 64 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: SCOTLAND + output: + # £258.15 per week * 52. + council_tax_reduction_applicable_amount: 13423.80 + housing_benefit_applicable_amount: 0 + +- name: Case 9, WALES personal allowance for ages 64 in 2016. + period: 2016 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £155.6 per week * 52. + council_tax_reduction_applicable_amount: 8091.20 + housing_benefit_applicable_amount: 0 + +- name: Case 10, WALES personal allowance for ages 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £159.35 per week * 52. + council_tax_reduction_applicable_amount: 8286.20 + housing_benefit_applicable_amount: 0 + +- name: Case 11, WALES personal allowance for ages 64 and 63 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + person2: + age: 63 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: WALES + output: + # £243.25 per week * 52. + council_tax_reduction_applicable_amount: 12649.00 + housing_benefit_applicable_amount: 0 + +- name: Case 12, WALES personal allowance for ages 65 and 64 in 2017. + period: 2017 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 65 + person2: + age: 64 + benunits: + benunit: + members: [person1, person2] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1, person2] + country: WALES + output: + # £258.15 per week * 52. + council_tax_reduction_applicable_amount: 13423.80 + housing_benefit_applicable_amount: 0 + +- name: Case 13, ENGLAND personal allowance for ages 64 in 2015. + period: 2015 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: ENGLAND + output: + # £151.2 per week * 52. + council_tax_reduction_applicable_amount: 7862.40 + housing_benefit_applicable_amount: 0 + +- name: Case 14, ENGLAND personal allowance for ages 64 in 2018. + period: 2018 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: ENGLAND + output: + # 244 days at £163 and 121 days at £176.40, divided by 365 and multiplied by 52. + council_tax_reduction_applicable_amount: 8706.99 + housing_benefit_applicable_amount: 0 + +- name: Case 15, SCOTLAND personal allowance for ages 64 in 2018. + period: 2018 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # £163 per week * 52. + council_tax_reduction_applicable_amount: 8476.00 + housing_benefit_applicable_amount: 0 + +- name: Case 16, WALES personal allowance for ages 64 in 2018. + period: 2018 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £163 per week * 52. + council_tax_reduction_applicable_amount: 8476.00 + housing_benefit_applicable_amount: 0 + +- name: Case 17, ENGLAND personal allowance for ages 64 in 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: ENGLAND + output: + # £181 per week * 52. + council_tax_reduction_applicable_amount: 9412.00 + housing_benefit_applicable_amount: 0 + +- name: Case 18, SCOTLAND personal allowance for ages 64 in 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # £167.25 per week * 52. + council_tax_reduction_applicable_amount: 8697.00 + housing_benefit_applicable_amount: 0 + +- name: Case 19, WALES personal allowance for ages 64 in 2019. + period: 2019 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £167.25 per week * 52. + council_tax_reduction_applicable_amount: 8697.00 + housing_benefit_applicable_amount: 0 + +- name: Case 20, SCOTLAND personal allowance for ages 64 in 2020. + period: 2020 + absolute_error_margin: 0.01 + input: + gov.dwp.housing_benefit.allowances.single.aged: 187.75 + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # 301 days at the retained £167.25 and 64 days at £187.75, annualised. + council_tax_reduction_applicable_amount: 8883.92 + housing_benefit_applicable_amount: 0 + +- name: Case 21, WALES personal allowance for ages 64 in 2020. + period: 2020 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £173.8 per week * 52. + council_tax_reduction_applicable_amount: 9037.60 + housing_benefit_applicable_amount: 0 + +- name: Case 22, SCOTLAND personal allowance for ages 64 in 2021. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: SCOTLAND + output: + # £191.15 per week * 52. + council_tax_reduction_applicable_amount: 9939.80 + housing_benefit_applicable_amount: 0 + +- name: Case 23, WALES personal allowance for ages 64 in 2021. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £177.1 per week * 52. + council_tax_reduction_applicable_amount: 9209.20 + housing_benefit_applicable_amount: 0 + +- name: Case 24, WALES personal allowance for ages 64 in 2022. + period: 2022 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 64 + benunits: + benunit: + members: [person1] + council_tax_reduction_pensioner: true + pension_age_benefits_premiums: 0 + housing_benefit_eligible: false + households: + household: + members: [person1] + country: WALES + output: + # £197.1 per week * 52. + council_tax_reduction_applicable_amount: 10249.20 + housing_benefit_applicable_amount: 0 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_earnings_disregard.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_earnings_disregard.yaml index c077000081..aaa1a27062 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_earnings_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_earnings_disregard.yaml @@ -225,6 +225,9 @@ employment_income: 10_000 weekly_hours: 20 is_disabled_for_benefits: true + # SI 2012/2885 Sch 4 para 5(1)(a)(iii): listed award, not a + # generic disability flag, establishes the 16-hour work route. + attendance_allowance: 1_000 benunits: benunit: members: [pensioner] @@ -452,3 +455,27 @@ council_tax_reduction_applicable_amount: 13_312 # 2,000 - 20% x (15,054 - 13,312) (main: 1,599.60). council_tax_reduction: 1_651.60 + +- name: Case 22, a generic disability flag alone does not establish the pensioner 16-hour route. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 70 + employment_income: 10_000 + weekly_hours: 20 + is_disabled_for_benefits: true + attendance_allowance: 0 + dla: 0 + pip: 0 + benunits: + benunit: + members: [person1] + households: + household: + members: [person1] + country: ENGLAND + output: + # SI 2012/2885 Sch 4 para 5(1) requires a listed award or condition. + council_tax_reduction_pensioner_earnings_disregard: 260 diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py index 9b4f657c29..ea872f4aab 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_amount.py @@ -1,4 +1,5 @@ from policyengine_uk.model_api import * +from policyengine_uk.utils.excise import fiscal_year_segments class council_tax_reduction_applicable_amount(Variable): @@ -14,6 +15,9 @@ class council_tax_reduction_applicable_amount(Variable): "https://www.legislation.gov.uk/wsi/2013/3029/schedule/7", "https://www.legislation.gov.uk/ssi/2012/319/schedule/1", "https://www.legislation.gov.uk/ssi/2021/249/schedule/1", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2018-04-01", + "https://www.legislation.gov.uk/ssi/2020/413/regulation/13/made", + "https://www.legislation.gov.uk/wsi/2022/51/regulation/5/made", ) def formula(benunit, period, parameters): @@ -32,16 +36,50 @@ def formula(benunit, period, parameters): single = benunit("is_single_person", period) couple = benunit("is_couple", period) lone_parent = benunit("is_lone_parent", period) + ctr = parameters( + period + ).gov.local_authorities.council_tax_reduction.pensioners.personal_allowance + country = benunit.household("country", period) + countries = country.possible_values + pension_single = 0 + pension_couple = 0 + pension_lone_parent = 0 + # The under-65 category ended at different dates in the three CTR + # schemes. Do not reuse HB's 6 December 2018 cutoff for all countries. + for rules, share in fiscal_year_segments( + parameters.gov.local_authorities.council_tax_reduction.pensioners.personal_allowance.history, + period.start.year, + ): + lower_category = select( + [ + country == countries.ENGLAND, + country == countries.SCOTLAND, + country == countries.WALES, + ], + # The Welsh amendment applies to whole financial-year + # schemes, not the last days of the previous model year. + [rules.england, rules.scotland, ctr.under_65_wales_scheme_applies], + default=False, + ) & (eldest_age < ctr.under_65_age) + pension_single += share * where( + lower_category, ctr.under_65_single[country], p.single.aged + ) + pension_couple += share * where( + lower_category, ctr.under_65_couple[country], p.couple.aged + ) + pension_lone_parent += share * where( + lower_category, ctr.under_65_single[country], p.lone_parent.aged + ) single_personal_allowance = ( - u_25 * p.single.younger + o_25 * p.single.older + pensioner * p.single.aged + u_25 * p.single.younger + o_25 * p.single.older + pensioner * pension_single ) couple_personal_allowance = ( - u_18 * p.couple.younger + o_18 * p.couple.older + pensioner * p.couple.aged + u_18 * p.couple.younger + o_18 * p.couple.older + pensioner * pension_couple ) lone_parent_personal_allowance = ( u_18 * p.lone_parent.younger + o_18 * p.lone_parent.older - + pensioner * p.lone_parent.aged + + pensioner * pension_lone_parent ) personal_allowance = ( single * single_personal_allowance