diff --git a/changelog.d/2696.fixed.md b/changelog.d/2696.fixed.md new file mode 100644 index 0000000000..c7b47bc94e --- /dev/null +++ b/changelog.d/2696.fixed.md @@ -0,0 +1 @@ +The programme registry identifies the correct responsible bodies and nations for Scottish income tax, tax credits, the Energy Price Guarantee, Council Tax, Council Tax Reduction and Winter Fuel Payment. diff --git a/policyengine_uk/programs.yaml b/policyengine_uk/programs.yaml index ed22040b61..1bdc217c07 100644 --- a/policyengine_uk/programs.yaml +++ b/policyengine_uk/programs.yaml @@ -375,13 +375,13 @@ programs: name: Tax credits full_name: Tax Credits (Working Tax Credit and Child Tax Credit) category: Benefits - agency: DWP + agency: HMRC status: complete coverage: UK variable: tax_credits parameter_prefix: gov.dwp.tax_credits verified_start_year: 2022 - notes: Legacy benefit being replaced by Universal Credit + notes: HMRC administered Working Tax Credit and Child Tax Credit until they ended on 5 April 2025 - id: sda name: SDA @@ -400,11 +400,11 @@ programs: category: Benefits agency: DWP status: complete - coverage: UK + coverage: England, Wales and Northern Ireland variable: winter_fuel_payment parameter_prefix: gov.dwp.winter_fuel_payment verified_start_year: 2022 - notes: Great Britain to winter 2023-24, then England and Wales; Northern Ireland's mirror scheme uses the same parameters. From winter 2025-26 paid to everyone of pensionable age and recovered by the winter fuel payment charge (income tax) + notes: Great Britain to winter 2023-24, then England and Wales; Northern Ireland's mirror scheme uses the same parameters. The Scottish Government replaced it with Pension Age Winter Heating Payment from winter 2024-25. From winter 2025-26 HMRC recovers payments from higher-income recipients through the winter fuel payment charge (income tax) - id: ssmg name: Sure Start Maternity Grant @@ -572,7 +572,7 @@ programs: category: Taxes agency: Local status: complete - coverage: UK + coverage: Great Britain variable: council_tax verified_start_year: 2022 @@ -582,7 +582,7 @@ programs: category: Benefits agency: Local status: partial - coverage: UK + coverage: Great Britain variable: council_tax_reduction parameter_prefix: gov.local_authorities verified_start_year: 2013 @@ -606,7 +606,7 @@ programs: name: Energy Price Guarantee full_name: Energy Price Guarantee category: Benefits - agency: Ofgem + agency: DESNZ status: partial coverage: UK parameter_prefix: gov.ofgem @@ -635,7 +635,7 @@ programs: name: Scottish income tax full_name: Scottish Income Tax Rates category: Taxes - agency: Revenue Scotland + agency: HMRC status: complete coverage: Scotland verified_start_year: 2019 diff --git a/policyengine_uk/tests/test_program_registry.py b/policyengine_uk/tests/test_program_registry.py index f4214066d8..2ff5fe25a3 100644 --- a/policyengine_uk/tests/test_program_registry.py +++ b/policyengine_uk/tests/test_program_registry.py @@ -2,6 +2,7 @@ import pytest import yaml +from hypothesis import given, settings, strategies as st from policyengine_core.parameters import ParameterNode from policyengine_uk import CountryTaxBenefitSystem @@ -54,3 +55,59 @@ def test_benefit_cap_does_not_advertise_unrelated_parameters(tax_benefit_system) advertised.get_child("non_single.outside_london") is benefit_cap.non_single.outside_london ) + + +@pytest.mark.parametrize( + "program_id, field, expected", + [ + ("scottish_income_tax", "agency", "HMRC"), + ("tax_credits", "agency", "HMRC"), + ("energy_price_guarantee", "agency", "DESNZ"), + ("council_tax", "coverage", "Great Britain"), + ("council_tax_reduction", "coverage", "Great Britain"), + ( + "winter_fuel_payment", + "coverage", + "England, Wales and Northern Ireland", + ), + ], + ids=lambda value: value, +) +def test_program_agency_and_coverage(program_id, field, expected): + """The registry identifies the administering body and nations (#2696).""" + programs = [p for p in PROGRAMS if p["id"] == program_id] + assert len(programs) == 1 + assert programs[0][field] == expected + + +@pytest.mark.parametrize( + "program_id, date", + [ + ("tax_credits", "5 April 2025"), + ("winter_fuel_payment", "from winter 2024-25"), + ], + ids=lambda value: value, +) +def test_program_notes_state_when_the_scheme_changed(program_id, date): + """The notes keep each programme's sourced end or replacement date (#2696).""" + programs = [p for p in PROGRAMS if p["id"] == program_id] + assert len(programs) == 1 + assert date in programs[0]["notes"] + + +@settings(max_examples=len(PROGRAMS), database=None, derandomize=True) +@given(program_id=st.sampled_from(tuple(p["id"] for p in PROGRAMS))) +def test_program_metadata_survives_loading(tax_benefit_system, program_id): + """Core exposes every program's agency and coverage strings unchanged.""" + registry_program = next(p for p in PROGRAMS if p["id"] == program_id) + loaded_programs = [ + p + for p in tax_benefit_system.modelled_policies["programs"] + if p["id"] == program_id + ] + assert len(loaded_programs) == 1 + for field in ("agency", "coverage"): + value = loaded_programs[0][field] + assert isinstance(value, str) + assert value + assert value == registry_program[field]