diff --git a/changelog.d/council-tax-reduction-kingston-upon-thames.md b/changelog.d/council-tax-reduction-kingston-upon-thames.md new file mode 100644 index 000000000..408646697 --- /dev/null +++ b/changelog.d/council-tax-reduction-kingston-upon-thames.md @@ -0,0 +1 @@ +- Add working-age Council Tax Reduction for Kingston upon Thames. diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/maximum_support_rate.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/maximum_support_rate.yaml new file mode 100644 index 000000000..740af1800 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/maximum_support_rate.yaml @@ -0,0 +1,10 @@ +description: Maximum share of eligible Council Tax liability covered for working-age households under the Kingston upon Thames Council Tax Reduction scheme. +values: + 2026-04-01: 1 +metadata: + unit: /1 + period: year + label: Kingston upon Thames Council Tax Reduction maximum support rate + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/capital_limit.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/capital_limit.yaml new file mode 100644 index 000000000..77e92a9fc --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/capital_limit.yaml @@ -0,0 +1,10 @@ +description: Capital limit for working-age households under the Kingston upon Thames Council Tax Reduction scheme. +values: + 2026-04-01: 16_000 +metadata: + unit: currency-GBP + period: year + label: Kingston upon Thames Council Tax Reduction capital limit + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_step.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_step.yaml new file mode 100644 index 000000000..6e625e581 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_step.yaml @@ -0,0 +1,10 @@ +description: Capital step above which one pound of weekly tariff income is added for working-age non-Universal Credit claimants under the Kingston upon Thames Council Tax Reduction scheme. +values: + 2026-04-01: 250 +metadata: + unit: currency-GBP + period: week + label: Kingston upon Thames Council Tax Reduction tariff income step + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_threshold.yaml new file mode 100644 index 000000000..daccd5b4d --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/tariff_income_threshold.yaml @@ -0,0 +1,10 @@ +description: Capital threshold above which tariff income is added for working-age non-Universal Credit claimants under the Kingston upon Thames Council Tax Reduction scheme. +values: + 2026-04-01: 6_000 +metadata: + unit: currency-GBP + period: year + label: Kingston upon Thames Council Tax Reduction tariff income threshold + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/withdrawal_rate.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/withdrawal_rate.yaml new file mode 100644 index 000000000..22af07972 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/withdrawal_rate.yaml @@ -0,0 +1,10 @@ +description: Withdrawal rate for working-age households under the Kingston upon Thames Council Tax Reduction scheme. +values: + 2026-04-01: 0.2 +metadata: + unit: /1 + period: year + label: Kingston upon Thames Council Tax Reduction withdrawal rate + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/amount.yaml new file mode 100644 index 000000000..36f093ce2 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/amount.yaml @@ -0,0 +1,27 @@ +description: Weekly working-age non-dependant deduction schedule under the Kingston upon Thames Council Tax Reduction scheme. +brackets: + - threshold: + 2026-04-01: 0 + amount: + 2026-04-01: 5.64 + - threshold: + 2026-04-01: 279 + amount: + 2026-04-01: 11.50 + - threshold: + 2026-04-01: 485 + amount: + 2026-04-01: 14.43 + - threshold: + 2026-04-01: 605 + amount: + 2026-04-01: 17.31 +metadata: + amount_unit: currency-GBP + period: week + threshold_unit: currency-GBP + type: single_amount + label: Kingston upon Thames Council Tax Reduction non-dependant deduction schedule + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/remunerative_work_hours.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/remunerative_work_hours.yaml new file mode 100644 index 000000000..35954ed4a --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/non_dep_deduction/remunerative_work_hours.yaml @@ -0,0 +1,10 @@ +description: Weekly hours threshold for remunerative work in the Kingston upon Thames Council Tax Reduction non-dependant deduction schedule. +values: + 2026-04-01: 16 +metadata: + unit: hour + period: week + label: Kingston upon Thames Council Tax Reduction remunerative work hours + reference: + - title: Council Tax Reduction Scheme 2026 - 2027 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction.yaml index 11f0cd3c7..cf60fff6b 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction.yaml @@ -251,3 +251,159 @@ output: uc_assessable_capital: 0 council_tax_reduction: 1_800 + +- name: Kingston upon Thames working-age claimant can receive full support + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + benunits: + benunit: + members: [claimant] + would_claim_uc: false + claims_all_entitled_benefits: true + households: + household: + members: [claimant] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 0 + output: + council_tax_reduction_scheme_supported: true + simulated_council_tax_reduction_benunit: 1_800 + council_tax_reduction: 1_800 + council_tax_less_benefit: 0 + +- name: Kingston upon Thames working-age claimant above capital limit gets no local support + period: 2026 + absolute_error_margin: 0 + input: + people: + claimant: + age: 35 + council_tax_benefit_reported: 500 + benunits: + benunit: + members: [claimant] + claims_all_entitled_benefits: true + households: + household: + members: [claimant] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 16_001 + output: + council_tax_reduction_scheme_supported: true + simulated_council_tax_reduction_benunit: 0 + council_tax_benefit: 0 + council_tax_reduction: 0 + +- name: Kingston upon Thames adds one weekly pound of tariff income for any partial 250 pounds above 6,000 + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + benunits: + benunit: + members: [claimant] + would_claim_uc: false + claims_all_entitled_benefits: true + council_tax_reduction_applicable_amount: 0 + council_tax_reduction_applicable_income: 0 + households: + household: + members: [claimant] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 6_001 + output: + kingston_upon_thames_council_tax_reduction: 1_789.60 + council_tax_reduction: 1_789.60 + council_tax_less_benefit: 10.40 + +- name: Kingston upon Thames applies its 2026 local non-dependant deduction schedule + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + non_dep: + age: 25 + employment_income: 15_000 + weekly_hours: 16 + benunits: + claimant_benunit: + members: [claimant] + would_claim_uc: false + claims_all_entitled_benefits: true + non_dep_benunit: + members: [non_dep] + households: + household: + members: [claimant, non_dep] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 0 + output: + council_tax_reduction_scheme_supported: true + council_tax_reduction: 1_202 + +- name: Kingston upon Thames UC claimant uses UC maximum amount and DWP income + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + benunits: + claimant_benunit: + members: [claimant] + would_claim_uc: true + claims_all_entitled_benefits: true + uc_maximum_amount: 5_000 + uc_income_reduction: 2_500 + uc_earned_income: 6_000 + uc_unearned_income: 0 + households: + household: + members: [claimant] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 0 + output: + universal_credit: 2_500 + council_tax_reduction: 1_100 + +- name: Kingston upon Thames UC claimant uses UC-reported capital + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 35 + benunits: + claimant_benunit: + members: [claimant] + would_claim_uc: true + claims_all_entitled_benefits: true + uc_reported_capital: 0 + households: + household: + members: [claimant] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + council_tax: 1_800 + savings: 20_000 + output: + uc_assessable_capital: 0 + council_tax_reduction: 1_800 diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py index 33e0fff1c..54883e9b4 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py @@ -16,6 +16,7 @@ def legacy_council_tax_reduction( ctr, working_age, non_dep_deductions_variable, + additional_applicable_income=0, ): is_household_head_benunit = benunit("benunit_contains_household_head", period) would_claim = benunit("would_claim_council_tax_reduction", period) @@ -31,6 +32,7 @@ def legacy_council_tax_reduction( ) applicable_amount = where(has_uc_award, uc_applicable_amount, applicable_amount) applicable_income = where(has_uc_award, uc_applicable_income, applicable_income) + applicable_income += additional_applicable_income relevant_income_based_benefit = benunit( "council_tax_reduction_relevant_income_based_benefit", period, diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/config.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/config.py index 00f99f3b1..2df056b71 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/config.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/config.py @@ -23,10 +23,23 @@ def is_merton_working_age(local_authority, country, has_pensioner): return (country == Country.ENGLAND) & ~has_pensioner & is_merton(local_authority) +def is_kingston_upon_thames(local_authority): + return local_authority == LocalAuthority.KINGSTON_UPON_THAMES + + +def is_kingston_upon_thames_working_age(local_authority, country, has_pensioner): + return ( + (country == Country.ENGLAND) + & ~has_pensioner + & is_kingston_upon_thames(local_authority) + ) + + def is_supported_scheme(country, has_pensioner, local_authority): return ( is_england_pensioner_scheme(country, has_pensioner) | is_scotland_scheme(country) | is_wales_scheme(country) | is_merton_working_age(local_authority, country, has_pensioner) + | is_kingston_upon_thames_working_age(local_authority, country, has_pensioner) ) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/simulated_council_tax_reduction_benunit.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/simulated_council_tax_reduction_benunit.py index 4a025b43e..8c0c42b67 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/simulated_council_tax_reduction_benunit.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/simulated_council_tax_reduction_benunit.py @@ -5,7 +5,10 @@ is_wales_scheme, ) -LOCAL_COUNCIL_TAX_REDUCTION_VARIABLES = ["merton_council_tax_reduction"] +LOCAL_COUNCIL_TAX_REDUCTION_VARIABLES = [ + "merton_council_tax_reduction", + "kingston_upon_thames_council_tax_reduction", +] class simulated_council_tax_reduction_benunit(Variable): diff --git a/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py new file mode 100644 index 000000000..7f9b1b766 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py @@ -0,0 +1,45 @@ +from policyengine_uk.model_api import * +import numpy as np +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction._legacy import ( + legacy_council_tax_reduction, +) +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction.config import ( + is_kingston_upon_thames_working_age, +) + + +class kingston_upon_thames_council_tax_reduction(Variable): + value_type = float + entity = BenUnit + label = "Kingston upon Thames Council Tax Reduction" + definition_period = YEAR + unit = GBP + + def formula(benunit, period, parameters): + ctr = parameters( + period + ).gov.local_authorities.kingston_upon_thames.council_tax_reduction + household = benunit.household + working_age = is_kingston_upon_thames_working_age( + household("local_authority", period), + household("country", period), + household("council_tax_reduction_household_has_pensioner", period), + ) + has_uc_award = benunit("universal_credit", period) > 0 + capital = household("savings", period) + weekly_tariff_income = np.ceil( + max_(0, capital - ctr.means_test.tariff_income_threshold) + / ctr.means_test.tariff_income_step + ) + return legacy_council_tax_reduction( + benunit, + period, + ctr, + working_age, + "kingston_upon_thames_council_tax_reduction_non_dep_deductions", + additional_applicable_income=where( + has_uc_award, + 0, + weekly_tariff_income * WEEKS_IN_YEAR, + ), + ) diff --git a/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction.py b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction.py new file mode 100644 index 000000000..c8ae7f4df --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction.py @@ -0,0 +1,34 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction._legacy import ( + normal_gross_income_non_dep_deduction, +) +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction.config import ( + is_kingston_upon_thames_working_age, +) + + +class kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction(Variable): + value_type = float + entity = Person + label = "Kingston upon Thames CTR individual non-dependent deduction" + definition_period = YEAR + unit = GBP + defined_for = "council_tax_reduction_individual_non_dep_deduction_eligible" + + def formula(person, period, parameters): + ctr = parameters( + period + ).gov.local_authorities.kingston_upon_thames.council_tax_reduction + household = person.household + working_age = is_kingston_upon_thames_working_age( + household("local_authority", period), + household("country", period), + household("council_tax_reduction_household_has_pensioner", period), + ) + return normal_gross_income_non_dep_deduction( + person, + period, + ctr, + working_age, + exempt_uc_no_earned_income=True, + ) diff --git a/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_non_dep_deductions.py b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_non_dep_deductions.py new file mode 100644 index 000000000..96d4c8ce9 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction_non_dep_deductions.py @@ -0,0 +1,20 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction._legacy import ( + local_non_dep_deductions, +) + + +class kingston_upon_thames_council_tax_reduction_non_dep_deductions(Variable): + value_type = float + entity = BenUnit + label = "Kingston upon Thames CTR non-dependent deductions" + definition_period = YEAR + unit = GBP + + def formula(benunit, period, parameters): + return local_non_dep_deductions( + benunit, + period, + "kingston_upon_thames_council_tax_reduction_individual_non_dep_deduction", + one_deduction_for_uc_couples=False, + )