From 6dc62f0840e42b8c518fb96b8466b8d470ef3891 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 20:52:53 -0400 Subject: [PATCH 01/22] Add child amounts, family premium and tariff income to pensioner CTR The pension-age Council Tax Reduction applicable amount now adds an amount for each child or young person in the family (England SI 2012/2885 Sch 1 para 6(1)(b) and Sch 2 para 2, with the 2018-19 to 2024-25 two-child limit and its Child Tax Credit exception; Wales WSI 2013/3029 Sch 2 para 2; Scotland SSI 2012/319 reg 20(b) and Sch 1 para 3) and the family premium where the scheme still has one (Wales; England and Scotland to April 2016). General-rule income now counts tariff income from capital over 10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg 27(2)), reusing the pension-age Housing Benefit tariff parameters. Four existing YAML expectations move with the law: the 16,000 capital case gains 624 a year of tariff income, and three pensioner cases with a child or young person gain the child amount. Co-Authored-By: Claude Opus 5.5 --- changelog.d/1933.fixed.md | 1 + .../applicable_amount/child_limit.yaml | 24 + .../child_or_young_person.yaml | 65 +++ .../applicable_amount/family_premium.yaml | 26 + .../child_or_young_person.yaml | 67 +++ .../applicable_amount/family_premium.yaml | 24 + .../child_or_young_person.yaml | 56 ++ .../applicable_amount/family_premium.yaml | 47 ++ .../council_tax_reduction_pension_credit.yaml | 9 +- ...tax_reduction_pensioner_child_amounts.yaml | 514 ++++++++++++++++++ ...tax_reduction_pensioner_child_benefit.yaml | 13 +- ...tax_reduction_pensioner_tariff_income.yaml | 366 +++++++++++++ .../council_tax_reduction_young_person.yaml | 6 +- ...council_tax_reduction_applicable_amount.py | 22 +- ...council_tax_reduction_applicable_income.py | 12 +- ...l_tax_reduction_pensioner_child_amounts.py | 77 +++ ..._tax_reduction_pensioner_family_premium.py | 58 ++ ...l_tax_reduction_pensioner_tariff_income.py | 74 +++ 18 files changed, 1446 insertions(+), 15 deletions(-) create mode 100644 changelog.d/1933.fixed.md create mode 100644 policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_limit.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml create mode 100644 policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml create mode 100644 policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml create mode 100644 policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml create mode 100644 policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py create mode 100644 policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py create mode 100644 policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py diff --git a/changelog.d/1933.fixed.md b/changelog.d/1933.fixed.md new file mode 100644 index 0000000000..229263ff01 --- /dev/null +++ b/changelog.d/1933.fixed.md @@ -0,0 +1 @@ +Pension-age Council Tax Reduction in England, Scotland and Wales now adds an amount for each child or young person, and in Wales the family premium, to the applicable amount, and counts tariff income from capital over £10,000. diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_limit.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_limit.yaml new file mode 100644 index 0000000000..438ab70a80 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_limit.yaml @@ -0,0 +1,24 @@ +description: Number of children and young persons whose amounts the England Council Tax Reduction prescribed requirements include in a pensioner's applicable amount, unless a Child Tax Credit award includes more. The limit applied to schemes for the financial years 2018-19 to 2024-25. +values: + 2013-04-01: + value: .inf + reference: + - title: SI 2012/2885 Sch. 1 para. 6(1)(b) as made ("any child or young person") + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6/made + 2018-04-01: + value: 2 + reference: + - title: The Council Tax Reduction Schemes (Amendment) (England) Regulations 2017 (SI 2017/1305) regs. 1(3) and 7, substituting Sch. 1 para. 6(1)(b) and inserting para. 6(1A) to (1C) + href: https://www.legislation.gov.uk/uksi/2017/1305/made + 2025-04-01: + value: .inf + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) (Amendment) Regulations 2025 (SI 2025/39) regs. 1(3) and 5(2) + href: https://www.legislation.gov.uk/uksi/2025/39/made +metadata: + unit: child + period: year + label: England Council Tax Reduction pensioner child limit + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Sch. 1 para. 6, as in force on 30 April 2024 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6/2024-04-30 diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml new file mode 100644 index 0000000000..9cc8420714 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -0,0 +1,65 @@ +description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the England Council Tax Reduction prescribed requirements. The amounts equal the Housing Benefit pension-age child or young person amounts in every year from 2013-14 to 2026-27. +values: + # Each value is the paragraph 2 amount in the version of Schedule 2 in + # force on 30 April of that year. The prescribed requirements set it for + # schemes for the financial year from 1 April. + 2013-04-01: + value: 65.62 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2013 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2013-04-30 + 2014-04-01: + value: 66.33 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2014 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2014-04-30 + 2015-04-01: + value: 66.9 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2015 (unchanged to 2019-20) + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2015-04-30 + 2020-04-01: + value: 68.27 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2020 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2020-04-30 + 2021-04-01: + value: 68.6 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2021 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2021-04-30 + 2022-04-01: + value: 70.8 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2022 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2022-04-30 + 2023-04-01: + value: 77.78 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2023 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2023-04-30 + 2024-04-01: + value: 83.24 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2024 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2024-04-30 + 2025-04-01: + value: 84.66 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as in force on 30 April 2025 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2025-04-30 + 2026-04-01: + value: 87.88 + reference: + - title: SI 2012/2885 Sch. 2 para. 2, as amended by SI 2026/27 for schemes for 2026-27 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2026-04-30 +metadata: + unit: currency-GBP + period: week + label: England Council Tax Reduction pensioner child or young person amount + uprating: gov.benefit_uprating_cpi + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Sch. 1 para. 6(1)(b) and Sch. 2 para. 2 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2 + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 Sch. 3 para. 2 (the same amounts) + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/3 diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml new file mode 100644 index 0000000000..834da9e98e --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -0,0 +1,26 @@ +description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the England Council Tax Reduction prescribed requirements. It is nil for reduction weeks beginning after 1 May 2016. +values: + 2013-04-01: + value: 17.4 + reference: + - title: SI 2012/2885 Sch. 2 para. 3, as in force on 30 April 2013 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2013-04-30 + 2014-04-01: + value: 17.45 + reference: + - title: SI 2012/2885 Sch. 2 para. 3, as in force on 30 April 2014 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/2014-04-30 + # Reduction weeks begin on a Monday; the first after 1 May 2016 began on + # 2 May 2016. + 2016-05-02: + value: 0 + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) (Amendment) Regulations 2015 (SI 2015/2041) reg. 2(4)(b), substituting Sch. 2 para. 3 + href: https://www.legislation.gov.uk/uksi/2015/2041/regulation/2/made +metadata: + unit: currency-GBP + period: week + label: England Council Tax Reduction pensioner family premium + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Sch. 1 para. 6(1)(c) and Sch. 2 para. 3 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/2 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml new file mode 100644 index 0000000000..06ad77698c --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -0,0 +1,67 @@ +description: Weekly amount for each child or young person in the applicant's family in the applicable amount under the Scottish State Pension Credit Council Tax Reduction regulations. From 2017-18 it exceeds the Housing Benefit amount by about a quarter. +values: + # Each value is the paragraph 3 amount in the version of Schedule 1 in + # force on 30 April of that year. + 2013-04-01: + value: 65.62 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2013 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2013-04-30 + 2014-04-01: + value: 66.33 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2014 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2014-04-30 + 2015-04-01: + value: 66.9 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2015 (unchanged for 2016-17) + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2015-04-30 + 2017-04-01: + value: 83.63 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2017 (unchanged to 2019-20) + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2017-04-30 + 2020-04-01: + value: 85.34 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2020 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2020-04-30 + 2021-04-01: + value: 85.75 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2021 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2021-04-30 + 2022-04-01: + value: 88.5 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2022 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2022-04-30 + 2023-04-01: + value: 97.23 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2023 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2023-04-30 + 2024-04-01: + value: 104.05 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2024 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2024-04-30 + 2025-04-01: + value: 105.85 + reference: + - title: The Council Tax Reduction (Miscellaneous Amendment) (Scotland) Regulations 2025 (SSI 2025/24), amending SSI 2012/319 Sch. 1 para. 3 + href: https://www.legislation.gov.uk/ssi/2025/24/made + 2026-04-01: + value: 109.85 + reference: + - title: SSI 2012/319 Sch. 1 para. 3, as in force on 30 April 2026 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2026-04-30 +metadata: + unit: currency-GBP + period: week + label: Scotland Council Tax Reduction pensioner child or young person amount + uprating: gov.benefit_uprating_cpi + reference: + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 20(b) and Sch. 1 para. 3 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml new file mode 100644 index 0000000000..a272ef1e4b --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -0,0 +1,24 @@ +description: Weekly family premium in the applicable amount of an applicant whose family includes a child or young person, under the Scottish State Pension Credit Council Tax Reduction regulations. Scotland removed it from 1 May 2016. +values: + 2013-04-01: + value: 17.4 + reference: + - title: SSI 2012/319 Sch. 1 Part 2, as in force on 30 April 2013 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2013-04-30 + 2014-04-01: + value: 17.45 + reference: + - title: SSI 2012/319 Sch. 1 Part 2, as in force on 30 April 2014 + href: https://www.legislation.gov.uk/ssi/2012/319/schedule/1/2014-04-30 + 2016-05-01: + value: 0 + reference: + - title: The Council Tax Reduction (Scotland) Amendment Regulations 2016 (SSI 2016/81) regs. 1(3) and 18, omitting reg. 20(c) and Sch. 1 Part 2 + href: https://www.legislation.gov.uk/ssi/2016/81/made +metadata: + unit: currency-GBP + period: week + label: Scotland Council Tax Reduction pensioner family premium + reference: + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 20 + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/20 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml new file mode 100644 index 0000000000..ef7176b53e --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -0,0 +1,56 @@ +description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the Welsh Council Tax Reduction prescribed requirements. Wales did not raise it for 2020-21 or 2021-22, so it differs from the Housing Benefit amount in those years. +values: + # Each value is the paragraph 2 amount in the version of Schedule 2 in + # force on 30 April of that year. + 2013-04-01: + value: 64.99 + reference: + - title: WSI 2012/3144 Sch. 2 para. 2 (schemes for 2013-14), as in force on 30 April 2013 + href: https://www.legislation.gov.uk/wsi/2012/3144/schedule/2/2013-04-30 + 2014-04-01: + value: 66.33 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as amended by WSI 2014/66 for schemes for 2014-15 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2014-04-30 + 2015-04-01: + value: 66.9 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2015 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2015-04-30 + - title: The Council Tax Reduction Schemes (Prescribed Requirements and Default Scheme) (Wales) (Amendment) Regulations 2020 (WSI 2020/16) reg. 8, which leaves para. 2 unchanged for 2020-21 + href: https://www.legislation.gov.uk/wsi/2020/16/made + - title: The Council Tax Reduction Schemes (Prescribed Requirements and Default Scheme) (Wales) (Amendment) Regulations 2021 (WSI 2021/34) reg. 5, which leaves para. 2 unchanged for 2021-22 + href: https://www.legislation.gov.uk/wsi/2021/34/made + 2022-04-01: + value: 70.8 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2022 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2022-04-30 + 2023-04-01: + value: 77.78 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2023 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2023-04-30 + 2024-04-01: + value: 83.24 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2024 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2024-04-30 + 2025-04-01: + value: 84.66 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2025 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2025-04-30 + 2026-04-01: + value: 87.88 + reference: + - title: WSI 2013/3029 Sch. 2 para. 2, as in force on 30 April 2026 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2026-04-30 +metadata: + unit: currency-GBP + period: week + label: Wales Council Tax Reduction pensioner child or young person amount + uprating: gov.benefit_uprating_cpi + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Sch. 1 para. 1(1)(b) and Sch. 2 para. 2 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml new file mode 100644 index 0000000000..f25c0da6bf --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -0,0 +1,47 @@ +description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the Welsh Council Tax Reduction prescribed requirements. Wales kept the premium after England and Scotland removed it in 2016. +values: + 2013-04-01: + value: 17.4 + reference: + - title: WSI 2012/3144 Sch. 2 para. 3 (schemes for 2013-14), as in force on 30 April 2013 + href: https://www.legislation.gov.uk/wsi/2012/3144/schedule/2/2013-04-30 + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2014 (unchanged for 2014-15) + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2014-04-30 + 2015-04-01: + value: 17.45 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2015 (unchanged to 2021-22; WSI 2020/16 reg. 8 and WSI 2021/34 reg. 5 leave it unchanged) + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2015-04-30 + 2022-04-01: + value: 17.85 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2022 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2022-04-30 + 2023-04-01: + value: 18.53 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2023 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2023-04-30 + 2024-04-01: + value: 19.15 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2024 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2024-04-30 + 2025-04-01: + value: 19.48 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2025 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2025-04-30 + 2026-04-01: + value: 20.22 + reference: + - title: WSI 2013/3029 Sch. 2 para. 3, as in force on 30 April 2026 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/2026-04-30 +metadata: + unit: currency-GBP + period: week + label: Wales Council Tax Reduction pensioner family premium + uprating: gov.benefit_uprating_cpi + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Sch. 1 para. 1(1)(c) and Sch. 2 para. 3 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/2 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml index 88c83a064e..a76d56450d 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml @@ -537,12 +537,13 @@ savings: 16_000 output: # The limit excludes capital that "exceeds" 16,000 (SI 2012/2885 reg 11(2)). - # The award pins the model's current value: it has no pensioner tariff - # income from capital (Sch 1 para 37, 624 a year here), a known gap - # (#1933), so this is not the full legal amount. + # Tariff income (Sch 1 para 37): (16,000 - 10,000) / 500 = 12 a week, or + # 624 a year. Income: 13,000 - 86 income tax + 624 = 13,538, so the + # award is 2,000 - 0.2 * (13,538 - 13,312) = 1,954.80. in_receipt_of_guarantee_credit: false council_tax_reduction_assessable_capital: 16_000 - council_tax_reduction: 2_000 + council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction: 1_954.80 - name: Capital just over 16,000 excludes a pensioner without Pension Credit period: 2026 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml new file mode 100644 index 0000000000..124e919b09 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -0,0 +1,514 @@ +# A pensioner's Council Tax Reduction applicable amount includes an amount for +# each child or young person in the family and, where the scheme still has one, +# a family premium: +# +# - England: SI 2012/2885 Sch 1 para 6(1)(b) and (c), Sch 2 paras 2 and 3. +# 2026-27 child or young person amount 87.88 a week (SI 2026/27); the family +# premium is nil for reduction weeks beginning after 1 May 2016. From +# 2018-19 to 2024-25 para 6(1)(b) counted up to two children or young +# persons, or those an award of Child Tax Credit included if more (SI +# 2017/1305 reg 7; removed by SI 2025/39 reg 5(2)). +# - Wales: WSI 2013/3029 Sch 1 para 1(1)(b) and (c), Sch 2 paras 2 and 3. +# 2026-27 amounts 87.88 and a family premium of 20.22. +# - Scotland: SSI 2012/319 reg 20(b), Sch 1 para 3. 2026-27 amount 109.85; +# the family premium was removed from 1 May 2016 (SSI 2016/81 reg 18). +# +# Each amount runs from birth to the day before the 20th birthday, for a +# Child Benefit qualifying young person. Every person aged 72 or 80 here +# reached State Pension age before 1 April 2021, so the single or lone parent +# personal allowance is 256.00 a week and the couple allowance 383.35 (SI +# 2012/2885 Sch 2 para 1; WSI 2013/3029 Sch 2 para 1; SSI 2012/319 Sch 1 +# para 2). Annual amounts are 52 weeks. + +- name: Case 1, an English 72-year-old alone gets the personal allowance only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner: true + council_tax_reduction_pensioner_child_amounts: 0 + council_tax_reduction_pensioner_family_premium: 0 + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: Case 2, an English 72-year-old with a ten-year-old gets the child amount but no family premium. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner: true + is_child_or_young_person_for_council_tax_reduction: [false, true] + # 87.88 * 52 = 4,569.76. + council_tax_reduction_pensioner_child_amounts: 4_569.76 + council_tax_reduction_pensioner_family_premium: 0 + # 13,312 + 4,569.76. + council_tax_reduction_applicable_amount: 17_881.76 + +- name: Case 3, an English 72-year-old with a 17-year-old at school gets the young person's amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + student: + age: 17 + current_education: UPPER_SECONDARY + age_started_or_accepted_current_education_or_training: 16 + benunits: + benunit: + members: [pensioner, student] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, student] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + is_qualifying_young_person_for_child_benefit: [false, true] + is_child_or_young_person_for_council_tax_reduction: [false, true] + council_tax_reduction_pensioner_child_amounts: 87.88 * 52 + council_tax_reduction_applicable_amount: (256.00 + 87.88) * 52 + +- name: Case 4, a Scottish 72-year-old alone gets the personal allowance only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner_child_amounts: 0 + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: Case 5, a Scottish 72-year-old with a ten-year-old gets Scotland's higher child amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 0 + output: + # 109.85 * 52 = 5,712.20; no family premium. + council_tax_reduction_pensioner_child_amounts: 5_712.20 + council_tax_reduction_pensioner_family_premium: 0 + # 13,312 + 5,712.20. + council_tax_reduction_applicable_amount: 19_024.20 + +- name: Case 6, a Welsh 72-year-old alone gets the personal allowance only. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner_child_amounts: 0 + council_tax_reduction_pensioner_family_premium: 0 + council_tax_reduction_applicable_amount: 256.00 * 52 + +- name: Case 7, a Welsh 72-year-old with a ten-year-old gets the child amount and the family premium. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 0 + output: + # 87.88 * 52 = 4,569.76. + council_tax_reduction_pensioner_child_amounts: 4_569.76 + # 20.22 * 52 = 1,051.44. + council_tax_reduction_pensioner_family_premium: 1_051.44 + # 13,312 + 4,569.76 + 1,051.44. + council_tax_reduction_applicable_amount: 18_933.20 + +- name: Case 8, an English pensioner couple with two children get two child amounts. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + older: + age: 74 + state_pension: 12_000 + younger: + age: 72 + state_pension: 9_000 + child_1: + age: 8 + child_2: + age: 12 + benunits: + benunit: + members: [older, younger, child_1, child_2] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [older, younger, child_1, child_2] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # 2 * 87.88 * 52 = 9,139.52. + council_tax_reduction_pensioner_child_amounts: 9_139.52 + # (383.35 + 2 * 87.88) * 52 = 19,934.20 + 9,139.52. + council_tax_reduction_applicable_amount: 29_073.72 + +- name: Case 9, England's 2024-25 scheme counts two of three children without a Child Tax Credit award. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child_1: + age: 5 + child_2: + age: 7 + child_3: + age: 9 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + would_claim_CTC: false + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # SI 2012/2885 Sch 1 para 6(1)(b) as in force for 2024-25: up to two. + # 2 * 83.24 * 52 = 8,656.96. + council_tax_reduction_pensioner_child_amounts: 8_656.96 + +- name: Case 10, England's 2024-25 scheme counts all three where Child Tax Credit includes all three. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child_1: + age: 5 + is_CTC_child_element_included: true + child_2: + age: 7 + is_CTC_child_element_included: true + child_3: + age: 9 + is_CTC_child_element_included: true + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + would_claim_CTC: true + is_CTC_eligible: true + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # Para 6(1B) and (1C): the award includes the individual element for + # three, which is more than two. 3 * 83.24 * 52 = 12,985.44. + council_tax_reduction_pensioner_child_amounts: 12_985.44 + +- name: Case 11, England's 2025-26 scheme counts every child. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child_1: + age: 5 + child_2: + age: 7 + child_3: + age: 9 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # SI 2025/39 reg 5(2) removed the limit. 3 * 84.66 * 52 = 13,206.96. + council_tax_reduction_pensioner_child_amounts: 13_206.96 + +- name: Case 12, Scotland has no two-child limit in 2024-25. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child_1: + age: 5 + child_2: + age: 7 + child_3: + age: 9 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 0 + output: + # SSI 2012/319 reg 20(b): any child or young person. 3 * 104.05 * 52. + council_tax_reduction_pensioner_child_amounts: 16_231.80 + +- name: Case 13, Wales kept its 2019-20 child amount and family premium in 2021-22. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 0 + output: + # WSI 2021/34 reg 5 leaves Sch 2 paras 2 and 3 at 66.90 and 17.45. + council_tax_reduction_pensioner_child_amounts: 66.90 * 52 + council_tax_reduction_pensioner_family_premium: 17.45 * 52 + +- name: Case 14, England's 2021-22 child amount follows the 2021 amending regulations. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner_child_amounts: 68.60 * 52 + council_tax_reduction_pensioner_family_premium: 0 + +- name: Case 15, England's 2015-16 scheme still had the family premium. + period: 2015 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + child: + age: 10 + benunits: + benunit: + members: [pensioner, child] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner_child_amounts: 66.90 * 52 + council_tax_reduction_pensioner_family_premium: 17.45 * 52 + +- name: Case 16, a pensioner household head who applies alone has no children in her family. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + grandmother: + age: 80 + is_household_head: true + mother: + age: 45 + is_parent: true + is_household_head: false + father: + age: 46 + is_parent: true + is_household_head: false + child: + age: 10 + is_household_head: false + benunits: + family: + members: [grandmother, mother, father, child] + would_claim_uc: false + would_claim_pc: false + households: + home: + members: [grandmother, mother, father, child] + country: WALES + local_authority: CARDIFF + council_tax: 1_800 + savings: 0 + output: + council_tax_reduction_head_applies_alone: true + council_tax_reduction_pensioner: true + council_tax_reduction_pensioner_child_amounts: 0 + council_tax_reduction_pensioner_family_premium: 0 + +- name: Case 17, a working-age Welsh parent's applicable amount is unchanged. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + employment_income: 15_000 + child: + age: 7 + benunits: + benunit: + members: [parent, child] + would_claim_uc: false + households: + household: + members: [parent, child] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_pensioner: false + council_tax_reduction_pensioner_child_amounts: 0 + council_tax_reduction_pensioner_family_premium: 0 + # Lone parent aged 18 or over, 95.55 * 52, as before. + council_tax_reduction_applicable_amount: 4_968.60 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml index dedf76043f..07f997b5c8 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml @@ -1,6 +1,8 @@ # Current GB pensioner income exclusions: England Sch1 para16(1)(j)(vi), # Wales Sch1 para10(1)(j)(vi), Scotland reg27(1)(j)(vii). # Model2026: eldest Child Benefit27.05*52=1406.60; aged allowance256*52=13312. +# An English pensioner's applicable amount adds 87.88*52=4569.76 for the +# child (SI 2012/2885 Sch 1 para 6(1)(b) and Sch 2 para 2). # These genuine claim/takeup inputs use the general rules, not PC overrides. - name: England pensioner Child Benefit is excluded before the CTR taper # Aged 72: State Pension age was reached in 2019, before 1 April 2021, so @@ -31,10 +33,11 @@ in_receipt_of_guarantee_credit: false in_receipt_of_savings_credit_only: false council_tax_reduction_applicable_income: 15314 - council_tax_reduction_applicable_amount: 13312 - # 3000 - .2*(16000 - 686 - 13312) = 2599.60. - council_tax_benefit: 2599.60 - council_tax_reduction: 2599.60 + # 13312 + 4569.76 for the child. + council_tax_reduction_applicable_amount: 17881.76 + # 16000 - 686 = 15314 is below 17881.76, so the award is the whole 3000. + council_tax_benefit: 3000 + council_tax_reduction: 3000 - name: Scottish pensioner Child Benefit does not reduce the final CTR award period: 2026 @@ -110,7 +113,7 @@ output: child_benefit: 0 council_tax_reduction_applicable_income: 15314 - council_tax_reduction: 2599.60 + council_tax_reduction: 3000 - name: Excluding pensioner Child Benefit retains the zero floor and liability cap period: 2026 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml new file mode 100644 index 0000000000..adabd260e6 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml @@ -0,0 +1,366 @@ +# Pensioner tariff income from capital. A pensioner's capital counts as a +# weekly income of £1 for each £500 over £10,000, and £1 for any part of £500: +# England SI 2012/2885 Sch 1 para 37 and Wales WSI 2013/3029 Sch 1 para 31 +# (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2). Capital +# over £16,000 ends entitlement (SI 2012/2885 reg 11(2); WSI 2013/3029 reg +# 30; SSI 2012/319 reg 40). A guarantee credit recipient's whole capital and +# income are disregarded (Sch 1 para 13; Sch 1 para 7; reg 24), and on a +# savings-credit-only award the Secretary of State's assessment of income is +# used (Sch 1 para 14; Sch 1 para 8; reg 25). +# +# Each 72-year-old reached State Pension age before 1 April 2021, so the +# applicable amount is 256.00 * 52 = 13,312. A State Pension of 12,570 is +# within the personal allowance, so it bears no income tax. The council tax is +# 2,000 and the pensioner schemes withdraw 20% of income above the applicable +# amount. + +- name: Case 1, England, capital of 10,000 gives no tariff income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 10_000 + output: + council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_applicable_income: 12_570 + +- name: Case 2, England, capital of 10,001 gives 1 a week for the part of 500. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 10_001 + output: + council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_applicable_income: 12_570 + 52 + +- name: Case 3, England, capital of 16,000 gives 12 a week. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 16_000 + output: + # (16,000 - 10,000) / 500 = 12; 12 * 52 = 624. + council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_applicable_income: 13_194 + # 13,194 is below 13,312, so the whole council tax. + council_tax_reduction: 2_000 + +- name: Case 4, Scotland, capital of 10,000 gives no tariff income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 10_000 + output: + council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_applicable_income: 12_570 + +- name: Case 5, Scotland, capital of 10,001 gives 1 a week for the part of 500. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 10_001 + output: + council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_applicable_income: 12_570 + 52 + +- name: Case 6, Scotland, capital of 16,000 gives 12 a week. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 16_000 + output: + council_tax_reduction_pensioner_tariff_income: 12 * 52 + council_tax_reduction_applicable_income: 12_570 + 12 * 52 + council_tax_reduction: 2_000 + +- name: Case 7, Wales, capital of 10,000 gives no tariff income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 10_000 + output: + council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_applicable_income: 12_570 + +- name: Case 8, Wales, capital of 10,001 gives 1 a week for the part of 500. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 10_001 + output: + council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_applicable_income: 12_570 + 52 + +- name: Case 9, Wales, capital of 16,000 gives 12 a week. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 16_000 + output: + council_tax_reduction_pensioner_tariff_income: 12 * 52 + council_tax_reduction_applicable_income: 12_570 + 12 * 52 + council_tax_reduction: 2_000 + +- name: Case 10, England, tariff income reduces an award above the applicable amount. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 15_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 16_000 + output: + # Income tax: (15,000 - 12,570) * 0.2 = 486. Income 15,000 - 486 + 624 + # = 15,138. Award 2,000 - 0.2 * (15,138 - 13,312) = 1,634.80. + council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_applicable_income: 15_138 + council_tax_reduction: 1_634.80 + +- name: Case 11, England, capital over 16,000 ends entitlement and the tariff stops at 16,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 20_000 + output: + council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction: 0 + +- name: Case 12, a guarantee credit recipient's capital is wholly disregarded. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 8_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: true + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 16_000 + output: + in_receipt_of_guarantee_credit: true + council_tax_reduction_assessable_capital: 0 + council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_applicable_income: 0 + council_tax_reduction: 2_000 + +- name: Case 13, a savings-credit-only award uses the Pension Credit assessment, with no tariff income on top. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 90 + state_pension: 12_000 + private_pension_income: 1_500 + benunits: + benunit: + members: [pensioner] + claims_all_entitled_benefits: true + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + savings: 16_000 + output: + # The same as the savings-credit-only case at 16,000 in + # council_tax_reduction_pension_credit.yaml: the Secretary of State's + # income already counts Pension Credit's deemed income from capital. + in_receipt_of_savings_credit_only: true + council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_applicable_income: 14_247.02 + +- name: Case 14, a working-age Welsh earner's capital gives no tariff income here. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + earner: + age: 40 + employment_income: 15_000 + benunits: + benunit: + members: [earner] + would_claim_uc: false + households: + household: + members: [earner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 12_000 + output: + council_tax_reduction_pensioner: false + council_tax_reduction_pensioner_tariff_income: 0 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml index 1abdbeba87..dc509f3b49 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml @@ -181,8 +181,10 @@ is_qualifying_young_person_for_universal_credit: [false, false] is_child_or_young_person_for_council_tax_reduction: [false, true] is_council_tax_reduction_lone_parent: true - # Lone parent of pension age: 256.00 * 52. - council_tax_reduction_applicable_amount: 13_312 + # Lone parent of pension age, 256.00 * 52 = 13,312, plus the young + # person's amount (SSI 2012/319 reg 20(b) and Sch 1 para 3), 109.85 * 52 + # = 5,712.20. + council_tax_reduction_applicable_amount: 19_024.20 - name: Case 6, Scotland's working-age scheme used the Child Benefit young person in 2021-22. period: 2021 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 27d9323edb..53447ffc96 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 @@ -13,14 +13,20 @@ class council_tax_reduction_applicable_amount(Variable): "Where the household head applies alone " "(council_tax_reduction_head_applies_alone), the head is a single " "person with no partner or children, whatever the benefit unit's " - "claimant and partner are. Premiums are council_tax_reduction_premiums." + "claimant and partner are. Premiums are council_tax_reduction_premiums. " + "A pensioner's applicable amount also has the amounts for the " + "children and young persons in the family " + "(council_tax_reduction_pensioner_child_amounts) and the family " + "premium (council_tax_reduction_pensioner_family_premium)." ) definition_period = YEAR unit = GBP reference = ( "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6", "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/1", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/20", "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", @@ -97,4 +103,16 @@ def formula(benunit, period, parameters): # The pension-age schedules have only the severe disability and carer # premiums; the same pensioner test chooses the schedule. premiums = benunit("council_tax_reduction_premiums", period) - return personal_allowance + premiums + # A pensioner's amounts for the children and young persons in the + # family and the family premium (SI 2012/2885 Sch 1 para 6(1)(b)-(c); + # WSI 2013/3029 Sch 1 para 1(1)(b)-(c); SSI 2012/319 reg 20(b)). + # Working-age families get neither here. + child_amounts = add( + benunit, + period, + [ + "council_tax_reduction_pensioner_child_amounts", + "council_tax_reduction_pensioner_family_premium", + ], + ) + return personal_allowance + premiums + child_amounts diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py index e1494e88cb..998cdb4e07 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py @@ -13,7 +13,9 @@ class council_tax_reduction_applicable_income(Variable): "use the Secretary of State's Pension Credit assessment of income, plus " "the savings credit payable, where the award is savings credit only. " "Otherwise a pension-age family's net earnings are reduced by the " - "pensioner earnings disregards. Great Britain's pensioner schemes " + "pensioner earnings disregards and its tariff income from capital " + "(council_tax_reduction_pensioner_tariff_income) is added. Great " + "Britain's pensioner schemes " "also exclude Child Benefit from general-rule income; statutory sick " "and maternity pay remain counted as earnings. The other adjustments those " "provisions allow (childcare charges, the £20 earnings disregards " @@ -46,6 +48,9 @@ class council_tax_reduction_applicable_income(Variable): "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/13", "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/14", "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/16", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/27", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/7", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/8", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/10", @@ -298,9 +303,12 @@ def formula(benunit, period, parameters): earnings_disregard = benunit( "council_tax_reduction_pensioner_earnings_disregard", period ) + # SI 2012/2885 Sch 1 para 37, WSI 2013/3029 Sch 1 para 31 and SSI + # 2012/319 reg 27(2): a pensioner's tariff income from capital, a + # separate source that the deductions above do not reduce. income_under_general_rules = max_( 0, increased_income - tax - pension_contributions - earnings_disregard - ) + ) + benunit("council_tax_reduction_pensioner_tariff_income", period) # SI 2012/2885 Sch 1 para 13, WSI 2013/3029 Sch 1 para 7 and SSI # 2012/319 reg 24: a guarantee credit recipient's whole income is # disregarded. Para 14, para 8 and reg 25: in savings-credit-only cases diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py new file mode 100644 index 0000000000..de4dfe85b6 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -0,0 +1,77 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.household.demographic.country import Country + + +class council_tax_reduction_pensioner_child_amounts(Variable): + value_type = float + entity = BenUnit + label = "Council Tax Reduction pensioner child or young person amounts" + documentation = ( + "The amounts for the children and young persons in a pensioner's " + "family in the Council Tax Reduction applicable amount, one weekly " + "amount for each. England's prescribed requirements limited them to " + "two children or young persons for the 2018-19 to 2024-25 schemes, " + "unless the applicant's Child Tax Credit award included the " + "individual element for more of them. The transitional protection " + "for families with more than two on 31 March 2018 is not modelled. " + "Nil where the household head applies alone " + "(council_tax_reduction_head_applies_alone), since the head's family " + "then has no children, and for working-age families, whose child " + "amounts are not modelled." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/2", + "https://www.legislation.gov.uk/uksi/2017/1305/regulation/7/made", + "https://www.legislation.gov.uk/uksi/2017/1305/regulation/17/made", + "https://www.legislation.gov.uk/uksi/2025/39/regulation/5/made", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/1", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/2", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/20", + "https://www.legislation.gov.uk/ssi/2012/319/schedule/1/paragraph/3", + ) + + def formula(benunit, period, parameters): + local_authorities = parameters(period).gov.local_authorities + england = local_authorities.england.council_tax_reduction.pensioners + wales = local_authorities.wales.council_tax_reduction.pensioners + scotland = local_authorities.scotland.council_tax_reduction.pensioners + country = benunit.household("country", period) + in_england = country == Country.ENGLAND + person = benunit.members + child = person("is_child_or_young_person_for_council_tax_reduction", period) + children = benunit.sum(child) + counted = children + limit = england.applicable_amount.child_limit + if np.isfinite(limit): + # SI 2012/2885 Sch 1 para 6(1)(b) and (1A) to (1C), from SI + # 2017/1305 reg 7: up to two, or those whose individual element + # an award of Child Tax Credit includes where that gives more. + # Every child or young person has the same amount, so the + # greatest total is the greatest count. + child_tax_credit_award = benunit("would_claim_CTC", period) & benunit( + "is_CTC_eligible", period + ) + child_tax_credit_children = benunit.sum( + child & person("is_CTC_child_element_included", period) + ) + limited = min_(children, limit) + counted = where( + in_england & child_tax_credit_award, + max_(limited, child_tax_credit_children), + where(in_england, limited, children), + ) + weekly_amount = select( + [in_england, country == Country.WALES, country == Country.SCOTLAND], + [ + england.applicable_amount.child_or_young_person, + wales.applicable_amount.child_or_young_person, + scotland.applicable_amount.child_or_young_person, + ], + default=0, + ) + pensioner = benunit("council_tax_reduction_pensioner", period) + applicant_family = ~benunit("council_tax_reduction_head_applies_alone", period) + return pensioner * applicant_family * counted * weekly_amount * WEEKS_IN_YEAR diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py new file mode 100644 index 0000000000..14fd069b8a --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py @@ -0,0 +1,58 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.household.demographic.country import Country + + +class council_tax_reduction_pensioner_family_premium(Variable): + value_type = float + entity = BenUnit + label = "Council Tax Reduction pensioner family premium" + documentation = ( + "The family premium in a pensioner's Council Tax Reduction applicable " + "amount, where the family includes a child or young person. Wales " + "keeps it. England's prescribed requirements make it nil for " + "reduction weeks beginning after 1 May 2016, and Scotland removed it " + "from 1 May 2016. Each saved it for families with a child who had a " + "reduction on 30 April 2016 until they make a new application or " + "have no child; that protection is not modelled. The model reads " + "each year's amount on 30 April, so 2016-17 keeps the premium." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/3", + "https://www.legislation.gov.uk/uksi/2015/2041/regulation/3/made", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/1", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/3", + "https://www.legislation.gov.uk/ssi/2016/81/regulation/2/made", + "https://www.legislation.gov.uk/ssi/2016/81/regulation/18/made", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/20", + ) + + def formula(benunit, period, parameters): + local_authorities = parameters(period).gov.local_authorities + england = local_authorities.england.council_tax_reduction.pensioners + wales = local_authorities.wales.council_tax_reduction.pensioners + scotland = local_authorities.scotland.council_tax_reduction.pensioners + country = benunit.household("country", period) + weekly_premium = select( + [ + country == Country.ENGLAND, + country == Country.WALES, + country == Country.SCOTLAND, + ], + [ + england.applicable_amount.family_premium, + wales.applicable_amount.family_premium, + scotland.applicable_amount.family_premium, + ], + default=0, + ) + pensioner = benunit("council_tax_reduction_pensioner", period) + # The head who applies alone has no children in their family. + has_child = ~benunit( + "council_tax_reduction_head_applies_alone", period + ) & benunit( + "is_responsible_for_child_or_young_person_for_council_tax_reduction", period + ) + return pensioner * has_child * weekly_premium * WEEKS_IN_YEAR diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py new file mode 100644 index 0000000000..b7e8ccc9bb --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -0,0 +1,74 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.household.demographic.country import Country + + +class council_tax_reduction_pensioner_tariff_income(Variable): + value_type = float + entity = BenUnit + label = "Council Tax Reduction pensioner tariff income from capital" + documentation = ( + "Weekly income the pensioner Council Tax Reduction schemes treat " + "capital as yielding, annualised: £1 for each £500, or part of £500, " + "of council_tax_reduction_assessable_capital above £10,000, up to the " + "£16,000 capital limit. England, Wales and Scotland use the " + "pension-age Housing Benefit amounts. Nil where Pension Credit sets " + "the means test: the guarantee credit disregards the whole of the " + "capital, and on a savings-credit-only award the Secretary of " + "State's assessment of income already includes Pension Credit's " + "deemed income from capital. Nil for working-age families, whose " + "tariff income is not modelled." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/13", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/14", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/7", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/8", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/27", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/24", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/25", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/29", + ) + + def formula(benunit, period, parameters): + tariff = parameters( + period + ).gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income + local_authorities = parameters(period).gov.local_authorities + country = benunit.household("country", period) + capital_limit = select( + [ + country == Country.ENGLAND, + country == Country.WALES, + country == Country.SCOTLAND, + ], + [ + local_authorities.england.council_tax_reduction.pensioners.means_test.capital_limit, + local_authorities.wales.council_tax_reduction.means_test.capital_limit, + local_authorities.scotland.council_tax_reduction.means_test.capital_limit, + ], + default=0, + ) + capital = benunit("council_tax_reduction_assessable_capital", period) + # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count + # the excess "not exceeding £16,000"; above it there is no reduction. + excess_capital = max_(0, min_(capital, capital_limit) - tariff.threshold) + weekly_tariff_income = np.ceil(excess_capital / tariff.step) * tariff.amount + # The Pension Credit routes (England Sch 1 paras 13 and 14, Wales + # Sch 1 paras 7 and 8, Scotland regs 24 and 25), as in + # council_tax_reduction_applicable_income. The benefit unit's + # Pension Credit is its claimant's and partner's. + applicant_family = ~benunit("council_tax_reduction_head_applies_alone", period) + pension_credit_route = applicant_family & ( + benunit("in_receipt_of_guarantee_credit", period) + | benunit("in_receipt_of_savings_credit_only", period) + ) + pensioner = benunit("council_tax_reduction_pensioner", period) + return where( + pensioner & ~pension_credit_route, + weekly_tariff_income * WEEKS_IN_YEAR, + 0, + ) From 432b76c87f053246f98eec5ed86cd1a579786505 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 22:00:39 -0400 Subject: [PATCH 02/22] Add property and differential tests for pensioner CTR children and tariff The new property tests check that tariff income is the statutory tariff and never falls as capital rises, that adding a dependent child never lowers the applicable amount, and that pensioners with no child and capital up to 10,000 and every working-age family get none of the new amounts. A frozen differential checks those households against values computed on origin/main at 2da212abc. Two existing property tests move with the law: the Child Benefit test's State Pension range rises so its award stays interior above an applicable amount that now includes the children, and the Pension Credit test's recomputed general-rules income adds the statutory tariff income. Wales's 2013-14 child amount is 65.62, set by WSI 2013/112 reg 5(b). Co-Authored-By: Claude Opus 5.5 --- .../child_or_young_person.yaml | 8 +- ..._tax_reduction_child_benefit_properties.py | 5 +- ...tax_reduction_pension_credit_properties.py | 19 +- ...on_pensioner_children_tariff_properties.py | 394 ++++++++++++++++++ 4 files changed, 419 insertions(+), 7 deletions(-) create mode 100644 policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml index ef7176b53e..7761946ec2 100644 --- a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -1,12 +1,12 @@ description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the Welsh Council Tax Reduction prescribed requirements. Wales did not raise it for 2020-21 or 2021-22, so it differs from the Housing Benefit amount in those years. values: # Each value is the paragraph 2 amount in the version of Schedule 2 in - # force on 30 April of that year. + # force on 30 April of that year, with the amending regulations it reflects. 2013-04-01: - value: 64.99 + value: 65.62 reference: - - title: WSI 2012/3144 Sch. 2 para. 2 (schemes for 2013-14), as in force on 30 April 2013 - href: https://www.legislation.gov.uk/wsi/2012/3144/schedule/2/2013-04-30 + - title: The Council Tax Reduction Schemes (Prescribed Requirements and Default Scheme) (Wales) (Amendment) Regulations 2013 (WSI 2013/112) reg. 5(b), amending WSI 2012/3144 Sch. 2 para. 2 for schemes for 2013-14 + href: https://www.legislation.gov.uk/wsi/2013/112/made 2014-04-01: value: 66.33 reference: diff --git a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py index b041c55dca..d3e982b309 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py @@ -79,7 +79,10 @@ def calculate(data, claim, status_first=False): @settings(max_examples=4, deadline=None, derandomize=True) @given( st.sampled_from(sorted(COUNTRIES)), - st.integers(15000, 19000), + # Income after tax exceeds the applicable amount, which includes the + # children's amounts (up to 2 * 109.85 * 52 in Scotland), so the award + # is interior and below the 35,000 Winter Fuel Payment charge threshold. + st.integers(30000, 34000), st.integers(1, 2), st.booleans(), ) diff --git a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py index 8f1c6c793b..10b7891b2a 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py @@ -24,8 +24,9 @@ 4. Differential: everyone else keeps the previous formula, max(0, L - 0.2 x max(0, I - A) - ND) when household savings are within 16,000, where I is the income definition on main before this change less pensioners' Child Benefit - and the schemes' pensioner earnings disregard, recomputed here (income from its components, - the disregard from the statutory sums) rather than read from the variables + and the schemes' pensioner earnings disregard, plus pensioners' tariff income + from capital, recomputed here (income from its components, the disregard and + the tariff from the statutory sums) rather than read from the variables under test. 5. Metamorphic: a guarantee credit recipient's CTR does not change when the State Pension changes. @@ -294,6 +295,13 @@ def situation( # 2013/3029 Sch 3; SSI 2012/319 Sch 2). PENSIONER_FLAT_DISREGARD = {"lone_parent": 25, "couple": 10, "single": 5} PENSIONER_ADDITIONAL_DISREGARD = 17.10 +# Since #1933, a pensioner family's general-rules income also adds tariff +# income from capital after the floor, written out from the law: £1 a week +# for each £500, or part of £500, of capital above £10,000 and up to £16,000 +# (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg +# 27(2)). Household savings are these families' capital. +TARIFF_THRESHOLD = 10_000 +TARIFF_STEP = 500 HOUSEHOLD_VARIABLES = [ "council_tax_reduction_maximum_eligible_liability", "savings", @@ -373,6 +381,13 @@ def benunit_total(names): - 0.5 * benunit_total(["pension_contributions"]) - pensioner_earnings_disregard(sim, claimants), ) + tariff_steps = np.ceil( + np.maximum(0, np.minimum(values["savings"], CAPITAL_LIMIT) - TARIFF_THRESHOLD) + / TARIFF_STEP + ) + values["income_under_main_definition"] += np.where( + values["council_tax_reduction_pensioner"], 52 * tariff_steps, 0 + ) # Each claim's scheme follows its own family's pensioner status. values["national"] = np.array( [ diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py new file mode 100644 index 0000000000..af3f44b18e --- /dev/null +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -0,0 +1,394 @@ +"""A pensioner's Council Tax Reduction child amounts and tariff income. + +The pensioner schemes add an amount for each child or young person in the +family and, in Wales, a family premium (SI 2012/2885 Sch 1 para 6(1)(b)-(c) +and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch 2 paras +2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). England counted at most two +from 2018-19 to 2024-25 unless a Child Tax Credit award included more (SI +2017/1305 reg 7; SI 2025/39 reg 5(2)). A pensioner's capital counts as a +weekly income of £1 for each £500, or part of £500, over £10,000 (SI +2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg +27(2)), up to the £16,000 capital limit, except where Pension Credit sets the +means test. + +Invariants: + +1. Tariff income is 52 times £1 for each £500, or part of £500, of capital + above £10,000 and up to £16,000, for a pensioner off Pension Credit, and + it never falls as capital rises. Capital changes nothing else in the + applicable income, and the award never rises with capital. +2. Adding a dependent child never lowers the applicable amount. For a + pensioner it adds the scheme's weekly amount for 52 weeks, unless England's + 2018-19 to 2024-25 limit is already reached, and in Wales the family + premium with the first child. +3. A pensioner with no child and capital up to £10,000, and every working-age + family, gets no child amount, family premium or tariff income, so their + applicable amount, applicable income and award are origin/main's. + test_matches_origin_main_on_unchanged_households checks that against + values computed on origin/main. +""" + +import math + +import numpy as np +import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +AUTHORITIES = {"ENGLAND": "MAIDSTONE", "SCOTLAND": "GLASGOW_CITY", "WALES": "CARDIFF"} +# Weekly child or young person amounts and family premiums, from the +# parameter files' sources. +CHILD_AMOUNT = { + ("ENGLAND", 2019): 66.90, + ("ENGLAND", 2021): 68.60, + ("ENGLAND", 2024): 83.24, + ("ENGLAND", 2025): 84.66, + ("ENGLAND", 2026): 87.88, + ("WALES", 2019): 66.90, + ("WALES", 2021): 66.90, + ("WALES", 2024): 83.24, + ("WALES", 2025): 84.66, + ("WALES", 2026): 87.88, + ("SCOTLAND", 2019): 83.63, + ("SCOTLAND", 2021): 85.75, + ("SCOTLAND", 2024): 104.05, + ("SCOTLAND", 2025): 105.85, + ("SCOTLAND", 2026): 109.85, +} +WELSH_FAMILY_PREMIUM = {2019: 17.45, 2021: 17.45, 2024: 19.15, 2025: 19.48, 2026: 20.22} +YEARS = (2019, 2021, 2024, 2025, 2026) +OUTPUTS = ( + "council_tax_reduction_pensioner", + "council_tax_reduction_applicable_amount", + "council_tax_reduction_applicable_income", + "council_tax_reduction_pensioner_child_amounts", + "council_tax_reduction_pensioner_family_premium", + "council_tax_reduction_pensioner_tariff_income", + "council_tax_benefit", +) +SETTINGS = settings( + max_examples=5, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +def situation(households, year): + """One benefit unit and household for each spec, in one simulation.""" + data = {"people": {}, "benunits": {}, "households": {}} + for index, spec in enumerate(households): + members = [] + adults = [spec["age"]] + if spec.get("partner_age") is not None: + adults.append(spec["partner_age"]) + for number, age in enumerate(adults): + name = f"adult_{index}_{number}" + income = "state_pension" if age >= 67 else "employment_income" + data["people"][name] = { + "age": {year: age}, + income: {year: spec["income"] if number == 0 else 0}, + } + members.append(name) + for number, age in enumerate(spec.get("children", ())): + name = f"child_{index}_{number}" + data["people"][name] = {"age": {year: age}} + members.append(name) + data["benunits"][f"family_{index}"] = { + "members": members, + "would_claim_pc": {year: spec.get("claims_pc", False)}, + "would_claim_uc": {year: False}, + } + data["households"][f"home_{index}"] = { + "members": members, + "country": {year: spec["country"]}, + "local_authority": { + year: spec.get("local_authority") or AUTHORITIES[spec["country"]] + }, + "tenure_type": {year: "OWNED_OUTRIGHT"}, + "council_tax": {year: 2_000}, + "savings": {year: spec["savings"]}, + } + return data + + +def calculate(households, year, names=OUTPUTS): + simulation = Simulation(situation=situation(households, year)) + return {name: np.asarray(simulation.calculate(name, year)) for name in names} + + +def tariff(capital): + excess = max(0, min(capital, 16_000) - 10_000) + return 52 * math.ceil(excess / 500) + + +countries = st.sampled_from(sorted(AUTHORITIES)) +pensioner = st.fixed_dictionaries( + { + "country": countries, + "age": st.integers(70, 95), + "partner_age": st.one_of(st.none(), st.integers(68, 95)), + "children": st.lists(st.integers(0, 15), max_size=3), + "income": st.integers(0, 30_000), + "savings": st.integers(0, 10_000), + } +) +family = st.fixed_dictionaries( + { + "country": countries, + "age": st.one_of(st.integers(25, 60), st.integers(70, 95)), + "partner_age": st.one_of(st.none(), st.integers(25, 60), st.integers(70, 95)), + "children": st.lists(st.integers(0, 15), max_size=3), + "income": st.integers(0, 30_000), + "savings": st.integers(0, 20_000), + "claims_pc": st.booleans(), + } +) + + +@SETTINGS +@given( + base=pensioner, + capitals=st.lists(st.integers(0, 30_000), min_size=2, max_size=6).map(sorted), + year=st.sampled_from(YEARS), +) +def test_tariff_income_is_the_tariff_and_never_falls_as_capital_rises( + base, capitals, year +): + households = [dict(base, savings=capital) for capital in capitals] + result = calculate(households, year) + assert result["council_tax_reduction_pensioner"].all() + tariffs = result["council_tax_reduction_pensioner_tariff_income"] + np.testing.assert_allclose(tariffs, [tariff(c) for c in capitals], atol=0.01) + assert (np.diff(tariffs) >= 0).all() + # Capital adds the tariff income and nothing else. + other_income = result["council_tax_reduction_applicable_income"] - tariffs + np.testing.assert_allclose(other_income, other_income[0], atol=0.01) + assert (np.diff(result["council_tax_benefit"]) <= 0.01).all() + + +@SETTINGS +@given( + households=st.lists(family, min_size=1, max_size=6), + child_age=st.integers(0, 15), + year=st.sampled_from(YEARS), +) +def test_adding_a_dependent_child_never_lowers_the_applicable_amount( + households, child_age, year +): + with_child = [ + dict(spec, children=[*spec["children"], child_age]) for spec in households + ] + before = calculate(households, year) + after = calculate(with_child, year) + rise = ( + after["council_tax_reduction_applicable_amount"] + - before["council_tax_reduction_applicable_amount"] + ) + assert (rise >= -0.01).all() + for index, spec in enumerate(households): + if not before["council_tax_reduction_pensioner"][index]: + assert after["council_tax_reduction_pensioner_child_amounts"][index] == 0 + continue + children = len(spec["children"]) + counted = ( + min(children + 1, 2) - min(children, 2) + if spec["country"] == "ENGLAND" and 2018 <= year <= 2024 + else 1 + ) + expected = 52 * counted * CHILD_AMOUNT[(spec["country"], year)] + if spec["country"] == "WALES" and children == 0: + expected += 52 * WELSH_FAMILY_PREMIUM[year] + added = ( + after["council_tax_reduction_pensioner_child_amounts"][index] + + after["council_tax_reduction_pensioner_family_premium"][index] + - before["council_tax_reduction_pensioner_child_amounts"][index] + - before["council_tax_reduction_pensioner_family_premium"][index] + ) + assert added == pytest.approx(expected, abs=0.01) + + +@SETTINGS +@given(households=st.lists(family, min_size=1, max_size=8), year=st.sampled_from(YEARS)) +def test_no_new_amounts_without_a_child_or_capital_over_10000_or_at_working_age( + households, year +): + result = calculate(households, year) + pensioner = result["council_tax_reduction_pensioner"] + for index, spec in enumerate(households): + child_amounts = result["council_tax_reduction_pensioner_child_amounts"][index] + premium = result["council_tax_reduction_pensioner_family_premium"][index] + tariff_income = result["council_tax_reduction_pensioner_tariff_income"][index] + if not pensioner[index]: + assert child_amounts == premium == tariff_income == 0 + continue + if not spec["children"]: + assert child_amounts == premium == 0 + if spec["savings"] <= 10_000: + assert tariff_income == 0 + + +def test_northern_ireland_gets_no_new_amounts(): + spec = { + "country": "NORTHERN_IRELAND", + "local_authority": "BELFAST", + "age": 72, + "children": [10], + "income": 12_000, + "savings": 16_000, + } + result = calculate([spec], 2026) + assert result["council_tax_reduction_pensioner_child_amounts"][0] == 0 + assert result["council_tax_reduction_pensioner_family_premium"][0] == 0 + assert result["council_tax_reduction_pensioner_tariff_income"][0] == 0 + + +# Pensioners with no child and capital up to £10,000, and working-age +# families with and without children and capital, in each nation, including +# English working-age families under the five local schemes the model runs. +UNCHANGED_HOUSEHOLDS = [ + spec + for country in sorted(AUTHORITIES) + for spec in ( + {"country": country, "age": 72, "income": 12_000, "savings": 0}, + { + "country": country, + "age": 80, + "partner_age": 75, + "income": 18_000, + "savings": 10_000, + }, + { + "country": country, + "age": 70, + "income": 9_000, + "savings": 9_999, + "claims_pc": True, + }, + { + "country": country, + "age": 40, + "children": [7], + "income": 15_000, + "savings": 12_000, + }, + { + "country": country, + "age": 35, + "partner_age": 33, + "children": [3, 9], + "income": 25_000, + "savings": 16_000, + }, + {"country": country, "age": 25, "income": 9_000, "savings": 8_000}, + ) +] + [ + { + "country": "ENGLAND", + "local_authority": authority, + "age": 40, + "children": [7], + "income": 12_000, + "savings": 14_000, + } + for authority in ( + "MERTON", + "KINGSTON_UPON_THAMES", + "NEWHAM", + "WESTMINSTER", + "OXFORD", + ) +] +DIFFERENTIAL_OUTPUTS = ( + "council_tax_reduction_applicable_amount", + "council_tax_reduction_applicable_income", + "council_tax_benefit", +) +# Computed on origin/main at 2da212abc for UNCHANGED_HOUSEHOLDS, in order: +# applicable amount, applicable income and council_tax_benefit. +ORIGIN_MAIN = { + 2019: [ + (9_412, 12_000, 1_482.4), + (14_071.2, 17_150, 1_384.24), + (9_412, 9_592.34, 1_963.93), + (3_801.2, 14_812.24, 0), + (5_972.2, 22_574.64, 0), + (3_801.2, 8_955.84, 0), + (9_412, 12_000, 1_482.4), + (14_071.2, 17_170, 1_380.24), + (9_412, 9_592.34, 1_963.93), + (3_801.2, 14_832.24, 0), + (5_972.2, 22_594.64, 0), + (3_801.2, 8_955.84, 969.07), + (9_412, 12_000, 1_482.4), + (14_071.2, 17_150, 1_384.24), + (9_412, 9_592.34, 1_963.93), + (3_801.2, 14_812.24, 0), + (5_972.2, 22_574.64, 0), + (3_801.2, 8_955.84, 969.07), + (3_801.2, 12_672.24, 225.79), + (3_801.2, 12_672.24, 0), + (3_801.2, 12_672.24, 0), + (3_801.2, 12_672.24, 0), + (3_801.2, 12_672.24, 2_000), + ], + 2024: [ + (12_230.4, 12_000, 2_000), + (18_304, 17_166, 2_000), + (12_230.4, 0, 2_000), + (4_706, 15_650.8, 0), + (7_397, 23_984.2, 0), + (4_706, 9_000, 0), + (12_230.4, 12_000, 2_000), + (18_304, 17_189.06, 2_000), + (12_230.4, 0, 2_000), + (4_706, 15_673.86, 0), + (7_397, 24_007.26, 0), + (4_706, 9_000, 1_141.2), + (12_230.4, 12_000, 2_000), + (18_304, 17_166, 2_000), + (12_230.4, 0, 2_000), + (4_706, 15_650.8, 0), + (7_397, 23_984.2, 0), + (4_706, 9_000, 1_141.2), + (4_706, 13_331.2, 274.96), + (4_706, 13_331.2, 0), + (4_706, 13_331.2, 0), + (4_706, 13_331.2, 0), + (4_706, 13_331.2, 2_000), + ], + 2026: [ + (13_312, 12_000, 2_000), + (19_934.2, 17_166, 2_000), + (12_376, 0, 2_000), + (4_968.6, 15_726.2, 0), + (7_807.8, 24_109, 0), + (4_968.6, 9_000, 0), + (13_312, 12_000, 2_000), + (19_934.2, 17_205.67, 2_000), + (13_312, 0, 2_000), + (4_968.6, 15_750.5, 0), + (7_807.8, 24_148.67, 0), + (4_968.6, 9_000, 1_193.72), + (13_312, 12_000, 2_000), + (19_934.2, 17_166, 2_000), + (13_312, 0, 2_000), + (4_968.6, 15_726.2, 0), + (7_807.8, 24_109, 0), + (4_968.6, 9_000, 1_193.72), + (4_968.6, 13_406.6, 312.4), + (4_968.6, 13_406.6, 0), + (4_968.6, 13_406.6, 0), + (4_968.6, 13_406.6, 0), + (4_968.6, 13_406.6, 2_000), + ], +} + + +@pytest.mark.parametrize("year", sorted(ORIGIN_MAIN)) +def test_matches_origin_main_on_unchanged_households(year): + result = calculate(UNCHANGED_HOUSEHOLDS, year, DIFFERENTIAL_OUTPUTS) + observed = np.stack([result[name] for name in DIFFERENTIAL_OUTPUTS], axis=1) + np.testing.assert_allclose(observed, ORIGIN_MAIN[year], atol=0.01, rtol=0) From 15f986ada5b7cebfaf674fd1ae889480a87be804 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 31 Oct 2026 22:10:58 -0400 Subject: [PATCH 03/22] Cite the Part-numbered England Schedule 2 paragraphs legislation.gov.uk serves SI 2012/2885 Schedule 2 paragraphs 2 and 3 under Parts 1 and 2. Co-Authored-By: Claude Opus 5.5 --- .../council_tax_reduction_pensioner_child_amounts.py | 2 +- .../council_tax_reduction_pensioner_family_premium.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index de4dfe85b6..d69f391756 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -23,7 +23,7 @@ class council_tax_reduction_pensioner_child_amounts(Variable): unit = GBP reference = ( "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6", - "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/2", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/part/1/paragraph/2", "https://www.legislation.gov.uk/uksi/2017/1305/regulation/7/made", "https://www.legislation.gov.uk/uksi/2017/1305/regulation/17/made", "https://www.legislation.gov.uk/uksi/2025/39/regulation/5/made", diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py index 14fd069b8a..4dd276bce8 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py @@ -20,7 +20,7 @@ class council_tax_reduction_pensioner_family_premium(Variable): unit = GBP reference = ( "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/6", - "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/3", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/part/2/paragraph/3", "https://www.legislation.gov.uk/uksi/2015/2041/regulation/3/made", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/1", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/3", From 9687620c16592e68044b34ef75de14130fd73dd8 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:49:42 -0500 Subject: [PATCH 04/22] Count a supplied Child Tax Credit award in England's child limit exception SI 2012/2885 Sch 1 para 6(1B)(a) asks whether the applicant has an award of Child Tax Credit "whether or not any amount is payable". The child amounts read an award only from would_claim_CTC and is_CTC_eligible, so an entered final child_tax_credit with three individual elements gave two child amounts. A positive final child_tax_credit now counts as an award too, and the claim-and-eligibility route stays for a nil-rate award. New YAML cases: the entered award (three amounts), a claim without eligibility (two), and a nil-rate award (three). Case 16's name uses "their". Co-Authored-By: Claude Opus 5.5 --- ...tax_reduction_pensioner_child_amounts.yaml | 114 +++++++++++++++++- ...l_tax_reduction_pensioner_child_amounts.py | 31 +++-- 2 files changed, 133 insertions(+), 12 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index 124e919b09..d67eeced7c 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -448,7 +448,7 @@ council_tax_reduction_pensioner_child_amounts: 66.90 * 52 council_tax_reduction_pensioner_family_premium: 17.45 * 52 -- name: Case 16, a pensioner household head who applies alone has no children in her family. +- name: Case 16, a pensioner household head who applies alone has no children in their family. period: 2026 absolute_error_margin: 0.01 input: @@ -512,3 +512,115 @@ council_tax_reduction_pensioner_family_premium: 0 # Lone parent aged 18 or over, 95.55 * 52, as before. council_tax_reduction_applicable_amount: 4_968.60 + +- name: Case 18, England's 2024-25 scheme counts all three where a final Child Tax Credit award is entered without a report. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 23_000 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + child_tax_credit: 9_800.95 + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # No child_tax_credit_reported, so the model reads no eligibility from + # reports; the entered final award is the award. + is_CTC_eligible: false + child_tax_credit: 9_800.95 + # Each child was born before 6 April 2017, so the model includes each + # one's individual element (is_CTC_child_limit_exempt). + is_CTC_child_element_included: [false, true, true, true] + # SI 2012/2885 Sch 1 para 6(1B) and (1C): an award with individual + # elements for three, more than the two under para 6(1)(b). + # 3 * 83.24 * 52 = 12,985.44. + council_tax_reduction_pensioner_child_amounts: 12_985.44 + +- name: Case 19, England's 2024-25 scheme counts two of three where the family would claim Child Tax Credit but has no award. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 23_000 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + would_claim_CTC: true + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # A claim without eligibility is no award: is_CTC_eligible needs a + # report, and child_tax_credit is nil without eligibility. + is_CTC_eligible: false + child_tax_credit: 0 + is_CTC_child_element_included: [false, true, true, true] + # Para 6(1)(b): up to two. 2 * 83.24 * 52 = 8,656.96. + council_tax_reduction_pensioner_child_amounts: 8_656.96 + +- name: Case 20, England's 2024-25 scheme counts all three on a nil-rate Child Tax Credit award. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 60_000 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + would_claim_CTC: true + is_CTC_eligible: true + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # Income of 60,000 withdraws the whole credit, so nothing is payable. + child_tax_credit: 0 + is_CTC_child_element_included: [false, true, true, true] + # Para 6(1B)(a): an award "whether or not any amount is payable". The + # individual elements for three give 3 * 83.24 * 52 = 12,985.44. + council_tax_reduction_pensioner_child_amounts: 12_985.44 diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index d69f391756..83d56e4e82 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -9,15 +9,18 @@ class council_tax_reduction_pensioner_child_amounts(Variable): documentation = ( "The amounts for the children and young persons in a pensioner's " "family in the Council Tax Reduction applicable amount, one weekly " - "amount for each. England's prescribed requirements limited them to " - "two children or young persons for the 2018-19 to 2024-25 schemes, " - "unless the applicant's Child Tax Credit award included the " - "individual element for more of them. The transitional protection " - "for families with more than two on 31 March 2018 is not modelled. " - "Nil where the household head applies alone " - "(council_tax_reduction_head_applies_alone), since the head's family " - "then has no children, and for working-age families, whose child " - "amounts are not modelled." + "amount for each. For the 2018-19 to 2024-25 schemes the Secretary of " + "State limited England's to two children or young persons, unless " + "the applicant's Child Tax Credit award included the individual " + "element for more of them. We read an award from a positive final " + "child_tax_credit, worked out or entered, or from the claim and " + "eligibility the model reads from reports, which keeps an award at a " + "nil rate. We do not model the transitional protection for families " + "with more than two on 31 March 2018. Where the household head " + "applies alone (council_tax_reduction_head_applies_alone), we assume " + "the head has no children in their family, because we cannot " + "identify their relationships. Nil for working-age families: we do " + "not model their child amounts here." ) definition_period = YEAR unit = GBP @@ -27,6 +30,7 @@ class council_tax_reduction_pensioner_child_amounts(Variable): "https://www.legislation.gov.uk/uksi/2017/1305/regulation/7/made", "https://www.legislation.gov.uk/uksi/2017/1305/regulation/17/made", "https://www.legislation.gov.uk/uksi/2025/39/regulation/5/made", + "https://www.legislation.gov.uk/ukpga/2002/21/section/14", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/1", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/2", "https://www.legislation.gov.uk/ssi/2012/319/regulation/20", @@ -51,8 +55,13 @@ def formula(benunit, period, parameters): # an award of Child Tax Credit includes where that gives more. # Every child or young person has the same amount, so the # greatest total is the greatest count. - child_tax_credit_award = benunit("would_claim_CTC", period) & benunit( - "is_CTC_eligible", period + # Para 6(1B)(a) needs an award of Child Tax Credit "whether or + # not any amount is payable", and HMRC may award it at a nil rate + # (TCA 2002 s.14(3)). A positive final child_tax_credit, worked + # out or entered, is an award; so are the claim and eligibility + # read from reports, whatever amount is payable. + child_tax_credit_award = (benunit("child_tax_credit", period) > 0) | ( + benunit("would_claim_CTC", period) & benunit("is_CTC_eligible", period) ) child_tax_credit_children = benunit.sum( child & person("is_CTC_child_element_included", period) From 05a414a721fd472d4e802055f7f289537459b3f2 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:50:11 -0500 Subject: [PATCH 05/22] Leave Scotland's pensioner tariff income uncapped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count capital in excess of £10,000 "but not exceeding £16,000". SSI 2012/319 reg 27(2) has no such ceiling; reg 40 separately ends entitlement above £16,000. The tariff now caps capital only in England and Wales, so a Scottish pensioner with £20,000 has 20 * 52 = £1,040 of tariff income, not £624, and still no reduction. New YAML cases for Scotland and Wales at £20,000. The Pension Credit and children/tariff property tests' reference calculations cap only England and Wales. Co-Authored-By: Claude Opus 5.5 --- ...tax_reduction_pensioner_tariff_income.yaml | 67 +++++++++++++++++-- ...tax_reduction_pension_credit_properties.py | 15 +++-- ...on_pensioner_children_tariff_properties.py | 12 ++-- ...l_tax_reduction_pensioner_tariff_income.py | 46 ++++++++----- 4 files changed, 107 insertions(+), 33 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml index adabd260e6..54a9528963 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml @@ -1,12 +1,12 @@ # Pensioner tariff income from capital. A pensioner's capital counts as a # weekly income of £1 for each £500 over £10,000, and £1 for any part of £500: # England SI 2012/2885 Sch 1 para 37 and Wales WSI 2013/3029 Sch 1 para 31 -# (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2). Capital -# over £16,000 ends entitlement (SI 2012/2885 reg 11(2); WSI 2013/3029 reg -# 30; SSI 2012/319 reg 40). A guarantee credit recipient's whole capital and -# income are disregarded (Sch 1 para 13; Sch 1 para 7; reg 24), and on a -# savings-credit-only award the Secretary of State's assessment of income is -# used (Sch 1 para 14; Sch 1 para 8; reg 25). +# (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2), which sets +# no ceiling. Capital over £16,000 ends entitlement (SI 2012/2885 reg 11(2); +# WSI 2013/3029 reg 30; SSI 2012/319 reg 40). Councils disregard a guarantee +# credit recipient's whole capital and income (Sch 1 para 13; Sch 1 para 7; +# reg 24), and on a savings-credit-only award they use the Secretary of +# State's assessment of income (Sch 1 para 14; Sch 1 para 8; reg 25). # # Each 72-year-old reached State Pension age before 1 April 2021, so the # applicable amount is 256.00 * 52 = 13,312. A State Pension of 12,570 is @@ -364,3 +364,58 @@ output: council_tax_reduction_pensioner: false council_tax_reduction_pensioner_tariff_income: 0 + +- name: Case 15, Scotland, capital of 20,000 gives 20 a week, with no ceiling, and the capital limit ends entitlement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 15_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 20_000 + output: + # SSI 2012/319 reg 27(2): (20,000 - 10,000) / 500 = 20; 20 * 1 * 52 = + # 1,040. + council_tax_reduction_pensioner_tariff_income: 1_040 + # Reg 40: capital over 16,000, so no reduction. + council_tax_reduction: 0 + +- name: Case 16, Wales, capital of 20,000 counts the excess up to 16,000 only, and the capital limit ends entitlement. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 12_570 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: WALES + local_authority: CARDIFF + council_tax: 2_000 + savings: 20_000 + output: + # WSI 2013/3029 Sch 1 para 31, "not exceeding £16,000": + # (16,000 - 10,000) / 500 = 12; 12 * 52 = 624. + council_tax_reduction_pensioner_tariff_income: 624 + # Reg 30: capital over 16,000, so no reduction. + council_tax_reduction: 0 + diff --git a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py index 10b7891b2a..73aad105d8 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py @@ -297,9 +297,10 @@ def situation( PENSIONER_ADDITIONAL_DISREGARD = 17.10 # Since #1933, a pensioner family's general-rules income also adds tariff # income from capital after the floor, written out from the law: £1 a week -# for each £500, or part of £500, of capital above £10,000 and up to £16,000 -# (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg -# 27(2)). Household savings are these families' capital. +# for each £500, or part of £500, of capital above £10,000, up to £16,000 in +# England and Wales (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31) +# and with no ceiling in Scotland (SSI 2012/319 reg 27(2)). Household +# savings are these families' capital. TARIFF_THRESHOLD = 10_000 TARIFF_STEP = 500 HOUSEHOLD_VARIABLES = [ @@ -381,9 +382,13 @@ def benunit_total(names): - 0.5 * benunit_total(["pension_contributions"]) - pensioner_earnings_disregard(sim, claimants), ) + tariff_capital = np.where( + [unit["country"] == "SCOTLAND" for unit in units], + values["savings"], + np.minimum(values["savings"], CAPITAL_LIMIT), + ) tariff_steps = np.ceil( - np.maximum(0, np.minimum(values["savings"], CAPITAL_LIMIT) - TARIFF_THRESHOLD) - / TARIFF_STEP + np.maximum(0, tariff_capital - TARIFF_THRESHOLD) / TARIFF_STEP ) values["income_under_main_definition"] += np.where( values["council_tax_reduction_pensioner"], 52 * tariff_steps, 0 diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index af3f44b18e..f3fc0878da 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -119,9 +119,11 @@ def calculate(households, year, names=OUTPUTS): return {name: np.asarray(simulation.calculate(name, year)) for name in names} -def tariff(capital): - excess = max(0, min(capital, 16_000) - 10_000) - return 52 * math.ceil(excess / 500) +def tariff(capital, country): + # England and Wales count the excess "not exceeding £16,000"; Scotland's + # reg 27(2) sets no ceiling. + counted = capital if country == "SCOTLAND" else min(capital, 16_000) + return 52 * math.ceil(max(0, counted - 10_000) / 500) countries = st.sampled_from(sorted(AUTHORITIES)) @@ -161,7 +163,9 @@ def test_tariff_income_is_the_tariff_and_never_falls_as_capital_rises( result = calculate(households, year) assert result["council_tax_reduction_pensioner"].all() tariffs = result["council_tax_reduction_pensioner_tariff_income"] - np.testing.assert_allclose(tariffs, [tariff(c) for c in capitals], atol=0.01) + np.testing.assert_allclose( + tariffs, [tariff(c, base["country"]) for c in capitals], atol=0.01 + ) assert (np.diff(tariffs) >= 0).all() # Capital adds the tariff income and nothing else. other_income = result["council_tax_reduction_applicable_income"] - tariffs diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index b7e8ccc9bb..d87988aad4 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -7,16 +7,19 @@ class council_tax_reduction_pensioner_tariff_income(Variable): entity = BenUnit label = "Council Tax Reduction pensioner tariff income from capital" documentation = ( - "Weekly income the pensioner Council Tax Reduction schemes treat " - "capital as yielding, annualised: £1 for each £500, or part of £500, " - "of council_tax_reduction_assessable_capital above £10,000, up to the " - "£16,000 capital limit. England, Wales and Scotland use the " - "pension-age Housing Benefit amounts. Nil where Pension Credit sets " - "the means test: the guarantee credit disregards the whole of the " - "capital, and on a savings-credit-only award the Secretary of " - "State's assessment of income already includes Pension Credit's " - "deemed income from capital. Nil for working-age families, whose " - "tariff income is not modelled." + "Weekly income that councils' pensioner Council Tax Reduction schemes " + "treat capital as yielding, annualised: £1 for each £500, or part of " + "£500, of council_tax_reduction_assessable_capital above £10,000. The " + "Secretary of State and the Welsh Ministers count the excess up to " + "£16,000; the Scottish Ministers set no ceiling, though capital over " + "£16,000 ends entitlement in every nation. We use the pension-age " + "Housing Benefit tariff amounts, which all three nations share. Nil " + "where Pension Credit sets the means test: councils disregard the " + "whole of a guarantee credit recipient's capital, and on a " + "savings-credit-only award they use the Secretary of State's " + "assessment of income, which already includes Pension Credit's " + "deemed income from capital. Nil for working-age families: we do not " + "model their tariff income here." ) definition_period = YEAR unit = GBP @@ -39,23 +42,30 @@ def formula(benunit, period, parameters): ).gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income local_authorities = parameters(period).gov.local_authorities country = benunit.household("country", period) - capital_limit = select( + capital = benunit("council_tax_reduction_assessable_capital", period) + # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count + # the excess "not exceeding £16,000", the capital limit. SSI 2012/319 + # reg 27(2) sets no ceiling; reg 40 ends entitlement above £16,000. + counted_capital = select( [ country == Country.ENGLAND, country == Country.WALES, country == Country.SCOTLAND, ], [ - local_authorities.england.council_tax_reduction.pensioners.means_test.capital_limit, - local_authorities.wales.council_tax_reduction.means_test.capital_limit, - local_authorities.scotland.council_tax_reduction.means_test.capital_limit, + min_( + capital, + local_authorities.england.council_tax_reduction.pensioners.means_test.capital_limit, + ), + min_( + capital, + local_authorities.wales.council_tax_reduction.means_test.capital_limit, + ), + capital, ], default=0, ) - capital = benunit("council_tax_reduction_assessable_capital", period) - # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count - # the excess "not exceeding £16,000"; above it there is no reduction. - excess_capital = max_(0, min_(capital, capital_limit) - tariff.threshold) + excess_capital = max_(0, counted_capital - tariff.threshold) weekly_tariff_income = np.ceil(excess_capital / tariff.step) * tariff.amount # The Pension Credit routes (England Sch 1 paras 13 and 14, Wales # Sch 1 paras 7 and 8, Scotland regs 24 and 25), as in From 573087580cbdf54ff726ba12f2f52aea278fdb15 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:50:37 -0500 Subject: [PATCH 06/22] Test that pension contributions cannot consume tariff income MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The general-rules income floors cash income after tax, pension contributions and the earnings disregards, then adds tariff income as a separate source. A pensioner with no cash income, £3,000 of pension contributions and £10,001 of capital has applicable income of £52. Moving the tariff inside the floor would give nil. Co-Authored-By: Claude Opus 5.5 --- ...tax_reduction_pensioner_tariff_income.yaml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml index 54a9528963..e816b5bd6e 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml @@ -419,3 +419,30 @@ # Reg 30: capital over 16,000, so no reduction. council_tax_reduction: 0 +- name: Case 17, England, pension contributions do not reduce tariff income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 0 + pension_contributions: 3_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 10_001 + output: + council_tax_reduction_pensioner_tariff_income: 52 + # Cash income nil; half the contributions, 0.5 * 3,000 = 1,500, is + # deducted from it, floored at nil: max(0, 0 - 1,500) = 0. Tariff income + # is a separate source, added after the floor: 0 + 1 * 52 = 52. + council_tax_reduction_applicable_income: 52 From e4254881f255e4e3e33caebcb6b1ca4368cc81af Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:50:42 -0500 Subject: [PATCH 07/22] State the pensioner children and tariff invariants on a fixed route Capital changes a savings-credit-only pensioner's applicable income through the Secretary of State's assessment, and a child who brings Universal Credit into payment for a mixed-age couple moves them to the working-age scheme. The property docstring now states each invariant for the route its generated families stay on, and names those route changes as model behaviour. Co-Authored-By: Claude Opus 5.5 --- ...on_pensioner_children_tariff_properties.py | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index f3fc0878da..97a0de48dd 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -1,26 +1,35 @@ """A pensioner's Council Tax Reduction child amounts and tariff income. -The pensioner schemes add an amount for each child or young person in the -family and, in Wales, a family premium (SI 2012/2885 Sch 1 para 6(1)(b)-(c) -and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch 2 paras -2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). England counted at most two -from 2018-19 to 2024-25 unless a Child Tax Credit award included more (SI -2017/1305 reg 7; SI 2025/39 reg 5(2)). A pensioner's capital counts as a -weekly income of £1 for each £500, or part of £500, over £10,000 (SI -2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg -27(2)), up to the £16,000 capital limit, except where Pension Credit sets the -means test. +Councils' pensioner schemes add an amount for each child or young person in +the family and, in Wales, a family premium (SI 2012/2885 Sch 1 para +6(1)(b)-(c) and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch +2 paras 2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). For 2018-19 to +2024-25 the Secretary of State limited England's to two unless a Child Tax +Credit award included more (SI 2017/1305 reg 7; SI 2025/39 reg 5(2)). A +pensioner's capital counts as a weekly income of £1 for each £500, or part +of £500, over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para +31; SSI 2012/319 reg 27(2)), except where Pension Credit sets the means +test. England and Wales count the excess up to £16,000; Scotland sets no +ceiling. -Invariants: +Each invariant holds on a fixed route and status. The generated families +claim no Universal Credit, so neither capital nor a child can move a family +between the pensioner and working-age schemes, and the first invariant's +pensioners claim no Pension Credit, so capital cannot move them onto a +Pension Credit route. Off those routes both can move, as the model intends: +capital changes a savings-credit-only pensioner's applicable income through +the Secretary of State's assessment, and a child who brings Universal Credit +into payment for a mixed-age couple moves them to the working-age scheme, +whose applicable amount can be lower. -1. Tariff income is 52 times £1 for each £500, or part of £500, of capital - above £10,000 and up to £16,000, for a pensioner off Pension Credit, and - it never falls as capital rises. Capital changes nothing else in the - applicable income, and the award never rises with capital. -2. Adding a dependent child never lowers the applicable amount. For a - pensioner it adds the scheme's weekly amount for 52 weeks, unless England's - 2018-19 to 2024-25 limit is already reached, and in Wales the family - premium with the first child. +1. For a pensioner off Pension Credit, tariff income is 52 times £1 for each + £500, or part of £500, of capital above £10,000 (up to £16,000 in England + and Wales), and it never falls as capital rises. Capital changes nothing + else in the applicable income, and the award never rises with capital. +2. For a family that claims no Universal Credit, adding a dependent child + never lowers the applicable amount. For a pensioner it adds the scheme's + weekly amount for 52 weeks, unless England's 2018-19 to 2024-25 limit is + already reached, and in Wales the family premium with the first child. 3. A pensioner with no child and capital up to £10,000, and every working-age family, gets no child amount, family premium or tariff income, so their applicable amount, applicable income and award are origin/main's. From 923eccf9ea496abfe2a8923923e4b18f6cc2d7e2 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:50:47 -0500 Subject: [PATCH 08/22] Name the pensioner premiums CTR includes and use they/them The applicable amount comment now says we include the severe disability and carer premiums for pensioners, rather than that the pension-age schedules have only those (England's Sch 2 paras 7 and 8 have more). The applicable income comment uses "them", and the new documentation names the Ministers, councils or "we" that act. Co-Authored-By: Claude Opus 5.5 --- .../council_tax_reduction_applicable_amount.py | 14 +++++++------- .../council_tax_reduction_applicable_income.py | 6 +++--- ...ncil_tax_reduction_pensioner_family_premium.py | 15 ++++++++------- 3 files changed, 18 insertions(+), 17 deletions(-) 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 53447ffc96..80896abcf3 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 @@ -14,10 +14,10 @@ class council_tax_reduction_applicable_amount(Variable): "(council_tax_reduction_head_applies_alone), the head is a single " "person with no partner or children, whatever the benefit unit's " "claimant and partner are. Premiums are council_tax_reduction_premiums. " - "A pensioner's applicable amount also has the amounts for the " - "children and young persons in the family " - "(council_tax_reduction_pensioner_child_amounts) and the family " - "premium (council_tax_reduction_pensioner_family_premium)." + "For a pensioner we also add an amount for each child or young " + "person in the family (council_tax_reduction_pensioner_child_amounts) " + "and the family premium " + "(council_tax_reduction_pensioner_family_premium)." ) definition_period = YEAR unit = GBP @@ -100,13 +100,13 @@ def formula(benunit, period, parameters): + couple * couple_personal_allowance + lone_parent * lone_parent_personal_allowance ) * WEEKS_IN_YEAR - # The pension-age schedules have only the severe disability and carer - # premiums; the same pensioner test chooses the schedule. + # We currently include the severe disability and carer premiums for + # pensioners; the same pensioner test chooses the schedule. premiums = benunit("council_tax_reduction_premiums", period) # A pensioner's amounts for the children and young persons in the # family and the family premium (SI 2012/2885 Sch 1 para 6(1)(b)-(c); # WSI 2013/3029 Sch 1 para 1(1)(b)-(c); SSI 2012/319 reg 20(b)). - # Working-age families get neither here. + # We add neither for working-age families here. child_amounts = add( benunit, period, diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py index 998cdb4e07..f7212b9578 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py @@ -13,8 +13,8 @@ class council_tax_reduction_applicable_income(Variable): "use the Secretary of State's Pension Credit assessment of income, plus " "the savings credit payable, where the award is savings credit only. " "Otherwise a pension-age family's net earnings are reduced by the " - "pensioner earnings disregards and its tariff income from capital " - "(council_tax_reduction_pensioner_tariff_income) is added. Great " + "pensioner earnings disregards, and we add its tariff income from " + "capital (council_tax_reduction_pensioner_tariff_income). Great " "Britain's pensioner schemes " "also exclude Child Benefit from general-rule income; statutory sick " "and maternity pay remain counted as earnings. The other adjustments those " @@ -98,7 +98,7 @@ def formula(benunit, period, parameters): # 21(3); SSI 2021/249 reg 36(2)); the other schemes count the # applicant's and partner's alone. Anyone else in the benefit unit does # not count either. A household head who applies alone is the - # applicant, whatever else the benefit unit reads her as. + # applicant, whatever else the benefit unit reads them as. person = benunit.members head_applies_alone = benunit("council_tax_reduction_head_applies_alone", period) applicant_family = ~head_applies_alone diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py index 4dd276bce8..a46d5d3641 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py @@ -8,13 +8,14 @@ class council_tax_reduction_pensioner_family_premium(Variable): label = "Council Tax Reduction pensioner family premium" documentation = ( "The family premium in a pensioner's Council Tax Reduction applicable " - "amount, where the family includes a child or young person. Wales " - "keeps it. England's prescribed requirements make it nil for " - "reduction weeks beginning after 1 May 2016, and Scotland removed it " - "from 1 May 2016. Each saved it for families with a child who had a " - "reduction on 30 April 2016 until they make a new application or " - "have no child; that protection is not modelled. The model reads " - "each year's amount on 30 April, so 2016-17 keeps the premium." + "amount, where the family includes a child or young person. The Welsh " + "Ministers keep it. The Secretary of State made England's nil for " + "reduction weeks beginning after 1 May 2016, and the Scottish " + "Ministers removed Scotland's from 1 May 2016. Each kept it for " + "families with a child who had a reduction on 30 April 2016 until " + "they make a new application or have no child; we do not model that " + "protection. We read each year's amount on 30 April, so model year " + "2016 keeps the premium." ) definition_period = YEAR unit = GBP From c91e960cfd1726e6ef8a5fcdf0212df9ff975c00 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 05:57:36 -0500 Subject: [PATCH 09/22] Reword the #1933 changelog fragment Co-Authored-By: Claude Opus 5.5 --- changelog.d/1933.fixed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/1933.fixed.md b/changelog.d/1933.fixed.md index 229263ff01..86c936388a 100644 --- a/changelog.d/1933.fixed.md +++ b/changelog.d/1933.fixed.md @@ -1 +1 @@ -Pension-age Council Tax Reduction in England, Scotland and Wales now adds an amount for each child or young person, and in Wales the family premium, to the applicable amount, and counts tariff income from capital over £10,000. +Added pensioner child amounts, family premiums and tariff income from capital over £10,000 to the Council Tax Reduction model for England, Scotland and Wales. From 168d4a52c973b044dadd024928e6f8772222ae51 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 06:52:10 -0500 Subject: [PATCH 10/22] Name the actors in the pensioner child and tariff documentation The tariff documentation and comments now say who acts (councils, the Scottish Ministers) rather than giving the verb to a regulation, and the "Nil for working-age families" fragments become sentences. No code changes. Co-Authored-By: Claude Opus 5.5 --- ...l_tax_reduction_pensioner_child_amounts.py | 15 ++++++----- ...l_tax_reduction_pensioner_tariff_income.py | 27 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index 83d56e4e82..c956d1e128 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -19,8 +19,8 @@ class council_tax_reduction_pensioner_child_amounts(Variable): "with more than two on 31 March 2018. Where the household head " "applies alone (council_tax_reduction_head_applies_alone), we assume " "the head has no children in their family, because we cannot " - "identify their relationships. Nil for working-age families: we do " - "not model their child amounts here." + "identify their relationships. We give working-age families nil, " + "because we do not model their child amounts here." ) definition_period = YEAR unit = GBP @@ -55,11 +55,12 @@ def formula(benunit, period, parameters): # an award of Child Tax Credit includes where that gives more. # Every child or young person has the same amount, so the # greatest total is the greatest count. - # Para 6(1B)(a) needs an award of Child Tax Credit "whether or - # not any amount is payable", and HMRC may award it at a nil rate - # (TCA 2002 s.14(3)). A positive final child_tax_credit, worked - # out or entered, is an award; so are the claim and eligibility - # read from reports, whatever amount is payable. + # Councils apply para 6(1B)(a) where the applicant has an award + # of Child Tax Credit "whether or not any amount is payable", and + # HMRC may award it at a nil rate (TCA 2002 s.14(3)). We count a + # positive final child_tax_credit, worked out or entered, as an + # award, and also the claim and eligibility read from reports, + # whatever amount is payable. child_tax_credit_award = (benunit("child_tax_credit", period) > 0) | ( benunit("would_claim_CTC", period) & benunit("is_CTC_eligible", period) ) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index d87988aad4..b78080b57e 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -7,19 +7,19 @@ class council_tax_reduction_pensioner_tariff_income(Variable): entity = BenUnit label = "Council Tax Reduction pensioner tariff income from capital" documentation = ( - "Weekly income that councils' pensioner Council Tax Reduction schemes " - "treat capital as yielding, annualised: £1 for each £500, or part of " - "£500, of council_tax_reduction_assessable_capital above £10,000. The " + "Weekly income that councils treat a pensioner's capital as " + "yielding, annualised: £1 for each £500, or part of £500, of " + "council_tax_reduction_assessable_capital above £10,000. The " "Secretary of State and the Welsh Ministers count the excess up to " - "£16,000; the Scottish Ministers set no ceiling, though capital over " - "£16,000 ends entitlement in every nation. We use the pension-age " - "Housing Benefit tariff amounts, which all three nations share. Nil " - "where Pension Credit sets the means test: councils disregard the " - "whole of a guarantee credit recipient's capital, and on a " - "savings-credit-only award they use the Secretary of State's " + "£16,000; the Scottish Ministers set no ceiling, though in every " + "nation nobody with capital over £16,000 gets a reduction. We use " + "the pension-age Housing Benefit tariff amounts, which all three " + "nations share. We give nil on the Pension Credit routes: councils " + "disregard the whole of a guarantee credit recipient's capital, and " + "on a savings-credit-only award they use the Secretary of State's " "assessment of income, which already includes Pension Credit's " - "deemed income from capital. Nil for working-age families: we do not " - "model their tariff income here." + "deemed income from capital. We also give working-age families nil, " + "because we do not model their tariff income here." ) definition_period = YEAR unit = GBP @@ -44,8 +44,9 @@ def formula(benunit, period, parameters): country = benunit.household("country", period) capital = benunit("council_tax_reduction_assessable_capital", period) # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count - # the excess "not exceeding £16,000", the capital limit. SSI 2012/319 - # reg 27(2) sets no ceiling; reg 40 ends entitlement above £16,000. + # the excess "not exceeding £16,000", the capital limit. The Scottish + # Ministers set no ceiling in SSI 2012/319 reg 27(2); under reg 40 + # nobody with capital above £16,000 gets a reduction. counted_capital = select( [ country == Country.ENGLAND, From 36f1dd17eb690c06c7305ac53b5cb25f787b84d9 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 07:43:42 -0500 Subject: [PATCH 11/22] Word the child-limit invariant actively in the property docstring Co-Authored-By: Claude Opus 5.5 --- ...cil_tax_reduction_pensioner_children_tariff_properties.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index 97a0de48dd..791575937d 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -28,8 +28,9 @@ else in the applicable income, and the award never rises with capital. 2. For a family that claims no Universal Credit, adding a dependent child never lowers the applicable amount. For a pensioner it adds the scheme's - weekly amount for 52 weeks, unless England's 2018-19 to 2024-25 limit is - already reached, and in Wales the family premium with the first child. + weekly amount for 52 weeks, unless the family already has the two children + that England's limit allowed from 2018-19 to 2024-25, and in Wales the + family premium with the first child. 3. A pensioner with no child and capital up to £10,000, and every working-age family, gets no child amount, family premium or tariff income, so their applicable amount, applicable income and award are origin/main's. From b320e25ecf6f7f9cc128bab648ae621e03da52b0 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 11:54:21 -0500 Subject: [PATCH 12/22] Infer no Child Tax Credit award from reports once tax credits close The child-limit exception in council_tax_reduction_pensioner_child_amounts now reads the claim and eligibility only while gov.dwp.tax_credits.active holds, as has_tax_credit_award does. A supplied positive final award still counts. Case 21 covers eligibility without a claim, and Case 22 an inactive-scheme reform with a reported award. Co-Authored-By: Claude Opus 5.5 --- ...tax_reduction_pensioner_child_amounts.yaml | 78 +++++++++++++++++++ ...l_tax_reduction_pensioner_child_amounts.py | 31 ++++---- 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index d67eeced7c..78c30176fb 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -624,3 +624,81 @@ # Para 6(1B)(a): an award "whether or not any amount is payable". The # individual elements for three give 3 * 83.24 * 52 = 12,985.44. council_tax_reduction_pensioner_child_amounts: 12_985.44 + +- name: Case 21, England's 2024-25 scheme counts two of three where the family is eligible for Child Tax Credit but would not claim it. + period: 2024 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 72 + state_pension: 23_000 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + would_claim_CTC: false + is_CTC_eligible: true + child_tax_credit: 0 + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + # Eligibility without a claim is no award (TCA 2002 s.3(1)), and the + # family has no final award either. + child_tax_credit: 0 + is_CTC_child_element_included: [false, true, true, true] + # Para 6(1)(b): up to two. 2 * 83.24 * 52 = 8,656.96. + council_tax_reduction_pensioner_child_amounts: 8_656.96 + +- name: Case 22, England's 2024-25 scheme counts two of three where a reform ends tax credits and the family reports Child Tax Credit. + period: 2024 + absolute_error_margin: 0.01 + input: + gov.dwp.tax_credits.active: false + people: + pensioner: + age: 72 + state_pension: 23_000 + child_tax_credit_reported: 1 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + savings: 0 + output: + # The report still gives a claim and eligibility, but the closed scheme + # pays nothing and has_tax_credit_award infers no award from it. + would_claim_CTC: true + is_CTC_eligible: true + child_tax_credit: 0 + has_tax_credit_award: false + council_tax_reduction_pensioner: true + is_CTC_child_element_included: [false, true, true, true] + # No award, so para 6(1)(b) counts up to two: 2 * 83.24 * 52 = 8,656.96. + council_tax_reduction_pensioner_child_amounts: 8_656.96 diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index c956d1e128..659590ad5c 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -7,15 +7,16 @@ class council_tax_reduction_pensioner_child_amounts(Variable): entity = BenUnit label = "Council Tax Reduction pensioner child or young person amounts" documentation = ( - "The amounts for the children and young persons in a pensioner's " - "family in the Council Tax Reduction applicable amount, one weekly " - "amount for each. For the 2018-19 to 2024-25 schemes the Secretary of " - "State limited England's to two children or young persons, unless " - "the applicant's Child Tax Credit award included the individual " - "element for more of them. We read an award from a positive final " - "child_tax_credit, worked out or entered, or from the claim and " - "eligibility the model reads from reports, which keeps an award at a " - "nil rate. We do not model the transitional protection for families " + "Councils add one weekly amount for each child or young person in a " + "pensioner's family to the Council Tax Reduction applicable amount. " + "For the 2018-19 to 2024-25 schemes the Secretary of State limited " + "England's to two children or young persons, unless the applicant's " + "Child Tax Credit award included the individual element for more of " + "them. We read an award from a positive final child_tax_credit, " + "worked out or entered, or, while the tax credit scheme pays awards " + "(gov.dwp.tax_credits.active), from the claim and eligibility the " + "model reads from reports, which keeps an award at a nil rate. We do " + "not model the transitional protection for families " "with more than two on 31 March 2018. Where the household head " "applies alone (council_tax_reduction_head_applies_alone), we assume " "the head has no children in their family, because we cannot " @@ -60,10 +61,14 @@ def formula(benunit, period, parameters): # HMRC may award it at a nil rate (TCA 2002 s.14(3)). We count a # positive final child_tax_credit, worked out or entered, as an # award, and also the claim and eligibility read from reports, - # whatever amount is payable. - child_tax_credit_award = (benunit("child_tax_credit", period) > 0) | ( - benunit("would_claim_CTC", period) & benunit("is_CTC_eligible", period) - ) + # whatever amount is payable. As in has_tax_credit_award, we infer + # no award from reports once the scheme stops paying awards. + child_tax_credit_award = benunit("child_tax_credit", period) > 0 + if parameters(period).gov.dwp.tax_credits.active: + child_tax_credit_award = child_tax_credit_award | ( + benunit("would_claim_CTC", period) + & benunit("is_CTC_eligible", period) + ) child_tax_credit_children = benunit.sum( child & person("is_CTC_child_element_included", period) ) From f5c75cbfc3cb6ffa14cac33fbd4867b32c64acd1 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 12:28:33 -0500 Subject: [PATCH 13/22] Qualify the capital limit and child-increment text, and name the actors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tariff documentation and its Scottish comment now say councils apply the £16,000 limit to assessable capital after statutory disregards and disregard all capital for Guarantee Credit recipients. The property module's child invariant states England's Child Tax Credit exception. The changelog, documentation fields and test docstrings name who acts. Co-Authored-By: Claude Opus 5.5 --- changelog.d/1933.fixed.md | 2 +- ..._tax_reduction_child_benefit_properties.py | 6 +-- ...tax_reduction_pension_credit_properties.py | 11 ++--- ...on_pensioner_children_tariff_properties.py | 37 +++++++++-------- ...council_tax_reduction_applicable_amount.py | 13 +++--- ...council_tax_reduction_applicable_income.py | 41 ++++++++++--------- ..._tax_reduction_pensioner_family_premium.py | 6 +-- ...l_tax_reduction_pensioner_tariff_income.py | 36 +++++++++------- 8 files changed, 81 insertions(+), 71 deletions(-) diff --git a/changelog.d/1933.fixed.md b/changelog.d/1933.fixed.md index 86c936388a..3877968f1a 100644 --- a/changelog.d/1933.fixed.md +++ b/changelog.d/1933.fixed.md @@ -1 +1 @@ -Added pensioner child amounts, family premiums and tariff income from capital over £10,000 to the Council Tax Reduction model for England, Scotland and Wales. +Add pensioner child amounts, family premiums and tariff income from capital over £10,000 to Council Tax Reduction in England, Scotland and Wales. diff --git a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py index d3e982b309..5ec02703f8 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py @@ -1,8 +1,8 @@ """Pensioner Child Benefit exclusion and unchanged adjacent CTR contracts. -These model2026 tests use actual Child Benefit claims and family incomes, not -forced applicable income, pensioner status or reduction awards. The 20% cash -relation is conditional on an interior award; the existing floor/cap still apply. +These tests calculate 2026 Council Tax Reduction awards from actual Child +Benefit claims and family incomes. They check the 20% cash relation where the +award lies between the floor and cap. """ from copy import deepcopy diff --git a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py index 73aad105d8..1c760eea79 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py @@ -7,8 +7,8 @@ 24). Capital for the 16,000 limit is calculated under the same Part (SI 2012/2885 reg 11(3); WSI 2013/3029 reg 30(2)), so the limit cannot apply. The award is the maximum reduction less non-dependant deductions. -- Savings credit only: the Secretary of State's assessment of income and - capital is used, adjusted for the savings credit payable (SI 2012/2885 Sch 1 +- Savings credit only: councils use the Secretary of State's assessment of + income and capital and add the savings credit payable (SI 2012/2885 Sch 1 para 14; WSI 2013/3029 Sch 1 para 8; SSI 2012/319 reg 25). Invariants, for any generated population of families, where L is the eligible @@ -539,9 +539,10 @@ def test_not_claiming_pension_credit_never_raises_a_recipients_ctr(units, guaran def test_ctr_income_deducts_tax_before_the_winter_fuel_payment_charge(): - """A pensioner with £39,500 of total income is charged the winter fuel - payment (ITEPA 2003 s.681I) through income tax. CTR deducts the tax - before the charge, so the routes agree with the main definition.""" + """We charge income tax to recover the Winter Fuel Payment from a pensioner + with £39,500 of total income (winter_fuel_payment_charge, ITEPA 2003 + s.681I). CTR deducts income tax before that charge, so the routes agree + with the main definition.""" family = dict( shape="single_pension", ages=[70], diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index 791575937d..26a2d5f0d2 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -1,16 +1,16 @@ """A pensioner's Council Tax Reduction child amounts and tariff income. -Councils' pensioner schemes add an amount for each child or young person in -the family and, in Wales, a family premium (SI 2012/2885 Sch 1 para -6(1)(b)-(c) and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch -2 paras 2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). For 2018-19 to -2024-25 the Secretary of State limited England's to two unless a Child Tax -Credit award included more (SI 2017/1305 reg 7; SI 2025/39 reg 5(2)). A -pensioner's capital counts as a weekly income of £1 for each £500, or part -of £500, over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para -31; SSI 2012/319 reg 27(2)), except where Pension Credit sets the means -test. England and Wales count the excess up to £16,000; Scotland sets no -ceiling. +Councils add an amount for each child or young person in the family and, in +Wales, a family premium for pensioners (SI 2012/2885 Sch 1 para 6(1)(b)-(c) +and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch 2 paras +2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). For 2018-19 to 2024-25 the +Secretary of State limited England's to two unless a Child Tax Credit award +included more (SI 2017/1305 reg 7; SI 2025/39 reg 5(2)). Councils treat a +pensioner's capital as a weekly income of £1 for each £500, or part of £500, +over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI +2012/319 reg 27(2)), except where Pension Credit sets the means test. The +Secretary of State and Welsh Ministers count the excess up to £16,000; the +Scottish Ministers set no ceiling. Each invariant holds on a fixed route and status. The generated families claim no Universal Credit, so neither capital nor a child can move a family @@ -27,13 +27,15 @@ and Wales), and it never falls as capital rises. Capital changes nothing else in the applicable income, and the award never rises with capital. 2. For a family that claims no Universal Credit, adding a dependent child - never lowers the applicable amount. For a pensioner it adds the scheme's - weekly amount for 52 weeks, unless the family already has the two children - that England's limit allowed from 2018-19 to 2024-25, and in Wales the - family premium with the first child. + never lowers the applicable amount. For a pensioner, the child amount + grows by 52 times the scheme's weekly rate for each extra child counted. + In England from 2018-19 to 2024-25, count up to two children, or more + where a Child Tax Credit award includes individual elements for more. Add + the family premium with the first child in Wales. The generated families + report no Child Tax Credit, so none has an award. 3. A pensioner with no child and capital up to £10,000, and every working-age family, gets no child amount, family premium or tariff income, so their - applicable amount, applicable income and award are origin/main's. + applicable amount, applicable income and award match origin/main. test_matches_origin_main_on_unchanged_households checks that against values computed on origin/main. """ @@ -87,7 +89,8 @@ def situation(households, year): - """One benefit unit and household for each spec, in one simulation.""" + """Build one benefit unit and household for each specification in one + simulation.""" data = {"people": {}, "benunits": {}, "households": {}} for index, spec in enumerate(households): members = [] 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 80896abcf3..e6f501bb84 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 @@ -7,13 +7,12 @@ class council_tax_reduction_applicable_amount(Variable): entity = BenUnit label = "applicable Council Tax Reduction amount" documentation = ( - "The applicant's personal allowance and premiums. Ages, couple status " - "and lone-parent status are those of the Council Tax Reduction " - "applicant and partner (is_council_tax_reduction_applicant_or_partner). " - "Where the household head applies alone " - "(council_tax_reduction_head_applies_alone), the head is a single " - "person with no partner or children, whatever the benefit unit's " - "claimant and partner are. Premiums are council_tax_reduction_premiums. " + "We add the personal allowance for the applicant, or for the " + "applicant and partner, and council_tax_reduction_premiums. We take " + "their ages, couple status and lone-parent status from " + "is_council_tax_reduction_applicant_or_partner. When the household " + "head applies alone (council_tax_reduction_head_applies_alone), we " + "treat them as single with no partner or children. " "For a pensioner we also add an amount for each child or young " "person in the family (council_tax_reduction_pensioner_child_amounts) " "and the family premium " diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py index f7212b9578..25f3e0d5c4 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py @@ -7,28 +7,29 @@ class council_tax_reduction_applicable_income(Variable): entity = BenUnit label = "relevant income for Council Tax Reduction means test" documentation = ( - "Income taken into account in the Council Tax Reduction means test. The " - "pensioner schemes disregard the whole income of an applicant who, or " - "whose partner, is in receipt of Pension Credit guarantee credit, and " - "use the Secretary of State's Pension Credit assessment of income, plus " - "the savings credit payable, where the award is savings credit only. " - "Otherwise a pension-age family's net earnings are reduced by the " - "pensioner earnings disregards, and we add its tariff income from " - "capital (council_tax_reduction_pensioner_tariff_income). Great " - "Britain's pensioner schemes " - "also exclude Child Benefit from general-rule income; statutory sick " - "and maternity pay remain counted as earnings. The other adjustments those " - "provisions allow (childcare charges, the £20 earnings disregards " - "and the rest) are not modelled. Spousal maintenance counts less one " + "Councils assess the applicant's and partner's income for the Council " + "Tax Reduction means test. Under the pensioner schemes, councils " + "disregard the whole income of an applicant who, or whose partner, is " + "in receipt of Pension Credit guarantee credit, and use the Secretary " + "of State's Pension Credit assessment of income, plus the savings " + "credit payable, where the award is savings credit only. Otherwise we " + "deduct the pensioner earnings disregards from a pension-age family's " + "net earnings, and add its tariff income from capital " + "(council_tax_reduction_pensioner_tariff_income). Councils in Great " + "Britain also exclude Child Benefit from a pensioner's general-rule " + "income and count statutory sick and maternity pay as earnings. We " + "omit the other " + "adjustments these provisions allow (childcare charges, the £20 " + "earnings disregards and the rest). Spousal maintenance counts less one " "£15 weekly disregard where the applicant's family includes a child " "or young person (the statutory family-premium condition in England's " "default and Welsh schemes). " "Widowed Parent's Allowance counts less £15 weekly per recipient. " - "Child maintenance is excluded. Scotland's working-age maintenance " + "We count no child maintenance. Scotland's working-age maintenance " "rule, like Universal Credit, requires a court order or agreement; " - "the input is assumed to meet that condition. " - "The income counted is the Council Tax Reduction applicant's and " - "partner's (is_council_tax_reduction_applicant_or_partner). " + "we assume the input meets that condition. " + "We count the applicant's and partner's income " + "(is_council_tax_reduction_applicant_or_partner). " "Where the household head applies alone " "(council_tax_reduction_head_applies_alone), the benefit unit's own " "awards (Child Benefit, Income Support, income-based JSA, " @@ -37,10 +38,10 @@ class council_tax_reduction_applicable_income(Variable): "head, so none of them counts. Industrial injuries disablement " "benefit, severe disablement allowance and incapacity benefit count " "in every scheme, for the applicant and partner only, not for " - "children or young persons. War pensions and Armed Forces " - "Compensation Scheme payments are not counted: Scotland disregards or " + "children or young persons. We disregard war pensions and Armed " + "Forces Compensation Scheme payments in full: Scotland disregards or " "omits them, and English and Welsh councils may relieve them beyond " - "the prescribed £10 a week, so the model takes the full disregard." + "the prescribed £10 a week." ) definition_period = YEAR unit = GBP diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py index a46d5d3641..8b6fa8f73a 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py @@ -7,9 +7,9 @@ class council_tax_reduction_pensioner_family_premium(Variable): entity = BenUnit label = "Council Tax Reduction pensioner family premium" documentation = ( - "The family premium in a pensioner's Council Tax Reduction applicable " - "amount, where the family includes a child or young person. The Welsh " - "Ministers keep it. The Secretary of State made England's nil for " + "Councils add the family premium to a pensioner's applicable amount " + "when their family includes a child or young person. The Welsh " + "Ministers retain it. The Secretary of State made England's nil for " "reduction weeks beginning after 1 May 2016, and the Scottish " "Ministers removed Scotland's from 1 May 2016. Each kept it for " "families with a child who had a reduction on 30 April 2016 until " diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index b78080b57e..ae02effeb8 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -7,19 +7,22 @@ class council_tax_reduction_pensioner_tariff_income(Variable): entity = BenUnit label = "Council Tax Reduction pensioner tariff income from capital" documentation = ( - "Weekly income that councils treat a pensioner's capital as " - "yielding, annualised: £1 for each £500, or part of £500, of " - "council_tax_reduction_assessable_capital above £10,000. The " - "Secretary of State and the Welsh Ministers count the excess up to " - "£16,000; the Scottish Ministers set no ceiling, though in every " - "nation nobody with capital over £16,000 gets a reduction. We use " - "the pension-age Housing Benefit tariff amounts, which all three " - "nations share. We give nil on the Pension Credit routes: councils " - "disregard the whole of a guarantee credit recipient's capital, and " - "on a savings-credit-only award they use the Secretary of State's " - "assessment of income, which already includes Pension Credit's " - "deemed income from capital. We also give working-age families nil, " - "because we do not model their tariff income here." + "Councils treat a pensioner's capital as weekly income of £1 for " + "each £500, or part of £500, of " + "council_tax_reduction_assessable_capital above £10,000. We " + "annualise that income. The Secretary of State and the Welsh " + "Ministers count the excess up to £16,000, and the Scottish Ministers " + "set no ceiling. All three bar a reduction where capital exceeds " + "£16,000. Councils apply the £16,000 limit to assessable capital " + "after statutory disregards. Councils disregard all capital for " + "Guarantee Credit recipients. We use the pension-age Housing Benefit " + "tariff amounts, which all three nations share. We give nil on both " + "Pension Credit routes: the guarantee credit disregard covers all " + "capital, and on a savings-credit-only award councils use the " + "Secretary of State's assessment of income, which already includes " + "Pension Credit's deemed income from capital. We also give " + "working-age families nil, because we do not model their tariff " + "income here." ) definition_period = YEAR unit = GBP @@ -45,8 +48,11 @@ def formula(benunit, period, parameters): capital = benunit("council_tax_reduction_assessable_capital", period) # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count # the excess "not exceeding £16,000", the capital limit. The Scottish - # Ministers set no ceiling in SSI 2012/319 reg 27(2); under reg 40 - # nobody with capital above £16,000 gets a reduction. + # Ministers set no ceiling in SSI 2012/319 reg 27(2), and reg 40 bars + # a reduction where capital exceeds £16,000. Councils apply the + # £16,000 limit to assessable capital after statutory disregards (reg + # 41(2)). Councils disregard all capital for Guarantee Credit + # recipients (reg 24). counted_capital = select( [ country == Country.ENGLAND, From c5b07aec7e28d84114efe49600eb54e055a85c14 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 16:07:43 -0500 Subject: [PATCH 14/22] Name HMRC as the payer in the award documentation Documentation and comments only: the child-amount award text names HMRC as the body that pays tax credit awards, the tariff text gives each Pension Credit route its reason, and Case 21's comment cites the claim requirement of TCA 2002 s.3(1). Co-Authored-By: Claude Opus 5.5 --- .../council_tax_reduction_pensioner_child_amounts.yaml | 4 ++-- .../council_tax_reduction_pensioner_child_amounts.py | 4 ++-- .../council_tax_reduction_pensioner_tariff_income.py | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index 78c30176fb..888a81b98f 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -655,8 +655,8 @@ council_tax: 2_000 savings: 0 output: - # Eligibility without a claim is no award (TCA 2002 s.3(1)), and the - # family has no final award either. + # Entitlement depends on a claim (TCA 2002 s.3(1)), so eligibility + # without one gives no award, and the family has no final award either. child_tax_credit: 0 is_CTC_child_element_included: [false, true, true, true] # Para 6(1)(b): up to two. 2 * 83.24 * 52 = 8,656.96. diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index 659590ad5c..4689afcb80 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -13,7 +13,7 @@ class council_tax_reduction_pensioner_child_amounts(Variable): "England's to two children or young persons, unless the applicant's " "Child Tax Credit award included the individual element for more of " "them. We read an award from a positive final child_tax_credit, " - "worked out or entered, or, while the tax credit scheme pays awards " + "worked out or entered, or, while HMRC pays tax credit awards " "(gov.dwp.tax_credits.active), from the claim and eligibility the " "model reads from reports, which keeps an award at a nil rate. We do " "not model the transitional protection for families " @@ -62,7 +62,7 @@ def formula(benunit, period, parameters): # positive final child_tax_credit, worked out or entered, as an # award, and also the claim and eligibility read from reports, # whatever amount is payable. As in has_tax_credit_award, we infer - # no award from reports once the scheme stops paying awards. + # no award from reports once HMRC stops paying awards. child_tax_credit_award = benunit("child_tax_credit", period) > 0 if parameters(period).gov.dwp.tax_credits.active: child_tax_credit_award = child_tax_credit_award | ( diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index ae02effeb8..fef69c0d28 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -17,10 +17,10 @@ class council_tax_reduction_pensioner_tariff_income(Variable): "after statutory disregards. Councils disregard all capital for " "Guarantee Credit recipients. We use the pension-age Housing Benefit " "tariff amounts, which all three nations share. We give nil on both " - "Pension Credit routes: the guarantee credit disregard covers all " - "capital, and on a savings-credit-only award councils use the " - "Secretary of State's assessment of income, which already includes " - "Pension Credit's deemed income from capital. We also give " + "Pension Credit routes: on guarantee credit because of that " + "disregard, and on a savings-credit-only award because councils use " + "the Secretary of State's assessment of income, which already " + "includes Pension Credit's deemed income from capital. We also give " "working-age families nil, because we do not model their tariff " "income here." ) From 547c6825e20bdc15d8b22585eaac35da0aa0cebb Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 02:38:09 -0500 Subject: [PATCH 15/22] Name the actors in the pensioner CTR comments and descriptions Councils, the Secretary of State, the Welsh and Scottish Ministers, HMRC and the model now act in the documentation, docstrings, code and YAML comments and parameter descriptions that #1933 adds. The tariff text keeps the partner limb of the guarantee credit disregard. No formula or expected value changes. Co-Authored-By: Claude Opus 5.5 --- .../child_or_young_person.yaml | 6 +- .../applicable_amount/family_premium.yaml | 2 +- .../child_or_young_person.yaml | 4 +- .../applicable_amount/family_premium.yaml | 2 +- .../child_or_young_person.yaml | 6 +- .../applicable_amount/family_premium.yaml | 2 +- .../council_tax_reduction_pension_credit.yaml | 2 +- ...tax_reduction_pensioner_child_amounts.yaml | 57 +++++++++++-------- ...tax_reduction_pensioner_child_benefit.yaml | 7 ++- ...tax_reduction_pensioner_tariff_income.yaml | 42 +++++++------- ..._tax_reduction_child_benefit_properties.py | 8 ++- ...tax_reduction_pension_credit_properties.py | 17 +++--- ...on_pensioner_children_tariff_properties.py | 50 ++++++++-------- ...council_tax_reduction_applicable_amount.py | 2 +- ...council_tax_reduction_applicable_income.py | 11 ++-- ...l_tax_reduction_pensioner_child_amounts.py | 22 +++---- ..._tax_reduction_pensioner_family_premium.py | 6 +- ...l_tax_reduction_pensioner_tariff_income.py | 25 ++++---- 18 files changed, 145 insertions(+), 126 deletions(-) diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml index 9cc8420714..3b5ec77377 100644 --- a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -1,8 +1,8 @@ description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the England Council Tax Reduction prescribed requirements. The amounts equal the Housing Benefit pension-age child or young person amounts in every year from 2013-14 to 2026-27. values: - # Each value is the paragraph 2 amount in the version of Schedule 2 in - # force on 30 April of that year. The prescribed requirements set it for - # schemes for the financial year from 1 April. + # We take each value from paragraph 2 of the version of Schedule 2 in force + # on 30 April of that year. The Secretary of State sets it for schemes for + # the financial year from 1 April. 2013-04-01: value: 65.62 reference: diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml index 834da9e98e..8ef7a673c4 100644 --- a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -1,4 +1,4 @@ -description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the England Council Tax Reduction prescribed requirements. It is nil for reduction weeks beginning after 1 May 2016. +description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the England Council Tax Reduction prescribed requirements. The Secretary of State made it nil for reduction weeks beginning after 1 May 2016. values: 2013-04-01: value: 17.4 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml index 06ad77698c..020a7bb0b0 100644 --- a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -1,7 +1,7 @@ description: Weekly amount for each child or young person in the applicant's family in the applicable amount under the Scottish State Pension Credit Council Tax Reduction regulations. From 2017-18 it exceeds the Housing Benefit amount by about a quarter. values: - # Each value is the paragraph 3 amount in the version of Schedule 1 in - # force on 30 April of that year. + # We take each value from paragraph 3 of the version of Schedule 1 in force + # on 30 April of that year. 2013-04-01: value: 65.62 reference: diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml index a272ef1e4b..f72fcc4d0e 100644 --- a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -1,4 +1,4 @@ -description: Weekly family premium in the applicable amount of an applicant whose family includes a child or young person, under the Scottish State Pension Credit Council Tax Reduction regulations. Scotland removed it from 1 May 2016. +description: Weekly family premium in the applicable amount of an applicant whose family includes a child or young person, under the Scottish State Pension Credit Council Tax Reduction regulations. The Scottish Ministers removed it from 1 May 2016. values: 2013-04-01: value: 17.4 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml index 7761946ec2..d108904dcc 100644 --- a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/child_or_young_person.yaml @@ -1,7 +1,7 @@ -description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the Welsh Council Tax Reduction prescribed requirements. Wales did not raise it for 2020-21 or 2021-22, so it differs from the Housing Benefit amount in those years. +description: Weekly amount for each child or young person in the applicant's family in the applicable amount of a pensioner under the Welsh Council Tax Reduction prescribed requirements. The Welsh Ministers did not raise it for 2020-21 or 2021-22, so it differs from the Housing Benefit amount in those years. values: - # Each value is the paragraph 2 amount in the version of Schedule 2 in - # force on 30 April of that year, with the amending regulations it reflects. + # We take each value from paragraph 2 of the version of Schedule 2 in force + # on 30 April of that year, and cite the amending regulations it reflects. 2013-04-01: value: 65.62 reference: diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml index f25c0da6bf..5e5c2d1a3b 100644 --- a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/pensioners/applicable_amount/family_premium.yaml @@ -1,4 +1,4 @@ -description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the Welsh Council Tax Reduction prescribed requirements. Wales kept the premium after England and Scotland removed it in 2016. +description: Weekly family premium in the applicable amount of a pensioner whose family includes a child or young person, under the Welsh Council Tax Reduction prescribed requirements. The Welsh Ministers kept the premium after the Secretary of State and the Scottish Ministers ended theirs in 2016. values: 2013-04-01: value: 17.4 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml index a76d56450d..74e8053b69 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pension_credit.yaml @@ -539,7 +539,7 @@ # The limit excludes capital that "exceeds" 16,000 (SI 2012/2885 reg 11(2)). # Tariff income (Sch 1 para 37): (16,000 - 10,000) / 500 = 12 a week, or # 624 a year. Income: 13,000 - 86 income tax + 624 = 13,538, so the - # award is 2,000 - 0.2 * (13,538 - 13,312) = 1,954.80. + # council awards 2,000 - 0.2 * (13,538 - 13,312) = 1,954.80. in_receipt_of_guarantee_credit: false council_tax_reduction_assessable_capital: 16_000 council_tax_reduction_pensioner_tariff_income: 624 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index 888a81b98f..792d906dc4 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -1,24 +1,26 @@ -# A pensioner's Council Tax Reduction applicable amount includes an amount for -# each child or young person in the family and, where the scheme still has one, -# a family premium: +# Councils include in a pensioner's Council Tax Reduction applicable amount an +# amount for each child or young person in the family and, where the scheme +# keeps one, a family premium: # # - England: SI 2012/2885 Sch 1 para 6(1)(b) and (c), Sch 2 paras 2 and 3. -# 2026-27 child or young person amount 87.88 a week (SI 2026/27); the family -# premium is nil for reduction weeks beginning after 1 May 2016. From -# 2018-19 to 2024-25 para 6(1)(b) counted up to two children or young -# persons, or those an award of Child Tax Credit included if more (SI -# 2017/1305 reg 7; removed by SI 2025/39 reg 5(2)). +# 2026-27 child or young person amount 87.88 a week (SI 2026/27); the +# Secretary of State made the family premium nil for reduction weeks +# beginning after 1 May 2016. For the 2018-19 to 2024-25 schemes the +# Secretary of State limited the para 6(1)(b) amounts to two children or +# young persons, or those an award of Child Tax Credit included if more (SI +# 2017/1305 reg 7), then removed the limit (SI 2025/39 reg 5(2)). # - Wales: WSI 2013/3029 Sch 1 para 1(1)(b) and (c), Sch 2 paras 2 and 3. # 2026-27 amounts 87.88 and a family premium of 20.22. # - Scotland: SSI 2012/319 reg 20(b), Sch 1 para 3. 2026-27 amount 109.85; -# the family premium was removed from 1 May 2016 (SSI 2016/81 reg 18). +# the Scottish Ministers removed the family premium from 1 May 2016 (SSI +# 2016/81 reg 18). # # Each amount runs from birth to the day before the 20th birthday, for a # Child Benefit qualifying young person. Every person aged 72 or 80 here -# reached State Pension age before 1 April 2021, so the single or lone parent -# personal allowance is 256.00 a week and the couple allowance 383.35 (SI -# 2012/2885 Sch 2 para 1; WSI 2013/3029 Sch 2 para 1; SSI 2012/319 Sch 1 -# para 2). Annual amounts are 52 weeks. +# reached State Pension age before 1 April 2021, so councils use a single or +# lone parent personal allowance of 256.00 a week and a couple allowance of +# 383.35 (SI 2012/2885 Sch 2 para 1; WSI 2013/3029 Sch 2 para 1; SSI 2012/319 +# Sch 1 para 2). We multiply each weekly amount by 52. - name: Case 1, an English 72-year-old alone gets the personal allowance only. period: 2026 @@ -311,7 +313,7 @@ savings: 0 output: # Para 6(1B) and (1C): the award includes the individual element for - # three, which is more than two. 3 * 83.24 * 52 = 12,985.44. + # three, more than two. 3 * 83.24 * 52 = 12,985.44. council_tax_reduction_pensioner_child_amounts: 12_985.44 - name: Case 11, England's 2025-26 scheme counts every child. @@ -542,7 +544,7 @@ savings: 0 output: # No child_tax_credit_reported, so the model reads no eligibility from - # reports; the entered final award is the award. + # reports; councils count the entered final award. is_CTC_eligible: false child_tax_credit: 9_800.95 # Each child was born before 6 April 2017, so the model includes each @@ -581,8 +583,9 @@ council_tax: 2_000 savings: 0 output: - # A claim without eligibility is no award: is_CTC_eligible needs a - # report, and child_tax_credit is nil without eligibility. + # HMRC makes no award on a claim without eligibility: is_CTC_eligible + # needs a report, and the model gives no child_tax_credit without + # eligibility. is_CTC_eligible: false child_tax_credit: 0 is_CTC_child_element_included: [false, true, true, true] @@ -618,11 +621,12 @@ council_tax: 2_000 savings: 0 output: - # Income of 60,000 withdraws the whole credit, so nothing is payable. + # At income of 60,000 HMRC withdraws the whole credit, so it pays nothing. child_tax_credit: 0 is_CTC_child_element_included: [false, true, true, true] - # Para 6(1B)(a): an award "whether or not any amount is payable". The - # individual elements for three give 3 * 83.24 * 52 = 12,985.44. + # Para 6(1B)(a): an award "whether or not any amount is payable". + # Councils count the three whose individual elements the award includes: + # 3 * 83.24 * 52 = 12,985.44. council_tax_reduction_pensioner_child_amounts: 12_985.44 - name: Case 21, England's 2024-25 scheme counts two of three where the family is eligible for Child Tax Credit but would not claim it. @@ -655,8 +659,9 @@ council_tax: 2_000 savings: 0 output: - # Entitlement depends on a claim (TCA 2002 s.3(1)), so eligibility - # without one gives no award, and the family has no final award either. + # Entitlement depends on a claim (TCA 2002 s.3(1)), so HMRC makes no + # award to a family that is eligible but does not claim, and the model + # gives it no final award either. child_tax_credit: 0 is_CTC_child_element_included: [false, true, true, true] # Para 6(1)(b): up to two. 2 * 83.24 * 52 = 8,656.96. @@ -692,13 +697,15 @@ council_tax: 2_000 savings: 0 output: - # The report still gives a claim and eligibility, but the closed scheme - # pays nothing and has_tax_credit_award infers no award from it. + # The model still reads a claim and eligibility from the report, but HMRC + # pays nothing under the closed scheme and has_tax_credit_award infers no + # award. would_claim_CTC: true is_CTC_eligible: true child_tax_credit: 0 has_tax_credit_award: false council_tax_reduction_pensioner: true is_CTC_child_element_included: [false, true, true, true] - # No award, so para 6(1)(b) counts up to two: 2 * 83.24 * 52 = 8,656.96. + # No award, so councils count up to two under para 6(1)(b): + # 2 * 83.24 * 52 = 8,656.96. council_tax_reduction_pensioner_child_amounts: 8_656.96 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml index 07f997b5c8..683ae4d2e2 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_benefit.yaml @@ -1,8 +1,8 @@ # Current GB pensioner income exclusions: England Sch1 para16(1)(j)(vi), # Wales Sch1 para10(1)(j)(vi), Scotland reg27(1)(j)(vii). # Model2026: eldest Child Benefit27.05*52=1406.60; aged allowance256*52=13312. -# An English pensioner's applicable amount adds 87.88*52=4569.76 for the -# child (SI 2012/2885 Sch 1 para 6(1)(b) and Sch 2 para 2). +# Councils add 87.88*52=4569.76 for the child to an English pensioner's +# applicable amount (SI 2012/2885 Sch 1 para 6(1)(b) and Sch 2 para 2). # These genuine claim/takeup inputs use the general rules, not PC overrides. - name: England pensioner Child Benefit is excluded before the CTR taper # Aged 72: State Pension age was reached in 2019, before 1 April 2021, so @@ -35,7 +35,8 @@ council_tax_reduction_applicable_income: 15314 # 13312 + 4569.76 for the child. council_tax_reduction_applicable_amount: 17881.76 - # 16000 - 686 = 15314 is below 17881.76, so the award is the whole 3000. + # 16000 - 686 = 15314 falls short of 17881.76, so the award covers the + # whole 3000. council_tax_benefit: 3000 council_tax_reduction: 3000 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml index e816b5bd6e..b01961b534 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml @@ -1,18 +1,20 @@ -# Pensioner tariff income from capital. A pensioner's capital counts as a -# weekly income of £1 for each £500 over £10,000, and £1 for any part of £500: -# England SI 2012/2885 Sch 1 para 37 and Wales WSI 2013/3029 Sch 1 para 31 -# (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2), which sets -# no ceiling. Capital over £16,000 ends entitlement (SI 2012/2885 reg 11(2); -# WSI 2013/3029 reg 30; SSI 2012/319 reg 40). Councils disregard a guarantee -# credit recipient's whole capital and income (Sch 1 para 13; Sch 1 para 7; +# Pensioner tariff income from capital. Councils treat a pensioner's capital +# as a weekly income of £1 for each £500 over £10,000, and £1 for any part of +# £500: England SI 2012/2885 Sch 1 para 37 and Wales WSI 2013/3029 Sch 1 para +# 31 (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2), where +# the Scottish Ministers set no ceiling. The Secretary of State, the Welsh +# Ministers and the Scottish Ministers bar a reduction where capital exceeds +# £16,000 (SI 2012/2885 reg 11(2); WSI 2013/3029 reg 30; SSI 2012/319 reg +# 40). Councils disregard the whole capital and income of an applicant who, +# or whose partner, receives guarantee credit (Sch 1 para 13; Sch 1 para 7; # reg 24), and on a savings-credit-only award they use the Secretary of # State's assessment of income (Sch 1 para 14; Sch 1 para 8; reg 25). # -# Each 72-year-old reached State Pension age before 1 April 2021, so the -# applicable amount is 256.00 * 52 = 13,312. A State Pension of 12,570 is -# within the personal allowance, so it bears no income tax. The council tax is -# 2,000 and the pensioner schemes withdraw 20% of income above the applicable -# amount. +# Each 72-year-old reached State Pension age before 1 April 2021, so councils +# use an applicable amount of 256.00 * 52 = 13,312. The income tax personal +# allowance covers a State Pension of 12,570, so the pensioner pays no income +# tax on it. Each household owes council tax of 2,000, and councils withdraw +# 20% of income above the applicable amount. - name: Case 1, England, capital of 10,000 gives no tariff income. period: 2026 @@ -86,7 +88,8 @@ # (16,000 - 10,000) / 500 = 12; 12 * 52 = 624. council_tax_reduction_pensioner_tariff_income: 624 council_tax_reduction_applicable_income: 13_194 - # 13,194 is below 13,312, so the whole council tax. + # 13,194 falls short of 13,312, so the council gives the maximum + # reduction, the whole 2,000. council_tax_reduction: 2_000 - name: Case 4, Scotland, capital of 10,000 gives no tariff income. @@ -335,9 +338,10 @@ council_tax: 2_000 savings: 16_000 output: - # The same as the savings-credit-only case at 16,000 in - # council_tax_reduction_pension_credit.yaml: the Secretary of State's - # income already counts Pension Credit's deemed income from capital. + # As in the savings-credit-only case at 16,000 in + # council_tax_reduction_pension_credit.yaml: the Secretary of State + # already counts Pension Credit's deemed income from capital in the + # assessment of income. in_receipt_of_savings_credit_only: true council_tax_reduction_pensioner_tariff_income: 0 council_tax_reduction_applicable_income: 14_247.02 @@ -442,7 +446,7 @@ savings: 10_001 output: council_tax_reduction_pensioner_tariff_income: 52 - # Cash income nil; half the contributions, 0.5 * 3,000 = 1,500, is - # deducted from it, floored at nil: max(0, 0 - 1,500) = 0. Tariff income - # is a separate source, added after the floor: 0 + 1 * 52 = 52. + # Cash income nil; we deduct half the contributions, 0.5 * 3,000 = 1,500, + # and floor the result at nil: max(0, 0 - 1,500) = 0. We add tariff + # income, a separate source, after the floor: 0 + 1 * 52 = 52. council_tax_reduction_applicable_income: 52 diff --git a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py index 5ec02703f8..fe5facca0c 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_child_benefit_properties.py @@ -1,8 +1,9 @@ """Pensioner Child Benefit exclusion and unchanged adjacent CTR contracts. These tests calculate 2026 Council Tax Reduction awards from actual Child -Benefit claims and family incomes. They check the 20% cash relation where the -award lies between the floor and cap. +Benefit claims and family incomes. Where the award lies between the floor and +the cap, they check that excluding Child Benefit raises it by 20% of the Child +Benefit. """ from copy import deepcopy @@ -81,7 +82,8 @@ def calculate(data, claim, status_first=False): st.sampled_from(sorted(COUNTRIES)), # Income after tax exceeds the applicable amount, which includes the # children's amounts (up to 2 * 109.85 * 52 in Scotland), so the award - # is interior and below the 35,000 Winter Fuel Payment charge threshold. + # falls between the floor and the cap, and total income stays under the + # £35,000 Winter Fuel Payment charge threshold. st.integers(30000, 34000), st.integers(1, 2), st.booleans(), diff --git a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py index 1c760eea79..7c83ba5086 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py @@ -295,12 +295,13 @@ def situation( # 2013/3029 Sch 3; SSI 2012/319 Sch 2). PENSIONER_FLAT_DISREGARD = {"lone_parent": 25, "couple": 10, "single": 5} PENSIONER_ADDITIONAL_DISREGARD = 17.10 -# Since #1933, a pensioner family's general-rules income also adds tariff -# income from capital after the floor, written out from the law: £1 a week +# We also add tariff income from capital to a pensioner family's +# general-rules income, after the floor, written out from the law: £1 a week # for each £500, or part of £500, of capital above £10,000, up to £16,000 in # England and Wales (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31) -# and with no ceiling in Scotland (SSI 2012/319 reg 27(2)). Household -# savings are these families' capital. +# and with no ceiling in Scotland (SSI 2012/319 reg 27(2)). We count +# household savings as these families' capital, as +# council_tax_reduction_assessable_capital does. TARIFF_THRESHOLD = 10_000 TARIFF_STEP = 500 HOUSEHOLD_VARIABLES = [ @@ -539,10 +540,10 @@ def test_not_claiming_pension_credit_never_raises_a_recipients_ctr(units, guaran def test_ctr_income_deducts_tax_before_the_winter_fuel_payment_charge(): - """We charge income tax to recover the Winter Fuel Payment from a pensioner - with £39,500 of total income (winter_fuel_payment_charge, ITEPA 2003 - s.681I). CTR deducts income tax before that charge, so the routes agree - with the main definition.""" + """This pensioner's total income of £39,500 exceeds £35,000, so they owe + income tax equal to their Winter Fuel Payment (ITEPA 2003 s.681I(1) and + (3); winter_fuel_payment_charge). CTR deducts income tax before that + charge, so the routes agree with the main definition.""" family = dict( shape="single_pension", ages=[70], diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index 26a2d5f0d2..dacfcc5662 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -1,14 +1,14 @@ """A pensioner's Council Tax Reduction child amounts and tariff income. -Councils add an amount for each child or young person in the family and, in -Wales, a family premium for pensioners (SI 2012/2885 Sch 1 para 6(1)(b)-(c) -and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch 2 paras -2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). For 2018-19 to 2024-25 the -Secretary of State limited England's to two unless a Child Tax Credit award -included more (SI 2017/1305 reg 7; SI 2025/39 reg 5(2)). Councils treat a -pensioner's capital as a weekly income of £1 for each £500, or part of £500, -over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI -2012/319 reg 27(2)), except where Pension Credit sets the means test. The +Under their pensioner schemes, councils add an amount for each child or young +person in the family and, in Wales, a family premium (SI 2012/2885 Sch 1 para +6(1)(b)-(c) and Sch 2 paras 2-3; WSI 2013/3029 Sch 1 para 1(1)(b)-(c) and Sch +2 paras 2-3; SSI 2012/319 reg 20(b) and Sch 1 para 3). For 2018-19 to 2024-25 +the Secretary of State limited England's child amounts to two unless a Child +Tax Credit award included more (SI 2017/1305 reg 7; SI 2025/39 reg 5(2)). +Councils treat a pensioner's capital as a weekly income of £1 for each £500, +or part of £500, over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch +1 para 31; SSI 2012/319 reg 27(2)), except on the Pension Credit routes. The Secretary of State and Welsh Ministers count the excess up to £16,000; the Scottish Ministers set no ceiling. @@ -16,22 +16,23 @@ claim no Universal Credit, so neither capital nor a child can move a family between the pensioner and working-age schemes, and the first invariant's pensioners claim no Pension Credit, so capital cannot move them onto a -Pension Credit route. Off those routes both can move, as the model intends: -capital changes a savings-credit-only pensioner's applicable income through -the Secretary of State's assessment, and a child who brings Universal Credit -into payment for a mixed-age couple moves them to the working-age scheme, -whose applicable amount can be lower. +Pension Credit route. Off those routes both can move. For a +savings-credit-only pensioner, councils use the Secretary of State's +assessment, which includes Pension Credit's deemed income from capital, so +capital can raise their applicable income. A mixed-age couple who gain a child, and so start to receive +Universal Credit, move to the working-age scheme, whose applicable amount can +be lower. 1. For a pensioner off Pension Credit, tariff income is 52 times £1 for each £500, or part of £500, of capital above £10,000 (up to £16,000 in England and Wales), and it never falls as capital rises. Capital changes nothing else in the applicable income, and the award never rises with capital. 2. For a family that claims no Universal Credit, adding a dependent child - never lowers the applicable amount. For a pensioner, the child amount - grows by 52 times the scheme's weekly rate for each extra child counted. - In England from 2018-19 to 2024-25, count up to two children, or more - where a Child Tax Credit award includes individual elements for more. Add - the family premium with the first child in Wales. The generated families + never lowers the applicable amount. For a pensioner, councils add 52 times + the scheme's weekly rate for each extra child they count. In England from + 2018-19 to 2024-25, they count up to two children, or more where a Child + Tax Credit award includes individual elements for more. In Wales, councils + also add the family premium with the first child. The generated families report no Child Tax Credit, so none has an award. 3. A pensioner with no child and capital up to £10,000, and every working-age family, gets no child amount, family premium or tariff income, so their @@ -133,8 +134,8 @@ def calculate(households, year, names=OUTPUTS): def tariff(capital, country): - # England and Wales count the excess "not exceeding £16,000"; Scotland's - # reg 27(2) sets no ceiling. + # The Secretary of State and the Welsh Ministers count the excess "not + # exceeding £16,000"; the Scottish Ministers set no ceiling in reg 27(2). counted = capital if country == "SCOTLAND" else min(capital, 16_000) return 52 * math.ceil(max(0, counted - 10_000) / 500) @@ -180,7 +181,8 @@ def test_tariff_income_is_the_tariff_and_never_falls_as_capital_rises( tariffs, [tariff(c, base["country"]) for c in capitals], atol=0.01 ) assert (np.diff(tariffs) >= 0).all() - # Capital adds the tariff income and nothing else. + # As capital rises, the model changes only the tariff income within the + # applicable income. other_income = result["council_tax_reduction_applicable_income"] - tariffs np.testing.assert_allclose(other_income, other_income[0], atol=0.01) assert (np.diff(result["council_tax_benefit"]) <= 0.01).all() @@ -323,8 +325,8 @@ def test_northern_ireland_gets_no_new_amounts(): "council_tax_reduction_applicable_income", "council_tax_benefit", ) -# Computed on origin/main at 2da212abc for UNCHANGED_HOUSEHOLDS, in order: -# applicable amount, applicable income and council_tax_benefit. +# We computed these on origin/main at 2da212abc for UNCHANGED_HOUSEHOLDS, in +# order: applicable amount, applicable income and council_tax_benefit. ORIGIN_MAIN = { 2019: [ (9_412, 12_000, 1_482.4), 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 e6f501bb84..8507549d97 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 @@ -100,7 +100,7 @@ def formula(benunit, period, parameters): + lone_parent * lone_parent_personal_allowance ) * WEEKS_IN_YEAR # We currently include the severe disability and carer premiums for - # pensioners; the same pensioner test chooses the schedule. + # pensioners, and choose the schedule by the same pensioner test. premiums = benunit("council_tax_reduction_premiums", period) # A pensioner's amounts for the children and young persons in the # family and the family premium (SI 2012/2885 Sch 1 para 6(1)(b)-(c); diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py index 25f3e0d5c4..bc7385f8db 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py @@ -7,8 +7,9 @@ class council_tax_reduction_applicable_income(Variable): entity = BenUnit label = "relevant income for Council Tax Reduction means test" documentation = ( - "Councils assess the applicant's and partner's income for the Council " - "Tax Reduction means test. Under the pensioner schemes, councils " + "We count the applicant's and partner's income " + "(is_council_tax_reduction_applicant_or_partner) in the Council Tax " + "Reduction means test. Under the pensioner schemes, councils " "disregard the whole income of an applicant who, or whose partner, is " "in receipt of Pension Credit guarantee credit, and use the Secretary " "of State's Pension Credit assessment of income, plus the savings " @@ -28,8 +29,6 @@ class council_tax_reduction_applicable_income(Variable): "We count no child maintenance. Scotland's working-age maintenance " "rule, like Universal Credit, requires a court order or agreement; " "we assume the input meets that condition. " - "We count the applicant's and partner's income " - "(is_council_tax_reduction_applicant_or_partner). " "Where the household head applies alone " "(council_tax_reduction_head_applies_alone), the benefit unit's own " "awards (Child Benefit, Income Support, income-based JSA, " @@ -39,8 +38,8 @@ class council_tax_reduction_applicable_income(Variable): "benefit, severe disablement allowance and incapacity benefit count " "in every scheme, for the applicant and partner only, not for " "children or young persons. We disregard war pensions and Armed " - "Forces Compensation Scheme payments in full: Scotland disregards or " - "omits them, and English and Welsh councils may relieve them beyond " + "Forces Compensation Scheme payments in full: Scottish councils count " + "none of them, and English and Welsh councils may relieve them beyond " "the prescribed £10 a week." ) definition_period = YEAR diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index 4689afcb80..b670528672 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -10,13 +10,13 @@ class council_tax_reduction_pensioner_child_amounts(Variable): "Councils add one weekly amount for each child or young person in a " "pensioner's family to the Council Tax Reduction applicable amount. " "For the 2018-19 to 2024-25 schemes the Secretary of State limited " - "England's to two children or young persons, unless the applicant's " - "Child Tax Credit award included the individual element for more of " - "them. We read an award from a positive final child_tax_credit, " - "worked out or entered, or, while HMRC pays tax credit awards " - "(gov.dwp.tax_credits.active), from the claim and eligibility the " - "model reads from reports, which keeps an award at a nil rate. We do " - "not model the transitional protection for families " + "England's child amounts to two children or young persons, unless " + "the applicant's Child Tax Credit award included the individual " + "element for more of them. We read an award from a positive final " + "child_tax_credit, worked out or entered. While HMRC pays tax credit " + "awards (gov.dwp.tax_credits.active), we also count an award, even a " + "nil-rate one, where the model reads a claim and eligibility from " + "reports. We do not model the transitional protection for families " "with more than two on 31 March 2018. Where the household head " "applies alone (council_tax_reduction_head_applies_alone), we assume " "the head has no children in their family, because we cannot " @@ -54,14 +54,14 @@ def formula(benunit, period, parameters): # SI 2012/2885 Sch 1 para 6(1)(b) and (1A) to (1C), from SI # 2017/1305 reg 7: up to two, or those whose individual element # an award of Child Tax Credit includes where that gives more. - # Every child or young person has the same amount, so the - # greatest total is the greatest count. + # Every child or young person has the same amount, so counting + # the most children gives the greatest total. # Councils apply para 6(1B)(a) where the applicant has an award # of Child Tax Credit "whether or not any amount is payable", and # HMRC may award it at a nil rate (TCA 2002 s.14(3)). We count a # positive final child_tax_credit, worked out or entered, as an - # award, and also the claim and eligibility read from reports, - # whatever amount is payable. As in has_tax_credit_award, we infer + # award, and also the claim and eligibility that the model reads + # from reports, whatever amount is payable. As in has_tax_credit_award, we infer # no award from reports once HMRC stops paying awards. child_tax_credit_award = benunit("child_tax_credit", period) > 0 if parameters(period).gov.dwp.tax_credits.active: diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py index 8b6fa8f73a..408607e2b6 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_family_premium.py @@ -14,8 +14,8 @@ class council_tax_reduction_pensioner_family_premium(Variable): "Ministers removed Scotland's from 1 May 2016. Each kept it for " "families with a child who had a reduction on 30 April 2016 until " "they make a new application or have no child; we do not model that " - "protection. We read each year's amount on 30 April, so model year " - "2016 keeps the premium." + "protection. We read each year's amount on 30 April, so we keep the " + "premium for the whole of model year 2016." ) definition_period = YEAR unit = GBP @@ -50,7 +50,7 @@ def formula(benunit, period, parameters): default=0, ) pensioner = benunit("council_tax_reduction_pensioner", period) - # The head who applies alone has no children in their family. + # We assume the head who applies alone has no children in their family. has_child = ~benunit( "council_tax_reduction_head_applies_alone", period ) & benunit( diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index fef69c0d28..f6b8f9204e 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -14,9 +14,11 @@ class council_tax_reduction_pensioner_tariff_income(Variable): "Ministers count the excess up to £16,000, and the Scottish Ministers " "set no ceiling. All three bar a reduction where capital exceeds " "£16,000. Councils apply the £16,000 limit to assessable capital " - "after statutory disregards. Councils disregard all capital for " - "Guarantee Credit recipients. We use the pension-age Housing Benefit " - "tariff amounts, which all three nations share. We give nil on both " + "after statutory disregards, and disregard all of an applicant's " + "capital where the applicant or their partner receives guarantee " + "credit. We use the pension-age Housing Benefit tariff amounts, which " + "the Secretary of State, the Welsh Ministers and the Scottish " + "Ministers also set. We give nil on both " "Pension Credit routes: on guarantee credit because of that " "disregard, and on a savings-credit-only award because councils use " "the Secretary of State's assessment of income, which already " @@ -46,13 +48,14 @@ def formula(benunit, period, parameters): local_authorities = parameters(period).gov.local_authorities country = benunit.household("country", period) capital = benunit("council_tax_reduction_assessable_capital", period) - # SI 2012/2885 Sch 1 para 37 and WSI 2013/3029 Sch 1 para 31 count - # the excess "not exceeding £16,000", the capital limit. The Scottish - # Ministers set no ceiling in SSI 2012/319 reg 27(2), and reg 40 bars - # a reduction where capital exceeds £16,000. Councils apply the - # £16,000 limit to assessable capital after statutory disregards (reg - # 41(2)). Councils disregard all capital for Guarantee Credit - # recipients (reg 24). + # The Secretary of State and the Welsh Ministers count the excess "not + # exceeding £16,000", the capital limit (SI 2012/2885 Sch 1 para 37; + # WSI 2013/3029 Sch 1 para 31). The Scottish Ministers set no ceiling + # in SSI 2012/319 reg 27(2), and bar a reduction where capital exceeds + # £16,000 (reg 40). Councils apply the £16,000 limit to assessable + # capital after statutory disregards (reg 41(2)), and disregard all of + # an applicant's capital where the applicant or their partner receives + # guarantee credit (reg 24). counted_capital = select( [ country == Country.ENGLAND, @@ -77,7 +80,7 @@ def formula(benunit, period, parameters): # The Pension Credit routes (England Sch 1 paras 13 and 14, Wales # Sch 1 paras 7 and 8, Scotland regs 24 and 25), as in # council_tax_reduction_applicable_income. The benefit unit's - # Pension Credit is its claimant's and partner's. + # Pension Credit belongs to its claimant and partner. applicant_family = ~benunit("council_tax_reduction_head_applies_alone", period) pension_credit_route = applicant_family & ( benunit("in_receipt_of_guarantee_credit", period) From 10c3df4bd655a2af1362c711af8c6665505c198a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 02:38:13 -0500 Subject: [PATCH 16/22] Pin an entered Child Tax Credit award after a reform closes tax credits Case 23 takes Case 22's reform and household and enters a final award of 9,800.95. Councils count the award under SI 2012/2885 Sch 1 para 6(1B)(a) and (1C), so all three children count: 3 * 83.24 * 52 = 12,985.44. Co-Authored-By: Claude Opus 5.5 --- ...tax_reduction_pensioner_child_amounts.yaml | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index 792d906dc4..862ba45801 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -709,3 +709,49 @@ # No award, so councils count up to two under para 6(1)(b): # 2 * 83.24 * 52 = 8,656.96. council_tax_reduction_pensioner_child_amounts: 8_656.96 + +- name: Case 23, England's 2024-25 scheme counts all three where a reform ends tax credits and the user enters a final Child Tax Credit award. + period: 2024 + absolute_error_margin: 0.01 + input: + gov.dwp.tax_credits.active: false + people: + pensioner: + age: 72 + state_pension: 23_000 + child_tax_credit_reported: 1 + child_1: + age: 10 + child_2: + age: 12 + child_3: + age: 14 + benunits: + benunit: + members: [pensioner, child_1, child_2, child_3] + would_claim_pc: false + would_claim_uc: false + child_tax_credit: 9_800.95 + households: + household: + members: [pensioner, child_1, child_2, child_3] + country: ENGLAND + local_authority: MAIDSTONE + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + savings: 0 + output: + # Under the reform has_tax_credit_award infers no award from the report, + # but the user entered the final award HMRC made. + child_tax_credit: 9_800.95 + has_tax_credit_award: false + council_tax_reduction_pensioner: true + is_CTC_child_element_included: [false, true, true, true] + # Councils apply SI 2012/2885 Sch 1 para 6(1C) where the applicant "has + # an award of child tax credit" (para 6(1B)(a)) and it gives more than + # para 6(1)(b), so they count the entered award. They count each child + # whose individual element it includes: three, more than the two under + # para 6(1)(b). The Secretary of State set the 2024-25 amount at + # 83.24 a week (Sch 2 para 2(1), as SI 2024/29 amended it), so + # 3 * 83.24 * 52 = 12,985.44. + council_tax_reduction_pensioner_child_amounts: 12_985.44 From e8831fb6b295d0c959b4694913574366997b26b3 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 2 Nov 2026 02:53:40 -0500 Subject: [PATCH 17/22] Rewrap two comment lines to the 88-character limit Co-Authored-By: Claude Opus 5.5 --- ...il_tax_reduction_pensioner_children_tariff_properties.py | 6 +++--- .../council_tax_reduction_pensioner_child_amounts.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index dacfcc5662..d24d35e242 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -19,9 +19,9 @@ Pension Credit route. Off those routes both can move. For a savings-credit-only pensioner, councils use the Secretary of State's assessment, which includes Pension Credit's deemed income from capital, so -capital can raise their applicable income. A mixed-age couple who gain a child, and so start to receive -Universal Credit, move to the working-age scheme, whose applicable amount can -be lower. +capital can raise their applicable income. A mixed-age couple who gain a +child, and so start to receive Universal Credit, move to the working-age +scheme, whose applicable amount can be lower. 1. For a pensioner off Pension Credit, tariff income is 52 times £1 for each £500, or part of £500, of capital above £10,000 (up to £16,000 in England diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py index b670528672..a3afe5ab76 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.py @@ -61,8 +61,9 @@ def formula(benunit, period, parameters): # HMRC may award it at a nil rate (TCA 2002 s.14(3)). We count a # positive final child_tax_credit, worked out or entered, as an # award, and also the claim and eligibility that the model reads - # from reports, whatever amount is payable. As in has_tax_credit_award, we infer - # no award from reports once HMRC stops paying awards. + # from reports, whatever amount is payable. As in + # has_tax_credit_award, we infer no award from reports once HMRC + # stops paying awards. child_tax_credit_award = benunit("child_tax_credit", period) > 0 if parameters(period).gov.dwp.tax_credits.active: child_tax_credit_award = child_tax_credit_award | ( From 06e51a8ab57d5c2bce6f98c3b2f0f763b17b6a0a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 2 Nov 2026 16:00:28 +0000 Subject: [PATCH 18/22] Clarify the Case 23 comment and the tariff income documentation Name the award and the counting rule where the Case 23 comment said "it", and cite SI 2024/29 reg 6(3) for the 2024-25 child amount. Say that the pension-age Housing Benefit tariff amounts equal those each Council Tax Reduction scheme sets. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LwQq6Gz4VGd6Cph9n66gKW --- ...ouncil_tax_reduction_pensioner_child_amounts.yaml | 12 ++++++------ .../council_tax_reduction_pensioner_tariff_income.py | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml index 862ba45801..aa0dc81a1a 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_amounts.yaml @@ -748,10 +748,10 @@ council_tax_reduction_pensioner: true is_CTC_child_element_included: [false, true, true, true] # Councils apply SI 2012/2885 Sch 1 para 6(1C) where the applicant "has - # an award of child tax credit" (para 6(1B)(a)) and it gives more than - # para 6(1)(b), so they count the entered award. They count each child - # whose individual element it includes: three, more than the two under - # para 6(1)(b). The Secretary of State set the 2024-25 amount at - # 83.24 a week (Sch 2 para 2(1), as SI 2024/29 amended it), so - # 3 * 83.24 * 52 = 12,985.44. + # an award of child tax credit" (para 6(1B)(a)) and counting under (1C) + # gives more than para 6(1)(b), so they count the entered award. They + # count each child whose individual element the award includes: three, + # more than the two under para 6(1)(b). The Secretary of State set the + # 2024-25 amount at 83.24 a week (Sch 2 para 2(1), as SI 2024/29 reg 6(3) + # substituted it), so 3 * 83.24 * 52 = 12,985.44. council_tax_reduction_pensioner_child_amounts: 12_985.44 diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py index f6b8f9204e..90014a52f3 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py @@ -17,8 +17,9 @@ class council_tax_reduction_pensioner_tariff_income(Variable): "after statutory disregards, and disregard all of an applicant's " "capital where the applicant or their partner receives guarantee " "credit. We use the pension-age Housing Benefit tariff amounts, which " - "the Secretary of State, the Welsh Ministers and the Scottish " - "Ministers also set. We give nil on both " + "equal those the Secretary of State, the Welsh Ministers and the " + "Scottish Ministers set for their Council Tax Reduction schemes. We " + "give nil on both " "Pension Credit routes: on guarantee credit because of that " "disregard, and on a savings-credit-only award because councils use " "the Secretary of State's assessment of income, which already " From aec20b6185b8f9d48d61e192229ca97cbe51dff9 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 13:09:05 +0000 Subject: [PATCH 19/22] Use main's CTR tariff income for pensioners and drop the duplicate Delete council_tax_reduction_pensioner_tariff_income, which the merge left unused, and point the pensioner tariff YAML and property tests at council_tax_reduction_tariff_income. That variable also carries the Welsh and Scottish working-age tariffs, so tariff Case 14 (a Welsh earner aged 40 with 12,000 of capital) now expects 1,248 (24 * 52 under WSI 2013/3029 Sch 6 para 33), the property test checks nil tariff income at working age only in England, and the frozen differential now holds main's values at 9dd44e142, which add those working-age tariffs in Wales and Scotland. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LwQq6HDAHLr6RSvBAdeFM1 --- ...tax_reduction_pensioner_tariff_income.yaml | 52 +++++----- ...on_pensioner_children_tariff_properties.py | 69 ++++++++------ ...council_tax_reduction_applicable_income.py | 2 +- ...l_tax_reduction_pensioner_tariff_income.py | 95 ------------------- 4 files changed, 69 insertions(+), 149 deletions(-) delete mode 100644 policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml index b01961b534..732ae42984 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.yaml @@ -1,8 +1,10 @@ -# Pensioner tariff income from capital. Councils treat a pensioner's capital -# as a weekly income of £1 for each £500 over £10,000, and £1 for any part of -# £500: England SI 2012/2885 Sch 1 para 37 and Wales WSI 2013/3029 Sch 1 para -# 31 (each "not exceeding £16,000"), Scotland SSI 2012/319 reg 27(2), where -# the Scottish Ministers set no ceiling. The Secretary of State, the Welsh +# Pensioner tariff income from capital, in council_tax_reduction_tariff_income, +# which also carries working-age tariff income in Wales and Scotland (Case 14). +# Councils treat a pensioner's capital as a weekly income of £1 for each £500 +# over £10,000, and £1 for any part of £500: England SI 2012/2885 Sch 1 para +# 37 and Wales WSI 2013/3029 Sch 1 para 31 (each "not exceeding £16,000"), +# Scotland SSI 2012/319 reg 27(2), where the Scottish Ministers set no +# ceiling. The Secretary of State, the Welsh # Ministers and the Scottish Ministers bar a reduction where capital exceeds # £16,000 (SI 2012/2885 reg 11(2); WSI 2013/3029 reg 30; SSI 2012/319 reg # 40). Councils disregard the whole capital and income of an applicant who, @@ -37,7 +39,7 @@ council_tax: 2_000 savings: 10_000 output: - council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_tariff_income: 0 council_tax_reduction_applicable_income: 12_570 - name: Case 2, England, capital of 10,001 gives 1 a week for the part of 500. @@ -61,7 +63,7 @@ council_tax: 2_000 savings: 10_001 output: - council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_tariff_income: 1 * 52 council_tax_reduction_applicable_income: 12_570 + 52 - name: Case 3, England, capital of 16,000 gives 12 a week. @@ -86,7 +88,7 @@ savings: 16_000 output: # (16,000 - 10,000) / 500 = 12; 12 * 52 = 624. - council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_tariff_income: 624 council_tax_reduction_applicable_income: 13_194 # 13,194 falls short of 13,312, so the council gives the maximum # reduction, the whole 2,000. @@ -113,7 +115,7 @@ council_tax: 2_000 savings: 10_000 output: - council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_tariff_income: 0 council_tax_reduction_applicable_income: 12_570 - name: Case 5, Scotland, capital of 10,001 gives 1 a week for the part of 500. @@ -137,7 +139,7 @@ council_tax: 2_000 savings: 10_001 output: - council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_tariff_income: 1 * 52 council_tax_reduction_applicable_income: 12_570 + 52 - name: Case 6, Scotland, capital of 16,000 gives 12 a week. @@ -161,7 +163,7 @@ council_tax: 2_000 savings: 16_000 output: - council_tax_reduction_pensioner_tariff_income: 12 * 52 + council_tax_reduction_tariff_income: 12 * 52 council_tax_reduction_applicable_income: 12_570 + 12 * 52 council_tax_reduction: 2_000 @@ -186,7 +188,7 @@ council_tax: 2_000 savings: 10_000 output: - council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_tariff_income: 0 council_tax_reduction_applicable_income: 12_570 - name: Case 8, Wales, capital of 10,001 gives 1 a week for the part of 500. @@ -210,7 +212,7 @@ council_tax: 2_000 savings: 10_001 output: - council_tax_reduction_pensioner_tariff_income: 1 * 52 + council_tax_reduction_tariff_income: 1 * 52 council_tax_reduction_applicable_income: 12_570 + 52 - name: Case 9, Wales, capital of 16,000 gives 12 a week. @@ -234,7 +236,7 @@ council_tax: 2_000 savings: 16_000 output: - council_tax_reduction_pensioner_tariff_income: 12 * 52 + council_tax_reduction_tariff_income: 12 * 52 council_tax_reduction_applicable_income: 12_570 + 12 * 52 council_tax_reduction: 2_000 @@ -261,7 +263,7 @@ output: # Income tax: (15,000 - 12,570) * 0.2 = 486. Income 15,000 - 486 + 624 # = 15,138. Award 2,000 - 0.2 * (15,138 - 13,312) = 1,634.80. - council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_tariff_income: 624 council_tax_reduction_applicable_income: 15_138 council_tax_reduction: 1_634.80 @@ -286,7 +288,7 @@ council_tax: 2_000 savings: 20_000 output: - council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_tariff_income: 624 council_tax_reduction: 0 - name: Case 12, a guarantee credit recipient's capital is wholly disregarded. @@ -312,7 +314,7 @@ output: in_receipt_of_guarantee_credit: true council_tax_reduction_assessable_capital: 0 - council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_tariff_income: 0 council_tax_reduction_applicable_income: 0 council_tax_reduction: 2_000 @@ -343,10 +345,10 @@ # already counts Pension Credit's deemed income from capital in the # assessment of income. in_receipt_of_savings_credit_only: true - council_tax_reduction_pensioner_tariff_income: 0 + council_tax_reduction_tariff_income: 0 council_tax_reduction_applicable_income: 14_247.02 -- name: Case 14, a working-age Welsh earner's capital gives no tariff income here. +- name: Case 14, a working-age Welsh earner's capital gives the working-age tariff, not the pensioner one. period: 2026 absolute_error_margin: 0.01 input: @@ -367,7 +369,11 @@ savings: 12_000 output: council_tax_reduction_pensioner: false - council_tax_reduction_pensioner_tariff_income: 0 + # The Welsh Ministers' working-age tariff (WSI 2013/3029 Sch 6 para 33): + # 1 a week for each 250, or part of 250, over 6,000. + # (12,000 - 6,000) / 250 = 24; 24 * 52 = 1,248. The pensioner tariff + # would give (12,000 - 10,000) / 500 = 4 a week, or 208 a year. + council_tax_reduction_tariff_income: 1_248 - name: Case 15, Scotland, capital of 20,000 gives 20 a week, with no ceiling, and the capital limit ends entitlement. period: 2026 @@ -392,7 +398,7 @@ output: # SSI 2012/319 reg 27(2): (20,000 - 10,000) / 500 = 20; 20 * 1 * 52 = # 1,040. - council_tax_reduction_pensioner_tariff_income: 1_040 + council_tax_reduction_tariff_income: 1_040 # Reg 40: capital over 16,000, so no reduction. council_tax_reduction: 0 @@ -419,7 +425,7 @@ output: # WSI 2013/3029 Sch 1 para 31, "not exceeding £16,000": # (16,000 - 10,000) / 500 = 12; 12 * 52 = 624. - council_tax_reduction_pensioner_tariff_income: 624 + council_tax_reduction_tariff_income: 624 # Reg 30: capital over 16,000, so no reduction. council_tax_reduction: 0 @@ -445,7 +451,7 @@ council_tax: 2_000 savings: 10_001 output: - council_tax_reduction_pensioner_tariff_income: 52 + council_tax_reduction_tariff_income: 52 # Cash income nil; we deduct half the contributions, 0.5 * 3,000 = 1,500, # and floor the result at nil: max(0, 0 - 1,500) = 0. We add tariff # income, a separate source, after the floor: 0 + 1 * 52 = 52. diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index d24d35e242..c350a67c19 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -10,7 +10,9 @@ or part of £500, over £10,000 (SI 2012/2885 Sch 1 para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg 27(2)), except on the Pension Credit routes. The Secretary of State and Welsh Ministers count the excess up to £16,000; the -Scottish Ministers set no ceiling. +Scottish Ministers set no ceiling. council_tax_reduction_tariff_income +carries that pensioner tariff, and also the Welsh and Scottish working-age +tariffs, which these tests do not recompute. Each invariant holds on a fixed route and status. The generated families claim no Universal Credit, so neither capital nor a child can move a family @@ -34,11 +36,13 @@ Tax Credit award includes individual elements for more. In Wales, councils also add the family premium with the first child. The generated families report no Child Tax Credit, so none has an award. -3. A pensioner with no child and capital up to £10,000, and every working-age - family, gets no child amount, family premium or tariff income, so their - applicable amount, applicable income and award match origin/main. +3. A pensioner with no child and capital up to £10,000 gets no child amount, + family premium or tariff income, and a working-age family gets no child + amount or family premium, so their applicable amount, applicable income + and award match main. An English working-age family also gets no tariff + income here, because its local scheme sets its own. test_matches_origin_main_on_unchanged_households checks that against - values computed on origin/main. + values computed on main. """ import math @@ -78,7 +82,7 @@ "council_tax_reduction_applicable_income", "council_tax_reduction_pensioner_child_amounts", "council_tax_reduction_pensioner_family_premium", - "council_tax_reduction_pensioner_tariff_income", + "council_tax_reduction_tariff_income", "council_tax_benefit", ) SETTINGS = settings( @@ -176,7 +180,7 @@ def test_tariff_income_is_the_tariff_and_never_falls_as_capital_rises( households = [dict(base, savings=capital) for capital in capitals] result = calculate(households, year) assert result["council_tax_reduction_pensioner"].all() - tariffs = result["council_tax_reduction_pensioner_tariff_income"] + tariffs = result["council_tax_reduction_tariff_income"] np.testing.assert_allclose( tariffs, [tariff(c, base["country"]) for c in capitals], atol=0.01 ) @@ -239,9 +243,11 @@ def test_no_new_amounts_without_a_child_or_capital_over_10000_or_at_working_age( for index, spec in enumerate(households): child_amounts = result["council_tax_reduction_pensioner_child_amounts"][index] premium = result["council_tax_reduction_pensioner_family_premium"][index] - tariff_income = result["council_tax_reduction_pensioner_tariff_income"][index] + tariff_income = result["council_tax_reduction_tariff_income"][index] if not pensioner[index]: - assert child_amounts == premium == tariff_income == 0 + assert child_amounts == premium == 0 + if spec["country"] == "ENGLAND": + assert tariff_income == 0 continue if not spec["children"]: assert child_amounts == premium == 0 @@ -261,7 +267,7 @@ def test_northern_ireland_gets_no_new_amounts(): result = calculate([spec], 2026) assert result["council_tax_reduction_pensioner_child_amounts"][0] == 0 assert result["council_tax_reduction_pensioner_family_premium"][0] == 0 - assert result["council_tax_reduction_pensioner_tariff_income"][0] == 0 + assert result["council_tax_reduction_tariff_income"][0] == 0 # Pensioners with no child and capital up to £10,000, and working-age @@ -325,8 +331,11 @@ def test_northern_ireland_gets_no_new_amounts(): "council_tax_reduction_applicable_income", "council_tax_benefit", ) -# We computed these on origin/main at 2da212abc for UNCHANGED_HOUSEHOLDS, in -# order: applicable amount, applicable income and council_tax_benefit. +# We computed these on main at 9dd44e142 for UNCHANGED_HOUSEHOLDS, in order: +# applicable amount, applicable income and council_tax_benefit. In Scotland +# and Wales the working-age families with savings of 12,000, 16,000 and 8,000 +# have working-age tariff income of 1 a week for each 250, or part, over +# 6,000: 24 * 52 = 1,248, 40 * 52 = 2,080 and 8 * 52 = 416 a year. ORIGIN_MAIN = { 2019: [ (9_412, 12_000, 1_482.4), @@ -338,15 +347,15 @@ def test_northern_ireland_gets_no_new_amounts(): (9_412, 12_000, 1_482.4), (14_071.2, 17_170, 1_380.24), (9_412, 9_592.34, 1_963.93), - (3_801.2, 14_832.24, 0), - (5_972.2, 22_594.64, 0), - (3_801.2, 8_955.84, 969.07), + (3_801.2, 16_080.24, 0), + (5_972.2, 24_674.64, 0), + (3_801.2, 9_371.84, 885.87), (9_412, 12_000, 1_482.4), (14_071.2, 17_150, 1_384.24), (9_412, 9_592.34, 1_963.93), - (3_801.2, 14_812.24, 0), - (5_972.2, 22_574.64, 0), - (3_801.2, 8_955.84, 969.07), + (3_801.2, 16_060.24, 0), + (5_972.2, 24_654.64, 0), + (3_801.2, 9_371.84, 885.87), (3_801.2, 12_672.24, 225.79), (3_801.2, 12_672.24, 0), (3_801.2, 12_672.24, 0), @@ -363,15 +372,15 @@ def test_northern_ireland_gets_no_new_amounts(): (12_230.4, 12_000, 2_000), (18_304, 17_189.06, 2_000), (12_230.4, 0, 2_000), - (4_706, 15_673.86, 0), - (7_397, 24_007.26, 0), - (4_706, 9_000, 1_141.2), + (4_706, 16_921.86, 0), + (7_397, 26_087.26, 0), + (4_706, 9_416, 1_058), (12_230.4, 12_000, 2_000), (18_304, 17_166, 2_000), (12_230.4, 0, 2_000), - (4_706, 15_650.8, 0), - (7_397, 23_984.2, 0), - (4_706, 9_000, 1_141.2), + (4_706, 16_898.8, 0), + (7_397, 26_064.2, 0), + (4_706, 9_416, 1_058), (4_706, 13_331.2, 274.96), (4_706, 13_331.2, 0), (4_706, 13_331.2, 0), @@ -388,15 +397,15 @@ def test_northern_ireland_gets_no_new_amounts(): (13_312, 12_000, 2_000), (19_934.2, 17_205.67, 2_000), (13_312, 0, 2_000), - (4_968.6, 15_750.5, 0), - (7_807.8, 24_148.67, 0), - (4_968.6, 9_000, 1_193.72), + (4_968.6, 16_998.5, 0), + (7_807.8, 26_228.67, 0), + (4_968.6, 9_416, 1_110.52), (13_312, 12_000, 2_000), (19_934.2, 17_166, 2_000), (13_312, 0, 2_000), - (4_968.6, 15_726.2, 0), - (7_807.8, 24_109, 0), - (4_968.6, 9_000, 1_193.72), + (4_968.6, 16_974.2, 0), + (7_807.8, 26_189, 0), + (4_968.6, 9_416, 1_110.52), (4_968.6, 13_406.6, 312.4), (4_968.6, 13_406.6, 0), (4_968.6, 13_406.6, 0), diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py index 81d28afff5..7b84a09992 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_applicable_income.py @@ -19,7 +19,7 @@ class council_tax_reduction_applicable_income(Variable): "credit payable, where the award is savings credit only. Otherwise we " "deduct the pensioner earnings disregards from a pension-age family's " "net earnings, and add its tariff income from capital " - "(council_tax_reduction_pensioner_tariff_income). Councils in Great " + "(council_tax_reduction_tariff_income). Councils in Great " "Britain also exclude Child Benefit from a pensioner's general-rule " "income and count statutory sick and maternity pay as earnings. We " "omit the other " diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py deleted file mode 100644 index 90014a52f3..0000000000 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_tariff_income.py +++ /dev/null @@ -1,95 +0,0 @@ -from policyengine_uk.model_api import * -from policyengine_uk.variables.household.demographic.country import Country - - -class council_tax_reduction_pensioner_tariff_income(Variable): - value_type = float - entity = BenUnit - label = "Council Tax Reduction pensioner tariff income from capital" - documentation = ( - "Councils treat a pensioner's capital as weekly income of £1 for " - "each £500, or part of £500, of " - "council_tax_reduction_assessable_capital above £10,000. We " - "annualise that income. The Secretary of State and the Welsh " - "Ministers count the excess up to £16,000, and the Scottish Ministers " - "set no ceiling. All three bar a reduction where capital exceeds " - "£16,000. Councils apply the £16,000 limit to assessable capital " - "after statutory disregards, and disregard all of an applicant's " - "capital where the applicant or their partner receives guarantee " - "credit. We use the pension-age Housing Benefit tariff amounts, which " - "equal those the Secretary of State, the Welsh Ministers and the " - "Scottish Ministers set for their Council Tax Reduction schemes. We " - "give nil on both " - "Pension Credit routes: on guarantee credit because of that " - "disregard, and on a savings-credit-only award because councils use " - "the Secretary of State's assessment of income, which already " - "includes Pension Credit's deemed income from capital. We also give " - "working-age families nil, because we do not model their tariff " - "income here." - ) - definition_period = YEAR - unit = GBP - reference = ( - "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37", - "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/13", - "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/14", - "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31", - "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/7", - "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/8", - "https://www.legislation.gov.uk/ssi/2012/319/regulation/27", - "https://www.legislation.gov.uk/ssi/2012/319/regulation/24", - "https://www.legislation.gov.uk/ssi/2012/319/regulation/25", - "https://www.legislation.gov.uk/uksi/2006/214/regulation/29", - ) - - def formula(benunit, period, parameters): - tariff = parameters( - period - ).gov.dwp.housing_benefit.means_test.capital.pension_age.tariff_income - local_authorities = parameters(period).gov.local_authorities - country = benunit.household("country", period) - capital = benunit("council_tax_reduction_assessable_capital", period) - # The Secretary of State and the Welsh Ministers count the excess "not - # exceeding £16,000", the capital limit (SI 2012/2885 Sch 1 para 37; - # WSI 2013/3029 Sch 1 para 31). The Scottish Ministers set no ceiling - # in SSI 2012/319 reg 27(2), and bar a reduction where capital exceeds - # £16,000 (reg 40). Councils apply the £16,000 limit to assessable - # capital after statutory disregards (reg 41(2)), and disregard all of - # an applicant's capital where the applicant or their partner receives - # guarantee credit (reg 24). - counted_capital = select( - [ - country == Country.ENGLAND, - country == Country.WALES, - country == Country.SCOTLAND, - ], - [ - min_( - capital, - local_authorities.england.council_tax_reduction.pensioners.means_test.capital_limit, - ), - min_( - capital, - local_authorities.wales.council_tax_reduction.means_test.capital_limit, - ), - capital, - ], - default=0, - ) - excess_capital = max_(0, counted_capital - tariff.threshold) - weekly_tariff_income = np.ceil(excess_capital / tariff.step) * tariff.amount - # The Pension Credit routes (England Sch 1 paras 13 and 14, Wales - # Sch 1 paras 7 and 8, Scotland regs 24 and 25), as in - # council_tax_reduction_applicable_income. The benefit unit's - # Pension Credit belongs to its claimant and partner. - applicant_family = ~benunit("council_tax_reduction_head_applies_alone", period) - pension_credit_route = applicant_family & ( - benunit("in_receipt_of_guarantee_credit", period) - | benunit("in_receipt_of_savings_credit_only", period) - ) - pensioner = benunit("council_tax_reduction_pensioner", period) - return where( - pensioner & ~pension_credit_route, - weekly_tariff_income * WEEKS_IN_YEAR, - 0, - ) From 5821ea1668e4d1f4e56888d42ead2efddbf9739a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 13:11:22 +0000 Subject: [PATCH 20/22] Count a Scottish pensioner's whole capital excess in CTR tariff income MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SSI 2012/319 reg 27(2) treats capital as yielding £1 a week for each £500, or part, over £10,000 with no ceiling; reg 40 separately bars a reduction above £16,000. council_tax_reduction_tariff_income now leaves the Scottish pensioner branch uncapped and keeps the £16,000 ceiling in England and Wales. No award moves: a Scottish pensioner with £16,500 or £20,000 of capital still gets no reduction. A new income_from_capital.yaml case checks a Scottish pensioner's 1,040 and an English one's 624 at £20,000, and the pension credit property test's tariff recomputation follows reg 27(2). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LwQq6HDAHLr6RSvBAdeFM1 --- .../income_from_capital.yaml | 44 +++++++++++++++++++ ...tax_reduction_pension_credit_properties.py | 41 +++++++++-------- ...ans_test_income_from_capital_properties.py | 6 ++- .../council_tax_reduction_tariff_income.py | 18 ++++---- 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml index e080bdba36..fa88904dfb 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml @@ -883,6 +883,50 @@ council_tax_reduction_tariff_income: [312, 312] council_tax_reduction_applicable_income: [12_312, 12_312] +- name: A Scottish pensioner's tariff income counts all capital over 10,000, and an English one's stops at 16,000 + # SSI 2012/319 reg 27(2) sets no ceiling: savings of 20,000 are 10,000 over + # 10,000, 20 steps of 500, so 20 a week, 1,040 a year. SI 2012/2885 Sch 1 + # para 37 counts the excess "not exceeding £16,000": 6,000 / 500 = 12 a + # week, 624 a year. Both pensioners' capital exceeds 16,000, so neither + # gets a reduction (SSI 2012/319 reg 40; SI 2012/2885 reg 11(2)). + period: 2026 + absolute_error_margin: 0.01 + input: + people: + scottish_pensioner: + age: 72 + state_pension: 12_570 + english_pensioner: + age: 72 + state_pension: 12_570 + benunits: + scottish: + members: [scottish_pensioner] + would_claim_pc: false + would_claim_uc: false + english: + members: [english_pensioner] + would_claim_pc: false + would_claim_uc: false + households: + scottish_household: + members: [scottish_pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + council_tax: 2_000 + savings: 20_000 + english_household: + members: [english_pensioner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 20_000 + output: + council_tax_reduction_pensioner: [true, true] + council_tax_reduction_assessable_capital: [20_000, 20_000] + council_tax_reduction_tariff_income: [1_040, 624] + council_tax_reduction: [0, 0] + - name: A savings credit recipient's council tax reduction income does not fall when more sub-tenant rent ends the savings credit # Before: 3,130.54 of sub-tenant rent counts 2,090.54 (less 20 a week). # Pension Credit income is 10,000 + 2,000 + 2,090.54 + 520 deemed income diff --git a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py index dbc41f8577..9afdf55140 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pension_credit_properties.py @@ -22,22 +22,22 @@ A) - ND) when the Pension Credit assessment of capital is within 16,000, and nothing otherwise. 4. Differential: everyone else keeps the general formula, max(0, L - 0.2 x - max(0, I - A) - ND) when capital C is within 16,000, where I is the - general income definition plus tariff income on C, both recomputed here - from their components and the regulations rather than read from the - variables under test, less pensioners' Child Benefit and the schemes' - pensioner earnings disregard (recomputed from the statutory sums). C is household savings plus other property at 90% - of its value (SI 2012/2885 Sch 1 para 32(a)), or, for a Welsh Universal - Credit recipient, the Universal Credit assessment of capital (WSI - 2013/3029 Sch 6 para 9(6)), or nil for a Welsh applicant on Income - Support or income-based JSA or ESA (Sch 10 para 8). A UC award includes - one the cap or deductions reduce to nil. Tariff income is 1 a week per - 500, or part, - over 10,000 for pensioners (Sch 1 para 37); for people under pension age - in Wales and Scotland 1 a week per 250, or part, over 6,000 (WSI - 2013/3029 Sch 6 para 33; SSI 2021/249 reg 63(1)(b)), or with Universal - Credit 4.35 a month (UC Regs 2013 reg 72; SSI 2021/249 reg 63(1)(a)), and - nil on Income Support or income-based JSA or ESA. + max(0, I - A) - ND) when capital C is within 16,000, where I is the general + income definition plus tariff income on C, both recomputed here from their + components and the regulations rather than read from the variables under + test, less pensioners' Child Benefit and the schemes' pensioner earnings + disregard (recomputed from the statutory sums). C is household savings plus + other property at 90% of its value (SI 2012/2885 Sch 1 para 32(a)), or, for + a Welsh Universal Credit recipient, the Universal Credit assessment of + capital (WSI 2013/3029 Sch 6 para 9(6)), or nil for a Welsh applicant on + Income Support or income-based JSA or ESA (Sch 10 para 8). A UC award + includes one the cap or deductions reduce to nil. Tariff income is 1 a week + per 500, or part, over 10,000 for pensioners (Sch 1 para 37), counting + capital up to 16,000 except in Scotland (SSI 2012/319 reg 27(2)); for people + under pension age in Wales and Scotland 1 a week per 250, or part, over + 6,000 (WSI 2013/3029 Sch 6 para 33; SSI 2021/249 reg 63(1)(b)), or with + Universal Credit 4.35 a month (UC Regs 2013 reg 72; SSI 2021/249 reg + 63(1)(a)), and nil on Income Support or income-based JSA or ESA. 5. Metamorphic: a guarantee credit recipient's CTR does not change when the State Pension changes. 6. Metamorphic: nor when its savings change. @@ -445,11 +445,14 @@ def expected_capital(unit, values, i): def expected_tariff_income(unit, values, i, capital): - def steps(threshold, step): - return np.ceil(max(0.0, min(capital, CAPITAL_LIMIT) - threshold) / step) + def steps(threshold, step, limit=CAPITAL_LIMIT): + return np.ceil(max(0.0, min(capital, limit) - threshold) / step) if values["council_tax_reduction_pensioner"][i]: - return steps(10_000, 500) * 52 + # SSI 2012/319 reg 27(2) sets no ceiling on a Scottish pensioner's + # counted capital. + limit = np.inf if unit["country"] == "SCOTLAND" else CAPITAL_LIMIT + return steps(10_000, 500, limit) * 52 if unit["country"] == "ENGLAND": return 0.0 if universal_credit_route(values, i): diff --git a/policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py b/policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py index ee4849fb03..550cf296fd 100644 --- a/policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py +++ b/policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py @@ -50,8 +50,10 @@ capital there. Each test floors the sum of the deduction over the members it counts at nil. 5. Tariff: the council tax reduction tariff income that replaces the actual - income from capital is never negative, never more than the yield at the - 16,000 capital limit (40 steps of 250 at 4.35 a month, 2,088 a year), nil + income from capital is never negative, never more than the Universal + Credit yield at the 16,000 capital limit (40 steps of 250 at 4.35 a month, + 2,088 a year), which exceeds the uncapped Scottish pensioner tariff on the + generated savings of up to 20,000 (20 steps of 500 at 1 a week, 1,040), nil outside the national schemes (Northern Ireland, and English people under pension age, whose local schemes set their own), and never falls when savings rise while the family stays on the same route (pensioner, UC diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_tariff_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_tariff_income.py index f69ff77239..d660f1e314 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_tariff_income.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_tariff_income.py @@ -8,8 +8,8 @@ def tariff_amount(capital, tariff, capital_limit): # `amount` for each complete `step` of capital above `threshold`, and - # `amount` for any part of a step. Capital above the limit leaves no - # entitlement, so it is not counted. + # `amount` for any part of a step, counting capital up to + # `capital_limit`. excess = max_(0, min_(capital, capital_limit) - tariff.threshold) return np.ceil(excess / tariff.step) * tariff.amount @@ -22,7 +22,10 @@ class council_tax_reduction_tariff_income(Variable): "Income the national Council Tax Reduction schemes (England for " "pensioners, Wales and Scotland) treat capital as yielding, annualised. " "Pensioners: £1 a week for each £500, or part of £500, of capital over " - "£10,000. People under pension age in Wales and Scotland: £1 a week " + "£10,000. The Secretary of State and the Welsh Ministers count capital " + "up to £16,000, the capital limit; the Scottish Ministers set no " + "ceiling (SSI 2012/319 reg 27(2)) and bar a reduction where capital " + "exceeds £16,000 (reg 40). People under pension age in Wales and Scotland: £1 a week " "for each £250, or part of £250, over £6,000; with an award of " "Universal Credit (council_tax_reduction_universal_credit_award, " "including an award the benefit cap or deductions reduce to nil), the " @@ -48,6 +51,7 @@ class council_tax_reduction_tariff_income(Variable): "https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/33", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/10/paragraph/8", "https://www.legislation.gov.uk/ssi/2012/319/regulation/27", + "https://www.legislation.gov.uk/ssi/2012/319/regulation/40", "https://www.legislation.gov.uk/ssi/2012/303/regulation/26", "https://www.legislation.gov.uk/ssi/2012/303/regulation/51", "https://www.legislation.gov.uk/ssi/2012/303/schedule/5/paragraph/7", @@ -82,11 +86,9 @@ def formula(benunit, period, parameters): wales_p.tariff_income.pensioner, wales_p.capital_limit, ), - tariff_amount( - capital, - scotland_p.tariff_income.pensioner, - scotland_p.capital_limit, - ), + # SSI 2012/319 reg 27(2) sets no ceiling; reg 40 bars a + # reduction where capital exceeds £16,000. + tariff_amount(capital, scotland_p.tariff_income.pensioner, np.inf), ], default=0, ) From 20a02e0338f3e9adff69483406010e6f125d5a62 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 13:11:31 +0000 Subject: [PATCH 21/22] Describe the CTR change in the changelog fragment Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LwQq6HDAHLr6RSvBAdeFM1 --- changelog.d/1933.fixed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/1933.fixed.md b/changelog.d/1933.fixed.md index 3877968f1a..81752fb1b7 100644 --- a/changelog.d/1933.fixed.md +++ b/changelog.d/1933.fixed.md @@ -1 +1 @@ -Add pensioner child amounts, family premiums and tariff income from capital over £10,000 to Council Tax Reduction in England, Scotland and Wales. +Add pensioner child amounts and family premiums to Council Tax Reduction in England, Scotland and Wales, and count a Scottish pensioner's whole capital over £10,000 in tariff income, as SSI 2012/319 reg 27(2) sets no ceiling. From 87cbc397ef3b38c78cc234a02bd18c0d6ad54560 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 4 Nov 2026 08:50:54 -0500 Subject: [PATCH 22/22] =?UTF-8?q?Check=20that=20capital=20over=20=C2=A316,?= =?UTF-8?q?000=20gives=20no=20pensioner=20award?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tariff property test now asserts invariant 4 of #2826's description: councils give no award where capital exceeds £16,000 (SI 2012/2885 reg 11(2); WSI 2013/3029 reg 30; SSI 2012/319 reg 40), so Scotland's uncapped pensioner tariff changes no award. Co-Authored-By: Claude Opus 5.5 --- ...l_tax_reduction_pensioner_children_tariff_properties.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py index c350a67c19..fc8e207c69 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_pensioner_children_tariff_properties.py @@ -29,6 +29,9 @@ £500, or part of £500, of capital above £10,000 (up to £16,000 in England and Wales), and it never falls as capital rises. Capital changes nothing else in the applicable income, and the award never rises with capital. + Councils give no award where capital exceeds £16,000 (SI 2012/2885 reg + 11(2); WSI 2013/3029 reg 30; SSI 2012/319 reg 40), so Scotland's uncapped + tariff changes no award. 2. For a family that claims no Universal Credit, adding a dependent child never lowers the applicable amount. For a pensioner, councils add 52 times the scheme's weekly rate for each extra child they count. In England from @@ -190,6 +193,10 @@ def test_tariff_income_is_the_tariff_and_never_falls_as_capital_rises( other_income = result["council_tax_reduction_applicable_income"] - tariffs np.testing.assert_allclose(other_income, other_income[0], atol=0.01) assert (np.diff(result["council_tax_benefit"]) <= 0.01).all() + # Councils give no award where capital exceeds £16,000, so Scotland's + # uncapped tariff changes no award. + over_limit = np.asarray(capitals) > 16_000 + assert (result["council_tax_benefit"][over_limit] <= 0.01).all() @SETTINGS