diff --git a/changelog.d/legacy-capital-derived-income.fixed.md b/changelog.d/legacy-capital-derived-income.fixed.md new file mode 100644 index 0000000000..ceb3702b10 --- /dev/null +++ b/changelog.d/legacy-capital-derived-income.fixed.md @@ -0,0 +1 @@ +Stop counting rent from property, and deducting tax on rent, interest and dividends, in the Income Support, Housing Benefit, Pension Credit and council tax reduction means tests, which treat income derived from capital as capital; count rent for letting part of the home less the £20 weekly sub-tenant disregard, except where a working-age council tax reduction applicant's income is the Universal Credit assessment. The residential finance-cost tax reduction now comes off the tax on property income. Council tax reduction now counts land and property other than the home as capital, at market value less 10% for the expenses of sale and less any debt secured on it; adds the national schemes' tariff income from capital (England for pensioners, Wales and Scotland); uses the Universal Credit assessment of capital for a working-age applicant with an award of Universal Credit, including one the benefit cap or deductions reduce to nil, where the scheme says so; and disregards the whole capital of an applicant on Income Support, income-based Jobseeker's Allowance or income-related Employment and Support Allowance in Wales, in Scotland before April 2022, and in the Kingston, Merton, Westminster and Oxford schemes. All four tests deduct the same income tax: the tax before the winter fuel payment charge, less the tax that rent, interest and dividends, and any Step 7 charge, would bear if nobody had earnings, so earnings carry the extra tax they cause. Council tax reduction counts the rent its own applicant and partner receive for letting part of the home: where a household head applies alone, it counts her rent and not the benefit unit's claimant's and partner's, and it counts her tariff income even when the claimant and partner receive Pension Credit. Each test floors at nil the sum of the deducted income tax over the members it counts, and Pension Credit first takes out the tax on self-employed profit that its notional tax replaces. diff --git a/docs/book/programs/gov/dwp/housing-benefit.ipynb b/docs/book/programs/gov/dwp/housing-benefit.ipynb index 90c8415910..f2c38fc2f1 100644 --- a/docs/book/programs/gov/dwp/housing-benefit.ipynb +++ b/docs/book/programs/gov/dwp/housing-benefit.ipynb @@ -42,7 +42,7 @@ "\n", "1. **Eligible rent**: the rent the benunit is liable for (`benunit_rent`). Where the Local Housing Allowance applies (`LHA_eligible`: renting, and no member in social housing), the eligible rent is the maximum rent (LHA), which is the LHA rate for the Housing Benefit category of dwelling (`housing_benefit_LHA_category`: the shared accommodation rate for a young individual with no non-dependant, or a claimant entitled to one bedroom who lacks exclusive use of self-contained accommodation, unless the severe disability premium applies, reg 13D(2)) or, where the rent is lower, the rent (`LHA_cap`; SI 2006/213 regs [12D(2)(a)](https://www.legislation.gov.uk/uksi/2006/213/regulation/12D) and [13D(5)](https://www.legislation.gov.uk/uksi/2006/213/regulation/13D)).\n", "2. **Applicable amount** (`housing_benefit_applicable_amount`): a personal allowance derived from the benunit's composition (single, couple, lone parent) and age, plus any disability/carer premiums. This is the \"minimum income\" the household needs before HB tapers begin.\n", - "3. **Means test** (`housing_benefit_entitlement`): the appropriate maximum Housing Benefit is the eligible rent less `housing_benefit_non_dep_deductions` for any non-dependant adults living in the household ([reg. 70](https://www.legislation.gov.uk/uksi/2006/213/regulation/70)). The published `withdrawal_rate` (currently 0.65) of the benunit's `housing_benefit_applicable_income` in excess of the applicable amount is deducted from that maximum ([SSCBA 1992 s. 130(3)(b)](https://www.legislation.gov.uk/ukpga/1992/4/section/130), [reg. 71](https://www.legislation.gov.uk/uksi/2006/213/regulation/71)). Because the LHA caps the eligible rent, the taper comes off the LHA: a private tenant with rent above the LHA and income above the applicable amount receives the LHA less the taper, not the lower of the LHA and the rent less the taper. The pension-age regulations (SI 2006/214) have the same rules at regs 12D, 13D, 50 and 51, and the Northern Ireland regulations at SR 2006/405 regs 13C, 14D, 68 and 69 and SR 2006/406 regs 13C, 14D, 48 and 49.\n", + "3. **Means test** (`housing_benefit_entitlement`): the appropriate maximum Housing Benefit is the eligible rent less `housing_benefit_non_dep_deductions` for any non-dependant adults living in the household ([reg. 70](https://www.legislation.gov.uk/uksi/2006/213/regulation/70)). The published `withdrawal_rate` (currently 0.65) of the benunit's `housing_benefit_applicable_income` in excess of the applicable amount is deducted from that maximum ([SSCBA 1992 s. 130(3)(b)](https://www.legislation.gov.uk/ukpga/1992/4/section/130), [reg. 71](https://www.legislation.gov.uk/uksi/2006/213/regulation/71)). Because the LHA caps the eligible rent, the taper comes off the LHA: a private tenant with rent above the LHA and income above the applicable amount receives the LHA less the taper, not the lower of the LHA and the rent less the taper. The pension-age regulations (SI 2006/214) have the same rules at regs 12D, 13D, 50 and 51, and the Northern Ireland regulations at SR 2006/405 regs 13C, 14D, 68 and 69 and SR 2006/406 regs 13C, 14D, 48 and 49. Applicable income counts earnings, pensions and benefits net of the income tax and National Insurance on them. Income derived from capital (rent from property, interest and dividends) is not income: regulation 46(4) of the Housing Benefit Regulations 2006 treats it as capital, and Schedule 5 paragraph 22 of the pension-age regulations disregards it. The capital counts instead through `housing_benefit_tariff_income` and the capital limit. Rent for letting part of the home is the exception: it counts, less £20 a week per occupier.\n", " If the claimant or partner is on Universal Credit, Income Support, income-based Jobseeker's Allowance or income-related Employment and Support Allowance (`housing_benefit_on_passporting_benefit`), the whole of the family's earnings, other income and capital is disregarded ([SI 2006/213 Sch. 4 para. 12](https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/12), [Sch. 5 para. 4](https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/4) and [Sch. 6 para. 5](https://www.legislation.gov.uk/uksi/2006/213/schedule/6/paragraph/5); Northern Ireland: [SR 2006/405 Sch. 5 para. 12](https://www.legislation.gov.uk/nisr/2006/405/schedule/5/paragraph/12), [Sch. 6 para. 4](https://www.legislation.gov.uk/nisr/2006/405/schedule/6/paragraph/4) and [Sch. 7 para. 5](https://www.legislation.gov.uk/nisr/2006/405/schedule/7/paragraph/5)). `housing_benefit_applicable_income` and `housing_benefit_assessable_capital` are then zero, so the award is that maximum. This applies at any age: a mixed-age couple whose younger member is on one of these benefits is assessed under the working-age regulations ([SI 2006/213 reg. 5(1)(b)](https://www.legislation.gov.uk/uksi/2006/213/regulation/5)). Income Support, income-based Jobseeker's Allowance and income-related Employment and Support Allowance count when a positive amount is paid on the claimant's or partner's award (`in_receipt_of_income_support_jsa_ib_or_esa_ir`, which reads `claimant_or_partner_jsa_income` and `claimant_or_partner_esa_income`). Another member's own award, such as a non-dependant's, is payable to them and does not passport the claimant. A person is on Universal Credit on any day they are entitled to it, whether it is in payment or not ([reg. 2(3B)](https://www.legislation.gov.uk/uksi/2006/213/regulation/2)); PolicyEngine reads that as Universal Credit above nil before the benefit cap and deductions (`is_uc_entitled`), for a family that claims it, so the passport adds no circular dependency through the benefit cap. The universal credit limb applies from 28 October 2013 in Great Britain and 8 May 2018 in Northern Ireland (`gov.dwp.housing_benefit.means_test.universal_credit_passport`). It matters only where Housing Benefit is paid alongside Universal Credit, for specified or temporary accommodation, which the eligibility rules above do not yet model.\n", "4. **Benefit cap** (`housing_benefit`): the post-means-test award is finally reduced by `housing_benefit_benefit_cap_reduction`, the excess of the family's welfare benefits over the Housing Benefit cap (`housing_benefit_benefit_cap`, SI 2006/213 reg 75CA), leaving at least 50 pence a week (reg 75D). The cap does not apply where the claimant or couple is entitled to working tax credit (reg 75E), the claimant or partner receives a benefit listed in reg 75F, or the claim is under the pension-age regulations (reg 5). Universal Credit has its own cap.\n", "\n", diff --git a/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/pension_age.yaml b/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/pension_age.yaml new file mode 100644 index 0000000000..135bc3414d --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/pension_age.yaml @@ -0,0 +1,27 @@ +description: > + Weekly amount disregarded from the rent a claimant over the qualifying age + for State Pension Credit receives from a person who occupies part of a + property the claimant lives in, under an agreement to pay rent; rent below + this amount is disregarded in full. Pension Credit and pension-age Housing + Benefit use it, and the pensioner council tax reduction schemes in England, + Wales and Scotland copy it. Before Pension Credit began on 6 October 2003 + there was no separate pension-age amount; Income Support, including for + claimants over 60, disregarded £4 (Schedule 9 paragraph 19 as made). +metadata: + label: Legacy benefits pension-age sub-tenant rent disregard + period: week + unit: currency-GBP + reference: + - title: The State Pension Credit Regulations 2002 Schedule IV para. 9 + href: https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV/paragraph/9 + - title: The Income Support (General) Regulations 1987 Schedule 9 para. 19 (as made) + href: https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/made + - title: The State Pension Credit Regulations 2002 Schedule IV para. 9 (as made) + href: https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV/made + - title: The Housing Benefit (Persons who have attained the qualifying age for state pension credit) Regulations 2006 Schedule 5 para. 10 + href: https://www.legislation.gov.uk/uksi/2006/214/schedule/5/paragraph/10 + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 5 para. 10 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/5/paragraph/10 +values: + 1988-04-11: 4 + 2003-10-06: 20 diff --git a/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/working_age.yaml b/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/working_age.yaml new file mode 100644 index 0000000000..af9db8f7bc --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/legacy_means_tests/sub_tenant_rent_disregard/working_age.yaml @@ -0,0 +1,30 @@ +description: > + Weekly amount disregarded from the rent a working-age claimant receives from + a person who occupies part of the claimant's home under a contractual + liability to pay for it, other than board and lodging; rent below this + amount is disregarded in full. Income Support, income-based Jobseeker's + Allowance, income-related Employment and Support Allowance and working-age + Housing Benefit use it, and the working-age council tax reduction schemes + in Wales and the English default scheme copy it. Before April 2008 the + disregard was £4 plus a further amount where the payment included heating; + the heating amount is not modelled. +metadata: + label: Legacy benefits working-age sub-tenant rent disregard + period: week + unit: currency-GBP + reference: + - title: The Income Support (General) Regulations 1987 Schedule 9 para. 19 + href: https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/19 + - title: The Income Support (General) Regulations 1987 Schedule 9 para. 19 (as made) + href: https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/made + - title: The Housing Benefit Regulations 2006 Schedule 5 para. 22 + href: https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/22 + - title: The Jobseeker's Allowance Regulations 1996 Schedule 7 para. 20 + href: https://www.legislation.gov.uk/uksi/1996/207/schedule/7/paragraph/20 + - title: The Employment and Support Allowance Regulations 2008 Schedule 8 para. 20 + href: https://www.legislation.gov.uk/uksi/2008/794/schedule/8/paragraph/20 + - title: The Social Security (Miscellaneous Amendments) (No. 5) Regulations 2007 regs. 1(2), 1(3), 5(12) and 11(12) + href: https://www.legislation.gov.uk/uksi/2007/2618/regulation/1/made +values: + 1988-04-11: 4 + 2008-04-07: 20 diff --git a/policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/income.yaml b/policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/income.yaml index 8b169fadd3..b00c30c47c 100644 --- a/policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/income.yaml +++ b/policyengine_uk/parameters/gov/dwp/pension_credit/guarantee_credit/income.yaml @@ -9,6 +9,8 @@ metadata: title: State Pension Credit Regulations 2002 reg. 15 - href: https://www.legislation.gov.uk/uksi/2026/246/article/17/made title: SI 2026/246 art. 17 (Scottish Carer Supplement excepted from reg. 15(1)) + - href: https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV/paragraph/18 + title: State Pension Credit Regulations 2002 Schedule IV para. 18 (actual income from capital disregarded) unit: list values: 2002-01-01: @@ -20,7 +22,11 @@ values: - pension_credit_war_pension_income - state_pension - private_pension_income - - property_income_after_finance_costs + # Rent from other property is actual income from capital, disregarded by + # Schedule IV para. 18; the property counts through deemed income. Rent for + # part of the claimant's home is reg. 15(5)(i) income, less the Schedule IV + # para. 9 disregard. + - legacy_benefits_home_letting_income - pension_credit_deemed_income # Reg. 15(5)(d): maintenance from a spouse, civil partner, former spouse or # former civil partner. Child maintenance is not listed. diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/rate.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/rate.yaml new file mode 100644 index 0000000000..692911d156 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/rate.yaml @@ -0,0 +1,31 @@ +description: > + Share of the current market or surrender value deducted from council tax + reduction capital where there would be expenses attributable to sale. It is + a flat 10% whatever the actual costs, taken from the market value before + any encumbrance secured on the asset is deducted (DMG 29624). The + encumbrance is then deducted where an asset-specific secured-debt input + exists (other residential and non-residential property); those inputs + default to nil because the survey does not record them. +values: + 2013-04-01: 0.1 +metadata: + label: Council tax reduction capital sale expense deduction + period: year + unit: /1 + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 1 para. 32 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/32 + - title: The Council Tax Reduction Schemes (Default Scheme) (England) Regulations 2012, Schedule para. 65 + href: https://www.legislation.gov.uk/uksi/2012/2886/schedule/paragraph/65 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 1 para. 26 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/26 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 28 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/28 + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 42 + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/42 + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 46 (persons under pension age, to 31 March 2022) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/46 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 70 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/70 + - title: Decision Makers' Guide chapter 29, para. 29624 (sale expenses before encumbrances) + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/sources.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/sources.yaml new file mode 100644 index 0000000000..43cd6052c6 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sale_expenses/sources.yaml @@ -0,0 +1,29 @@ +description: > + Council tax reduction capital sources whose sale would incur expenses, so + that they are valued at 90% of market value. Real property always has costs + of sale (R(IS) 21/93, as DMG 29622 applies it to the identically worded + Income Support rule), so `owned_land`, `other_residential_property_value` + and `non_residential_property_value` are listed. `savings` is not: a bank or + building society account is valued at its balance, and the costs of + withdrawing money, such as travel to a building society, are not costs of + sale (DMG 29623, on the identically worded Income Support rule). +metadata: + label: Council tax reduction capital sources with sale expenses + period: year + unit: list + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 1 para. 32(a) + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/32 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 28(a) + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/28 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 70(1)(a) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/70 + - title: Decision Makers' Guide chapter 29, para. 29622 (real property, R(IS) 21/93) + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf#page=124 + - title: Decision Makers' Guide chapter 29, para. 29623 (costs of withdrawing money are not costs of sale) + href: https://assets.publishing.service.gov.uk/media/69d8f3a496c86b751317022c/dmg-Ch-29.pdf +values: + 2013-04-01: + - owned_land + - other_residential_property_value + - non_residential_property_value diff --git a/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sources.yaml b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sources.yaml new file mode 100644 index 0000000000..c8d6ee6133 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/council_tax_reduction/capital/sources.yaml @@ -0,0 +1,44 @@ +description: > + Household capital counted for the council tax reduction capital limit and + tariff income, outside the Pension Credit and Universal Credit routes. Every + scheme counts the whole of the applicant's capital unless a schedule + disregards it, including land and property other than the home: the + prescribed requirements for pensioners in England (Schedule 1 paragraph + 31(1)) and Wales (Schedule 1 paragraph 25(1)), the Welsh working-age rules + (Schedule 6 paragraph 26(1)), the English default scheme (paragraph 63(1)), + the Scottish pension-age scheme (regulation 41(1)) and the Scottish + working-age schemes (SSI 2012/303 regulation 43(1) to 31 March 2022, then + SSI 2021/249 regulations 67 and 69). `main_residence_value` is left out + because the home is disregarded. `corporate_wealth` is also left out for + now: in the data it is mostly imputed pension wealth, which the schemes + disregard, and it cannot yet be separated (issue 1936). Land and property + are valued less sale expenses (`sale_expenses`). +metadata: + label: Council tax reduction capital sources + unit: list + period: year + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 reg. 11(2) and Schedule 1 para. 31 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/31 + - title: The Council Tax Reduction Schemes (Default Scheme) (England) Regulations 2012, Schedule para. 63 + href: https://www.legislation.gov.uk/uksi/2012/2886/schedule/paragraph/63 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 reg. 30 + href: https://www.legislation.gov.uk/wsi/2013/3029/regulation/30 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 1 para. 25 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/25 + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 26 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/26 + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 regs. 40 and 41 + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/41 + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 43 (persons under pension age, to 31 March 2022) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/43 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 67 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/67 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 69 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/69 +values: + 2013-04-01: + - savings + - owned_land + - other_residential_property_value + - non_residential_property_value diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/amount.yaml new file mode 100644 index 0000000000..9bcd3e8f7c --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/amount.yaml @@ -0,0 +1,10 @@ +description: Weekly tariff income the England Council Tax Reduction pensioner scheme counts for each step of capital, or part of one, above the threshold. +values: + 2013-04-01: 1 +metadata: + unit: currency-GBP + period: year + label: England Council Tax Reduction pensioner weekly tariff income per capital step + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 1 para. 37 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37 diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/step.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/step.yaml new file mode 100644 index 0000000000..92751f8871 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/step.yaml @@ -0,0 +1,10 @@ +description: Step of capital above the threshold, or part of one, that the England Council Tax Reduction pensioner scheme treats as yielding one amount of weekly tariff income. +values: + 2013-04-01: 500 +metadata: + unit: currency-GBP + period: year + label: England Council Tax Reduction pensioner tariff income capital step + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 1 para. 37 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37 diff --git a/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/threshold.yaml new file mode 100644 index 0000000000..2dc0adce1f --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/england/council_tax_reduction/pensioners/means_test/tariff_income/threshold.yaml @@ -0,0 +1,10 @@ +description: Capital above which the England Council Tax Reduction pensioner scheme treats capital as yielding a weekly tariff income. +values: + 2013-04-01: 10_000 +metadata: + unit: currency-GBP + period: year + label: England Council Tax Reduction pensioner tariff income threshold + reference: + - title: The Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 Schedule 1 para. 37 + href: https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/37 diff --git a/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml new file mode 100644 index 0000000000..1243ad537f --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/kingston_upon_thames/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml @@ -0,0 +1,17 @@ +description: > + Whether the Kingston upon Thames council tax reduction scheme for people + under pension age disregards the whole capital of an applicant on Income + Support, income-based Jobseeker's Allowance or income-related Employment and + Support Allowance. The council's 2026-27 scheme disregards the whole capital + of an applicant on Income Support, income-based Jobseeker's Allowance or + income-related Employment and Support Allowance (Schedule 10 paragraph 8), + as the default scheme does. +metadata: + label: Kingston upon Thames council tax reduction disregards passported applicants' capital + unit: bool + period: year + reference: + - title: Royal Borough of Kingston upon Thames Council Tax Reduction Scheme 2026-27, Schedule 10 para. 8 + href: https://www.kingston.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%202026%20-%202027.pdf +values: + 2026-04-01: true diff --git a/policyengine_uk/parameters/gov/local_authorities/merton/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml b/policyengine_uk/parameters/gov/local_authorities/merton/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml new file mode 100644 index 0000000000..273c993180 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/merton/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml @@ -0,0 +1,17 @@ +description: > + Whether the Merton council tax reduction scheme for people under pension age + disregards the whole capital of an applicant on Income Support, income-based + Jobseeker's Allowance or income-related Employment and Support Allowance. + The council's 2026-27 scheme disregards the whole capital of an applicant on + Income Support, income-based Jobseeker's Allowance or income-related + Employment and Support Allowance (Schedule 10 paragraph 8), as the default + scheme does. +metadata: + label: Merton council tax reduction disregards passported applicants' capital + unit: bool + period: year + reference: + - title: London Borough of Merton Council Tax Reduction Scheme 2026-27, Schedule 10 para. 8 + href: https://www.merton.gov.uk/sites/default/files/2026-03/Council%20Tax%20Reduction%20Scheme%20L%20B%20Merton%202026-27.pdf +values: + 2026-04-01: true diff --git a/policyengine_uk/parameters/gov/local_authorities/newham/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml b/policyengine_uk/parameters/gov/local_authorities/newham/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml new file mode 100644 index 0000000000..c9eb7ec1d8 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/newham/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml @@ -0,0 +1,18 @@ +description: > + Whether the Newham council tax reduction scheme for people under pension age + disregards the whole capital of an applicant on Income Support, income-based + Jobseeker's Allowance or income-related Employment and Support Allowance. + The council's 2026 scheme omits the default scheme's disregard of the whole + capital of an applicant on Income Support, income-based Jobseeker's + Allowance or income-related Employment and Support Allowance: Schedule 10 + paragraphs 8 and 9 are left blank, so that capital is tested against the + limit. +metadata: + label: Newham council tax reduction disregards passported applicants' capital + unit: bool + period: year + reference: + - title: London Borough of Newham Council Tax Reduction Scheme 2026, Schedule 10 paras. 8-9 + href: https://www.newham.gov.uk/downloads/file/10753/council-tax-reduction-scheme-2026 +values: + 2026-04-01: false diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml new file mode 100644 index 0000000000..6a1ff33dd6 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml @@ -0,0 +1,24 @@ +description: > + Whether the Scottish council tax reduction scheme for people under pension + age disregards the whole capital of an applicant on Income Support, + income-based Jobseeker's Allowance or income-related Employment and Support + Allowance. The Council Tax Reduction (Scotland) Regulations 2012 did + (Schedule 5 paragraph 7). The Council Tax Reduction (Scotland) Regulations + 2021, in force from 1 April 2022, have no such disregard in Schedule 4: + regulation 13(11) treats a qualifying income-related benefit claimant as + meeting the income conditions, and regulation 13(1) still applies the + capital limit. +metadata: + label: Scotland working-age council tax reduction disregards passported applicants' capital + unit: bool + period: year + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 Schedule 5 para. 7 (as at 1 April 2021) + href: https://www.legislation.gov.uk/ssi/2012/303/schedule/5/paragraph/7/2021-04-01 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 1 (commencement, 1 April 2022) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/1 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 13 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/13 +values: + 2013-04-01: true + 2022-04-01: false diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml new file mode 100644 index 0000000000..0563d2fd66 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml @@ -0,0 +1,10 @@ +description: Weekly tariff income the Scotland Council Tax Reduction pensioner scheme counts for each step of capital, or part of one, above the threshold. +values: + 2013-04-01: 1 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction pensioner weekly tariff income per capital step + reference: + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 27(2) + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/27 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml new file mode 100644 index 0000000000..236abcc702 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml @@ -0,0 +1,10 @@ +description: Step of capital above the threshold, or part of one, that the Scotland Council Tax Reduction pensioner scheme treats as yielding one amount of weekly tariff income. +values: + 2013-04-01: 500 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction pensioner tariff income capital step + reference: + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 27(2) + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/27 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml new file mode 100644 index 0000000000..cb51a4ec39 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml @@ -0,0 +1,10 @@ +description: Capital above which the Scotland Council Tax Reduction pensioner scheme treats capital as yielding a weekly tariff income. +values: + 2013-04-01: 10_000 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction pensioner tariff income threshold + reference: + - title: The Council Tax Reduction (State Pension Credit) (Scotland) Regulations 2012 reg. 27(2) + href: https://www.legislation.gov.uk/ssi/2012/319/regulation/27 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml new file mode 100644 index 0000000000..7ef585b74b --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml @@ -0,0 +1,12 @@ +description: Weekly tariff income the Scotland Council Tax Reduction working-age scheme counts for each step of capital, or part of one, above the threshold. +values: + 2013-04-01: 1 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction working-age weekly tariff income per capital step + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 51 (persons under pension age, to 31 March 2022) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/51 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 63(1)(b) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/63 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/step.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/step.yaml new file mode 100644 index 0000000000..64edd8615f --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/step.yaml @@ -0,0 +1,12 @@ +description: Step of capital above the threshold, or part of one, that the Scotland Council Tax Reduction working-age scheme treats as yielding one amount of weekly tariff income. +values: + 2013-04-01: 250 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction working-age tariff income capital step + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 51 (persons under pension age, to 31 March 2022) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/51 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 63(1)(b) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/63 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml new file mode 100644 index 0000000000..49a77b2b39 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml @@ -0,0 +1,12 @@ +description: Capital above which the Scotland Council Tax Reduction working-age scheme treats capital as yielding a weekly tariff income. +values: + 2013-04-01: 6_000 +metadata: + unit: currency-GBP + period: year + label: Scotland Council Tax Reduction working-age tariff income threshold + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 51 (persons under pension age, to 31 March 2022) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/51 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 63(1)(b) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/63 diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/uses_universal_credit_capital_assessment.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/uses_universal_credit_capital_assessment.yaml new file mode 100644 index 0000000000..7fc675e578 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/uses_universal_credit_capital_assessment.yaml @@ -0,0 +1,24 @@ +description: > + Whether the Scottish council tax reduction scheme for people under pension + age takes the capital of an applicant with an award of Universal Credit + from the Secretary of State's calculation for that award. The Council Tax + Reduction (Scotland) Regulations 2012 did (regulation 26(4) as made; + regulation 26(6) after SSI 2018/69 substituted the regulation). The Council Tax Reduction (Scotland) Regulations 2021, in force + from 1 April 2022, have no such rule: the authority calculates every + applicant's capital itself (regulations 66 to 70). +metadata: + label: Scotland working-age council tax reduction uses the Universal Credit capital assessment + unit: bool + period: year + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 26(4) (as made) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/26/made + - title: The Council Tax Reduction (Scotland) Regulations 2012 reg. 26(6) (as at 1 April 2021) + href: https://www.legislation.gov.uk/ssi/2012/303/regulation/26/2021-04-01 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 1 (commencement, 1 April 2022) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/1 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 66 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/66 +values: + 2013-04-01: true + 2022-04-01: false diff --git a/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/working_age_counts_home_letting_income.yaml b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/working_age_counts_home_letting_income.yaml new file mode 100644 index 0000000000..56fee06843 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/scotland/council_tax_reduction/means_test/working_age_counts_home_letting_income.yaml @@ -0,0 +1,21 @@ +description: > + Whether the Scottish council tax reduction scheme for people under pension + age counts rent from letting part of the applicant's home as income. The + Council Tax Reduction (Scotland) Regulations 2012 did, less £20 a week + (Schedule 4 paragraph 25). The Council Tax Reduction (Scotland) Regulations + 2021, in force from 1 April 2022, list unearned income in full in + regulation 57(1), and the list has no head for it. +metadata: + label: Scotland working-age council tax reduction counts home-letting income + unit: bool + period: year + reference: + - title: The Council Tax Reduction (Scotland) Regulations 2012 Schedule 4 para. 25 (as at 1 April 2021) + href: https://www.legislation.gov.uk/ssi/2012/303/schedule/4/2021-04-01 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 1 (commencement, 1 April 2022) + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/1 + - title: The Council Tax Reduction (Scotland) Regulations 2021 reg. 57 + href: https://www.legislation.gov.uk/ssi/2021/249/regulation/57 +values: + 2013-04-01: true + 2022-04-01: false diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml new file mode 100644 index 0000000000..dd91c21484 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/amount.yaml @@ -0,0 +1,10 @@ +description: Weekly tariff income the Wales Council Tax Reduction pensioner scheme counts for each step of capital, or part of one, above the threshold. +values: + 2013-04-01: 1 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction pensioner weekly tariff income per capital step + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 1 para. 31 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml new file mode 100644 index 0000000000..ad37548b57 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/step.yaml @@ -0,0 +1,10 @@ +description: Step of capital above the threshold, or part of one, that the Wales Council Tax Reduction pensioner scheme treats as yielding one amount of weekly tariff income. +values: + 2013-04-01: 500 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction pensioner tariff income capital step + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 1 para. 31 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml new file mode 100644 index 0000000000..5f1c4de9ce --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/pensioner/threshold.yaml @@ -0,0 +1,10 @@ +description: Capital above which the Wales Council Tax Reduction pensioner scheme treats capital as yielding a weekly tariff income. +values: + 2013-04-01: 10_000 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction pensioner tariff income threshold + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 1 para. 31 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/31 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml new file mode 100644 index 0000000000..8f0e0aba6a --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/amount.yaml @@ -0,0 +1,10 @@ +description: Weekly tariff income the Wales Council Tax Reduction working-age scheme counts for each step of capital, or part of one, above the threshold. +values: + 2013-04-01: 1 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction working-age weekly tariff income per capital step + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 33 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/33 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/step.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/step.yaml new file mode 100644 index 0000000000..c9f3b07f99 --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/step.yaml @@ -0,0 +1,10 @@ +description: Step of capital above the threshold, or part of one, that the Wales Council Tax Reduction working-age scheme treats as yielding one amount of weekly tariff income. +values: + 2013-04-01: 250 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction working-age tariff income capital step + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 33 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/33 diff --git a/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml new file mode 100644 index 0000000000..cbe82c917e --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/wales/council_tax_reduction/means_test/tariff_income/working_age/threshold.yaml @@ -0,0 +1,10 @@ +description: Capital above which the Wales Council Tax Reduction working-age scheme treats capital as yielding a weekly tariff income. +values: + 2013-04-01: 6_000 +metadata: + unit: currency-GBP + period: year + label: Wales Council Tax Reduction working-age tariff income threshold + reference: + - title: The Council Tax Reduction Schemes and Prescribed Requirements (Wales) Regulations 2013 Schedule 6 para. 33 + href: https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/33 diff --git a/policyengine_uk/parameters/gov/local_authorities/westminster/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml b/policyengine_uk/parameters/gov/local_authorities/westminster/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml new file mode 100644 index 0000000000..ea35f41d5d --- /dev/null +++ b/policyengine_uk/parameters/gov/local_authorities/westminster/council_tax_reduction/means_test/disregards_passported_applicants_capital.yaml @@ -0,0 +1,23 @@ +description: > + Whether the Westminster council tax reduction scheme for people under + pension age disregards the whole capital of an applicant on Income Support, + income-based Jobseeker's Allowance or income-related Employment and Support + Allowance. The council's working-age scheme mirrors the Council Tax + Reduction Schemes (Default Scheme) (England) Regulations 2012 with uprated + amounts and a war pension disregard (cabinet report, 15 December 2025, para. + 4.22), so it keeps the default scheme's disregard of the whole capital of an + applicant on Income Support, income-based Jobseeker's Allowance or income- + related Employment and Support Allowance (the default scheme's Schedule 10 + paragraph 8). The council's full scheme text is not published, so this is + inferred from that statement. +metadata: + label: Westminster council tax reduction disregards passported applicants' capital + unit: bool + period: year + reference: + - title: Westminster City Council cabinet report, 15 December 2025, para. 4.22 + href: https://www.westminster.gov.uk/sites/default/files/media/documents/cabinet-public-pack-15-december-2025.pdf + - title: The Council Tax Reduction Schemes (Default Scheme) (England) Regulations 2012, Schedule (the scheme), Schedule 10 para. 8 + href: https://www.legislation.gov.uk/uksi/2012/2886/schedule +values: + 2026-04-01: true 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 new file mode 100644 index 0000000000..e080bdba36 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml @@ -0,0 +1,2131 @@ +# Income derived from capital in the legacy means tests. +# +# Income Support, Housing Benefit, Pension Credit and council tax reduction +# treat rent, interest and dividends as capital, not income (IS Regs 1987 reg +# 48(4) and Sch 9 para 22; HB Regs 2006 reg 46(4) and Sch 5 para 17; HB (SPC) +# Regs 2006 Sch 5 para 22; SPC Regs 2002 Sch IV para 18; CTR equivalents), and +# disregard tax only on income they take into account (IS Sch 9 para 1; HB Sch 5 +# para 1; HB (SPC) reg 33(12); SPC reg 17(10)(a)). Rent for letting part of the +# home stays income less £20 a week per occupier (IS Sch 9 para 19; HB Sch 5 +# para 22; HB (SPC) Sch 5 para 10; SPC Sch IV para 9). +# +# Tax figures: personal allowance £12,570; basic rate 20%; property allowance +# £1,000 (gross receipts are supplied as property_rental_income, with no +# expenses, so the allowance is deducted by partial relief, ITTOIA 2005 +# s.783BH); personal savings allowance £1,000 for a basic-rate taxpayer; +# dividend allowance £500; dividend ordinary rate 8.75% in 2025-26 and 10.75% +# in 2026-27 (the model's rate); employee NI 8% above £12,570. +# +# The tax deducted (legacy_means_test_deducted_income_tax) is the income tax +# before the winter fuel payment charge, less the tax the rent, interest and +# dividends, and any Step 7 charge, would bear if nobody had earnings: earnings +# carry the extra tax they cause, including what they add on income from +# capital by using up the personal allowance or a band. + +- name: Income Support, lone parent with earnings and rent from a let property + # Earnings 10,000 use 10,000 of the personal allowance, so the remaining + # 2,570 goes against taxable rent of 5,200 - 1,000 = 4,200. Tax on rent: + # (4,200 - 2,570) x 20% = 326. NI: nil. Without the earnings the rent is + # within the personal allowance and bears no tax, so the whole 326 is tax + # the earnings cause, and it is deducted. + # Main counted the rent and deducted its tax: 10,000 + 5,200 - 326 - 1,040. + # This counts the earnings net of the tax they cause, not the rent: + # 10,000 - 326 - 1,040 (the £20 lone parent disregard) = 8,634. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 30 + employment_income: 10_000 + property_income: 5_200 + property_rental_income: 5_200 + income_support_reported: 1 + child: + age: 3 + benunits: + benunit: + members: [parent, child] + households: + household: + members: [parent, child] + output: + income_tax: [326, 0] + property_income_tax: [326, 0] + legacy_means_test_income_tax: [0, 0] + legacy_means_test_uncounted_income_tax_without_earnings: [0, 0] + legacy_means_test_deducted_income_tax: [326, 0] + income_support_applicable_income: 8_634 + +- name: Working-age Housing Benefit counts earnings net of the tax they cause, not the rent, interest or dividends + # Earnings 14,000: tax (14,000 - 12,570) x 20% = 286; NI (14,000 - 12,570) + # x 8% = 114.40. Rent 6,000: tax (6,000 - 1,000) x 20% = 1,000. Interest 500 + # is within the personal savings allowance. Dividends 1,000: (1,000 - 500) x + # 8.75% = 43.75. Income tax 1,329.75, of which 286 is the Step 4 tax on + # counted income. Without the earnings, rent 5,000, interest 500 and + # dividends 1,000 total 6,500, within the personal allowance: no tax. So + # all 1,329.75 is tax the earnings cause, and it is deducted. + # Applicable income: 14,000 - 1,329.75 - 114.40 - 260 (the £5 weekly + # disregard, set as an input here) = 12,295.85. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 14_000 + property_income: 6_000 + property_rental_income: 6_000 + savings_interest_income: 500 + dividend_income: 1_000 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person] + output: + income_tax: 1_329.75 + property_income_tax: 1_000 + dividend_income_tax: 43.75 + savings_income_tax: 0 + legacy_means_test_income_tax: 286 + legacy_means_test_uncounted_income_tax_without_earnings: 0 + legacy_means_test_deducted_income_tax: 1_329.75 + national_insurance: 114.40 + housing_benefit_applicable_income: 12_295.85 + +- name: Pension-age Housing Benefit counts rent from part of the home less £20 a week, not rent from other property + # State Pension 12,000 and private pension 2,000 use the personal allowance + # and leave 1,430 taxable: tax 286. Rent from other property 3,000: taxable + # 2,000, tax 400, not deducted. Sub-tenant rent 5,200 (£100 a week): HB (SPC) + # reg 29(1)(v) less Sch 5 para 10's £20, so 80 x 52 = 4,160. + # Applicable income: 14,000 + 4,160 - 286 = 17,874 (no earnings disregard, + # set to 0). Pension Credit income is the same 17,874, above the £238 x 52 = + # 12,376 guarantee, so there is no guarantee credit passport. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + state_pension: 12_000 + private_pension_income: 2_000 + property_income: 3_000 + property_rental_income: 3_000 + sublet_income: 5_200 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person] + output: + income_tax: 686 + legacy_means_test_income_tax: 286 + legacy_benefits_home_letting_income: 4_160 + pension_credit_income: 17_874 + guarantee_credit: 0 + housing_benefit_applicable_income: 17_874 + +- name: Pension Credit ignores rent from a let property + # SPC Sch IV para 18. Rent 4,000: taxable 3,000, of which 3,000 - (12,570 - + # 10,000) = 430 is taxed: 86, not deducted. Income 10,000 (State Pension). + # Guarantee credit (238 - 10,000 / 52) x 52 = 12,376 - 10,000 = 2,376. + # Savings credit: qualifying income 10,000 is below the threshold of + # 208.07 x 52 = 10,819.64, so nil. Main counted the rent less its tax: + # 13,914, which paid no guarantee credit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 80 + state_pension: 10_000 + property_income: 4_000 + property_rental_income: 4_000 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + output: + income_tax: 86 + legacy_means_test_income_tax: 0 + pension_credit_income: 10_000 + guarantee_credit: 2_376 + savings_credit: 0 + pension_credit: 2_376 + +- name: Pension Credit does not deduct tax on dividends + # State Pension 12,000 leaves 570 of the personal allowance for dividends + # 3,000: taxable 2,430 - 500 allowance = 1,930, at 10.75% = 207.475. That tax + # is on income Pension Credit does not count, so it is not deducted. + # Deemed income on savings 20,000: ceil((20,000 - 10,000) / 500) = £20 a week, + # 1,040 a year. Income 12,000 + 1,040 = 13,040, above 12,376: no guarantee + # credit. Savings credit: threshold 10,819.64; maximum 0.6 x (12,376 - + # 10,819.64) = 933.816; phase-in 0.6 x (13,040 - 10,819.64) = 1,332.22, + # capped at 933.816; less 0.4 x (13,040 - 12,376) = 265.60; 668.216. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 80 + state_pension: 12_000 + dividend_income: 3_000 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + savings: 20_000 + output: + dividend_income_tax: 207.475 + legacy_means_test_income_tax: 0 + pension_credit_deemed_income: 1_040 + pension_credit_income: 13_040 + guarantee_credit: 0 + savings_credit: 668.216 + pension_credit: 668.216 + +- name: Pension Credit deducts the tax wages add on dividends, but not the tax on dividends due without wages + # 2025-26. Wages 10,000 and State Pension 12,000: non-savings tax (22,000 - + # 12,570) x 20% = 1,886. Dividends 30,000 fill the rest of the 37,700 basic + # band: 28,270, of which 500 is the dividend allowance, so 27,770 x 8.75% = + # 2,429.875, and 1,730 x 33.75% = 583.875. Income tax before the winter + # fuel payment charge 4,899.75; the charge is not deducted. + # Without wages, the 570 of allowance the State Pension leaves covers + # dividends: (30,000 - 570 - 500) x 8.75% = 2,531.375, all tax on dividends, + # which Pension Credit does not count (reg 17(10)(a), Sch IV para 18), so it + # is not deducted. The tax on earnings is the extra tax the wages cause, + # 4,899.75 - 2,531.375 = 2,368.375, including what they add on dividends. + # Net earnings 10,000 - 2,368.375 = 7,631.625; disregard 5 x 52 = 260. + # Income 12,000 + 10,000 - 2,368.375 - 260 = 19,371.625. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + state_pension: 12_000 + employment_income: 10_000 + dividend_income: 30_000 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + output: + income_tax_before_winter_fuel_payment_charge: 4_899.75 + pension_credit_employment_income_tax: 2_368.375 + legacy_means_test_uncounted_income_tax_without_earnings: 2_531.375 + pension_credit_earnings_disregard: 260 + pension_credit_income: 19_371.625 + +- name: English pensioner council tax reduction counts sub-tenant rent less £20, not other rent + # SI 2012/2885 Sch 1 para 16(1)(v) and Sch 5 para 10 for the sub-tenant rent: + # 2,600 / 52 = £50 a week, less £20 = 30 x 52 = 1,560. Sch 5 para 23 + # disregards actual income from capital, so the other rent 4,000 and its tax + # 486 ((15,000 - 12,570) x 20%) are left out: 12,000 + 1,560 = 13,560. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 70 + state_pension: 12_000 + property_income: 4_000 + property_rental_income: 4_000 + sublet_income: 2_600 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + region: NORTH_EAST + output: + income_tax: 486 + legacy_means_test_income_tax: 0 + council_tax_reduction_applicable_income: 13_560 + +- name: Scottish working-age council tax reduction counts neither rent from property nor sub-tenant rent + # SSI 2021/249 reg 57(1) lists unearned income in full; it includes the + # assumed yield from capital (reg 63) but no head for actual rent or rent + # from part of the home. Earnings 12,000 are below the personal allowance + # and the NI threshold, but they use 12,000 of the allowance, leaving 570 + # against the rent of 3,000: (3,000 - 570) x 19% (the Scottish starter + # rate) = 461.70. Without the earnings the rent bears no tax, so the 461.70 + # is tax the earnings cause and is deducted: 12,000 - 461.70 = 11,538.30. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 12_000 + property_income: 3_000 + sublet_income: 2_600 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + region: SCOTLAND + output: + legacy_means_test_income_tax: 0 + legacy_means_test_deducted_income_tax: 461.70 + council_tax_reduction_applicable_income: 11_538.30 + +- name: Welsh working-age council tax reduction counts sub-tenant rent less £20, not other rent + # WSI 2013/3029 Sch 6 para 27(5) treats income derived from capital as + # capital; Sch 9 para 26 disregards £20 a week of sub-tenant rent. The + # earnings use 12,000 of the personal allowance, so the rent of 3,000 bears + # (3,000 - 570) x 20% = 486, all caused by the earnings and deducted: + # 12,000 + (50 - 20) x 52 - 486 = 13,074. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 12_000 + property_income: 3_000 + sublet_income: 2_600 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + region: WALES + output: + legacy_means_test_income_tax: 0 + legacy_means_test_deducted_income_tax: 486 + council_tax_reduction_applicable_income: 13_074 + +- name: Sub-tenant rent below £20 a week is disregarded in full + # 1,000 / 52 = 19.23 a week. + period: 2026 + input: + age: 40 + sublet_income: 1_000 + output: + legacy_benefits_home_letting_income: 0 + +- name: Working-age sub-tenant disregard was £4 before April 2008 + # IS Sch 9 para 19 before SI 2007/2618: £4 (the extra heating amount is not + # modelled). (100 - 4) x 52 = 4,992. + period: 2007 + input: + age: 40 + sublet_income: 5_200 + output: + legacy_benefits_home_letting_income: 4_992 + +- name: Working-age sub-tenant disregard is £20 from April 2008 + period: 2009 + input: + age: 40 + sublet_income: 5_200 + output: + legacy_benefits_home_letting_income: 4_160 + +- name: Pension-age sub-tenant disregard was already £20 before 2008 + # SPC Sch IV para 9 as made. + period: 2007 + input: + age: 70 + sublet_income: 5_200 + output: + legacy_benefits_home_letting_income: 4_160 + +- name: A couple's sub-tenant rent is treated as from one occupier + # The data give no count of occupiers, so the model assumes one: + # (2 x 2,600) / 52 = £100 a week, less £20 = 4,160. + period: 2026 + input: + people: + claimant: + age: 40 + sublet_income: 2_600 + partner: + age: 40 + sublet_income: 2_600 + benunits: + benunit: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + output: + legacy_benefits_home_letting_income: 4_160 + +- name: A dependant's sublet rent is not the claimant's + # legacy_benefits_home_letting_income counts the claimant's and partner's + # rent only. + period: 2026 + input: + people: + parent: + age: 40 + young_person: + age: 17 + current_education: UPPER_SECONDARY + sublet_income: 5_200 + benunits: + benunit: + members: [parent, young_person] + households: + household: + members: [parent, young_person] + output: + legacy_benefits_home_letting_income: 0 + +- name: Before Pension Credit, the £4 disregard applied at every age + # IS Regs 1987 Sch 9 para 19 as made; the pension-age £20 starts with + # Pension Credit on 6 October 2003. (100 - 4) x 52 = 4,992. + period: 2002 + input: + age: 70 + sublet_income: 5_200 + output: + legacy_benefits_home_letting_income: 4_992 + +- name: Tax reductions are shared between counted income and income from capital + # ITA 2007 s.23: Step 4 tax is 286 on earnings ((14,000 - 12,570) x 20%) and + # 1,000 on rent ((6,000 - 1,000) x 20%), 1,286 in all; Step 6 deducts a + # 1,000 tax reduction. other_tax_credits records no source, so the model + # shares it in proportion to the Step 4 tax (a stated convention: a credit + # for foreign tax on the rent would relieve only the rent, TIOPA 2010 + # s.18(2)): the rent's share is 1,000 x 1,000 / 1,286 = 777.60, leaving + # 222.40 of tax on rent. Income tax 286 less 222.40 = 63.60 is the tax on + # counted income. Without the earnings the rent bears no tax, so all 286 is + # tax the earnings cause and is deducted: HB applicable income is + # 14,000 - 286 - 114.40 (NI) - 260 = 13,339.60. The sharing sets the tax + # deducted only without earnings (the next case). + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 14_000 + property_income: 6_000 + property_rental_income: 6_000 + other_tax_credits: 1_000 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person] + output: + income_tax: 286 + legacy_means_test_income_tax: 63.605 + legacy_means_test_uncounted_income_tax_without_earnings: 0 + legacy_means_test_deducted_income_tax: 286 + housing_benefit_applicable_income: 13_339.60 + +- name: Without earnings, the tax reductions shared with income from capital set the tax deducted + # The same Step 4 and Step 6 figures with a private pension of 14,000 in + # place of the earnings: 286 on the pension, 1,000 on the rent, a 1,000 + # reduction shared pro rata, income tax 286. Nobody has earnings, so the + # tax on uncounted income is the 222.40 left on the rent, and the tax + # deducted is 286 - 222.40 = 63.60, the tax on counted income. A pension + # bears no NI. HB applicable income: 14,000 - 63.60 - 260 (the £5 weekly + # disregard, set as an input) = 13,676.40. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + private_pension_income: 14_000 + property_income: 6_000 + property_rental_income: 6_000 + other_tax_credits: 1_000 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person] + output: + income_tax: 286 + legacy_means_test_income_tax: 63.605 + legacy_means_test_uncounted_income_tax_without_earnings: 222.395 + legacy_means_test_deducted_income_tax: 63.605 + housing_benefit_applicable_income: 13_676.395 + +- name: Step 7 charges are not tax on counted income + # The High Income Child Benefit Charge is added at Step 7 of ITA 2007 s.23 + # (s.30(1)); it is not tax calculated on any income the means tests count. + # Earnings 20,000: (20,000 - 12,570) x 20% = 1,486. Income tax with a 500 + # charge is 1,986; 1,486 is deducted. + period: 2025 + input: + age: 40 + employment_income: 20_000 + CB_HITC: 500 + output: + income_tax: 1_986 + legacy_means_test_income_tax: 1_486 + +- name: Tax on counted income is nil when Step 6 reductions exceed the Step 5 tax + # Step 4 tax is 286 on earnings and 1,000 on rent. The 2,000 of Step 6 + # reductions are deducted only so far as there is Step 5 tax (ITA 2007 + # s.29(2)), so 1,286 is used and the tax left is nil; the 500 Step 7 + # charge is then added (s.23 Step 7), so the liability before the winter + # fuel payment charge is 500. Rent bears 1,286 x 1,000 / 1,286 = 1,000 of + # the reductions, so its tax after them is nil, and the helper gives + # 500 - 0 - 500 (the charge) = 0. + period: 2025 + input: + age: 40 + employment_income: 14_000 + property_income: 6_000 + property_rental_income: 6_000 + other_tax_credits: 2_000 + CB_HITC: 500 + output: + earned_income_tax: 286 + property_income_tax: 1_000 + income_tax_reductions: 1_286 + income_tax_before_winter_fuel_payment_charge: 500 + legacy_means_test_income_tax: 0 + +- name: Tax on counted income is floored at nil when the supplied tax is below the charges + # An isolation of the helper's floor, not a statutory tax calculation: the + # case above with the income tax before the winter fuel payment charge + # supplied at nil rather than its statutory 500. The helper gives 0 - 0 + # (rent's tax after its share of reductions) - 500 (the charge), floored + # at nil. + period: 2025 + input: + age: 40 + employment_income: 14_000 + property_income: 6_000 + property_rental_income: 6_000 + other_tax_credits: 2_000 + CB_HITC: 500 + income_tax_before_winter_fuel_payment_charge: 0 + output: + earned_income_tax: 286 + property_income_tax: 1_000 + legacy_means_test_income_tax: 0 + +- name: The finance-cost reduction comes off the tax on rent first + # ITTOIA 2005 ss.274A-274AA give the reduction on the property business's + # finance costs, at most its profits, so it relieves the tax on rent. The + # tax components are supplied: 286 on earnings, 1,000 on rent, a 400 + # finance-cost reduction. Income tax 1,286 - 400 = 886; the rent's tax + # after the reduction is 600, so the tax on counted income is 886 - 600 = + # 286 (shared pro rata it would be 197.04). + period: 2025 + absolute_error_margin: 0.01 + input: + age: 40 + earned_income_tax: 286 + property_income_tax: 1_000 + property_finance_cost_relief: 400 + output: + income_tax: 886 + legacy_means_test_income_tax: 286 + +- name: Other reductions are shared pro rata after the finance-cost reduction + # As above with 500 of other tax credits. The finance-cost reduction leaves + # 286 + 600 = 886 of tax; the 500 is shared in proportion to it: counted + # income bears 500 x 286 / 886 = 161.40, leaving 124.60. Income tax is + # 1,286 - 900 = 386, and 386 - (600 - 500 x 600 / 886 = 261.40) = 124.60. + period: 2025 + absolute_error_margin: 0.01 + input: + age: 40 + earned_income_tax: 286 + property_income_tax: 1_000 + property_finance_cost_relief: 400 + other_tax_credits: 500 + output: + income_tax: 386 + legacy_means_test_income_tax: 124.60 + +- name: Working-age Housing Benefit award with rent from a let property + # A continuing award (2025-26). Earnings 10,000 use 10,000 of the personal + # allowance; taxable rent 5,000 - 1,000 = 4,000, of which 4,000 - 2,570 = + # 1,430 is taxed: 286, all on rent. Without the earnings the rent bears no + # tax, so the 286 is tax the earnings cause and is deducted. NI is nil + # below 12,570. Applicable income: 10,000 - 286 - 260 (the £5 disregard, as + # an input) = 9,454. With the single 25-or-over personal allowance of + # £92.05 a week (4,786.60, an input here), HB = 6,000 - 65% x (9,454 - + # 4,786.60) = 6,000 - 3,033.81 = 2,966.19. Counting the rent would leave + # nothing. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 10_000 + property_income: 5_000 + property_rental_income: 5_000 + housing_benefit_reported: 1 + benunits: + benunit: + members: [person] + would_claim_uc: false + housing_benefit_applicable_income_disregard: 260 + housing_benefit_applicable_amount: 4_786.60 + households: + household: + members: [person] + tenure_type: RENT_FROM_COUNCIL + rent: 6_000 + region: NORTH_EAST + output: + property_income_tax: 286 + legacy_means_test_income_tax: 0 + legacy_means_test_deducted_income_tax: 286 + housing_benefit_applicable_income: 9_454 + housing_benefit: 2_966.19 + +- name: An English pensioner with a let property worth more than £16,000 gets no council tax reduction + # The rent no longer counts as income, but the property counts as capital: + # SI 2012/2885 Sch 1 para 31(1) ("the whole of his capital") and reg 11(2) + # (no reduction above 16,000). It is valued less 10% for the expenses of + # sale (para 32(a)): 100,000 x 0.9 = 90,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 14_000 + property_income: 7_000 + 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 + other_residential_property_value: 100_000 + output: + council_tax_reduction_assessable_capital: 90_000 + council_tax_reduction: 0 + +- name: A Welsh working-age applicant with a let property worth more than £16,000 gets no council tax reduction + # WSI 2013/3029 reg 30: no reduction where capital exceeds 16,000. The + # property is valued less 10% for the expenses of sale (Sch 6 para 28(a)): + # 45,000. Tariff income (Sch 6 para 33) counts capital up to 16,000: + # (16,000 - 6,000) / 250 = 40 a week, 2,080 a year. The earnings use 9,000 + # of the personal allowance, so the rent of 5,200 bears (14,200 - 12,570) + # x 20% = 326, all caused by the earnings and deducted. Income is 9,000 - + # 326 + 2,080 = 10,754. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 9_000 + property_income: 5_200 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: RENT_FROM_COUNCIL + rent: 5_000 + council_tax: 1_500 + other_residential_property_value: 50_000 + output: + council_tax_reduction_assessable_capital: 45_000 + council_tax_reduction_tariff_income: 2_080 + council_tax_reduction_applicable_income: 10_754 + council_tax_reduction: 0 + +- name: A Scottish mixed-age couple on Universal Credit is under the working-age scheme + # SSI 2021/249 reg 3(1)(b)(ii): it applies where the applicant has reached + # pensionable age but the applicant or partner has an award of UC. Its reg + # 57(1) has no head for sub-tenant rent, so only the UC (1,000, an input) + # counts here. The couple are 30 years apart, so their roles are supplied. + period: 2026 + input: + people: + claimant: + age: 70 + sublet_income: 5_200 + is_claimant_or_partner: true + partner: + age: 40 + is_claimant_or_partner: true + benunits: + benunit: + members: [claimant, partner] + universal_credit: 1_000 + households: + household: + members: [claimant, partner] + country: SCOTLAND + local_authority: GLASGOW_CITY + output: + legacy_benefits_home_letting_income: 4_160 + council_tax_reduction_applicable_income: 1_000 + +- name: Before April 2022 the Scottish working-age scheme counted sub-tenant rent less £20 + # SSI 2012/303 Sch 4 para 25 (as at 1 April 2021): (100 - 20) x 52 = 4,160. + period: 2021 + input: + people: + person: + age: 40 + sublet_income: 5_200 + benunits: + benunit: + members: [person] + universal_credit: 0 + claims_universal_credit: false + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + output: + council_tax_reduction_applicable_income: 4_160 + +- name: From April 2022 the Scottish working-age scheme does not count sub-tenant rent + # SSI 2021/249, in force 1 April 2022 (reg 1); reg 57(1) has no head for it. + period: 2023 + input: + people: + person: + age: 40 + sublet_income: 5_200 + benunits: + benunit: + members: [person] + universal_credit: 0 + claims_universal_credit: false + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + output: + council_tax_reduction_applicable_income: 0 + +- name: Welsh working-age tariff income on a let property below the capital limit + # The rent no longer counts, but the property counts as capital at 90% of + # its value (WSI 2013/3029 Sch 6 para 28(a)): 9,000. Sch 6 para 33 treats it + # as a weekly income of 1 for each 250, or part of 250, over 6,000: 12 a + # week, 624 a year. Earnings 9,000 are below the personal allowance and the + # NI threshold, but they leave 3,570 of the allowance for the rent of + # 5,200, which bears (5,200 - 3,570) x 20% = 326. Without the earnings the + # rent bears no tax, so the 326 is deducted. Income 9,000 - 326 + 624 = + # 9,298. With the applicable amount supplied as 6,000, CTR = 1,500 - 20% x + # (9,298 - 6,000) = 840.40. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 9_000 + property_income: 5_200 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: RENT_FROM_COUNCIL + rent: 5_000 + council_tax: 1_500 + other_residential_property_value: 10_000 + output: + council_tax_reduction_assessable_capital: 9_000 + council_tax_reduction_tariff_income: 624 + legacy_means_test_deducted_income_tax: 326 + council_tax_reduction_applicable_income: 9_298 + council_tax_reduction: 840.40 + +- name: Scottish working-age assumed yield on a let property below the capital limit + # SSI 2021/249 reg 70(1)(a) values the property less 10%: 9,000. Reg + # 63(1)(b): a weekly income of 1 for each 250 over 6,000 and 1 for any part + # of 250: 12 a week, 624 a year; reg 63(3) treats the actual rent as + # capital. The earnings leave 3,570 of the personal allowance for the rent + # of 5,200, which bears (5,200 - 3,570) x 19% (the Scottish starter rate) = + # 309.70, all caused by the earnings and deducted. Income 9,000 - 309.70 + + # 624 = 9,314.30. CTR = 1,500 - 20% x (9,314.30 - 6,000) = 837.14. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 9_000 + property_income: 5_200 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: RENT_FROM_COUNCIL + rent: 5_000 + council_tax: 1_500 + other_residential_property_value: 10_000 + output: + council_tax_reduction_assessable_capital: 9_000 + council_tax_reduction_tariff_income: 624 + legacy_means_test_deducted_income_tax: 309.70 + council_tax_reduction_applicable_income: 9_314.30 + council_tax_reduction: 837.14 + +- name: An English pensioner's let property valued less sale expenses stays within the limit + # A 17,000 property is valued at 15,300 (SI 2012/2885 Sch 1 para 32(a)), so + # the 16,000 limit (reg 11(2)) does not exclude the pensioner. Tariff income + # (Sch 1 para 37): 5,300 / 500 = 10.6, so 11 a week, 572 a year. Pension + # 14,000 less its tax 286 ((14,000 - 12,570) x 20%) + 572 = 14,286; the rent + # and its tax (400) do not count (Sch 5 para 23). With the 238 a week + # allowance (12,376) supplied as the applicable amount, CTR = 2,000 - 20% x + # (14,286 - 12,376) = 1,618. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 14_000 + property_income: 3_000 + benunits: + benunit: + members: [pensioner] + claims_all_entitled_benefits: true + would_claim_pc: false + council_tax_reduction_applicable_amount: 12_376 + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 17_000 + output: + legacy_means_test_income_tax: 286 + council_tax_reduction_assessable_capital: 15_300 + council_tax_reduction_tariff_income: 572 + council_tax_reduction_applicable_income: 14_286 + council_tax_reduction: 1_618 + +- name: Welsh and Scottish pensioner tariff income is 1 a week per 500 over 10,000 + # WSI 2013/3029 Sch 1 para 31 and SSI 2012/319 reg 27(2): savings 12,600 + # are 2,600 over 10,000, 5.2 steps of 500, so 6 a week, 312 a year. + period: 2026 + input: + people: + welsh_pensioner: + age: 75 + private_pension_income: 12_000 + scottish_pensioner: + age: 75 + private_pension_income: 12_000 + benunits: + welsh: + members: [welsh_pensioner] + would_claim_pc: false + scottish: + members: [scottish_pensioner] + would_claim_pc: false + households: + welsh_household: + members: [welsh_pensioner] + country: WALES + local_authority: CARDIFF + savings: 12_600 + scottish_household: + members: [scottish_pensioner] + country: SCOTLAND + local_authority: GLASGOW_CITY + savings: 12_600 + output: + council_tax_reduction_pensioner: [true, true] + council_tax_reduction_tariff_income: [312, 312] + council_tax_reduction_applicable_income: [12_312, 12_312] + +- 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 + # (savings 15,000: 10 steps of 500 over 10,000) = 14,610.54. Savings credit + # = 60% x (238 - 208.07) x 52 - 40% x (14,610.54 - 238 x 52) = 933.816 - + # 893.816 = 40.00, so the award is savings credit only and council tax + # reduction counts 14,610.54 + 40 = 14,650.54 (SI 2012/2885 Sch 1 para 14). + # CTR = 2,000 - 20% x (14,650.54 - 13,312) = 1,732.29. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 90 + state_pension: 10_000 + private_pension_income: 2_000 + sublet_income: 3_130.54 + 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: 15_000 + output: + pension_credit_income: 14_610.54 + savings_credit: 40 + in_receipt_of_savings_credit_only: true + council_tax_reduction_tariff_income: 0 + council_tax_reduction_applicable_income: 14_650.54 + council_tax_reduction: 1_732.29 + +- name: The same pensioner with 200 more sub-tenant rent is assessed under the general rules with tariff income + # 3,330.54 counts 2,290.54. Pension Credit income 14,810.54 leaves a savings + # credit of 933.816 - 40% x (14,810.54 - 12,376) < 0, so nil. Under the + # general rules: 12,000 + 2,290.54, no tax (12,000 is under the personal + # allowance), plus tariff income on 15,000 (Sch 1 para 37): 10 a week, 520 + # a year = 14,810.54, more than the 14,650.54 counted before. CTR = 2,000 - + # 20% x (14,810.54 - 13,312) = 1,700.29. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 90 + state_pension: 10_000 + private_pension_income: 2_000 + sublet_income: 3_330.54 + 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: 15_000 + output: + savings_credit: 0 + in_receipt_of_savings_credit_only: false + council_tax_reduction_tariff_income: 520 + council_tax_reduction_applicable_income: 14_810.54 + council_tax_reduction: 1_700.29 + +- name: Oxford tests a Universal Credit recipient on the Universal Credit assessment of capital + # The household's let property is worth 20,000 (18,000 after sale + # expenses), but the claimant's Universal Credit capital is 15,000 (a + # reported assessment). Oxford's Appendix 6 ignores capital already taken + # into account for Universal Credit, so the 16,000 limit (paragraph 28) + # does not exclude the claimant. UC: 424.90 - 36 x 4.35 (assumed yield on + # 9,000 over 6,000) = 268.30 a month, 3,219.60 a year, 61.92 a week: band 1, + # 100% of 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: true + uc_reported_capital: 15_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: OXFORD + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 3_219.60 + council_tax_reduction_assessable_capital: 15_000 + oxford_council_tax_reduction: 2_000 + +- name: Oxford ignores the capital of an Income Support recipient + # Appendix 6 also ignores capital already taken into account for Income + # Support, so the household's 18,000 of property (after sale expenses) does + # not exclude the claimant; Income Support recipients' income is nil for the + # bands, so the award is 100% of 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: OXFORD + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + oxford_council_tax_reduction: 2_000 + +- name: Wales uses the Secretary of State's capital for a Universal Credit recipient + # WSI 2013/3029 Sch 6 para 9(6): with a UC award the authority uses the + # Secretary of State's calculation of capital, 15,000 here (a reported + # assessment), not the household's 18,000 of property after sale expenses. + # The income includes the UC assumed yield (UC Regs 2013 reg 72): 36 x 4.35 + # x 12 = 1,879.20. Income 3,219.60 (UC, an input) + 1,879.20 = 5,098.80 is + # below the applicable amount (6,000, an input), so CTR is the full 1,500. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + universal_credit: 3_219.60 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 15_000 + council_tax_reduction_tariff_income: 1_879.20 + council_tax_reduction_applicable_income: 5_098.80 + council_tax_reduction: 1_500 + +- name: From April 2022 Scotland calculates a Universal Credit recipient's capital itself + # SSI 2021/249 regs 66 to 70 have no rule taking capital from the + # Universal Credit assessment, so the household's property counts: 18,000 + # after sale expenses, over the 16,000 limit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + universal_credit: 3_219.60 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 0 + +- name: Before April 2022 Scotland used the Universal Credit assessment of capital + # SSI 2012/303 reg 26(6) (reg 26(4) as made): the Secretary of State's + # capital, 15,000. Income 3,219.60 + 1,879.20 assumed yield = 5,098.80, + # below the applicable amount, so CTR is the full 1,500. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + universal_credit: 3_219.60 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 15_000 + council_tax_reduction_tariff_income: 1_879.20 + council_tax_reduction: 1_500 + +- name: A Welsh Income Support recipient has no tariff income + # WSI 2013/3029 Sch 10 para 8 disregards the whole capital of an applicant + # on Income Support, so it yields no tariff income. + period: 2026 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + would_claim_uc: false + income_support: 4_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + savings: 10_000 + output: + council_tax_reduction_tariff_income: 0 + +- name: A Scottish couple whose joint Universal Credit award is held only by people over pension age is under the pension-age scheme + # SSI 2021/249 reg 3(2): the working-age scheme does not apply where the + # award is held only by people over pensionable age. Universal Credit + # itself needs a claimant under that age (UC Regs 2013 reg 3(2)(a)), so the + # model treats such an award as not selecting the working-age scheme. SSI + # 2012/319 counts the sub-tenant rent less 20 a week: (100 - 20) x 52 = + # 4,160, plus the UC (1,000, an input) as the model counts it: 5,160. The + # couple do not claim Pension Credit, whose guarantee credit would + # otherwise disregard their whole income. + period: 2026 + input: + people: + claimant: + age: 71 + sublet_income: 5_200 + partner: + age: 70 + benunits: + benunit: + members: [claimant, partner] + universal_credit: 1_000 + would_claim_pc: false + households: + household: + members: [claimant, partner] + country: SCOTLAND + local_authority: GLASGOW_CITY + output: + council_tax_reduction_pensioner: true + council_tax_reduction_applicable_income: 5_160 + +- name: Wales disregards the whole capital of an Income Support recipient + # WSI 2013/3029 Sch 6 para 26(2) and Sch 10 para 8: the whole capital of an + # applicant on Income Support is disregarded, so £20,000 of property (an + # input; £18,000 after sale expenses) does not breach the £16,000 limit. + # The Income Support (an input) is below the applicable amount (an input), + # so the award is the full 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 0 + council_tax_reduction: 2_000 + +- name: Scotland disregarded an Income Support recipient's capital before April 2022 + # SSI 2012/303 Sch 5 para 7 (as at 1 April 2021): the whole capital of an + # applicant on Income Support is disregarded. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 0 + council_tax_reduction: 2_000 + +- name: From April 2022 Scotland tests an Income Support recipient's capital + # SSI 2021/249 has no disregard of a passported applicant's capital: reg + # 13(11) treats only the income conditions as met, and reg 13(1) applies + # the £16,000 limit. £20,000 of property less 10% sale expenses is 18,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 0 + +- name: Kingston upon Thames disregards the whole capital of an Income Support recipient + # The council keeps the disregard (its 2026-27 scheme, Schedule 10 para 8), so the + # household's £18,000 of property (after sale expenses) does not breach the + # £16,000 limit, and the passported award is the full 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: KINGSTON_UPON_THAMES + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 2_000 + +- name: Merton disregards the whole capital of an Income Support recipient + # The council keeps the disregard (its 2026-27 scheme, Schedule 10 para 8), so the + # household's £18,000 of property (after sale expenses) does not breach the + # £16,000 limit, and the passported award is the full 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: MERTON + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 2_000 + +- name: Westminster disregards the whole capital of an Income Support recipient + # The council keeps the disregard (the default scheme's Schedule 10 para 8, which the council's scheme mirrors), so the + # household's £18,000 of property (after sale expenses) does not breach the + # £16,000 limit, and the passported award is the full 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: WESTMINSTER + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 2_000 + +- name: Newham tests an Income Support recipient's capital + # Newham's 2026 scheme leaves the default scheme's Schedule 10 paragraphs 8 + # and 9 blank, so the £18,000 of property (after sale expenses) is tested + # against its £6,000 capital limit and there is no award. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + would_claim_uc: false + income_support: 4_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: NEWHAM + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction: 0 + +- name: Wales uses the Universal Credit capital assessment when the benefit cap reduces the award to nil + # The benefit cap reduces a Universal Credit award (UC Regs 2013 reg 81) + # rather than ending it: here a £1,000 award (an input) is capped to nil. + # WSI 2013/3029 Sch 6 para 9(6) still takes capital from the award's + # assessment, £15,000 (an input), not the household's £18,000 of property + # after sale expenses. The UC assumed yield on 9,000 over 6,000: 36 x 4.35 + # x 12 = 1,879.20, below the applicable amount (an input), so the award is + # the full 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + claims_universal_credit: true + universal_credit_pre_benefit_cap: 1_000 + uc_benefit_cap_reduction_after_floor: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 0 + council_tax_reduction_universal_credit_award: true + council_tax_reduction_assessable_capital: 15_000 + council_tax_reduction_tariff_income: 1_879.20 + council_tax_reduction: 2_000 + +- name: Before April 2022 Scotland used the Universal Credit capital assessment for a capped award + # SSI 2012/303 reg 26(6) (reg 26(4) as made), with the award capped to nil + # as above. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + claims_universal_credit: true + universal_credit_pre_benefit_cap: 1_000 + uc_benefit_cap_reduction_after_floor: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 0 + council_tax_reduction_universal_credit_award: true + council_tax_reduction_assessable_capital: 15_000 + council_tax_reduction_tariff_income: 1_879.20 + council_tax_reduction: 2_000 + +- name: Oxford ignores a capped Universal Credit award's capital + # Appendix 3 covers applicants who would be awarded Universal Credit but for + # deductions or other adjustments, and Appendix 6 ignores capital already + # taken into account for it, so the £18,000 of property does not breach + # paragraph 28's £16,000 limit. Weekly income nil: band 1, 100% of 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + claims_universal_credit: true + universal_credit_pre_benefit_cap: 1_000 + uc_benefit_cap_reduction_after_floor: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: OXFORD + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 0 + council_tax_reduction_universal_credit_award: true + council_tax_reduction_assessable_capital: 15_000 + oxford_council_tax_reduction: 2_000 + council_tax_reduction: 2_000 + +- name: Oxford adds no tariff income from a capped Universal Credit award's capital + # As above, the award is capped to nil but is still an award (Appendix 3), + # and Appendix 6 ignores the £15,000 taken into account for it, so no tariff + # income is added. Weekly income 24,000 / 52 = 461.54, in band 1 (up to + # £480): 100% of 2,000. Treating the nil payment as no award would add + # ceil((15,000 - 6,000) / 250) = £36 a week, giving 497.54, band 2 (75%). + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + claims_universal_credit: true + universal_credit_pre_benefit_cap: 1_000 + uc_benefit_cap_reduction_after_floor: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + council_tax_reduction_applicable_income: 24_000 + households: + household: + members: [person] + country: ENGLAND + local_authority: OXFORD + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 0 + council_tax_reduction_universal_credit_award: true + council_tax_reduction_assessable_capital: 15_000 + oxford_council_tax_reduction: 2_000 + council_tax_reduction: 2_000 + +- name: From April 2022 Scotland applies the Universal Credit yield to a capped award on its own capital + # The benefit cap reduces the award rather than ending it (UC Regs 2013 + # reg 81), so there is still an award of Universal Credit. With one, + # unearned income, which includes the assumed yield (reg 57(1)(l)), is + # calculated monthly (reg 64(1)), so reg 63(1)(a) applies the monthly + # yield, £4.35 per £250 over £6,000, to the capital + # the authority calculates, here the £18,000 of property after sale + # expenses (counted up to the limit: 40 x 4.35 x 12 = 2,088). It is over the + # £16,000 limit, so there is no award. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + claims_universal_credit: true + universal_credit_pre_benefit_cap: 1_000 + uc_benefit_cap_reduction_after_floor: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 2_000 + other_residential_property_value: 20_000 + output: + universal_credit: 0 + council_tax_reduction_universal_credit_award: true + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction_tariff_income: 2_088 + council_tax_reduction: 0 + +- name: An English pensioner couple's Universal Credit input does not bring in the working-age capital rules + # Universal Credit needs a claimant under the qualifying age (UC Regs 2013 + # reg 3(2)(a)), so the £1,000 award supplied to a couple aged 71 and 70 is + # disregarded in choosing the scheme (council_tax_reduction_pensioner), + # and the Universal Credit capital assessment (£15,000, an input) is not + # used either: the household's £20,000 of property, valued at £18,000, + # exceeds the £16,000 limit. Pensioner tariff income on capital up to + # £16,000: 12 x 52 = 624. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + partner: + age: 70 + benunits: + benunit: + members: [claimant, partner] + claims_all_entitled_benefits: true + would_claim_pc: false + universal_credit: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [claimant, partner] + country: ENGLAND + local_authority: MAIDSTONE + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + other_residential_property_value: 20_000 + output: + council_tax_reduction_pensioner: true + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction_tariff_income: 624 + council_tax_reduction: 0 + +- name: A Welsh pensioner couple's Universal Credit input does not bring in the working-age capital rules + # Universal Credit needs a claimant under the qualifying age (UC Regs 2013 + # reg 3(2)(a)), so the £1,000 award supplied to a couple aged 71 and 70 is + # disregarded in choosing the scheme (council_tax_reduction_pensioner), + # and the Universal Credit capital assessment (£15,000, an input) is not + # used either: the household's £20,000 of property, valued at £18,000, + # exceeds the £16,000 limit. Pensioner tariff income on capital up to + # £16,000: 12 x 52 = 624. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 71 + partner: + age: 70 + benunits: + benunit: + members: [claimant, partner] + claims_all_entitled_benefits: true + would_claim_pc: false + universal_credit: 1_000 + uc_reported_capital: 15_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [claimant, partner] + country: WALES + local_authority: CARDIFF + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + other_residential_property_value: 20_000 + output: + council_tax_reduction_pensioner: true + council_tax_reduction_assessable_capital: 18_000 + council_tax_reduction_tariff_income: 624 + council_tax_reduction: 0 + +- name: Wales does not count sub-tenant rent for a Universal Credit recipient + # WSI 2013/3029 Sch 6 para 9(1): the authority uses the Secretary of State's assessment of income + # for the award, adjusted only for the award itself and non-dependants. + # Universal Credit's unearned income (UC Regs 2013 reg 66) has no head for + # rent from a sub-tenant, so the £5,200 (£4,160 after the £20 a week + # disregard) does not count. Income is the award, 3,000 (an input), below + # the applicable amount (an input): the full 1,500. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + sublet_income: 5_200 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + universal_credit: 3_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: WALES + local_authority: CARDIFF + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + output: + legacy_benefits_home_letting_income: 4_160 + council_tax_reduction_applicable_income: 3_000 + council_tax_reduction: 1_500 + +- name: Scotland before April 2022 does not count sub-tenant rent for a Universal Credit recipient + # SSI 2012/303 reg 26(1): the authority uses the Secretary of State's assessment of income + # for the award, adjusted only for the award itself and non-dependants. + # Universal Credit's unearned income (UC Regs 2013 reg 66) has no head for + # rent from a sub-tenant, so the £5,200 (£4,160 after the £20 a week + # disregard) does not count. Income is the award, 3,000 (an input), below + # the applicable amount (an input): the full 1,500. + period: 2021 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + sublet_income: 5_200 + benunits: + benunit: + members: [person] + claims_all_entitled_benefits: true + universal_credit: 3_000 + council_tax_reduction_applicable_amount: 6_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + tenure_type: OWNED_OUTRIGHT + council_tax: 1_500 + output: + legacy_benefits_home_letting_income: 4_160 + council_tax_reduction_applicable_income: 3_000 + council_tax_reduction: 1_500 + +- name: Welsh working-age tariff income counts any part of a £250 step + # WSI 2013/3029 Sch 6 para 33: £1 a week for each complete £250 over + # £6,000 and £1 for any part. Savings 6,001, 6,250 and 6,251 give 1, 1 and 2 + # a week: 52, 52 and 104 a year. + period: 2026 + input: + people: + a: + age: 40 + b: + age: 40 + c: + age: 40 + benunits: + ba: + members: [a] + would_claim_uc: false + bb: + members: [b] + would_claim_uc: false + bc: + members: [c] + would_claim_uc: false + households: + ha: + members: [a] + country: WALES + local_authority: CARDIFF + savings: 6_001 + hb: + members: [b] + country: WALES + local_authority: CARDIFF + savings: 6_250 + hc: + members: [c] + country: WALES + local_authority: CARDIFF + savings: 6_251 + output: + council_tax_reduction_tariff_income: [52, 52, 104] + +- name: The Universal Credit yield also counts any part of a £250 step + # UC Regs 2013 reg 72(1): £4.35 a month for each £250 over £6,000 and for + # any part. UC capital 6,001, 6,250 and 6,251 (inputs) give 1, 1 and 2 + # steps: 52.20, 52.20 and 104.40 a year. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a: + age: 40 + b: + age: 40 + c: + age: 40 + benunits: + ba: + members: [a] + universal_credit: 1_000 + uc_reported_capital: 6_001 + bb: + members: [b] + universal_credit: 1_000 + uc_reported_capital: 6_250 + bc: + members: [c] + universal_credit: 1_000 + uc_reported_capital: 6_251 + households: + ha: + members: [a] + country: WALES + local_authority: CARDIFF + hb: + members: [b] + country: WALES + local_authority: CARDIFF + hc: + members: [c] + country: WALES + local_authority: CARDIFF + output: + council_tax_reduction_tariff_income: [52.20, 52.20, 104.40] + +- name: Debt secured on a let property comes off its value after the sale expenses + # SI 2012/2885 Sch 1 para 32: market value less 10% where there would be + # expenses of sale, then less any encumbrance secured on it. £20,000 less + # £2,000, less £4,000 secured on it (an input), is £14,000, within the + # £16,000 limit. Tariff income (Sch 1 para 37): 4,000 / 500 = 8 a week, 416 + # a year. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 14_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + other_residential_property_value: 20_000 + other_residential_property_secured_debt: 4_000 + output: + council_tax_reduction_assessable_capital: 14_000 + council_tax_reduction_tariff_income: 416 + +- name: Negative equity in one property does not reduce other capital + # The debt is deducted from the asset it is secured on, and that asset is + # valued at nil, not below: a £10,000 property (£9,000 after sale + # expenses) with £15,000 secured on it adds nothing to £12,000 of savings. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 14_000 + benunits: + benunit: + members: [pensioner] + would_claim_pc: false + households: + household: + members: [pensioner] + country: ENGLAND + local_authority: MAIDSTONE + savings: 12_000 + other_residential_property_value: 10_000 + other_residential_property_secured_debt: 15_000 + output: + council_tax_reduction_assessable_capital: 12_000 + +- name: A Scottish mixed-age couple on Income Support is under the working-age scheme + # SSI 2021/249 reg 3(1): the scheme for people under pensionable age applies + # where the applicant has reached pensionable age but the applicant or + # partner has a qualifying income-related benefit, here Income Support (an + # input, with no Universal Credit). Its reg 57(1) has no head for + # sub-tenant rent, so only the Income Support, 3,000, counts. + period: 2026 + input: + people: + claimant: + age: 70 + sublet_income: 5_200 + partner: + age: 40 + benunits: + benunit: + members: [claimant, partner] + income_support: 3_000 + would_claim_uc: false + would_claim_pc: false + households: + household: + members: [claimant, partner] + country: SCOTLAND + local_authority: GLASGOW_CITY + output: + council_tax_reduction_pensioner: false + legacy_benefits_home_letting_income: 4_160 + council_tax_reduction_applicable_income: 3_000 + +- name: A Scottish Income Support recipient's capital counts but yields no tariff income + # SSI 2021/249 has no disregard of a passported applicant's capital, so the + # 10,000 of savings is the applicant's capital (under the 16,000 limit, + # reg 13(1)). But reg 13(11) treats a qualifying income-related benefit + # claimant as meeting the income conditions, so their income, including + # the reg 63 assumed yield, is not assessed: nil tariff income. + period: 2026 + input: + people: + person: + age: 40 + benunits: + benunit: + members: [person] + would_claim_uc: false + income_support: 4_000 + households: + household: + members: [person] + country: SCOTLAND + local_authority: GLASGOW_CITY + savings: 10_000 + output: + council_tax_reduction_assessable_capital: 10_000 + council_tax_reduction_tariff_income: 0 + +# A household head who applies alone for council tax reduction is the +# applicant (SI 2012/2885 reg 2(1)), so her own income counts (Sch 1 para 11), +# including rent for letting part of her home (Sch 1 para 16(1)(v), less £20 a +# week under Sch 5 para 10), and the benefit unit's claimant's and partner's +# does not. In the first three cases below the head, aged 70, reached State +# Pension age after 1 April 2021, so her 2026-27 personal allowance is £238 a +# week: 238 x 52 = 12,376. Maidstone runs England's pensioner scheme: +# maximum 100% of the £2,000 council tax, withdrawn at 20% of income above the +# applicable amount. Her £12,000 private pension falls within the £12,570 +# personal allowance, and the model taxes none of the rent: income tax nil. + +- name: A household head applying alone counts her own rent from letting part of the home in council tax reduction + # Rent 5,200 / 52 = 100 a week, less 20 = 80; 80 x 52 = 4,160. + # Income 12,000 + 4,160 = 16,160. CTR 2,000 - 20% x (16,160 - 12,376) + # = 2,000 - 756.80 = 1,243.20. The young couple's legacy measure + # (legacy_benefits_home_letting_income, their claimant and partner) holds + # none of it. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 70 + is_household_head: true + private_pension_income: 12_000 + sublet_income: 5_200 + mother: + age: 16 + is_parent: true + is_household_head: false + father: + age: 16 + is_parent: true + is_household_head: false + baby: + age: 0 + is_household_head: false + benunits: + family: + members: [head, mother, father, baby] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + home: + members: [head, mother, father, baby] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_head_applies_alone: [true] + is_council_tax_reduction_applicant_or_partner: [true, false, false, false] + income_tax: [0, 0, 0, 0] + legacy_benefits_home_letting_income: [0] + council_tax_reduction_home_letting_income: [4_160] + council_tax_reduction_applicable_income: [16_160] + council_tax_reduction_applicable_amount: [12_376] + council_tax_reduction: 1_243.20 + +- name: The same head in her own benefit unit gets the same council tax reduction + # The control: the head is her own benefit unit's claimant, so both + # measures count her rent: 4,160, income 16,160 and CTR 1,243.20 as above. + # The couple's unit counts the baby's Child Benefit, 27.05 x 52 = 1,406.60; + # neither parent is liable for the council tax, so they get no reduction. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 70 + is_household_head: true + private_pension_income: 12_000 + sublet_income: 5_200 + mother: + age: 16 + is_parent: true + is_household_head: false + father: + age: 16 + is_parent: true + is_household_head: false + baby: + age: 0 + is_household_head: false + benunits: + head_unit: + members: [head] + claims_all_entitled_benefits: true + would_claim_uc: false + couple_unit: + members: [mother, father, baby] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + home: + members: [head, mother, father, baby] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_head_applies_alone: [false, false] + legacy_benefits_home_letting_income: [4_160, 0] + council_tax_reduction_home_letting_income: [4_160, 0] + council_tax_reduction_applicable_income: [16_160, 1_406.60] + council_tax_reduction: 1_243.20 + +- name: A household head applying alone does not count the young couple's rent from letting part of the home + # The converse: the mother receives the 5,200, and the head has none. The + # couple's own measure counts it, 4,160, but the head's CTR income is her + # pension alone: 12,000, below 12,376, so CTR pays the whole 2,000. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 70 + is_household_head: true + private_pension_income: 12_000 + mother: + age: 16 + is_parent: true + is_household_head: false + sublet_income: 5_200 + father: + age: 16 + is_parent: true + is_household_head: false + baby: + age: 0 + is_household_head: false + benunits: + family: + members: [head, mother, father, baby] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + home: + members: [head, mother, father, baby] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 0 + output: + council_tax_reduction_head_applies_alone: [true] + legacy_benefits_home_letting_income: [4_160] + council_tax_reduction_home_letting_income: [0] + council_tax_reduction_applicable_income: [12_000] + council_tax_reduction: 2_000 + +- name: A household head applying alone keeps her tariff income when the couple she lives with gets Pension Credit + # The head, aged 85, reached State Pension age before 1 April 2021, so her + # allowance is 256 x 52 = 13,312. A pensioner couple flagged as parents + # forms the benefit unit's claimant and partner, and gets guarantee credit. + # That award is theirs, so the head's capital and tariff income follow the + # general rule: household savings 14,000 stand in for her capital. Tariff + # (Sch 1 para 37): £1 a week for each £500, or part, over £10,000: + # 4,000 / 500 = 8; 8 x 52 = 416. Tax on her pension: (13,000 - 12,570) + # x 20% = 86. Income 13,000 - 86 + 416 = 13,330. CTR 2,000 - 20% x + # (13,330 - 13,312) = 1,996.40. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 85 + is_household_head: true + private_pension_income: 13_000 + older_partner: + age: 67 + is_parent: true + is_household_head: false + younger_partner: + age: 66 + is_parent: true + is_household_head: false + benunits: + family: + members: [head, older_partner, younger_partner] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + home: + members: [head, older_partner, younger_partner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 14_000 + output: + is_claimant_or_partner: [false, true, true] + council_tax_reduction_head_applies_alone: [true] + in_receipt_of_guarantee_credit: [true] + council_tax_reduction_assessable_capital: [14_000] + council_tax_reduction_tariff_income: [416] + council_tax_reduction_applicable_income: [13_330] + council_tax_reduction_applicable_amount: [13_312] + council_tax_reduction: 1_996.40 + +- name: A household head applying alone keeps her tariff income when the couple she lives with gets savings credit only + # As the guarantee credit case, but the couple are 80 and 78 and the elder + # has a £20,000 private pension, so the model gives them savings credit of + # £928 a year and no guarantee credit. That award is theirs, so the head + # keeps her tariff income. The head, aged 90, reached State Pension age + # before 1 April 2021, so her allowance is 256 x 52 = 13,312. Tariff + # 8 x 52 = 416; tax (13,000 - 12,570) x 20% = 86; income 13,000 - 86 + 416 + # = 13,330. CTR 2,000 - 20% x (13,330 - 13,312) = 1,996.40. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + head: + age: 90 + is_household_head: true + private_pension_income: 13_000 + older_partner: + age: 80 + is_parent: true + is_household_head: false + private_pension_income: 20_000 + younger_partner: + age: 78 + is_parent: true + is_household_head: false + benunits: + family: + members: [head, older_partner, younger_partner] + claims_all_entitled_benefits: true + would_claim_uc: false + households: + home: + members: [head, older_partner, younger_partner] + country: ENGLAND + local_authority: MAIDSTONE + council_tax: 2_000 + savings: 14_000 + output: + is_claimant_or_partner: [false, true, true] + council_tax_reduction_head_applies_alone: [true] + in_receipt_of_guarantee_credit: [false] + in_receipt_of_savings_credit_only: [true] + council_tax_reduction_assessable_capital: [14_000] + council_tax_reduction_tariff_income: [416] + council_tax_reduction_applicable_income: [13_330] + council_tax_reduction_applicable_amount: [13_312] + council_tax_reduction: 1_996.40 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_tax_caused_by_earnings.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_tax_caused_by_earnings.yaml new file mode 100644 index 0000000000..9a50ebbd02 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_tax_caused_by_earnings.yaml @@ -0,0 +1,369 @@ +# The income tax Income Support, Housing Benefit, Pension Credit and council +# tax reduction deduct (legacy_means_test_deducted_income_tax): the income tax +# before the winter fuel payment charge, less the tax that rent, interest and +# dividends, and any Step 7 charge, would bear if nobody had employed earnings +# or self-employment income. The tests treat income derived from capital as +# capital (IS Regs 1987 reg 48(4) and Sch 9 para 22; HB Regs 2006 reg 46(4) +# and Sch 5 para 17) and disregard tax only on income they take into account +# (IS Sch 9 para 1; HB Sch 5 para 1); earnings are net of the income tax +# deducted from them (IS reg 36(3)(a); HB reg 36(3)(a)). Earnings carry the +# extra tax they cause. +# +# 2026-27 figures: personal allowance £12,570; basic rate 20% to £37,700 of +# taxable income, higher rate 40%; starting rate for savings 0% on £5,000, +# less taxable non-savings income; personal savings allowance £1,000 for a +# basic-rate and £500 for a higher-rate taxpayer; employee NI 8% from £12,570 +# to £50,270. Each person is 40 and lives in England unless stated. + +- name: Pay of 30,000 and interest of 60,000, the tests deduct the tax the pay adds on the interest + # With the pay: non-savings taxable income 30,000 - 12,570 = 17,430, tax + # 3,486. Taxable income 77,430 exceeds 37,700, so the savings allowance is + # 500 and the starting rate is lost (17,430 > 5,000). Interest: 500 at nil + # in the band, 37,700 - 17,430 - 500 = 19,770 at 20% = 3,954, and 60,000 - + # 20,270 = 39,730 at 40% = 15,892. Income tax 3,486 + 19,846 = 23,332. + # Without the pay: taxable interest 60,000 - 12,570 = 47,430; 5,000 at the + # starting rate and 500 savings allowance at nil, 37,700 - 5,500 = 32,200 at + # 20% = 6,440, 47,430 - 37,700 = 9,730 at 40% = 3,892: 10,332, none of it on + # counted income. Tax deducted: 23,332 - 10,332 = 13,000, against the Step 4 + # tax on the pay of 3,486. + # NI: (30,000 - 12,570) x 8% = 1,394.40. + # Income Support: 30,000 - 13,000 - 1,394.40 - 260 (the £5 single + # disregard, IS Sch 8) = 15,345.60. Housing Benefit, with its £5 disregard + # supplied as an input: the same. The council tax reduction general rule, + # with no working-age earnings disregard in the model's English default: + # 30,000 - 13,000 - 1,394.40 = 15,605.60. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 30_000 + savings_interest_income: 60_000 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person] + region: NORTH_EAST + output: + income_tax_before_winter_fuel_payment_charge: 23_332 + legacy_means_test_income_tax: 3_486 + legacy_means_test_uncounted_income_tax_without_earnings: 10_332 + legacy_means_test_deducted_income_tax: 13_000 + national_insurance: 1_394.40 + income_support_applicable_income: 15_345.60 + housing_benefit_applicable_income: 15_345.60 + council_tax_reduction_applicable_income: 15_605.60 + +- name: Pay and rent with mortgage interest, the tests deduct the rent's tax the pay causes, net of the finance-cost reduction + # Pay 20,000 and a property profit of 10,000 with 4,000 of mortgage + # interest. Non-savings taxable income 30,000 - 12,570 = 17,430; the pay + # takes 7,430 of it (tax 1,486) and the rent 10,000 (tax 2,000). The + # residential finance-cost reduction is 20% x 4,000 = 800 (ITTOIA 2005 + # s.274A), so income tax is 3,486 - 800 = 2,686, and the Step 4 tax on + # counted income is 1,486. Without the pay the rent of 10,000 is within the + # personal allowance and bears no tax, so the whole 2,686 is tax the pay + # causes and is deducted: the 1,200 of tax on rent that the reduction leaves. + # NI: (20,000 - 12,570) x 8% = 594.40. + # Income Support: 20,000 - 2,686 - 594.40 - 260 = 16,459.60. Housing + # Benefit, with its £5 disregard as an input: the same. Council tax + # reduction general rule: 20,000 - 2,686 - 594.40 = 16,719.60. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 20_000 + property_income: 10_000 + property_finance_costs: 4_000 + benunits: + benunit: + members: [person] + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person] + region: NORTH_EAST + output: + property_income_tax: 2_000 + property_finance_cost_relief: 800 + income_tax_before_winter_fuel_payment_charge: 2_686 + legacy_means_test_income_tax: 1_486 + legacy_means_test_uncounted_income_tax_without_earnings: 0 + legacy_means_test_deducted_income_tax: 2_686 + income_support_applicable_income: 16_459.60 + housing_benefit_applicable_income: 16_459.60 + council_tax_reduction_applicable_income: 16_719.60 + +- name: The High Income Child Benefit Charge the pay brings in is deducted + # A parent aged 35 with one child, pay 40,000 and interest 30,000. Child + # Benefit 27.05 x 52 = 1,406.60 (1,406 in whole pounds). Adjusted net income + # 70,000 is half-way through the 60,000 to 80,000 taper: charge 50% x 1,406 + # = 703 (ITEPA 2003 s.681C). Pay: (40,000 - 12,570) x 20% = 5,486. Interest, + # higher-rate (savings allowance 500): 500 at nil, 37,700 - 27,430 - 500 = + # 9,770 at 20% = 1,954, 30,000 - 10,270 = 19,730 at 40% = 7,892; 9,846. + # Income tax before the winter fuel payment charge: 5,486 + 9,846 + 703 = + # 16,035. Without the pay: adjusted net income 30,000, no charge; interest + # 17,430 taxable, 5,000 at the starting rate and 1,000 savings allowance at + # nil, 11,430 at 20% = 2,286. Tax deducted: 16,035 - 2,286 = 13,749, which + # includes the whole 703 charge. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 35 + employment_income: 40_000 + savings_interest_income: 30_000 + child: + age: 5 + benunits: + benunit: + members: [parent, child] + households: + household: + members: [parent, child] + region: NORTH_EAST + output: + CB_HITC: [703, 0] + income_tax_before_winter_fuel_payment_charge: [16_035, 0] + legacy_means_test_income_tax: [5_486, 0] + legacy_means_test_uncounted_income_tax_without_earnings: [2_286, 0] + legacy_means_test_deducted_income_tax: [13_749, 0] + +- name: Only the part of the High Income Child Benefit Charge that the pay adds is deducted + # A parent aged 35 with one child, pay 10,000 and interest 65,000. With the + # pay: adjusted net income 75,000, charge 75% x 1,406 = 1,054.50, 1,054 in + # whole pounds. The pay is within the personal allowance and leaves 2,570 of + # it; taxable interest 62,430, higher-rate: 5,000 starting rate and 500 + # savings allowance at nil, 32,200 at 20% = 6,440, 24,730 at 40% = 9,892; + # 16,332. Income tax 16,332 + 1,054 = 17,386. Without the pay: adjusted net + # income 65,000, charge 25% x 1,406 = 351.50, 351; taxable interest 52,430: + # 6,440 + 14,730 x 40% = 12,332; 12,683 in all. Tax deducted: 17,386 - + # 12,683 = 4,703: the 4,000 the pay adds on the interest and 703 of the + # charge. The 351 the parent would pay without the pay is not deducted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 35 + employment_income: 10_000 + savings_interest_income: 65_000 + child: + age: 5 + benunits: + benunit: + members: [parent, child] + households: + household: + members: [parent, child] + region: NORTH_EAST + output: + CB_HITC: [1_054, 0] + income_tax_before_winter_fuel_payment_charge: [17_386, 0] + legacy_means_test_uncounted_income_tax_without_earnings: [12_683, 0] + legacy_means_test_deducted_income_tax: [4_703, 0] + +- name: Only the part of the annual allowance charge that the pay adds is deducted + # Pay 45,000, interest 2,000 and employer contributions of 70,000 to a + # money-purchase scheme: a chargeable amount of 70,000 - 60,000 = 10,000 + # (Finance Act 2004 s.227). Pay: (45,000 - 12,570) x 20% = 6,486; interest + # (basic-rate, savings allowance 1,000): 1,000 x 20% = 200. The charge is + # the chargeable amount as the top slice of reduced net income 47,000 - + # 12,570 = 34,430: 3,270 at 20% = 654 and 6,730 at 40% = 2,692; 3,346. + # Income tax 6,486 + 200 + 3,346 = 10,032. Without the pay: the interest is + # within the personal allowance, reduced net income is nil, and the charge + # is 10,000 x 20% = 2,000. Tax deducted: 10,032 - 2,000 = 8,032: the 6,686 + # on the pay and interest and the 1,346 of the charge the pay adds. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person: + age: 40 + employment_income: 45_000 + savings_interest_income: 2_000 + employer_pension_contributions: 70_000 + benunits: + benunit: + members: [person] + households: + household: + members: [person] + region: NORTH_EAST + output: + pension_annual_allowance_chargeable_amount: 10_000 + personal_pension_contributions_tax: 3_346 + income_tax_before_winter_fuel_payment_charge: 10_032 + legacy_means_test_income_tax: 6_486 + legacy_means_test_uncounted_income_tax_without_earnings: 2_000 + legacy_means_test_deducted_income_tax: 8_032 + +- name: When one partner's pay moves the High Income Child Benefit Charge off the other, the couple's deduction nets it + # A couple with one child. Partner a has interest of 70,000 and partner b + # pay of 80,000. Child Benefit 1,406 in whole pounds. The charge falls on + # the partner with the higher adjusted net income (ITEPA 2003 s.681B): b, + # at 80,000, the whole 1,406. a's interest: 57,430 taxable, 5,000 at the + # starting rate and 500 savings allowance at nil, 32,200 at 20% = 6,440, + # 19,730 at 40% = 7,892; 14,332. b's pay: 37,700 at 20% = 7,540 and 29,730 + # at 40% = 11,892; 19,432, plus the charge, 20,838. + # Without the pay, a has the higher income (70,000) and pays 50% x 1,406 = + # 703 of charge: 15,035 in all, none on counted income. So a's deduction is + # 14,332 - 15,035 = -703, and b's is 20,838. Together they deduct 20,135: + # the 19,432 on the pay and the 703 of charge the pay adds. The deduction is + # not floored per person, so the couple's total is the extra tax the pay + # causes. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a: + age: 40 + savings_interest_income: 70_000 + b: + age: 40 + employment_income: 80_000 + child: + age: 5 + benunits: + benunit: + members: [a, b, child] + households: + household: + members: [a, b, child] + region: NORTH_EAST + output: + CB_HITC: [0, 1_406, 0] + income_tax_before_winter_fuel_payment_charge: [14_332, 20_838, 0] + legacy_means_test_uncounted_income_tax_without_earnings: [15_035, 0, 0] + legacy_means_test_deducted_income_tax: [-703, 20_838, 0] + +- name: Where the test counts only the member whose deduction is negative, it floors the sum at nil + # The couple's incomes above, with a aged 64 and b aged 44: the model + # presumes b, 20 years younger, to be a's child, so each test counts a + # alone (is_claimant_or_partner). The taxes stay as above: a's deduction is + # 14,332 - 15,035 = -703, b's 20,838. Each test sums the deduction over the + # members it counts, here -703, and floors that sum at nil, so it deducts + # nothing. Without the floor each would add 703 of tax a never paid on + # counted income. + # - Income Support counts none of a's interest (reg 48(4)): income 0. + # - Pension Credit counts none of it either (Sch IV para 18): income 0. + # - Council tax reduction counts the benefit unit's Child Benefit, + # 27.05 x 52 = 1,406.60, and nothing else of a's: income 1,406.60. + # The household rents at 9,000 and pays council tax of 1,500; the family + # claims no Universal Credit. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a: + age: 64 + savings_interest_income: 70_000 + b: + age: 44 + employment_income: 80_000 + child: + age: 3 + benunits: + benunit: + members: [a, b, child] + would_claim_uc: false + households: + household: + members: [a, b, child] + country: ENGLAND + tenure_type: RENT_PRIVATELY + rent: 9_000 + council_tax: 1_500 + output: + is_claimant_or_partner: [true, false, false] + is_council_tax_reduction_applicant_or_partner: [true, false, false] + legacy_means_test_deducted_income_tax: [-703, 20_838, 0] + income_support_applicable_income: [0] + pension_credit_income: [0] + council_tax_reduction_applicable_income: [1_406.60] + +- name: Housing Benefit's means test floors the counted member's negative deduction at nil + # The same household with a child aged 5. It reports no Income Support + # award, which income_support_eligible requires, so it gets none + # (income_support 0), and it claims no Universal Credit, so Housing Benefit + # takes income through its own means test. Housing Benefit counts none of + # a's interest (reg 46(4)) and excludes Child Benefit, so a's income is + # nil; the sum of the deduction over the members it counts, -703, floors at + # nil: income 0, not 703. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a: + age: 64 + savings_interest_income: 70_000 + b: + age: 44 + employment_income: 80_000 + child: + age: 5 + benunits: + benunit: + members: [a, b, child] + would_claim_uc: false + claims_all_entitled_benefits: true + households: + household: + members: [a, b, child] + country: ENGLAND + tenure_type: RENT_PRIVATELY + rent: 9_000 + council_tax: 1_500 + output: + is_claimant_or_partner: [true, false, false] + legacy_means_test_deducted_income_tax: [-703, 20_838, 0] + income_support: [0] + housing_benefit_pension_age_regulations_apply: [false] + housing_benefit_applicable_income: [0] + +- name: Pension Credit floors the counted tax after taking off the actual tax on self-employed profit + # The floor cases' household, with a aged 70 and a self-employed profit of + # 2,000. The model presumes b, 26 years younger, to be a's child, so + # Pension Credit counts a alone. b's pay moves the 703 Child Benefit charge + # off a, so a's deduction is the 800 of tax the profit adds less 703: 97. + # The profit's actual tax (pension_credit_self_employment_income_tax) is + # 940: the 800, and the 140 it adds to the charge when b has no pay (843, + # 60% of 1,406 rounded down, against 703). The formula replaces that tax + # with notional tax, nil on 2,000, and deducts no other tax for a: + # max(0, 97 - 940) = 0. Income is the profit less the £20 weekly lone + # parent disregard: 2,000 - 1,040 = 960. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a: + age: 70 + savings_interest_income: 70_000 + self_employment_income: 2_000 + b: + age: 44 + employment_income: 80_000 + child: + age: 3 + benunits: + benunit: + members: [a, b, child] + would_claim_uc: false + households: + household: + members: [a, b, child] + country: ENGLAND + tenure_type: RENT_PRIVATELY + rent: 9_000 + council_tax: 1_500 + output: + is_claimant_or_partner: [true, false, false] + legacy_means_test_deducted_income_tax: [97, 20_838, 0] + pension_credit_self_employment_income_tax: [940] + pension_credit_income: [960] diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_earnings_disregard.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_earnings_disregard.yaml index f3f11f8954..2131ed247c 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_earnings_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_earnings_disregard.yaml @@ -430,12 +430,16 @@ # (12,000 - 4,530 - 1,000 PSA) x 20% = 1,294, giving total tax 1,388. # Without wages tax is 1,086 (next case), so employment tax is 302 and # net earnings/disregard are 1,040 - 302 = 738, below the 1,040 cap. - # PC counts deemed capital income, not interest: 12,000 + 1,040 - 1,388 - # - 738 = 10,914. HMRC: /apply-tax-free-interest-on-savings/how-much-is-tax-free. + # PC counts deemed capital income, not interest, and does not deduct the + # 1,086 of tax on the interest that is due without earnings (reg 17(10)(a), + # Sch IV para 18); the 302 the wages add stays tax on earnings. So the tax + # deducted is 1,388 - 1,086 = 302, and income is 12,000 + 1,040 - 302 - + # 738 = 12,000. HMRC: /apply-tax-free-interest-on-savings/how-much-is-tax-free. income_tax: 1_388 pension_credit_employment_income_tax: 302 + legacy_means_test_uncounted_income_tax_without_earnings: 1_086 pension_credit_earnings_disregard: 738 - pension_credit_income: 10_914 + pension_credit_income: 12_000 - name: The same claimant with savings and no earnings has the same Pension Credit income. period: 2024 @@ -455,8 +459,44 @@ output: income_tax: 1_086 pension_credit_earnings_disregard: 0 - # 12,000 - 1,086. - pension_credit_income: 10_914 + # The 1,086 is all tax on the interest, which Pension Credit does not + # count, so none of it is deducted: 12,000. + legacy_means_test_uncounted_income_tax_without_earnings: 1_086 + pension_credit_income: 12_000 + +- name: Statutory sick pay leaves Pension Credit income unchanged when the tax on interest is uncounted, as wages do. + # The wages case above with 1,040 of statutory sick pay in place of the + # wages. SPC Regs 2002 reg 17A(2)(h) makes it earnings of an employed + # earner, so the tax without earnings is measured with it zeroed. The tax + # is the same: 94 non-savings and 1,294 on interest, 1,388 in all; 1,086 + # without the sick pay. The 1,086 due without earnings is all tax on + # interest, which Pension Credit does not count (reg 17(10)(a), Sch IV + # para 18), so it is not deducted; the 302 the sick pay adds is tax on + # earnings. Net earnings and the disregard are 1,040 - 302 = 738, and + # income is 12,000 + 1,040 - 302 - 738 = 12,000. Measuring the uncounted + # tax with the sick pay left in would take 1,388 - 1,294 = 94 as counted + # tax and leave 1,086 - 94 = 992 uncounted. + period: 2024 + input: + people: + claimant: + age: 70 + state_pension: 12_000 + savings_interest_income: 12_000 + attendance_allowance: 3_000 + statutory_sick_pay: 1_040 + benunits: + benunit: + members: [claimant] + households: + household: + members: [claimant] + output: + income_tax_before_winter_fuel_payment_charge: 1_388 + pension_credit_employment_income_tax: 302 + legacy_means_test_uncounted_income_tax_without_earnings: 1_086 + pension_credit_earnings_disregard: 738 + pension_credit_income: 12_000 - name: Pension contribution relief already available without earnings does not reduce tax attributed to earnings. period: 2024 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml index d98e564feb..6b32d58624 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/pension_credit/pension_credit_income.yaml @@ -63,7 +63,12 @@ pension_credit_deemed_income: 52 pension_credit_income: 52 -- name: Case 4, property income and non-main-home capital count for Pension Credit. +- name: Case 4, rent from a let property is not Pension Credit income; the property counts through deemed income. + # SPC Regs 2002 Sch IV para 18 disregards any actual income from capital, so + # the £10,476 of rent does not count. Deemed income (reg 15(6)): capital + # 55,825 - 10,000 = 45,825, ceil(45,825 / 500) = 92, so £92 a week, 4,784 a + # year. Guarantee credit = (238 - 92) x 52 = 7,592. Savings credit is nil, as + # qualifying income (£92 a week) is below the savings credit threshold. period: 2026 absolute_error_margin: 0.01 input: @@ -82,8 +87,10 @@ output: pension_credit_assessable_capital: 55_825 pension_credit_deemed_income: 4_784 - pension_credit_income: 15_260 - pension_credit: 0 + pension_credit_income: 4_784 + guarantee_credit: 7_592 + savings_credit: 0 + pension_credit: 7_592 - name: Case 5, 2026 Pension Credit uses tariff income with the published guarantee rate. period: 2026 @@ -174,7 +181,7 @@ pension_credit_income: 18_514 pension_credit: 0 -- name: Positive property income still counts in Pension Credit income. +- name: Positive property income does not count in Pension Credit income, nor does its tax. period: 2026 absolute_error_margin: 1 input: @@ -192,8 +199,11 @@ region: WALES tenure_type: OWNED_OUTRIGHT output: - # 20,000 + 3,000, less income tax of 20% of (23,000 - 12,570) = 2,086. - pension_credit_income: 20_914 + # SPC Regs 2002 Sch IV para 18 disregards actual income from capital; the + # let property counts through deemed income instead. Only the tax on the + # pension is deducted (reg 17(10)(a)): 20,000 - 20% x (20,000 - 12,570) = + # 18,514, as without the property. + pension_credit_income: 18_514 pension_credit: 0 # Issue #2255, earnings. A self-employment loss is not set against wages diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml index e1a3cfe812..35bb1e0ff4 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml @@ -758,24 +758,34 @@ income_tax: [4_086] - name: 2025 a landlord's property allowance election counts the charge - # Private pension £32,520; property receipts £3,500, expenses £200 (profit - # £3,300), finance costs £1,500; five children. With expenses: (35,820 - - # 12,570) x 20% = £4,650, less the finance-cost reduction 20% x £1,500 = - # £300, so £4,350. With partial relief (£1,000 allowance, no reduction): - # (35,020 - 12,570) x 20% = £4,490. Total income is over £35,000 either - # way (£35,820 and £35,020), so Pension Credit decides the charge. Pension - # Credit income is £29,970 with - # expenses and £29,830 with the allowance, against the model's minimum - # guarantee of £29,893.76 (with the amounts for the children), so only the - # allowance route gets Pension Credit, which exempts the pensioner from the - # charge (s.681I(4)). Total tax: £4,350 + £200 = £4,550 with expenses, - # £4,490 with the allowance, so the pensioner elects for partial relief. + # Wages £27,000; private pension £9,070; property receipts £3,500, expenses + # £200 (profit £3,300), finance costs £1,500; five children. A pensioner + # pays no employee National Insurance. + # With expenses: (39,370 - 12,570) x 20% = £5,360, less the finance-cost + # reduction 20% x £1,500 = £300, so £5,060. With partial relief (£1,000 + # allowance, no reduction): (38,570 - 12,570) x 20% = £5,200. Total income + # exceeds £35,000 on both routes (£39,370 and £38,570), so Pension Credit + # decides the charge. + # The formula counts no property profits in Pension Credit income (SPC Sch + # IV para 18), but it deducts the tax the wages cause. Without the wages, + # pension and profits (£12,370 or £11,570) fall within the personal + # allowance and bear no tax, so the wages cause the whole tax, and Pension + # Credit deducts it all: wages and pension less tax less the £20 weekly + # lone parent earnings disregard (£1,040). Pension Credit income is + # 36,070 - 5,060 - 1,040 = £29,970 with expenses and 36,070 - 5,200 - + # 1,040 = £29,830 with the allowance, against the model's minimum guarantee of + # £29,893.76 (with the amounts for the children). Only the allowance route + # gets Pension Credit (£63.76), which exempts the pensioner from the charge + # (s.681I(4)). Total tax: £5,060 + £200 = £5,260 with expenses, £5,200 with + # the allowance, so the pensioner elects for partial relief. period: 2025 + absolute_error_margin: 0.01 input: people: pensioner: age: 70 - private_pension_income: 32_520 + employment_income: 27_000 + private_pension_income: 9_070 property_rental_income: 3_500 property_income: 3_300 property_finance_costs: 1_500 @@ -800,35 +810,50 @@ country: ENGLAND output: uses_property_allowance: [true, false, false, false, false, false] + legacy_means_test_uncounted_income_tax_without_earnings: [0, 0, 0, 0, 0, 0] pension_credit_income: 29_830 + pension_credit: 63.76 winter_fuel_payment: [200, 0, 0, 0, 0, 0] winter_fuel_payment_charge: [0, 0, 0, 0, 0, 0] - income_tax_before_winter_fuel_payment_charge: [4_490, 0, 0, 0, 0, 0] - income_tax: [4_490, 0, 0, 0, 0, 0] + income_tax_before_winter_fuel_payment_charge: [5_200, 0, 0, 0, 0, 0] + income_tax: [5_200, 0, 0, 0, 0, 0] - name: 2025 a landlord without finance costs takes the allowance even where it ends Pension Credit (a model limit) - # Private pension £35,207; property receipts £3,500, expenses £200 (profit - # £3,300), no finance costs; six children. With partial relief (the £1,000 - # allowance in place of £200 of expenses): total income £37,707, tax - # (37,707 - 12,570) x 20% = £5,027.40. With expenses: total income £38,507, - # tax (38,507 - 12,570) x 20% = £5,187.40. Total income is over £35,000 - # either way, so Pension Credit decides the charge. Pension Credit income - # (pension and property profits, less tax before the charge) is £33,479.60 - # with the allowance and £33,319.60 with expenses, against the model's - # minimum guarantee of £33,399.60 (with the amounts for the children), so - # only the expenses route gets Pension Credit (£80), which exempts the - # pensioner from the £200 charge (s.681I(4)). Total tax: £5,227.40 with the - # allowance, £5,187.40 with expenses, so a pensioner choosing the lower tax - # would not elect for partial relief. The model does not compare routes for - # landlords without finance costs (uses_property_allowance), so it takes the - # allowance: no Pension Credit, charged the £200. This case pins that limit. + # Wages £31,562; private pension £9,070; property receipts £3,500, expenses + # £200 (profit £3,300), no finance costs; six children. A pensioner pays no + # employee National Insurance. With partial relief (the £1,000 allowance in + # place of £200 of expenses): total income £43,132, tax (43,132 - 12,570) x + # 20% = £6,112.40. With expenses: total income £43,932, tax (43,932 - + # 12,570) x 20% = £6,272.40. Total income exceeds £35,000 on both routes, + # so Pension Credit decides the charge. + # The formula counts no property profits in Pension Credit income (SPC Sch + # IV para 18), but without the wages, pension and profits (£11,570 or + # £12,370) fall within the personal allowance, so the wages cause the whole + # tax, and Pension Credit deducts it all. Pension Credit income (wages and + # pension, less that tax, less the £20 weekly lone parent earnings + # disregard of £1,040) is 40,632 - 6,112.40 - 1,040 = £33,479.60 with the + # allowance and 40,632 - 6,272.40 - 1,040 = £33,319.60 with expenses, + # against the model's minimum guarantee of £33,399.60 (with the amounts for + # the children). Only the expenses route gets Pension Credit (£80), which + # exempts the pensioner from the £200 charge (s.681I(4)). Total tax: + # £6,312.40 with the allowance, £6,272.40 with expenses, so a pensioner + # choosing the lower tax would not elect for partial relief. The model does + # not compare routes for landlords without finance costs + # (uses_property_allowance), so it takes the allowance: no Pension Credit, + # charged the £200. This case pins that limit. The wages carry the whole + # tax on the profits here, so the route moves the tax the formula deducts + # by the full £160. Without earnings the route still moves that tax where + # the profits change the tax on counted income: through its share of a + # general tax reduction, through the Marriage Allowance or through the + # personal allowance taper. period: 2025 absolute_error_margin: 0.01 input: people: pensioner: age: 70 - private_pension_income: 35_207 + employment_income: 31_562 + private_pension_income: 9_070 property_rental_income: 3_500 property_income: 3_300 child_1: @@ -854,29 +879,136 @@ country: ENGLAND output: uses_property_allowance: [true, false, false, false, false, false, false] - total_income_charged_to_tax: [37_707, 0, 0, 0, 0, 0, 0] + total_income_charged_to_tax: [43_132, 0, 0, 0, 0, 0, 0] pension_credit_income: 33_479.60 pension_credit: 0 winter_fuel_payment: [200, 0, 0, 0, 0, 0, 0] winter_fuel_payment_charge: [200, 0, 0, 0, 0, 0, 0] - income_tax: [5_227.40, 0, 0, 0, 0, 0, 0] + income_tax: [6_312.40, 0, 0, 0, 0, 0, 0] + +- name: 2025 a single landlord without earnings, tax reductions or a tapered personal allowance has the same Pension Credit income on both routes + # The same pensioner and six children with no wages, no tax reduction and a + # private pension of £40,632. Without earnings, the formula deducts only + # the Step 4 tax on the pension, (40,632 - 12,570) x 20% = £5,612.40, on + # both property routes: the profits sit on top of the pension and bear + # their own tax, and no tax reduction, Marriage Allowance or allowance + # taper ties them to the tax on the pension. Pension Credit income is + # 40,632 - 5,612.40 = £35,019.60 on both routes, which exceeds the minimum + # guarantee of £33,399.60, so neither route gets Pension Credit. Total + # income exceeds £35,000 on both routes, so the £200 charge applies either + # way, and the allowance, which gives the lower tax before the charge, + # gives the lower income tax: (43,132 - 12,570) x 20% + 200 = £6,312.40. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 40_632 + property_rental_income: 3_500 + property_income: 3_300 + child_1: + age: 10 + child_2: + age: 10 + child_3: + age: 10 + child_4: + age: 10 + child_5: + age: 10 + child_6: + age: 10 + benunits: + unit: + members: [pensioner, child_1, child_2, child_3, child_4, child_5, child_6] + would_claim_pc: true + would_claim_uc: false + households: + household: + members: [pensioner, child_1, child_2, child_3, child_4, child_5, child_6] + country: ENGLAND + output: + uses_property_allowance: [true, false, false, false, false, false, false] + legacy_means_test_deducted_income_tax: [5_612.40, 0, 0, 0, 0, 0, 0] + pension_credit_income: 35_019.60 + pension_credit: 0 + winter_fuel_payment_charge: [200, 0, 0, 0, 0, 0, 0] + income_tax: [6_312.40, 0, 0, 0, 0, 0, 0] + +- name: 2025 the same single landlord on expenses has the same Pension Credit income + # The case above with the expenses route as an input: total income £43,932, + # tax before the charge (43,932 - 12,570) x 20% = £6,272.40. The formula + # still deducts only the £5,612.40 on the pension, so Pension Credit income + # is £35,019.60 on both routes, and income tax with the £200 charge is + # £6,472.40. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + pensioner: + age: 70 + private_pension_income: 40_632 + property_rental_income: 3_500 + property_income: 3_300 + uses_property_allowance: false + child_1: + age: 10 + child_2: + age: 10 + child_3: + age: 10 + child_4: + age: 10 + child_5: + age: 10 + child_6: + age: 10 + benunits: + unit: + members: [pensioner, child_1, child_2, child_3, child_4, child_5, child_6] + would_claim_pc: true + would_claim_uc: false + households: + household: + members: [pensioner, child_1, child_2, child_3, child_4, child_5, child_6] + country: ENGLAND + output: + legacy_means_test_deducted_income_tax: [5_612.40, 0, 0, 0, 0, 0, 0] + pension_credit_income: 35_019.60 + pension_credit: 0 + winter_fuel_payment_charge: [200, 0, 0, 0, 0, 0, 0] + income_tax: [6_472.40, 0, 0, 0, 0, 0, 0] - name: 2025 landlords in two benefit units of one household each elect with the other's route fixed - # One household. Unit A: a claimant aged 70 with private pension - # £42,772.55, a partner aged 85 with no income, and five children. Unit B: - # an unrelated person aged 85 with private pension £40,000. Each landlord - # has property receipts £3,500 and expenses £200 (profit £3,300); finance - # costs are £1,200 (A) and £675 (B). Unit A claims Pension Credit; B does - # not. - # A: with partial relief, total income £45,272.55 and tax before the charge - # (45,272.55 - 12,570) x 20% = £6,540.51, less the Marriage Allowance - # reduction 20% x £1,260 = £252, so £6,288.51. Unit A then gets Pension - # Credit (a savings credit of £16 in the model), which exempts A from the - # charge and makes A the person paid for the couple, so A's partner is not - # entitled (SI 2025/969 reg 4(2)(a)); A is paid the couple's full £300. - # With expenses, A's tax before the charge is £6,700.51 - £252 - 20% x - # £1,200 = £6,208.51, unit A gets no Pension Credit, and A's £100 shared - # payment is charged: £6,308.51. A elects for partial relief. + # One household. Unit A: a claimant aged 70 with wages £37,047.55 and + # private pension £9,000, a partner aged 85 with no income, and five + # children. Unit B: an unrelated person aged 85 with private pension + # £40,000. Each landlord has property receipts £3,500 and expenses £200 + # (profit £3,300); finance costs are £1,200 (A) and £675 (B). Unit A claims + # Pension Credit; B does not. Pensioners pay no employee National + # Insurance. + # A: with partial relief, total income £48,547.55 and tax before the charge + # (48,547.55 - 12,570) x 20% = £7,195.51, less the Marriage Allowance + # reduction 20% x £1,260 = £252, so £6,943.51. With expenses, total income + # £49,347.55 and tax (49,347.55 - 12,570) x 20% = £7,355.51, less £252 and + # the finance-cost reduction 20% x £1,200 = £240, so £6,863.51. + # The formula counts no property profits in Pension Credit income (SPC Sch + # IV para 18). Without the wages, A's pension and profits (£11,500 or + # £12,300) fall within the personal allowance and bear no tax, so the wages + # cause the whole tax, and Pension Credit deducts it all. Its income, less + # the £10 weekly couple earnings disregard (£520), is 46,047.55 - + # 6,943.51 - 520 = £38,584.04 with the allowance and 46,047.55 - 6,863.51 - 520 = + # £38,664.04 with expenses. Both exceed the model's minimum guarantee of + # £36,107.76 (with the amounts for the children), so the model can pay + # savings credit only: the model's maximum of £1,006.51 less 40% of income + # above the guarantee. With the allowance that gives 1,006.51 - 40% x + # 2,476.28 = £16.00; with expenses 1,006.51 - 40% x 2,556.28, below nil. + # So with the allowance unit A gets Pension Credit, which exempts A from + # the charge and makes A the person paid for the couple, so A's partner is + # not entitled (SI 2025/969 reg 4(2)(a)); A receives the couple's full + # £300. With expenses, unit A gets no Pension Credit, and HMRC charges A's + # £100 shared payment: £6,963.51. A elects for partial relief. # B: tax before the charge is (42,500 - 12,570) x 20% = £5,986 with the # allowance and (43,300 - 12,570) x 20% - 20% x £675 = £6,011 with # expenses. B's total income is over £35,000 on both routes, so B is @@ -894,7 +1026,8 @@ claimant: age: 70 is_benunit_head: true - private_pension_income: 42_772.55 + employment_income: 37_047.55 + private_pension_income: 9_000 property_rental_income: 3_500 property_income: 3_300 property_finance_costs: 1_200 @@ -932,11 +1065,13 @@ country: ENGLAND output: uses_property_allowance: [true, false, true, false, false, false, false, false] - income_tax_before_winter_fuel_payment_charge: [6_288.51, 0, 5_986, 0, 0, 0, 0, 0] + income_tax_before_winter_fuel_payment_charge: [6_943.51, 0, 5_986, 0, 0, 0, 0, 0] + # Unit B: pension less its Step 4 tax, 40,000 - (40,000 - 12,570) x 20%. + pension_credit_income: [38_584.04, 34_514] pension_credit: [16, 0] winter_fuel_payment: [300, 0, 200, 0, 0, 0, 0, 0] winter_fuel_payment_charge: [0, 0, 200, 0, 0, 0, 0, 0] - income_tax: [6_288.51, 0, 6_186, 0, 0, 0, 0, 0] + income_tax: [6_943.51, 0, 6_186, 0, 0, 0, 0, 0] - name: 2025 net pay pension contributions come off total income # The model takes employee contributions as paid under a net pay 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..033ddb88c5 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 @@ -480,7 +480,7 @@ council_tax_reduction_assessable_capital: 17_000 council_tax_reduction: 0 -- name: The same pensioner not claiming Pension Credit is tested on household savings only +- name: The same pensioner not claiming Pension Credit is tested on savings and the second property period: 2026 absolute_error_margin: 0.01 input: @@ -505,13 +505,17 @@ other_residential_property_value: 7_000 output: in_receipt_of_savings_credit_only: false - # Pensioners without Pension Credit are tested on household savings, a - # proxy that leaves out the second property the schemes' own capital rules - # count (SI 2012/2885 Sch 1 Part 6 Chapter 3). So, unlike the claimant - # above, this pensioner keeps CTR: the gap is in the proxy, not the law. - council_tax_reduction_assessable_capital: 10_000 - council_tax_reduction_applicable_income: 13_314 - council_tax_reduction: 1_999.60 + # SI 2012/2885 Sch 1 para 31(1) counts "the whole of his capital", so the + # second property counts as it does for the claimant above, valued less + # 10% for the expenses of sale (para 32(a)): 10,000 + 7,000 x 0.9 = + # 16,300, over the 16,000 limit (reg 11(2)). Shares and other investments + # are still left out of the proxy (issue 1936). + council_tax_reduction_assessable_capital: 16_300 + # 13,500 - 186 tax ((13,500 - 12,570) x 20%) = 13,314, plus tariff income + # (Sch 1 para 37) on capital up to 16,000: 12 x 52 = 624. + council_tax_reduction_tariff_income: 624 + council_tax_reduction_applicable_income: 13_938 + council_tax_reduction: 0 - name: Capital of exactly 16,000 is within the limit for a pensioner without Pension Credit # Aged 72: State Pension age was reached in 2019, before 1 April 2021, so @@ -537,12 +541,16 @@ 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, 624 + # a year. Income 13,000 - 86 tax ((13,000 - 12,570) x 20%) + 624 = + # 13,538. The award, 2,000 - 0.2 x (13,538 - 13,312) = 1,954.80, uses the + # model's applicable amount of 256 a week; the 238 a week allowance for + # people reaching pensionable age from April 2021 is a known gap (#1933). in_receipt_of_guarantee_credit: false council_tax_reduction_assessable_capital: 16_000 - council_tax_reduction: 2_000 + council_tax_reduction_tariff_income: 624 + council_tax_reduction_applicable_income: 13_538 + 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/household/income/property_income_after_finance_costs.yaml b/policyengine_uk/tests/policy/baseline/household/income/property_income_after_finance_costs.yaml index 902f7720a1..33c8f7df91 100644 --- a/policyengine_uk/tests/policy/baseline/household/income/property_income_after_finance_costs.yaml +++ b/policyengine_uk/tests/policy/baseline/household/income/property_income_after_finance_costs.yaml @@ -1,10 +1,12 @@ -# Means tests count property income after the costs of dwelling-related -# loans. Tax credits do so by statute: The Tax Credits (Definition and -# Calculation of Income) Regulations 2002 reg. 11(2A) disregards the ITTOIA -# 2005 s. 272A restriction, and reg. 11(1) counts "annual taxable profits", so -# costs above the profit leave nil rather than a loss. The legacy means tests -# deduct income tax, which the finance-cost reduction lowers, so they count -# the profit after the costs too. +# Tax credits count property income after the costs of dwelling-related +# loans by statute: The Tax Credits (Definition and Calculation of Income) +# Regulations 2002 reg. 11(2A) disregards the ITTOIA 2005 s. 272A +# restriction, and reg. 11(1) counts "annual taxable profits", so costs above +# the profit leave nil rather than a loss. The legacy means tests treat rent +# from a let property as capital (HB Regs 2006 reg 46(4) and Sch 5 para 17; +# HB (SPC) Regs 2006 Sch 5 para 22), so it counts in neither case, and they +# deduct only the tax on the income they count: the finance-cost reduction +# comes off the tax on the rent (legacy_means_test_income_tax). - name: Finance costs are deducted from property income for tax credits period: 2023 @@ -56,8 +58,14 @@ output: # (16,000 + 12,000 + 6,000 - 12,570) x 20%. income_tax: 4_286 - # 16,000 + 12,000 + 6,000 - 4,286, less the 5 a week earnings disregard. - housing_benefit_applicable_income: 29_454 + # The rent does not count, nor the tax it would bear without the + # earnings: (12,000 + 6,000 - 12,570) x 20% = 1,086. The earnings carry + # the rest, 4,286 - 1,086 = 3,200: the 3,086 on the earnings and pension + # and the 114 they add on the rent by using the personal allowance. So + # 16,000 + 12,000 - 3,200, less the 5 a week earnings disregard. + legacy_means_test_uncounted_income_tax_without_earnings: 1_086 + legacy_means_test_deducted_income_tax: 3_200 + housing_benefit_applicable_income: 24_540 - name: Housing Benefit, finance costs equal to the profit do not lower it period: 2026 @@ -74,6 +82,9 @@ # 4,286 less the 20% x 6,000 reduction. income_tax: 3_086 property_income_after_finance_costs: 0 - # 16,000 + 12,000 - 3,086 - 260: the property income nets to nil, so the - # lower tax does not raise the income counted. + # 16,000 + 12,000 - 3,086 - 260: the rent does not count. Without the + # earnings the 1,200 reduction clears the 1,086 of tax on the rent, so no + # tax is left on uncounted income and the whole 3,086 is deducted. + legacy_means_test_uncounted_income_tax_without_earnings: 0 + legacy_means_test_deducted_income_tax: 3_086 housing_benefit_applicable_income: 24_654 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..b87444776e 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 @@ -21,12 +21,23 @@ 3. Savings-credit-only recipients get max(0, L - 0.2 x max(0, PC income + SC - A) - ND) when the Pension Credit assessment of capital is within 16,000, and nothing otherwise. -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 - under test. +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. 5. Metamorphic: a guarantee credit recipient's CTR does not change when the State Pension changes. 6. Metamorphic: nor when its savings change. @@ -83,6 +94,7 @@ guarantees = st.one_of(st.none(), st.floats(240, 450)) CAPITAL_LIMIT = 16_000 WITHDRAWAL_RATE = 0.2 +SALE_EXPENSES = 0.1 @st.composite @@ -258,16 +270,24 @@ def situation( "pension_credit_income", "pension_credit_assessable_capital", "council_tax_reduction_pensioner", + "council_tax_reduction_relevant_income_based_benefit", + "universal_credit", + "uc_assessable_capital", + "claims_universal_credit", + "universal_credit_pre_benefit_cap", + "council_tax_reduction_head_applies_alone", + "legacy_benefits_home_letting_income", ] -# council_tax_reduction_applicable_income on main before this change (1c5b4d04): -# these incomes and benefits, less income tax, National Insurance and half of -# pension contributions, floored at zero. Since #2033, a pensioner family's -# earnings disregard also comes off before the floor. These GB families now -# exclude Child Benefit on the pensioner general-rules route as well. +# council_tax_reduction_applicable_income outside the Pension Credit routes: +# these incomes and benefits, less the income tax on them, National Insurance, +# half of pension contributions and, for pensioner families, Child Benefit and +# the pensioner earnings disregard (since #2033), floored at zero. Rent from property, +# interest and dividends are income from capital and do not count, and nor +# does the tax on them; rent for part of the home counts less £20 a week. MAIN_INCOME_COMPONENTS = [ "employment_income", "self_employment_income", - "property_income", + "legacy_benefits_home_letting_income", "private_pension_income", "carers_allowance", "esa_contrib", @@ -284,10 +304,12 @@ def situation( "esa_income", "universal_credit", ] -# The means tests deduct income tax before the winter fuel payment charge -# (ITEPA 2003 s.681I), which recovers a payment rather than taxing the income -# they assess. A pensioner over £35,000 of total income is charged it. -MAIN_DEDUCTIONS = ["income_tax_before_winter_fuel_payment_charge", "national_insurance"] +# The means tests deduct the income tax before the winter fuel payment charge +# (ITEPA 2003 s.681I), less the tax on income they do not take into account +# due without earnings (legacy_means_test_deducted_income_tax): the charge +# recovers a payment rather than taxing the income they assess. A pensioner +# over £35,000 of total income is charged it. +MAIN_DEDUCTIONS = ["legacy_means_test_deducted_income_tax", "national_insurance"] # The pensioner earnings disregards in 2026, written out from the law, not # read from the parameters: £25 a week for a lone parent, £10 with a partner, # £5 otherwise, plus £17.10 (SI 2012/2885 Sch 4 paras 2, 8 and 10; WSI @@ -297,6 +319,7 @@ def situation( HOUSEHOLD_VARIABLES = [ "council_tax_reduction_maximum_eligible_liability", "savings", + "other_residential_property_value", ] @@ -383,6 +406,59 @@ def benunit_total(names): return values +def universal_credit_route(values, i): + """A working-age applicant with an award of Universal Credit: paid, or + claimed and entitled before the cap and deductions (UC Regs 2013 reg 81), + unless the household head applies alone.""" + award = values["universal_credit"][i] > 0 or ( + values["claims_universal_credit"][i] + and values["universal_credit_pre_benefit_cap"][i] > 0 + ) + return ( + award + and not values["council_tax_reduction_head_applies_alone"][i] + and not values["council_tax_reduction_pensioner"][i] + ) + + +def passported(values, i): + # council_tax_reduction_relevant_income_based_benefit already leaves out a + # household head who applies alone (#2078). + return ( + values["council_tax_reduction_relevant_income_based_benefit"][i] + and not values["council_tax_reduction_pensioner"][i] + ) + + +def expected_capital(unit, values, i): + # In 2026 Wales takes a UC award's capital from the Secretary of State + # (WSI 2013/3029 Sch 6 para 9(6)) and disregards a passported applicant's + # whole capital (Sch 10 para 8); Scotland does neither (SSI 2021/249). + if unit["country"] == "WALES" and universal_credit_route(values, i): + return values["uc_assessable_capital"][i] + if unit["country"] == "WALES" and passported(values, i): + return 0.0 + return ( + values["savings"][i] + + (1 - SALE_EXPENSES) * values["other_residential_property_value"][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) + + if values["council_tax_reduction_pensioner"][i]: + return steps(10_000, 500) * 52 + if unit["country"] == "ENGLAND": + return 0.0 + if universal_credit_route(values, i): + return steps(6_000, 250) * 4.35 * 12 + if passported(values, i): + return 0.0 + return steps(6_000, 250) * 52 + + def tapered(liability, income, applicable_amount, non_dep): excess = max(0.0, income - applicable_amount) return max(0.0, liability - WITHDRAWAL_RATE * excess - non_dep) @@ -439,13 +515,25 @@ def check_routes(units, values): values["pension_credit_assessable_capital"][i] <= CAPITAL_LIMIT ) else: - income = values["income_under_main_definition"][i] + capital = expected_capital(unit, values, i) + # A UC award's income is the Secretary of State's assessment, which + # has no head for rent from part of the home. + home_letting = ( + values["legacy_benefits_home_letting_income"][i] + if universal_credit_route(values, i) + else 0.0 + ) + income = ( + values["income_under_main_definition"][i] + - home_letting + + expected_tariff_income(unit, values, i, capital) + ) assert ( abs(values["council_tax_reduction_applicable_income"][i] - income) < 0.01 ), unit expected = tapered(liability, income, applicable_amount, non_dep) * ( - values["savings"][i] <= CAPITAL_LIMIT + capital <= CAPITAL_LIMIT ) assert abs(ctr - expected) < 0.01, (unit, ctr, expected) 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 new file mode 100644 index 0000000000..ee4849fb03 --- /dev/null +++ b/policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py @@ -0,0 +1,778 @@ +"""Property-based tests for income derived from capital in the legacy means tests. + +Income Support, Housing Benefit, Pension Credit and council tax reduction +treat rent, interest and dividends as capital, not income (IS Regs 1987 reg +48(4) and Sch 9 para 22; HB Regs 2006 reg 46(4) and Sch 5 para 17; HB (SPC) +Regs 2006 Sch 5 para 22; SPC Regs 2002 Sch IV para 18), and disregard tax only +on income they take into account. Rent for letting part of the home stays +income, less £20 a week per occupier. + +Invariants, for any generated population of families: + +1. Invariance: where nobody in the population has employed earnings or + self-employment income, scaling property, savings interest and dividend + income (by 0 and 3) changes none of the four means-test incomes, and none + of Income Support, Housing Benefit, Pension Credit or council tax + reduction. Universal Credit and tax credits, which have their own income + rules, are held fixed. Incomes are kept within the basic rate band, where + extra income from capital cannot change the tax on other income through + the personal allowance taper or the High Income Child Benefit Charge. + Marriage Allowance is held at nil: whether a spouse can transfer it + depends on their income including income from capital, which is a + legitimate way for income from capital to change the tax on counted + income. + Intended exception: earnings carry the extra tax they cause, including on + savings, dividends and rent, in all four tests. With + earnings, income from capital can move that tax: earnings under the + personal allowance can leave rent or dividends taxable. Where someone has + earnings, each means-test income changes by exactly minus the change in + the tax that test deducts (legacy_means_test_deducted_income_tax, summed + over the members it counts) and in its earnings disregard, which is + capped at net earnings, unless floored or on a route that does not use + the test's own income rules. The awards are compared wherever none of + those taxes or disregards moves. +2. Bounds: the counted home-letting income is between nil and the rent, and + equals the rent less £20 a week, floored at nil. +3. Monotone: more rent from part of the home never lowers a means-test income + and never raises Income Support, Housing Benefit, Pension Credit or council + tax reduction. +4. Tax: legacy_means_test_income_tax, the Step 4 split the tests read + without earnings, is between nil and both income tax and the tax on + counted income before reductions (earned_income_tax), and equals income + tax when there is no savings, dividend or property income and no Step 7 + charge. The tax each test deducts (legacy_means_test_deducted_income_tax) + is between nil and the income tax before the winter fuel payment charge; + it equals that tax when nobody has savings, dividend or property income + and no Step 7 charge applies; and without earnings it equals + legacy_means_test_income_tax, except where the nil floor on the tax on + uncounted income binds. Within the basic rate band it is never below + legacy_means_test_income_tax: earnings never lower the tax on income from + 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 + 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 + award, passport, guarantee credit, savings credit only). +6. Differential: for every generated family without self-employment income, + Income Support, Housing Benefit and the council tax reduction line deduct, + for each person they count, the same income tax as Pension Credit's tax + line: the pre-charge income tax less + legacy_means_test_uncounted_income_tax_without_earnings. +7. Applicant: where the household head does not apply alone for council tax + reduction, council_tax_reduction_home_letting_income equals + legacy_benefits_home_letting_income; where the head applies alone, her + council tax reduction income moves with her own rent from letting part of + the home and not with anyone else's. +""" + +import numpy as np +from hypothesis import HealthCheck, example, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +PROPERTY_SETTINGS = settings( + max_examples=8, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +YEARS = [2025, 2026] +REGIONS = ["NORTH_EAST", "LONDON", "WALES", "SCOTLAND", "NORTHERN_IRELAND"] +TENURES = ["RENT_FROM_COUNCIL", "RENT_PRIVATELY", "OWNED_OUTRIGHT"] +PENSION_AGE = st.integers(67, 95) +WORKING_AGE = st.integers(18, 60) +SHAPES = { + "single_pension": [("adult", PENSION_AGE)], + "couple_pension": [("adult", PENSION_AGE), ("adult", PENSION_AGE)], + "single_working": [("adult", WORKING_AGE)], + "couple_working": [("adult", WORKING_AGE), ("adult", WORKING_AGE)], + "lone_parent": [("adult", WORKING_AGE), ("child", st.integers(0, 5))], +} +MEANS_TEST_INCOMES = [ + "income_support_applicable_income", + "housing_benefit_applicable_income", + "pension_credit_income", + "council_tax_reduction_applicable_income", +] +AWARDS = ["income_support", "housing_benefit", "pension_credit", "council_tax_benefit"] +# Each adult's earnings plus pensions stay below £22,000 and each income from +# capital below £2,000, so even at three times the capital income an adult's +# income stays inside the basic rate band. +small = st.floats(0, 2_000, allow_nan=False, allow_infinity=False) + + +@st.composite +def adults(draw, age): + return dict( + age=age, + employment_income=draw(st.one_of(st.just(0.0), st.floats(0, 12_000))), + state_pension=draw(st.floats(0, 10_000)) if age >= 67 else 0.0, + private_pension_income=draw(st.one_of(st.just(0.0), st.floats(0, 2_000))), + property_income=draw(st.one_of(st.just(0.0), small)), + savings_interest_income=draw(st.one_of(st.just(0.0), small)), + dividend_income=draw(st.one_of(st.just(0.0), small)), + sublet_income=draw(st.one_of(st.just(0.0), st.floats(0, 8_000))), + ) + + +@st.composite +def families(draw): + shape = draw(st.sampled_from(sorted(SHAPES))) + members = [] + for role, age in SHAPES[shape]: + a = draw(age) + members.append((role, draw(adults(a)) if role == "adult" else dict(age=a))) + return dict( + shape=shape, + members=members, + region=draw(st.sampled_from(REGIONS)), + tenure=draw(st.sampled_from(TENURES)), + rent=draw(st.floats(0, 15_000)), + savings=draw(st.one_of(st.just(0.0), st.floats(0, 20_000))), + reported=draw(st.booleans()), + universal_credit=draw(st.sampled_from([0.0, 3_000.0])), + ) + + +populations = st.lists(families(), min_size=1, max_size=4) +ZERO_INCOME = dict( + employment_income=0.0, + state_pension=0.0, + private_pension_income=0.0, + property_income=0.0, + savings_interest_income=0.0, + dividend_income=0.0, +) + + +@st.composite +def taxed_adults(draw, age): + """Adults with no earnings whose pensions use up the personal allowance + and whose interest, at least 7,000, bears tax without earnings.""" + return dict( + age=age, + employment_income=0.0, + state_pension=draw(st.floats(0, 10_000)) if age >= 67 else 0.0, + private_pension_income=draw(st.floats(12_570, 20_000)), + property_income=draw(st.floats(0, 20_000)), + savings_interest_income=draw(st.floats(7_000, 20_000)), + dividend_income=draw(st.floats(0, 20_000)), + sublet_income=0.0, + ) + + +@st.composite +def taxed_families(draw): + family = draw(families()) + members = [ + (role, draw(taxed_adults(attrs["age"])) if role == "adult" else attrs) + for role, attrs in family["members"] + ] + return dict(family, members=members) + + +taxed_populations = st.lists(taxed_families(), min_size=1, max_size=4) + + +def situation( + units, year, capital_income_scale=1.0, sublet_extra=0.0, savings_extra=0.0 +): + people, benunits, households = {}, {}, {} + for i, unit in enumerate(units): + names = [] + for j, (role, attrs) in enumerate(unit["members"]): + name = f"p{i}_{j}" + person = {"age": {year: attrs["age"]}} + if role == "adult": + for k, v in attrs.items(): + if k == "age": + continue + if k in ( + "property_income", + "savings_interest_income", + "dividend_income", + ): + v = v * capital_income_scale + if k == "sublet_income" and j == 0: + v = v + sublet_extra + person[k] = {year: v} + person["marriage_allowance"] = {year: 0.0} + if j == 0 and unit["reported"]: + person["income_support_reported"] = {year: 1.0} + person["housing_benefit_reported"] = {year: 1.0} + people[name] = person + names.append(name) + benunits[f"b{i}"] = { + "members": names, + # Universal Credit and tax credits have their own income rules and + # are held fixed here. + "universal_credit": {year: unit["universal_credit"]}, + "tax_credits": {year: 0.0}, + "would_claim_uc": {year: False}, + } + households[f"h{i}"] = { + "members": names, + "region": {year: unit["region"]}, + "tenure_type": {year: unit["tenure"]}, + "rent": {year: unit["rent"]}, + "savings": {year: unit["savings"] + savings_extra}, + "council_tax": {year: 1_500.0}, + } + return {"people": people, "benunits": benunits, "households": households} + + +def calculate(units, year, variables, **kwargs): + sim = Simulation(situation=situation(units, year, **kwargs)) + return {v: np.asarray(sim.calculate(v, year), dtype=float) for v in variables} + + +# The members whose income and tax each test counts. +TEST_MEMBERS = { + "income_support_applicable_income": "is_claimant_or_partner", + "housing_benefit_applicable_income": "is_claimant_or_partner", + "pension_credit_income": "is_claimant_or_partner", + "council_tax_reduction_applicable_income": ( + "is_council_tax_reduction_applicant_or_partner" + ), +} +# Each test's earnings disregard, which is capped at net earnings, so it moves +# with the tax on them. +EARNINGS_DISREGARDS = { + "income_support_applicable_income": "income_support_earnings_disregard", + "housing_benefit_applicable_income": "housing_benefit_applicable_income_disregard", + "pension_credit_income": "pension_credit_earnings_disregard", + "council_tax_reduction_applicable_income": ( + "council_tax_reduction_pensioner_earnings_disregard" + ), +} +EARNINGS = ["employment_income", "self_employment_income"] + + +def calculate_with_taxes(units, year, variables, **kwargs): + """Benefit-unit values of ``variables``, each test's deducted tax summed + over the members it counts (keyed ``tax:``), and whether anyone in + the unit has earnings (``earners``).""" + sim = Simulation(situation=situation(units, year, **kwargs)) + out = {v: np.asarray(sim.calculate(v, year), dtype=float) for v in variables} + tax = np.asarray( + sim.calculate("legacy_means_test_deducted_income_tax", year), dtype=float + ) + for income, members in TEST_MEMBERS.items(): + mask = np.asarray(sim.calculate(members, year), dtype=float) + out[f"tax:{income}"] = sim.map_result(tax * mask, "person", "benunit") + earnings = sum( + np.abs(np.asarray(sim.calculate(v, year), dtype=float)) for v in EARNINGS + ) + out["earners"] = sim.map_result(earnings, "person", "benunit") > 0 + return out + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS)) +def test_income_from_capital_changes_no_legacy_means_test(units, year): + disregards = sorted(set(EARNINGS_DISREGARDS.values())) + routes = [ + "council_tax_reduction_universal_credit_award", + "housing_benefit_on_passporting_benefit", + ] + variables = MEANS_TEST_INCOMES + AWARDS + disregards + routes + base = calculate_with_taxes(units, year, variables) + for scale in (0.0, 3.0): + scaled = calculate_with_taxes( + units, year, variables, capital_income_scale=scale + ) + moved = { + income: (scaled[f"tax:{income}"] - base[f"tax:{income}"]) + + (scaled[EARNINGS_DISREGARDS[income]] - base[EARNINGS_DISREGARDS[income]]) + for income in MEANS_TEST_INCOMES + } + steady = np.all( + [np.abs(moved[income]) < 0.01 for income in MEANS_TEST_INCOMES], axis=0 + ) + # Without earnings, the tax each test deducts does not move. + assert np.all(steady[~base["earners"]]) + # Where the deducted tax is steady, nothing moves. + for v in MEANS_TEST_INCOMES + AWARDS: + np.testing.assert_allclose( + scaled[v][steady], + base[v][steady], + atol=0.01, + err_msg=f"{v} at scale {scale}", + ) + # Intended exception: where earnings make it move, each means-test + # income moves by minus that change, wherever neither run hits a + # floor and the test uses its own income rules. + pension_credit_route = (base["pension_credit"] > 0) | ( + scaled["pension_credit"] > 0 + ) + own_rules = { + "income_support_applicable_income": np.ones_like(steady), + "pension_credit_income": np.ones_like(steady), + "housing_benefit_applicable_income": ~pension_credit_route + & (base["housing_benefit_on_passporting_benefit"] == 0), + "council_tax_reduction_applicable_income": ~pension_credit_route + & (base["council_tax_reduction_universal_credit_award"] == 0), + } + for income in MEANS_TEST_INCOMES: + checked = ( + ~steady & own_rules[income] & (base[income] > 0) & (scaled[income] > 0) + ) + np.testing.assert_allclose( + (scaled[income] - base[income])[checked], + -moved[income][checked], + atol=0.01, + err_msg=f"{income} decomposition at scale {scale}", + ) + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS + [2007])) +# A couple 23 years apart: the model presumes the younger, who has the rent, +# to be the elder's child, so the measure counts none of it. +@example( + [ + dict( + shape="couple_working", + members=[ + ("adult", dict(ZERO_INCOME, age=56, sublet_income=0.0)), + ("adult", dict(ZERO_INCOME, age=33, sublet_income=5_000.0)), + ], + region="NORTH_EAST", + tenure="RENT_PRIVATELY", + rent=6_000.0, + savings=0.0, + reported=False, + universal_credit=0.0, + ) + ], + 2026, +) +def test_home_letting_income_bounds(units, year): + sim = Simulation(situation=situation(units, year)) + counted = np.asarray(sim.calculate("legacy_benefits_home_letting_income", year)) + # The claimant's and partner's rent and ages, which the measure counts. + counted_member = np.asarray( + sim.calculate("is_claimant_or_partner", year), dtype=float + ) + rent = sim.map_result( + np.asarray(sim.calculate("sublet_income", year)) * counted_member, + "person", + "benunit", + ) + pension_age = ( + sim.map_result( + np.asarray(sim.calculate("is_SP_age", year), dtype=float) * counted_member, + "person", + "benunit", + ) + > 0 + ) + disregard = 20 if year >= 2009 else np.where(pension_age, 20, 4) + assert np.all(counted >= 0) + assert np.all(counted <= rent + 0.01) + np.testing.assert_allclose( + counted, np.maximum(0, rent / 52 - disregard) * 52, atol=0.01 + ) + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS), st.floats(1, 10_000)) +def test_home_letting_rent_is_monotone(units, year, extra): + variables = MEANS_TEST_INCOMES + AWARDS + base = calculate(units, year, variables) + more = calculate(units, year, variables, sublet_extra=extra) + for v in MEANS_TEST_INCOMES: + assert np.all(more[v] >= base[v] - 0.01), v + for v in AWARDS: + assert np.all(more[v] <= base[v] + 0.01), v + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS)) +def test_legacy_means_test_income_tax_bounds(units, year): + variables = [ + "legacy_means_test_income_tax", + "legacy_means_test_deducted_income_tax", + "legacy_means_test_uncounted_income_tax_without_earnings", + "income_tax", + "income_tax_before_winter_fuel_payment_charge", + "income_tax_charges", + "earned_income_tax", + "savings_income_tax", + "dividend_income_tax", + "property_income_tax", + ] + v = calculate(units, year, variables) + tax = v["legacy_means_test_income_tax"] + assert np.all(tax >= 0) + assert np.all(tax <= v["income_tax"] + 0.01) + assert np.all(tax <= v["earned_income_tax"] + 0.01) + no_capital_tax = ( + v["savings_income_tax"] + v["dividend_income_tax"] + v["property_income_tax"] + ) == 0 + np.testing.assert_allclose(tax[no_capital_tax], v["income_tax"][no_capital_tax]) + + # The tax each test deducts. + deducted = v["legacy_means_test_deducted_income_tax"] + pre_charge = v["income_tax_before_winter_fuel_payment_charge"] + assert np.all(deducted >= -0.01) + assert np.all(deducted <= pre_charge + 0.01) + # Within the basic rate band, earnings never lower the tax on income + # from capital, so the deduction is never below the Step 4 split. + assert np.all(deducted >= tax - 0.01) + + # Nobody has savings, dividend or property income: it is the pre-charge + # tax wherever no Step 7 charge applies. + without_capital = calculate(units, year, variables, capital_income_scale=0.0) + no_charge = without_capital["income_tax_charges"] == 0 + np.testing.assert_allclose( + without_capital["legacy_means_test_deducted_income_tax"][no_charge], + without_capital["income_tax_before_winter_fuel_payment_charge"][no_charge], + atol=0.01, + ) + np.testing.assert_allclose( + without_capital["legacy_means_test_income_tax"], + without_capital["income_tax"], + atol=0.01, + ) + + +@PROPERTY_SETTINGS +@given(taxed_populations, st.sampled_from(YEARS)) +def test_deducted_tax_without_earnings_is_the_step_4_split(units, year): + """Nobody has earnings, and every adult's interest of at least 7,000 + exceeds the 5,000 starting rate for savings and the 1,000 personal savings + allowance on top of a pension that uses up the personal allowance, so the + tax on uncounted income is positive and the deduction must leave all of + it out.""" + v = calculate( + units, + year, + [ + "legacy_means_test_income_tax", + "legacy_means_test_deducted_income_tax", + "legacy_means_test_uncounted_income_tax_without_earnings", + "income_tax_before_winter_fuel_payment_charge", + ], + ) + assert (v["legacy_means_test_uncounted_income_tax_without_earnings"] > 0).any() + # Equal unless the nil floor on the tax on uncounted income binds, where + # the Step 4 split exceeds the pre-charge tax and the deduction is the + # pre-charge tax. + np.testing.assert_allclose( + v["legacy_means_test_deducted_income_tax"], + np.minimum( + v["legacy_means_test_income_tax"], + v["income_tax_before_winter_fuel_payment_charge"], + ), + atol=0.01, + ) + floor_binds = ( + v["legacy_means_test_income_tax"] + > v["income_tax_before_winter_fuel_payment_charge"] + 0.01 + ) + np.testing.assert_allclose( + v["legacy_means_test_deducted_income_tax"][~floor_binds], + v["legacy_means_test_income_tax"][~floor_binds], + atol=0.01, + ) + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS)) +def test_the_four_tests_deduct_the_same_income_tax(units, year): + """Income Support, Housing Benefit and the council tax reduction line + deduct, for each person they count, the income tax Pension Credit's tax + line deducts. Each test's income is recomputed with the person's income + tax raised by one pound and compared with the original, so the check + reads each formula rather than the shared variable. The families have no + self-employment income, where Pension Credit's notional tax applies.""" + sim = Simulation(situation=situation(units, year)) + people = sim.populations["person"].count + pension_credit_tax = np.asarray( + sim.calculate("income_tax_before_winter_fuel_payment_charge", year) + ) - np.asarray( + sim.calculate("legacy_means_test_uncounted_income_tax_without_earnings", year) + ) + np.testing.assert_allclose( + np.asarray(sim.calculate("legacy_means_test_deducted_income_tax", year)), + pension_credit_tax, + atol=0.01, + ) + # Each test's income responds one-for-one to the shared deduction for the + # members it counts, and not at all to the Step 4 split. + bumped = Simulation(situation=situation(units, year)) + bumped.set_input( + "legacy_means_test_deducted_income_tax", + year, + np.asarray(sim.calculate("legacy_means_test_deducted_income_tax", year)) + 1.0, + ) + split = Simulation(situation=situation(units, year)) + split.set_input( + "legacy_means_test_income_tax", + year, + np.asarray(sim.calculate("legacy_means_test_income_tax", year)) + 1.0, + ) + split.set_input( + "legacy_means_test_deducted_income_tax", + year, + np.asarray(sim.calculate("legacy_means_test_deducted_income_tax", year)), + ) + assert people > 0 + for income, members in TEST_MEMBERS.items(): + base = np.asarray(sim.calculate(income, year), dtype=float) + counted = sim.map_result( + np.asarray(sim.calculate(members, year), dtype=float), "person", "benunit" + ) + moved = np.asarray(bumped.calculate(income, year), dtype=float) + unfloored = (base > 1) & (moved > 0) + own_rules = (np.asarray(sim.calculate("pension_credit", year)) == 0) | ( + income == "pension_credit_income" + ) + if income == "housing_benefit_applicable_income": + own_rules &= ( + np.asarray( + sim.calculate("housing_benefit_on_passporting_benefit", year) + ) + == 0 + ) + if income == "council_tax_reduction_applicable_income": + own_rules &= ( + np.asarray( + sim.calculate("council_tax_reduction_universal_credit_award", year) + ) + == 0 + ) + checked = unfloored & own_rules + # The earnings disregard is capped at net earnings, so it can fall + # with them. + disregard = EARNINGS_DISREGARDS[income] + disregard_change = np.asarray( + bumped.calculate(disregard, year), dtype=float + ) - np.asarray(sim.calculate(disregard, year), dtype=float) + np.testing.assert_allclose( + (base - moved)[checked], + (counted + disregard_change)[checked], + atol=0.01, + err_msg=income, + ) + np.testing.assert_allclose( + np.asarray(split.calculate(income, year), dtype=float), + base, + atol=0.01, + err_msg=f"{income} reads the Step 4 split", + ) + + +MAXIMUM_TARIFF_INCOME = 40 * 4.35 * 12 +ENGLISH_REGIONS = {"NORTH_EAST", "LONDON"} + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS), st.floats(1, 20_000)) +def test_council_tax_reduction_tariff_income_is_bounded_and_monotone( + units, year, extra +): + variables = [ + "council_tax_reduction_tariff_income", + "council_tax_reduction_pensioner", + "council_tax_reduction_universal_credit_award", + "council_tax_reduction_relevant_income_based_benefit", + "in_receipt_of_guarantee_credit", + "in_receipt_of_savings_credit_only", + ] + base = calculate(units, year, variables) + more = calculate(units, year, variables, savings_extra=extra) + tariff = base["council_tax_reduction_tariff_income"] + assert np.all(tariff >= 0) + assert np.all(tariff <= MAXIMUM_TARIFF_INCOME + 0.01) + region = np.array([unit["region"] for unit in units]) + pensioner = base["council_tax_reduction_pensioner"].astype(bool) + outside_national_schemes = (region == "NORTHERN_IRELAND") | ( + np.isin(region, list(ENGLISH_REGIONS)) & ~pensioner + ) + assert np.all(tariff[outside_national_schemes] == 0) + + def route(values): + return ( + values["council_tax_reduction_pensioner"].astype(int) * 16 + + values["council_tax_reduction_universal_credit_award"].astype(int) * 8 + + values["council_tax_reduction_relevant_income_based_benefit"].astype(int) + * 4 + + values["in_receipt_of_guarantee_credit"].astype(int) * 2 + + values["in_receipt_of_savings_credit_only"].astype(int) + ) + + same_route = route(base) == route(more) + assert np.all( + more["council_tax_reduction_tariff_income"][same_route] + >= tariff[same_route] - 0.01 + ) + + +@PROPERTY_SETTINGS +@given(populations, st.sampled_from(YEARS)) +def test_council_tax_reduction_letting_income_matches_the_legacy_measure(units, year): + """7. Applicant. Where the household head does not apply alone, the + council tax reduction applicant and partner are the benefit unit's + claimant and partner, so council_tax_reduction_home_letting_income equals + legacy_benefits_home_letting_income. (The two use different pension-age + tests, but the working-age and pension-age disregards have both stood at + £20 since April 2008.)""" + v = calculate( + units, + year, + [ + "council_tax_reduction_head_applies_alone", + "council_tax_reduction_home_letting_income", + "legacy_benefits_home_letting_income", + ], + ) + family = v["council_tax_reduction_head_applies_alone"] == 0 + np.testing.assert_allclose( + v["council_tax_reduction_home_letting_income"][family], + v["legacy_benefits_home_letting_income"][family], + atol=0.01, + ) + + +# A household head who applies alone: a liable head sharing a benefit unit +# with a young couple flagged as parents and their baby, so the couple are the +# benefit unit's claimant and partner. +head_alone_household = st.fixed_dictionaries( + dict( + head_age=st.integers(40, 95), + parent_ages=st.tuples(st.integers(16, 17), st.integers(16, 17)), + head_pension=st.floats(0, 20_000), + head_wages=st.one_of(st.just(0.0), st.floats(0, 20_000)), + head_rent=st.one_of(st.just(0.0), st.floats(0, 10_000)), + parent_rent=st.one_of(st.just(0.0), st.floats(0, 10_000)), + region=st.sampled_from(REGIONS), + ) +) + + +def head_alone_situation(households, year, head_extra=0.0, parent_extra=0.0): + people, benunits, homes = {}, {}, {} + for i, h in enumerate(households): + head, mother, father, baby = (f"{r}{i}" for r in "hmfb") + people[head] = { + "age": {year: h["head_age"]}, + "is_household_head": {year: True}, + "private_pension_income": {year: h["head_pension"]}, + "employment_income": {year: h["head_wages"]}, + "sublet_income": {year: h["head_rent"] + head_extra}, + } + people[mother] = { + "age": {year: h["parent_ages"][0]}, + "is_parent": {year: True}, + "is_household_head": {year: False}, + "sublet_income": {year: h["parent_rent"] + parent_extra}, + } + people[father] = { + "age": {year: h["parent_ages"][1]}, + "is_parent": {year: True}, + "is_household_head": {year: False}, + } + people[baby] = {"age": {year: 0}, "is_household_head": {year: False}} + members = [head, mother, father, baby] + benunits[f"b{i}"] = { + "members": members, + "would_claim_uc": {year: False}, + "universal_credit": {year: 0.0}, + "tax_credits": {year: 0.0}, + } + homes[f"h{i}"] = { + "members": members, + "region": {year: h["region"]}, + "council_tax": {year: 1_500.0}, + "savings": {year: 0.0}, + } + return {"people": people, "benunits": benunits, "households": homes} + + +HEAD_ALONE_VARIABLES = [ + "council_tax_reduction_head_applies_alone", + "council_tax_reduction_pensioner", + "council_tax_reduction_home_letting_income", + "legacy_benefits_home_letting_income", + "council_tax_reduction_applicable_income", +] + + +def head_alone_values(households, year, **kwargs): + sim = Simulation(situation=head_alone_situation(households, year, **kwargs)) + return { + v: np.asarray(sim.calculate(v, year), dtype=float) for v in HEAD_ALONE_VARIABLES + } + + +@PROPERTY_SETTINGS +@given( + st.lists(head_alone_household, min_size=1, max_size=4), + st.sampled_from(YEARS), + st.floats(1, 5_000), +) +# A Scottish working-age head, whose scheme does not count the rent. +@example( + [ + dict( + head_age=50, + parent_ages=(16, 16), + head_pension=12_000.0, + head_wages=0.0, + head_rent=5_200.0, + parent_rent=0.0, + region="SCOTLAND", + ) + ], + 2026, + 1_000.0, +) +def test_a_head_applying_alone_counts_only_her_own_letting_income( + households, year, extra +): + """7. Applicant. Where the household head applies alone, she is the + council tax reduction applicant (SI 2012/2885 reg 2(1), Sch 1 para 11): + her income moves with her own rent from letting part of the home, by the + change in council_tax_reduction_home_letting_income wherever the scheme + counts it, and not with the benefit unit's claimant's or partner's.""" + base = head_alone_values(households, year) + assert np.all(base["council_tax_reduction_head_applies_alone"] == 1) + more_own = head_alone_values(households, year, head_extra=extra) + more_others = head_alone_values(households, year, parent_extra=extra) + # Scottish councils count no such income for people under pension age + # (SSI 2021/249 reg 57(1)). + region = np.array([h["region"] for h in households]) + counts = ~((region == "SCOTLAND") & (base["council_tax_reduction_pensioner"] == 0)) + income = "council_tax_reduction_applicable_income" + letting = "council_tax_reduction_home_letting_income" + np.testing.assert_allclose( + more_own[income] - base[income], + np.where(counts, more_own[letting] - base[letting], 0), + atol=0.02, + ) + assert np.all(more_own[letting] >= base[letting] - 0.01) + # Where her own rent with the extra exceeds the £20 weekly disregard, with + # a margin for float32 rounding, her letting income is positive. + above = np.array([(h["head_rent"] + extra) / 52 > 20.01 for h in households]) + assert np.all(more_own[letting][above] > 0) + np.testing.assert_allclose(more_others[income], base[income], atol=0.01) + np.testing.assert_allclose(more_others[letting], base[letting], atol=0.01) + # The couple's own legacy measure does count it, less the £20 weekly + # disregard. + parent_rent = np.array([h["parent_rent"] for h in households]) + np.testing.assert_allclose( + more_others["legacy_benefits_home_letting_income"] + - base["legacy_benefits_home_letting_income"], + ( + np.maximum(0, (parent_rent + extra) / 52 - 20) + - np.maximum(0, parent_rent / 52 - 20) + ) + * 52, + atol=0.02, + ) diff --git a/policyengine_uk/tests/test_pension_credit_earnings_disregard_properties.py b/policyengine_uk/tests/test_pension_credit_earnings_disregard_properties.py index fa856dc008..db43f0d917 100644 --- a/policyengine_uk/tests/test_pension_credit_earnings_disregard_properties.py +++ b/policyengine_uk/tests/test_pension_credit_earnings_disregard_properties.py @@ -210,9 +210,25 @@ def test_statute_bounds_differential_and_monotonicity(case): simulate(without(case, ["employment_income"])), "income_tax_before_winter_fuel_payment_charge", ) + no_earnings_sim = simulate( + without(case, ["employment_income", "self_employment_income"]) + ) no_earnings = person_values( - simulate(without(case, ["employment_income", "self_employment_income"])), - "income_tax_before_winter_fuel_payment_charge", + no_earnings_sim, "income_tax_before_winter_fuel_payment_charge" + ) + # Pension Credit income does not deduct the tax on income it does not + # count (interest here) or the other Step 7 charges, measured without + # earnings (SPC Regs 2002 reg 17(10)(a), Sch IV para 18): the extra tax + # the earnings cause stays in the tax on earnings. A separate simulation, + # so this also checks the branch the model computes it on. + uncounted_without_earnings = np.maximum( + 0, + no_earnings - person_values(no_earnings_sim, "legacy_means_test_income_tax"), + ) + assert np.allclose( + person_values(sim, "legacy_means_test_uncounted_income_tax_without_earnings"), + uncounted_without_earnings, + atol=0.01, ) employment_tax = max(0.0, float((income_tax - no_employment)[adult].sum())) self_employment_tax = max(0.0, float((no_employment - no_earnings)[adult].sum())) @@ -239,6 +255,7 @@ def test_statute_bounds_differential_and_monotonicity(case): - actual_self_employment + float(notional[adult].sum()) + float(contributions[adult].sum()) + - float(uncounted_without_earnings[adult].sum()) ) before = max(0.0, total - deductions) assert np.isclose( diff --git a/policyengine_uk/tests/test_property_income_properties.py b/policyengine_uk/tests/test_property_income_properties.py index 4fa3853c96..2135a8bb38 100644 --- a/policyengine_uk/tests/test_property_income_properties.py +++ b/policyengine_uk/tests/test_property_income_properties.py @@ -381,8 +381,8 @@ def test_no_one_lowers_their_tax_by_switching_route_alone(couple_sim, drawn): # household. Each landlord with finance costs to relieve must still choose # the route that gives them the lower income tax including the charge, with # every other route held fixed. Landlords without finance costs take the -# allowance without comparing (uses_property_allowance); review r7's lone -# pensioner below shows that can cost more, an intended limit pinned by its +# allowance without comparing (uses_property_allowance); the lone pensioner +# with wages below shows that can cost more, an intended limit pinned by its # own test. PENSIONER_YEAR = 2025 PENSIONER_HOUSEHOLDS = 6 @@ -399,6 +399,7 @@ def test_no_one_lowers_their_tax_by_switching_route_alone(couple_sim, drawn): st.one_of(amount, st.sampled_from([3_300.0])), # profit st.floats(min_value=0, max_value=950), # expenses st.sampled_from([0.0, 0.0, 675.0, 1_200.0, 1_500.0]), # finance costs + st.sampled_from([0.0, 0.0, 27_000.0, 31_562.0, 37_047.55]), # wages ) pensioner_household = st.tuples( st.sampled_from([66, 70, 80, 85]), # claimant's age @@ -414,29 +415,33 @@ def test_no_one_lowers_their_tax_by_switching_route_alone(couple_sim, drawn): min_size=PENSIONER_HOUSEHOLDS, max_size=PENSIONER_HOUSEHOLDS, ) -NO_INCOME = (0.0, 0.0, 0.0, 0.0, 0.0) -# Review r7's cases (2026-10-16). A pensioner with six children and no -# finance costs: the allowance lowers tax before the charge by £160, which -# ends Pension Credit of £80 and so the exemption from the £200 charge. +NO_INCOME = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +# A pensioner with wages and six children and no finance costs. Pension +# Credit counts no property profits (SPC Sch IV para 18), but without the +# wages the pension and profits fall within the personal allowance, so the +# wages cause all the tax and Pension Credit deducts it. The allowance lowers +# that tax by £160, which ends Pension Credit of £80 and so the exemption +# from the £200 charge. LONE_PENSIONER = ( 70, 10, 40, - (35_207.0, 0.0, 3_300.0, 200.0, 0.0), + (9_070.0, 0.0, 3_300.0, 200.0, 0.0, 31_562.0), NO_INCOME, NO_INCOME, False, ) -# A couple's Pension Credit, through the claimant's election, takes the +# A couple's Pension Credit (savings credit), through the claimant's +# election and the tax the claimant's wages cause on the profits, takes the # partner out of entitlement and raises the lodger's shared payment and # charge from £150 to £200; the lodger's own election must hold that fixed. SHARED_PAYMENT = ( 70, 85, 85, - (42_772.55, 0.0, 3_300.0, 200.0, 1_200.0), + (9_000.0, 0.0, 3_300.0, 200.0, 1_200.0, 37_047.55), NO_INCOME, - (40_000.0, 0.0, 3_300.0, 200.0, 675.0), + (40_000.0, 0.0, 3_300.0, 200.0, 675.0, 0.0), False, ) PENSIONER_SETTINGS = settings( @@ -458,6 +463,7 @@ def person(age): "property_income": {PENSIONER_YEAR: 0}, "property_rental_income": {PENSIONER_YEAR: 0}, "property_finance_costs": {PENSIONER_YEAR: 0}, + "employment_income": {PENSIONER_YEAR: 0}, } people, benunits, households = {}, {}, {} @@ -499,13 +505,14 @@ def set_pensioner_inputs(sim, drawn, uses_allowance=None): for age, landlord in zip(household_ages, landlords) ] + [NO_INCOME] * CHILDREN claims_pc += [True, claims] - pension, dividends, profit, expenses, costs = map(np.array, zip(*incomes)) + pension, dividends, profit, expenses, costs, wages = map(np.array, zip(*incomes)) sim.set_input("age", PENSIONER_YEAR, np.array(ages, dtype=float)) sim.set_input("private_pension_income", PENSIONER_YEAR, pension) sim.set_input("dividend_income", PENSIONER_YEAR, dividends) sim.set_input("property_income", PENSIONER_YEAR, profit) sim.set_input("property_rental_income", PENSIONER_YEAR, profit + expenses) sim.set_input("property_finance_costs", PENSIONER_YEAR, costs) + sim.set_input("employment_income", PENSIONER_YEAR, wages) sim.set_input("would_claim_pc", PENSIONER_YEAR, np.array(claims_pc)) if uses_allowance is None: sim.delete_arrays("uses_property_allowance", PENSIONER_YEAR) @@ -552,13 +559,14 @@ def test_no_pensioner_lowers_their_tax_and_charge_by_switching_alone( def test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more( pensioner_sim, ): - """Intended violation: review r7's lone pensioner (no finance costs). - - The allowance lowers tax before the charge by £160 but ends £80 of Pension - Credit and with it the exemption from the £200 charge, so expenses would - give the lower income tax (£5,187.40 against £5,227.40). The model does - not compare routes for landlords without finance costs, so it takes the - allowance. + """Intended violation: a lone pensioner with wages (no finance costs). + + Without the wages, the pension and profits fall within the personal + allowance, so Pension Credit deducts the whole tax as the wages'. The + allowance lowers that tax by £160 but ends £80 of Pension Credit and with + it the exemption from the £200 charge, so expenses would give the lower + income tax (£6,272.40 against £6,312.40). The model does not compare + routes for landlords without finance costs, so it takes the allowance. """ sim = pensioner_sim drawn = [LONE_PENSIONER] * PENSIONER_HOUSEHOLDS @@ -573,10 +581,10 @@ def test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_cost routes = sim.calculate("uses_property_allowance", PENSIONER_YEAR) income_tax = sim.calculate("income_tax", PENSIONER_YEAR).astype(float) assert routes[claimants].all() - assert income_tax[pinned] == pytest.approx(5_227.40, abs=0.01) + assert income_tax[pinned] == pytest.approx(6_312.40, abs=0.01) set_pensioner_inputs(sim, drawn, routes & ~claimants) with_expenses = sim.calculate("income_tax", PENSIONER_YEAR).astype(float) - assert with_expenses[pinned] == pytest.approx(5_187.40, abs=0.01) + assert with_expenses[pinned] == pytest.approx(6_272.40, abs=0.01) # Reviews r1 and r2 of #2695. winter_fuel_payment_charge_ceiling bounds the diff --git a/policyengine_uk/tests/test_savings_credit_only_receipt_properties.py b/policyengine_uk/tests/test_savings_credit_only_receipt_properties.py index 98d8f646c7..7197148782 100644 --- a/policyengine_uk/tests/test_savings_credit_only_receipt_properties.py +++ b/policyengine_uk/tests/test_savings_credit_only_receipt_properties.py @@ -185,7 +185,7 @@ def family(ages, **overrides): # recipient; and a working-age family. KNOWN_FAMILIES = [ family([90], state_pension=12_480.0), - family([90], state_pension=12_480.0, savings=12_000.0, other_property=5_000.0), + family([90], state_pension=12_480.0, savings=12_000.0, other_property=4_400.0), family([90], state_pension=12_480.0, savings=12_000.0, rent=6_000.0), family([90], state_pension=12_480.0, would_claim_pc=False), family([70], state_pension=9_000.0), @@ -394,9 +394,11 @@ def test_known_families_detect_main(): ) assert not np.any(fix[FLAG]) # Main keeps the Pension Credit assessment. The owner with capital is - # tested on 17,000 against the 16,000 limit and gets no council tax - # reduction, where the scheme's own rules give 2,000 on savings of - # 12,000. The tenant has no Housing Benefit tariff income, where + # tested on 16,400 (savings 12,000 and property 4,400) against the + # 16,000 limit and gets no council tax reduction, where the scheme's + # own rules count the property less 10% for the expenses of sale, + # 12,000 + 3,960 = 15,960, and give 2,000. The tenant has no Housing + # Benefit tariff income, where # Housing Benefit's own rules count 4 a week on savings of 12,000 # (208). Its Housing Benefit income is the same on both routes: with # no savings credit paid, the Pension Credit assessment is the State @@ -408,6 +410,9 @@ def test_known_families_detect_main(): "simulated_council_tax_reduction_benunit", "housing_benefit_tariff_income", ] + capital = "council_tax_reduction_assessable_capital" + assert main[capital][OWNER_WITH_CAPITAL] == 16_400 + assert fix[capital][OWNER_WITH_CAPITAL] == 15_960 reduction = "simulated_council_tax_reduction_benunit" assert main[reduction][OWNER_WITH_CAPITAL] == 0 assert abs(fix[reduction][OWNER_WITH_CAPITAL] - 2_000) < 0.01 @@ -496,22 +501,40 @@ def read(simulation, variable): def test_stopping_pension_credit_payments_ends_the_pension_credit_capital_test(): - # Savings of 12,000 and other property worth 5,000. The Pension Credit - # assessment of capital counts both (17,000), above the 16,000 limit, so + # Savings of 12,000 and other property worth 4,400. The Pension Credit + # assessment of capital counts both (16,400), above the 16,000 limit, so # the savings-credit-only award leaves no council tax reduction. Deemed - # income is 1 a week for each 500 over 10,000: 14 a week, so the savings - # credit is 0.6 x 29.93 - 0.4 x (254.00 - 238.00) = 11.558 a week (601.02). - data = single_pensioner(savings=12_000.0, other_property=5_000.0) + # income is 1 a week for each 500, or part of 500, over 10,000: 6,400 / + # 500 = 12.8, so 13 a week (SPC Regs 2002 reg 15(6)). Income is 240.00 + + # 13.00 = 253.00 a week, so the savings credit is 0.6 x (238.00 - 208.07) + # - 0.4 x (253.00 - 238.00) = 17.958 - 6.00 = 11.958 a week (621.82). + data = single_pensioner(savings=12_000.0, other_property=4_400.0) unreformed = Simulation(situation=data) - assert abs(unreformed.calculate("savings_credit", YEAR)[0] - 601.02) < 0.01 + assert abs(unreformed.calculate("savings_credit", YEAR)[0] - 621.82) < 0.01 assert unreformed.calculate(FLAG, YEAR).tolist() == [True] capital = "council_tax_reduction_assessable_capital" - assert unreformed.calculate(capital, YEAR)[0] == 17_000 + assert unreformed.calculate(capital, YEAR)[0] == 16_400 assert unreformed.calculate("council_tax_reduction", YEAR)[0] == 0 - # With Pension Credit not paid the scheme's own capital rule applies, for - # which household savings (12,000) stand in, within the limit. + # With Pension Credit not paid the scheme's own capital rule applies: the + # savings and the property less 10% for the expenses of sale (SI + # 2012/2885 Sch 1 para 32(a)), 12,000 + 3,960 = 15,960, within the limit. + # Tariff income is 1 a week for each 500, or part of 500, over 10,000 + # (Sch 1 para 37): 5,960 / 500 = 11.92, so 12 a week, 624 a year. Income + # 12,480 + 624 = 13,104 is below the applicable amount of 256.00 a week + # (13,312), so the reduction is the whole 2,000. stopped = Simulation(situation=data, scenario=scenario(stopped=True)) assert stopped.calculate(FLAG, YEAR).tolist() == [False] - assert stopped.calculate(capital, YEAR)[0] == 12_000 + assert stopped.calculate(capital, YEAR)[0] == 15_960 + assert ( + abs(stopped.calculate("council_tax_reduction_tariff_income", YEAR)[0] - 624) + < 0.01 + ) + assert ( + abs( + stopped.calculate("council_tax_reduction_applicable_income", YEAR)[0] + - 13_104 + ) + < 0.01 + ) assert abs(stopped.calculate("council_tax_reduction", YEAR)[0] - 2_000) < 0.01 diff --git a/policyengine_uk/tests/test_trading_loss_properties.py b/policyengine_uk/tests/test_trading_loss_properties.py index 1209ab80a9..6dc0a3a7b8 100644 --- a/policyengine_uk/tests/test_trading_loss_properties.py +++ b/policyengine_uk/tests/test_trading_loss_properties.py @@ -933,6 +933,15 @@ def values(sim, variable): "blind_persons_allowance", "marriage_allowance", "married_couples_allowance_deduction", + # The legacy means tests leave out the tax on uncounted income due + # without earnings, which reads the Step 4 split on its branch, and + # deduct the rest (legacy_means_test_deducted_income_tax). Each is + # recomputed from the tax components, so a loss that moves interest + # or dividends between bands would move them with income_tax held. + # Hold them as the tax the tests deduct. + "legacy_means_test_income_tax", + "legacy_means_test_uncounted_income_tax_without_earnings", + "legacy_means_test_deducted_income_tax", ] tax = {v: values(with_loss, v) for v in deductions} # SPC Regs reg 17(11) substitutes CER notional deductions for the tax diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py index cdbb33b564..ff06230650 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py @@ -59,8 +59,11 @@ def hb_income_before_deductions(benunit, period, parameters): INCOME_COMPONENTS = [ "employment_income", "self_employment_income", - "property_income_after_finance_costs", "private_pension_income", + # Rent for letting part of the home, less the sub-tenant disregard. + # Other income derived from capital is capital (HB Regs 2006 reg + # 46(4), Sch 5 para 17; HB (SPC) Regs 2006 Sch 5 para 22). + "legacy_benefits_home_letting_income", ] bi = parameters(period).gov.contrib.ubi_center.basic_income # Add personal benefits, credits and total benefits to income @@ -101,11 +104,18 @@ def hb_income_before_deductions(benunit, period, parameters): add_for_members(benunit, period, ["pension_contributions"], members) * p.pension_contribution_deduction_rate ) - TAX_COMPONENTS = [ - "income_tax_before_winter_fuel_payment_charge", - "national_insurance", - ] - tax = add_for_members(benunit, period, TAX_COMPONENTS, members) + # Tax only on the income taken into account (HB Regs 2006 Sch 5 para 1; + # HB (SPC) Regs 2006 reg 33(12)), before the winter fuel payment charge, + # with earnings carrying the extra tax they cause. + # The deduction can be negative for one person, where another + # member's earnings move a Step 7 charge off them; the test deducts the + # counted members' sum, floored at nil, so it never adds tax to income. + tax = max_( + 0, + add_for_members( + benunit, period, ["legacy_means_test_deducted_income_tax"], members + ), + ) + add_for_members(benunit, period, ["national_insurance"], members) increased_income_reduced_by_tax_and_pensions = ( increased_income - tax - pension_contributions ) @@ -128,7 +138,17 @@ class housing_benefit_applicable_income(Variable): "assessment of income plus the savings credit payable, less childcare " "charges and the earnings disregards. Otherwise it is the family's " "income under the Housing Benefit rules, including the separate " - "Working Tax Credit disregard before childcare." + "Working Tax Credit disregard before childcare. Income derived from " + "capital, such as rent from property, interest and dividends, is not " + "income: for working-age claimants regulation 46(4) treats it as " + "capital and Schedule 5 paragraph 17 disregards it, and for claimants " + "over the qualifying age for State Pension Credit Schedule 5 paragraph " + "22 of the pension-age regulations disregards any actual income from " + "capital. The capital counts through the capital limit and tariff " + "income. Tax on that income is not deducted. Rent for letting part of " + "the home stays income, less the sub-tenant disregard. Rent from other " + "premises whose value is disregarded also stays income, but the model " + "cannot identify those premises." ) reference = ( "https://www.legislation.gov.uk/uksi/2006/213/regulation/25", @@ -153,6 +173,9 @@ class housing_benefit_applicable_income(Variable): "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", "https://www.legislation.gov.uk/nisr/2006/406/regulation/24", "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/46", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/5", ) definition_period = YEAR unit = GBP diff --git a/policyengine_uk/variables/gov/dwp/income_support_applicable_income.py b/policyengine_uk/variables/gov/dwp/income_support_applicable_income.py index 5321aefba7..2a2783a629 100644 --- a/policyengine_uk/variables/gov/dwp/income_support_applicable_income.py +++ b/policyengine_uk/variables/gov/dwp/income_support_applicable_income.py @@ -8,11 +8,20 @@ class income_support_applicable_income(Variable): documentation = ( "The claimant's and partner's income for Income Support, including " "statutory sick, maternity and paternity pay, spousal maintenance and " - "tariff income from capital, less income tax, National Insurance, " - "half of pension contributions, £10 a week of widowed parent's " - "allowance and the Schedule 8 earnings disregard, which is capped at " - "net earnings (income_support_earnings_disregard). Child maintenance " - "is disregarded." + "tariff income from capital, less the income tax on that income, " + "National Insurance, half of pension contributions, £10 a week of " + "widowed parent's allowance and the Schedule 8 earnings disregard, " + "which is capped at net earnings (income_support_earnings_disregard). " + "Child maintenance is disregarded. Income derived from capital, such " + "as rent from property, interest and dividends, is treated as capital " + "from the date it is due (regulation 48(4)) and disregarded as income " + "(Schedule 9 paragraph 22); the capital counts through the capital " + "limit and tariff income. Tax on that income is not deducted, as " + "Schedule 9 paragraph 1 disregards tax only on income taken into " + "account. Rent for letting part of the home stays income, less the " + "paragraph 19 disregard. Rent from other premises whose value is " + "disregarded (Schedule 10 paragraphs 2, 4 and 25 to 28) also stays " + "income, but the model cannot identify those premises." ) definition_period = YEAR unit = GBP @@ -22,10 +31,13 @@ class income_support_applicable_income(Variable): "https://www.legislation.gov.uk/uksi/1987/1967/regulation/38", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/35", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/40", + "https://www.legislation.gov.uk/uksi/1987/1967/regulation/48", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/1", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/4", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/15", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/16", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/19", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/22", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/73", ) @@ -41,8 +53,8 @@ def formula(benunit, period, parameters): INCOME_COMPONENTS = [ "employment_income", "self_employment_income", - "property_income_after_finance_costs", "private_pension_income", + "legacy_benefits_home_letting_income", # Employer statutory pay is other income (regs 35(2)(b), 40(1)). "statutory_sick_pay", "statutory_maternity_pay", @@ -56,12 +68,15 @@ def formula(benunit, period, parameters): if bi.interactions.include_in_means_tests: INCOME_COMPONENTS.append("basic_income") income = add_for_members(benunit, period, INCOME_COMPONENTS, members) - tax = add_for_members( - benunit, - period, - ["income_tax_before_winter_fuel_payment_charge", "national_insurance"], - members, - ) + # The deduction can be negative for one person, where another + # member's earnings move a Step 7 charge off them; the test deducts the + # counted members' sum, floored at nil, so it never adds tax to income. + tax = max_( + 0, + add_for_members( + benunit, period, ["legacy_means_test_deducted_income_tax"], members + ), + ) + add_for_members(benunit, period, ["national_insurance"], members) income += add_for_members(benunit, period, ["social_security_income"], members) # IS Regs 1987 Sch 9 para 16(h): £10 a week of widowed parent's # allowance is disregarded; social_security_income counts it in full. diff --git a/policyengine_uk/variables/gov/dwp/legacy_benefits_home_letting_income.py b/policyengine_uk/variables/gov/dwp/legacy_benefits_home_letting_income.py new file mode 100644 index 0000000000..c8f89f0af7 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/legacy_benefits_home_letting_income.py @@ -0,0 +1,54 @@ +from policyengine_uk.model_api import * + + +def home_letting_income(benunit, period, parameters, counted, pension_age): + """Annual rent the `counted` members receive for letting part of their + home, less the weekly sub-tenant disregard for one occupier: the + pension-age amount where `pension_age` holds, else the working-age one.""" + p = parameters(period).gov.dwp.legacy_means_tests.sub_tenant_rent_disregard + person = benunit.members + weekly_rent = benunit.sum(person("sublet_income", period) * counted) / WEEKS_IN_YEAR + disregard = where(pension_age, p.pension_age, p.working_age) + return max_(0, weekly_rent - disregard) * WEEKS_IN_YEAR + + +class legacy_benefits_home_letting_income(Variable): + value_type = float + entity = BenUnit + label = "Rent from letting part of the home counted in the legacy means tests" + documentation = ( + "Rent the claimant and any partner receive for letting part of the home " + "they live in (sublet_income), after the weekly sub-tenant disregard. " + "The legacy means tests treat other income derived from capital, such as " + "rent from other property, interest and dividends, as capital, but the " + "home is disregarded capital, so rent for part of it stays income: " + "Income Support Schedule 9 paragraph 19, Housing Benefit Schedule 5 " + "paragraph 22, and for claimants over the qualifying age for State " + "Pension Credit Pension Credit regulation 15(5)(i) with Schedule IV " + "paragraph 9 and pension-age Housing Benefit regulation 29(1)(v) with " + "Schedule 5 paragraph 10. The disregard applies per occupier; the data " + "give one annual amount and no count of occupiers, so the model assumes " + "one. The pension-age amount applies when the claimant or partner is " + "over State Pension age, which stands in for the qualifying age for " + "State Pension Credit; the two amounts have been equal since April " + "2008. The calculation is annual, so a year with an April change uses " + "the amount in force at the start of the year." + ) + definition_period = YEAR + unit = GBP + reference = [ + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/19", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/22", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/29", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/5/paragraph/10", + "https://www.legislation.gov.uk/uksi/2002/1792/regulation/15", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV/paragraph/9", + ] + + def formula(benunit, period, parameters): + person = benunit.members + claimant_or_partner = person("is_claimant_or_partner", period) + pension_age = benunit.any(person("is_SP_age", period) & claimant_or_partner) + return home_letting_income( + benunit, period, parameters, claimant_or_partner, pension_age + ) diff --git a/policyengine_uk/variables/gov/dwp/legacy_means_test_deducted_income_tax.py b/policyengine_uk/variables/gov/dwp/legacy_means_test_deducted_income_tax.py new file mode 100644 index 0000000000..258e08e62b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/legacy_means_test_deducted_income_tax.py @@ -0,0 +1,55 @@ +from policyengine_uk.model_api import * + + +class legacy_means_test_deducted_income_tax(Variable): + value_type = float + entity = Person + label = "Income tax deducted in the legacy means tests" + documentation = ( + "The income tax that Income Support, Housing Benefit, Pension Credit " + "and council tax reduction deduct for the person: their income tax " + "before the winter fuel payment charge, less the tax that the income " + "the tests treat as capital (rent from property, interest and " + "dividends), and the other Step 7 charges, would bear if nobody had " + "employed earnings or self-employment income " + "(legacy_means_test_uncounted_income_tax_without_earnings). The tests " + "disregard tax only on income they take into account (IS Regs 1987 " + "Sch 9 para 1; HB Regs 2006 Sch 5 para 1; HB (SPC) Regs 2006 reg " + "33(12); SPC Regs 2002 reg 17(10)(a)) and deduct the income tax " + "deducted from earnings (IS Regs 1987 reg 36(3)(a); HB Regs 2006 reg " + "36(3)(a)). The model has no PAYE codes and no provision says how to " + "split one liability, so earnings carry the extra tax they cause, " + "including what they add on savings, dividends and rent and any Step " + "7 charge they bring in, as Pension Credit measures the tax on " + "earnings. Without earnings it equals legacy_means_test_income_tax. " + "It is not floored: where one partner's earnings move a Step 7 " + "charge or the marriage allowance off the other partner, that " + "partner's value can be negative, and the claimant's and partner's " + "values together give the extra tax the earnings cause. Each test " + "sums it over the members it counts and floors that sum at nil, so " + "where the earner is a member the test does not count (for example " + "one the model presumes to be the claimant's child), the counted " + "member's negative value adds nothing to income. The floor binds " + "only where the sum turns negative. Where the counted member also " + "pays tax on counted income, the charge that the uncounted member's " + "earnings move off them still lowers the deduction, and the test's " + "income rises by up to that charge. Pension Credit takes the tax on " + "self-employed profit out of the sum before the floor and adds " + "notional tax in its place (pension_credit_income); the other tests " + "deduct this tax as it is." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/1987/1967/regulation/36", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/1", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/36", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/1", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/33", + "https://www.legislation.gov.uk/uksi/2002/1792/regulation/17", + ) + + def formula(person, period, parameters): + return person("income_tax_before_winter_fuel_payment_charge", period) - person( + "legacy_means_test_uncounted_income_tax_without_earnings", period + ) diff --git a/policyengine_uk/variables/gov/dwp/legacy_means_test_income_tax.py b/policyengine_uk/variables/gov/dwp/legacy_means_test_income_tax.py new file mode 100644 index 0000000000..906eab1282 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/legacy_means_test_income_tax.py @@ -0,0 +1,110 @@ +from policyengine_uk.model_api import * + + +class legacy_means_test_income_tax(Variable): + value_type = float + entity = Person + label = "Income tax on income the legacy means tests count, by Step 4 component" + documentation = ( + "The part of the person's income tax that Step 4 of Income Tax Act " + "2007 s.23 calculates on the income the legacy means tests take into " + "account, less that income's share of the Step 6 tax reductions. The " + "tests do not deduct it directly: " + "legacy_means_test_uncounted_income_tax_without_earnings reads it on " + "a branch where nobody has employed earnings or self-employment " + "income, and takes the rest of the pre-charge tax there as the tax on " + "uncounted income, which legacy_means_test_deducted_income_tax leaves " + "out. Income Support, Housing Benefit, Pension Credit and council tax " + "reduction treat savings interest, dividends and property income as " + "capital, not income, so the counted income here is the person's " + "other income (earned_income_tax, which covers earnings, pensions and " + "taxable benefits). Its share of the Step 6 reductions (the married " + "couple's allowance, other tax credits, the residential finance-cost " + "reduction and the Pension Tax Allowance) follows two rules. Most " + "reductions are not tied to any income: s.27 orders them only to " + "give the greatest reduction in liability. Two are: foreign tax " + "credit relief reduces the tax on the income the foreign tax was paid " + "on (Taxation (International and Other Provisions) Act 2010 ss.18(2) " + "and 36), and the residential finance-cost reduction is given on at " + "most the property business's profits, plus any current-year estate " + "amounts and within the adjusted total income limit (Income Tax " + "(Trading and Other Income) Act 2005 ss.274A and 274AA). The " + "finance-cost reduction (property_finance_cost_relief) therefore " + "comes off the tax on property income first. The model's " + "other_tax_credits input mixes foreign tax credit relief with other " + "reductions (venture capital trust, enterprise investment and " + "maintenance relief, among others) and records no source, so those " + "reductions, and the Pension Tax Allowance, are shared in proportion " + "to the Step 4 tax on each kind of income, as a stated convention. A " + "credit for foreign tax on rent is therefore partly attributed to " + "counted income. Step 7 charges, such as the High Income Child " + "Benefit Charge, the pension annual allowance charge (s.30) and the " + "winter fuel payment charge, are not tax calculated on any of this " + "income, so none is included. The result is " + "income_tax_before_winter_fuel_payment_charge less the tax attributed " + "to capital and the other charges, floored at nil, so a supplied " + "value of the pre-charge tax flows through; if it differs from the " + "tax the components imply, the difference falls on the tax on " + "counted income." + ) + definition_period = YEAR + unit = GBP + reference = [ + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9/paragraph/1", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5/paragraph/1", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/33", + "https://www.legislation.gov.uk/uksi/2002/1792/regulation/17", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/17", + "https://www.legislation.gov.uk/ukpga/2007/3/section/23", + "https://www.legislation.gov.uk/ukpga/2007/3/section/27", + "https://www.legislation.gov.uk/ukpga/2007/3/section/30", + "https://www.legislation.gov.uk/ukpga/2010/8/section/18", + "https://www.legislation.gov.uk/ukpga/2010/8/section/36", + "https://www.legislation.gov.uk/ukpga/2005/5/section/274A", + "https://www.legislation.gov.uk/ukpga/2005/5/section/274AA", + ] + + def formula(person, period, parameters): + # Step 4 tax on the income the means tests count, and on the income + # they treat as capital. + counted = person("earned_income_tax", period) + capital = add( + person, + period, + ["savings_income_tax", "dividend_income_tax", "property_income_tax"], + ) + before_reductions = counted + capital + # Step 7 charges other than the winter fuel payment charge, which the + # starting value below already leaves out. + charges = person("income_tax_charges", period) + # Step 6 reductions, limited to the Step 5 tax. The residential + # finance-cost reduction is relief for the property business's costs, + # given on at most its profits (ITTOIA 2005 ss.274A-274AA), so it + # comes off the tax on property income first. The rest have no + # recorded source and are shared in proportion to the Step 4 tax left. + reductions = min_(person("income_tax_reductions", period), before_reductions) + finance_cost_relief = min_( + person("property_finance_cost_relief", period), + min_(person("property_income_tax", period), reductions), + ) + general_reductions = reductions - finance_cost_relief + capital_after_relief = capital - finance_cost_relief + tax_after_relief = before_reductions - finance_cost_relief + capital_share = np.divide( + capital_after_relief, + tax_after_relief, + out=np.zeros_like(capital_after_relief, dtype=float), + where=tax_after_relief > 0, + ) + capital_after_reductions = ( + capital_after_relief - general_reductions * capital_share + ) + # Starting from the income tax the means tests deduct keeps any + # supplied value: the result is the tax on counted income less its + # share of reductions whenever that tax is calculated. + return max_( + 0, + person("income_tax_before_winter_fuel_payment_charge", period) + - capital_after_reductions + - charges, + ) diff --git a/policyengine_uk/variables/gov/dwp/legacy_means_test_uncounted_income_tax_without_earnings.py b/policyengine_uk/variables/gov/dwp/legacy_means_test_uncounted_income_tax_without_earnings.py new file mode 100644 index 0000000000..b982e91bd2 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/legacy_means_test_uncounted_income_tax_without_earnings.py @@ -0,0 +1,58 @@ +from policyengine_uk.model_api import * +from policyengine_uk.utils.pension_credit import employed_earnings_sources +from policyengine_uk.variables.gov.dwp.pension_credit.pension_credit_earnings_income_tax import ( + DECISION, + person_variable_with_inputs_zeroed, +) + + +class legacy_means_test_uncounted_income_tax_without_earnings(Variable): + value_type = float + entity = Person + label = "Income tax on income the legacy means tests do not count, without earnings" + documentation = ( + "The part of the person's income tax before the winter fuel payment " + "charge, if nobody in the simulation had employed earnings (employment " + "income and statutory sick, maternity and paternity pay) or " + "self-employment income, that is not tax on income the legacy means " + "tests take into account: the tax on rent from property, interest and " + "dividends, and the other Step 7 charges. It is that pre-charge tax " + "less legacy_means_test_income_tax, both on the branch without " + "earnings, floored at nil. Income Support, Housing Benefit, Pension " + "Credit and council tax reduction treat income derived from capital " + "as capital and disregard tax only on income they take into account " + "(IS Regs 1987 Sch 9 paras 1 and 22; HB Regs 2006 Sch 5 paras 1 and " + "17; HB (SPC) Regs 2006 reg 33(12) and Sch 5 para 22; SPC Regs 2002 " + "reg 17(10)(a) and Sch IV para 18), so none of them deducts this tax " + "(legacy_means_test_deducted_income_tax). It is measured without " + "earnings because the tax on earnings is the extra tax the earnings " + "cause, including on savings, dividends and rent, and the tests do " + "deduct that. " + DECISION + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/9", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/5", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/33", + "https://www.legislation.gov.uk/uksi/2002/1792/regulation/17", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV", + ) + + def formula(person, period, parameters): + income_tax = person("pension_credit_income_tax_without_earnings", period) + # Zero the same earnings as pension_credit_income_tax_without_earnings, + # so both taxes describe the same world without earnings. + sources = employed_earnings_sources(parameters, period) + [ + "self_employment_income" + ] + if not any((person(source, period) != 0).any() for source in sources): + counted = person("legacy_means_test_income_tax", period) + else: + counted = person_variable_with_inputs_zeroed( + person.simulation, + period, + sources, + "legacy_means_test_income_tax", + ) + return max_(0, income_tax - counted) diff --git a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_earnings_income_tax.py b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_earnings_income_tax.py index 5d50272dee..b357b84891 100644 --- a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_earnings_income_tax.py +++ b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_earnings_income_tax.py @@ -3,9 +3,9 @@ DECISION = ( "PolicyEngine does not model PAYE codes, so which part of a person's " - "income tax is payable on their earnings is a methodology choice, put to " - "Max on PolicyEngine/policyengine-uk#2019 and settled as option (a): treat " - "earnings as the top slice of the person's income. " + "income tax is payable on their earnings is a methodology choice " + "(PolicyEngine/policyengine-uk#2019): earnings are treated as the top " + "slice of the person's income. " ) # Income tax here is before the winter fuel payment charge, as in every means @@ -18,6 +18,14 @@ def income_tax_with_inputs_zeroed(simulation, period, variables): """Each person's income tax before the winter fuel payment charge with every person's value of each of ``variables`` set to nil, on a branch that is dropped afterwards.""" + return person_variable_with_inputs_zeroed( + simulation, period, variables, PRE_CHARGE_TAX + ) + + +def person_variable_with_inputs_zeroed(simulation, period, variables, output): + """Each person's ``output`` with every person's value of each of + ``variables`` set to nil, on a branch that is dropped afterwards.""" name = "pension_credit_without_" + "_and_".join(variables) while name in simulation.branches or name == simulation.branch_name: name += "_" @@ -29,7 +37,7 @@ def income_tax_with_inputs_zeroed(simulation, period, variables): people = branch.populations["person"] for variable in variables: branch.set_input(variable, period, np.zeros(people.count)) - return people(PRE_CHARGE_TAX, period) + return people(output, period) finally: del simulation.branches[name] diff --git a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_income.py b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_income.py index 57efbf50e8..6580a3a3fa 100644 --- a/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_income.py +++ b/policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_income.py @@ -47,16 +47,35 @@ def formula(benunit, period, parameters): pension_contributions = benunit.sum( person("pension_contributions", period) * is_claimant_or_partner ) - # Self-employed earnings are net of the notional tax and contributions - # of the Computation of Earnings Regulations 1996 reg. 14, in place of - # those actually payable on the profit (reg. 17(11)). - tax = benunit.sum( + # Reg 17(10)(a) disregards tax only on income taken into account, and + # Schedule IV paragraph 18 disregards actual income from capital. The + # tax on earnings is the extra tax the earnings cause, so the income + # tax deducted leaves out the tax on uncounted income, and the Step 7 + # charges, that the claimant and partner would pay without earnings + # (legacy_means_test_deducted_income_tax, which the other legacy + # means tests deduct too). Self-employed earnings are net of the + # notional tax and contributions of the Computation of Earnings + # Regulations 1996 reg. 14, in place of those actually payable on the + # profit (reg. 17(11)). + # The deduction can be negative for one person, where another + # member's earnings move a Step 7 charge off them. The test takes the + # counted members' sum less the tax actually payable on self-employed + # profit, which the notional tax replaces, and floors that at nil, so + # it never adds tax to income. + income_tax = max_( + 0, + benunit.sum( + person("legacy_means_test_deducted_income_tax", period) + * is_claimant_or_partner + ) + - benunit("pension_credit_self_employment_income_tax", period), + ) + tax = income_tax + benunit.sum( ( add( person, period, [ - "income_tax_before_winter_fuel_payment_charge", "national_insurance", "pension_credit_self_employment_deductions", ], @@ -64,7 +83,7 @@ def formula(benunit, period, parameters): - add(person, period, ["ni_class_2", "ni_class_4"]) ) * is_claimant_or_partner - ) - benunit("pension_credit_self_employment_income_tax", period) + ) pen_con_deduction_rate = pc.income.pension_contributions_deduction deductions = tax + pension_contributions * pen_con_deduction_rate # Schedule VI earnings disregards (reg. 17(9)). diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/housing_costs_element/non_dep_deduction/uc_non_dep_receives_pension_credit.py b/policyengine_uk/variables/gov/dwp/universal_credit/housing_costs_element/non_dep_deduction/uc_non_dep_receives_pension_credit.py index 84dd97e376..d04efdbf02 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/housing_costs_element/non_dep_deduction/uc_non_dep_receives_pension_credit.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/housing_costs_element/non_dep_deduction/uc_non_dep_receives_pension_credit.py @@ -31,9 +31,12 @@ def formula(benunit, period, parameters): # through the renter's UC entitlement and pension-age route. simulation = benunit.simulation # Income tax is independent of the UC housing element. Calculate - # both earnings counterfactuals on the parent so this branch and + # the earnings counterfactuals on the parent so this branch and # ordinary Pension Credit share them whichever is requested first. benunit.members("pension_credit_income_tax_without_earnings", period) + benunit.members( + "legacy_means_test_uncounted_income_tax_without_earnings", period + ) name = "uc_non_dep_pension_credit" while name in simulation.branches or name == simulation.branch_name: name += "_" diff --git a/policyengine_uk/variables/gov/hmrc/income_tax/allowances/uses_property_allowance.py b/policyengine_uk/variables/gov/hmrc/income_tax/allowances/uses_property_allowance.py index d7c264d120..3d07f76bb2 100644 --- a/policyengine_uk/variables/gov/hmrc/income_tax/allowances/uses_property_allowance.py +++ b/policyengine_uk/variables/gov/hmrc/income_tax/allowances/uses_property_allowance.py @@ -137,8 +137,15 @@ class uses_property_allowance(Variable): "allowance is used whenever it lowers taxable property income, " "without comparing tax. That is always the lower tax before the " "winter fuel payment charge. While the charge has effect it can " - "rarely cost more: the lower tax can raise the income Pension Credit " - "counts and end an award that exempts the person from the charge. " + "rarely cost more: the lower tax can lower the income tax the " + "Pension Credit formula deducts " + "(legacy_means_test_deducted_income_tax), which raises the income " + "Pension Credit counts and can end an award that exempts the person " + "from the charge. The deduction moves with the route where earnings " + "carry tax on the profits, and, without earnings, where the profits " + "change the tax on income Pension Credit counts: through its share " + "of a general tax reduction, the Marriage Allowance or the personal " + "allowance taper. " "The model does not compare routes for these landlords, because " "that works out the benefits on both routes for the whole " "population and made simulations several times slower; on the " @@ -177,8 +184,10 @@ def formula(person, period, parameters): # Without a reduction at stake, lower taxable property income means # lower tax before the winter fuel payment charge, so the allowance # is used without comparing. The charge can rarely reverse that - # (lower tax can end Pension Credit and with it the exemption, - # s.681I(4)); see the documentation for why that is not compared. + # (lower tax can lower the tax the Pension Credit formula deducts, + # and so end Pension Credit and with it the exemption, s.681I(4)); + # see the documentation for when that happens and why it is not + # compared. uses = lowers_income & ~reduction_at_stake choosing = lowers_income & reduction_at_stake if not choosing.any(): diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py index 4383dba483..aefde51258 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/_legacy.py @@ -12,11 +12,11 @@ def is_full_time_student_non_dep(person, period): def applicant_has_universal_credit(benunit, period): """Whether the Council Tax Reduction applicant has the benefit unit's - Universal Credit award. The award belongs to the benefit unit's claimant - and partner, so not to a household head who applies alone.""" - return (benunit("universal_credit", period) > 0) & ~benunit( - "council_tax_reduction_head_applies_alone", period - ) + Universal Credit award (council_tax_reduction_universal_credit_award), + including one the benefit cap or deductions reduce to nil. The award + belongs to the benefit unit's claimant and partner, so not to a household + head who applies alone.""" + return benunit("council_tax_reduction_universal_credit_award", period) def legacy_council_tax_reduction( @@ -73,10 +73,20 @@ def legacy_council_tax_reduction( - excess_income * ctr.means_test.withdrawal_rate - non_dep_deductions, ) + # council_tax_reduction_assessable_capital takes the Universal Credit + # assessment for an award of Universal Credit (the default scheme's + # para 37(6)), including one the benefit cap or deductions reduce to nil. + # Most councils keep the default scheme's disregard of the whole capital of + # an applicant on Income Support, income-based JSA or income-related ESA + # (its Schedule 10 para 8); each scheme says whether it does. + passported_capital_disregarded = ( + relevant_income_based_benefit + & ctr.means_test.disregards_passported_applicants_capital + ) capital = where( - has_uc_award, - benunit("uc_assessable_capital", period), - benunit.household("savings", period), + passported_capital_disregarded, + 0, + benunit("council_tax_reduction_assessable_capital", period), ) capital_eligible = capital <= ctr.means_test.capital_limit return ( 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..90d36dd6c3 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 @@ -1,4 +1,7 @@ from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction.config import ( + is_scotland_scheme, +) from policyengine_uk.variables.household.demographic.country import Country @@ -38,7 +41,27 @@ class council_tax_reduction_applicable_income(Variable): "children or young persons. War pensions and Armed Forces " "Compensation Scheme payments are not counted: 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, so the model takes the full disregard. " + "No scheme " + "counts income derived from capital, such as rent from property, " + "interest and dividends, as income, so it is not listed and tax on it " + "is not deducted (legacy_means_test_income_tax). The pensioner schemes " + "disregard any actual income from capital; the Welsh working-age " + "scheme and the English default scheme treat it as capital; the " + "Scottish working-age scheme counts only the unearned income it " + "lists, which includes the assumed yield from capital but not actual " + "rent, interest or dividends. Instead, the national schemes (England " + "for pensioners, Wales and Scotland) count the tariff income they " + "treat capital as yielding (council_tax_reduction_tariff_income); the " + "English local schemes for people under pension age add their own. " + "Rent the applicant and partner receive for letting part of the home " + "counts, less the sub-tenant disregard, on the schemes' own income " + "rules (council_tax_reduction_home_letting_income). It does not count " + "where a working-age applicant has an award of Universal Credit, " + "whose income the schemes take from the Secretary of State's " + "Universal Credit assessment (which does not count it), or in the " + "Scottish scheme for people under pension age from April 2022, which " + "does not list it." ) definition_period = YEAR unit = GBP @@ -68,6 +91,17 @@ class council_tax_reduction_applicable_income(Variable): "https://www.legislation.gov.uk/uksi/2012/2885/schedule/4", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/3", "https://www.legislation.gov.uk/ssi/2012/319/schedule/2", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/5", + "https://www.legislation.gov.uk/uksi/2012/2886/schedule/paragraph/37", + "https://www.legislation.gov.uk/uksi/2012/2886/schedule/paragraph/64", + "https://www.legislation.gov.uk/uksi/2012/2886/schedule/8", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/4", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/9", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/9", + "https://www.legislation.gov.uk/ssi/2012/319/schedule/3", + "https://www.legislation.gov.uk/ssi/2012/303/regulation/26", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/3", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/63", "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/11", "https://www.legislation.gov.uk/ssi/2012/319/regulation/21", "https://www.legislation.gov.uk/wsi/2013/3029/schedule/1/paragraph/5", @@ -198,7 +232,6 @@ def formula(benunit, period, parameters): income_components = [ "employment_income", "self_employment_income", - "property_income_after_finance_costs", "private_pension_income", ] bi = parameters(period).gov.contrib.ubi_center.basic_income @@ -272,6 +305,39 @@ def formula(benunit, period, parameters): - maintenance_disregard + widowed_parents_allowance ) + # Rent the applicant and partner receive for letting part of the home + # counts under the schemes' own income rules, less the sub-tenant + # disregard (SI 2012/2885 Sch 1 paras 11 and 16(1)(v), Sch 5 para 10). Two exceptions: + # - A working-age applicant with an award of Universal Credit: the + # schemes use the Secretary of State's assessment of income for the + # award (SI 2012/2886 Sch para 37(1); WSI 2013/3029 Sch 6 para 9(1); + # SSI 2012/303 reg 26(1)), which does not count it (UC Regs 2013 + # reg 66), and Oxford's Appendix 3 disregards it. + # - The Scottish scheme for people under pension age from 1 April 2022 + # (SSI 2021/249, whose reg 57(1) list has no head for it). That + # scheme applies under reg 3(1) to everyone the pension-age scheme + # does not cover (council_tax_reduction_pensioner). An award held + # only by people over pensionable age does not count (reg 3(2)); the + # selector stands this in by requiring a younger applicant or + # partner, as Universal Credit itself does (UC Regs 2013 reg + # 3(2)(a)). The model cannot represent reg 3(2)'s other statuses or + # a claim awaiting determination (reg 3(1)(b)(ii), from April 2023). + universal_credit_route = ~pensioner & benunit( + "council_tax_reduction_universal_credit_award", period + ) + scottish_working_age_scheme = is_scotland_scheme(country) & ~pensioner + p_scotland = parameters( + period + ).gov.local_authorities.scotland.council_tax_reduction.means_test + counts_home_letting = ~universal_credit_route & ( + ~scottish_working_age_scheme + | p_scotland.working_age_counts_home_letting_income + ) + increased_income += where( + counts_home_letting, + benunit("council_tax_reduction_home_letting_income", period), + 0, + ) if not bi.interactions.include_in_means_tests: increased_income -= add_for_members( @@ -285,12 +351,15 @@ def formula(benunit, period, parameters): pension_contributions = add_for_members( benunit, period, ["pension_contributions"], members ) * benunit("council_tax_reduction_pension_contribution_deduction_rate", period) - tax = add_for_members( - benunit, - period, - ["income_tax_before_winter_fuel_payment_charge", "national_insurance"], - members, - ) + # The deduction can be negative for one person, where another + # member's earnings move a Step 7 charge off them; the test deducts the + # counted members' sum, floored at nil, so it never adds tax to income. + tax = max_( + 0, + add_for_members( + benunit, period, ["legacy_means_test_deducted_income_tax"], members + ), + ) + add_for_members(benunit, period, ["national_insurance"], members) # SI 2012/2885 Sch 1 para 17(9) and Sch 4; WSI 2013/3029 Sch 1 para # 11(9) and Sch 3; SSI 2012/319 reg 31(8) and Sch 2: the pensioner # earnings disregards, capped at net earnings. Zero for working-age @@ -298,9 +367,12 @@ def formula(benunit, period, parameters): earnings_disregard = benunit( "council_tax_reduction_pensioner_earnings_disregard", period ) + # The national schemes also treat capital as yielding a tariff income + # (council_tax_reduction_tariff_income); the English local schemes for + # people under pension age add their own. income_under_general_rules = max_( 0, increased_income - tax - pension_contributions - earnings_disregard - ) + ) + benunit("council_tax_reduction_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_assessable_capital.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_assessable_capital.py index 46ef19a7d1..05115192ad 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_assessable_capital.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_assessable_capital.py @@ -1,4 +1,17 @@ from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction.config import ( + is_scotland_scheme, + is_wales_scheme, +) + +# The debt input secured on each capital source. The schemes deduct "the +# amount of any encumbrance secured on it" from that asset after the sale +# expenses, so a source is never valued below nil and negative equity in one +# source does not reduce another. Land has no secured-debt input. +SECURED_DEBT = { + "other_residential_property_value": "other_residential_property_secured_debt", + "non_residential_property_value": "non_residential_property_secured_debt", +} class council_tax_reduction_assessable_capital(Variable): @@ -6,28 +19,54 @@ class council_tax_reduction_assessable_capital(Variable): entity = BenUnit label = "capital for the Council Tax Reduction capital limit" documentation = ( - "Capital tested against the Council Tax Reduction capital limit. The " - "pensioner schemes disregard the whole capital 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 capital where " - "the award is savings credit only. Otherwise household savings stand in " - "for the applicant's capital; the schemes' own capital rules also count " - "other property and investments, so this understates capital for " - "pensioners without Pension Credit. The recalculation when capital rises " - "above the limit during an assessed income period is not modelled." + "Capital tested against the Council Tax Reduction capital limit and " + "used for tariff income. The pensioner schemes disregard the whole " + "capital 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 capital where the award is savings " + "credit only. Where an applicant who is not a pensioner, or their " + "partner, has an award of Universal Credit " + "(council_tax_reduction_universal_credit_award, which includes an " + "award the benefit cap or deductions reduce to nil), the schemes use " + "the Secretary of State's assessment of capital for that award " + "(uc_assessable_capital), except the Scottish scheme from April 2022, " + "under which the authority calculates capital itself. The Welsh " + "scheme, and the Scottish scheme before April 2022, disregard the " + "whole capital of an applicant on Income Support, income-based " + "Jobseeker's Allowance or income-related Employment and Support " + "Allowance; the English local schemes that do the same apply it in " + "their own formulas. Otherwise the household's capital stands in for " + "the applicant's: savings, land and property other than the home " + "(gov.local_authorities.council_tax_reduction.capital.sources), with " + "land and property valued at market value less 10% for the expenses " + "of sale, then less any debt secured on that property (which defaults " + "to nil because the survey does not record it). The schemes also " + "count shares and other investments, which in the data are mixed " + "with pension wealth the schemes disregard, so they are left out for " + "now. The recalculation when capital rises above the limit during an " + "assessed income period is not modelled." ) definition_period = YEAR unit = GBP quantity_type = STOCK reference = [ "https://www.legislation.gov.uk/uksi/2012/2885/regulation/11", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/31", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/32", "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/2886/schedule/paragraph/37", "https://www.legislation.gov.uk/wsi/2013/3029/regulation/30", "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/6/paragraph/9", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/26", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/10/paragraph/8", "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/ssi/2012/303/regulation/26", + "https://www.legislation.gov.uk/ssi/2012/303/schedule/5/paragraph/7", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/70", ] def formula(benunit, period, parameters): @@ -41,8 +80,60 @@ def formula(benunit, period, parameters): has_savings_credit_only_award = applicant_family & benunit( "in_receipt_of_savings_credit_only", period ) + country = benunit.household("country", period) + scotland = is_scotland_scheme(country) + wales = is_wales_scheme(country) + p_scotland = parameters( + period + ).gov.local_authorities.scotland.council_tax_reduction.means_test + working_age = ~benunit("council_tax_reduction_pensioner", period) + # SI 2012/2886 Sch para 37(6), WSI 2013/3029 Sch 6 para 9(6) and SSI + # 2012/303 reg 26: with an award of Universal Credit, the authority + # uses the Secretary of State's calculation of capital. These are + # working-age rules. SSI 2021/249 has no such rule. + uses_universal_credit_assessment = ~scotland | ( + p_scotland.uses_universal_credit_capital_assessment + ) + universal_credit_route = ( + working_age + & benunit("council_tax_reduction_universal_credit_award", period) + & uses_universal_credit_assessment + ) + # WSI 2013/3029 Sch 10 para 8 and SSI 2012/303 Sch 5 para 7: the whole + # capital of an applicant on Income Support, income-based JSA or + # income-related ESA is disregarded. SSI 2021/249 has no such + # disregard: reg 13(11) treats only the income conditions as met. + passported = working_age & benunit( + "council_tax_reduction_relevant_income_based_benefit", period + ) + disregards_passported_capital = wales | ( + scotland & p_scotland.disregards_passported_applicants_capital + ) + p = parameters(period).gov.local_authorities.council_tax_reduction.capital + # Capital is valued at market value less 10% where there would be + # expenses of sale, then less any encumbrance secured on it (SI + # 2012/2885 Sch 1 para 32 and equivalents). + household_capital = 0 + for source in p.sources: + value = max_(0, benunit.household(source, period)) + if source in p.sale_expenses.sources: + value = value * (1 - p.sale_expenses.rate) + if source in SECURED_DEBT: + debt = max_(0, benunit.household(SECURED_DEBT[source], period)) + value = max_(0, value - debt) + household_capital = household_capital + value return select( - [in_receipt_of_guarantee_credit, has_savings_credit_only_award], - [0, benunit("pension_credit_assessable_capital", period)], - default=benunit.household("savings", period), + [ + in_receipt_of_guarantee_credit, + has_savings_credit_only_award, + universal_credit_route, + passported & disregards_passported_capital, + ], + [ + 0, + benunit("pension_credit_assessable_capital", period), + benunit("uc_assessable_capital", period), + 0, + ], + default=household_capital, ) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_home_letting_income.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_home_letting_income.py new file mode 100644 index 0000000000..07fb3c23c4 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_home_letting_income.py @@ -0,0 +1,39 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.dwp.legacy_benefits_home_letting_income import ( + home_letting_income, +) + + +class council_tax_reduction_home_letting_income(Variable): + value_type = float + entity = BenUnit + label = "Rent from letting part of the home counted for Council Tax Reduction" + documentation = ( + "Rent the Council Tax Reduction applicant and any partner " + "(is_council_tax_reduction_applicant_or_partner) receive for letting " + "part of the home they live in (sublet_income), after the weekly " + "sub-tenant disregard for one occupier. Where the household head " + "applies alone, the head is the applicant, so the head's own rent " + "counts and the benefit unit's claimant's and partner's does not. The " + "pension-age disregard applies where the applicant falls under the " + "pension-age scheme (council_tax_reduction_pensioner). " + "council_tax_reduction_applicable_income decides on which routes it " + "counts." + ) + definition_period = YEAR + unit = GBP + reference = [ + "https://www.legislation.gov.uk/uksi/2012/2885/regulation/2", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/11", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/16", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/5/paragraph/10", + ] + + def formula(benunit, period, parameters): + applicant_or_partner = benunit.members( + "is_council_tax_reduction_applicant_or_partner", period + ) + pensioner = benunit("council_tax_reduction_pensioner", period) + return home_letting_income( + benunit, period, parameters, applicant_or_partner, pensioner + ) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner.py index f070259c7d..49821a91ec 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner.py @@ -24,8 +24,10 @@ class council_tax_reduction_pensioner(Variable): "and each claims, a working-age family is assessed under the " "working-age rules even if the household head's family is " "pension-age, and the reverse. The shared applicable allowance uses " - "this test, as does English scheme selection; Welsh and Scottish " - "scheme selection retains its existing approximations." + "this test, as does English scheme selection, the choice between the " + "pensioner and working-age tariff income from capital, and the " + "Scottish income rules; Welsh and Scottish award formulas retain " + "their existing approximations." ) definition_period = YEAR reference = ( 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 new file mode 100644 index 0000000000..f69ff77239 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_tariff_income.py @@ -0,0 +1,143 @@ +from policyengine_uk.model_api import * +from policyengine_uk.variables.gov.local_authorities.council_tax_reduction.config import ( + is_scotland_scheme, + is_wales_scheme, +) +from policyengine_uk.variables.household.demographic.country import Country + + +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. + excess = max_(0, min_(capital, capital_limit) - tariff.threshold) + return np.ceil(excess / tariff.step) * tariff.amount + + +class council_tax_reduction_tariff_income(Variable): + value_type = float + entity = BenUnit + label = "Council Tax Reduction tariff income from capital" + documentation = ( + "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 " + "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 " + "Universal Credit assumed yield of £4.35 a month " + "for each £250, or part, over £6,000, which the Welsh scheme and the " + "Scottish scheme to March 2022 take from the Secretary of State's " + "assessment of income and the Scottish scheme from April 2022 sets at " + "the same rate. Nil for the Pension Credit routes, whose income " + "already includes the Pension Credit deemed income (or is wholly " + "disregarded), for people on Income Support, income-based " + "Jobseeker's Allowance or income-related Employment and Support " + "Allowance, whose whole capital the Welsh scheme and the Scottish " + "scheme to March 2022 disregard and whose income the Scottish scheme " + "from April 2022 does not assess, and for English people under " + "pension age, whose local schemes set their own tariff income." + ) + definition_period = YEAR + unit = GBP + reference = [ + "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/wsi/2013/3029/schedule/6/paragraph/9", + "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/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", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/13", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/63", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/72", + ] + + def formula(benunit, period, parameters): + local_authorities = parameters(period).gov.local_authorities + england_p = local_authorities.england.council_tax_reduction.pensioners + wales_p = local_authorities.wales.council_tax_reduction.means_test + scotland_p = local_authorities.scotland.council_tax_reduction.means_test + uc_tariff = parameters( + period + ).gov.dwp.universal_credit.means_test.capital.tariff_income + country = benunit.household("country", period) + england = country == Country.ENGLAND + wales = is_wales_scheme(country) + scotland = is_scotland_scheme(country) + capital = benunit("council_tax_reduction_assessable_capital", period) + pensioner_weekly = select( + [england, wales, scotland], + [ + tariff_amount( + capital, + england_p.means_test.tariff_income, + england_p.means_test.capital_limit, + ), + tariff_amount( + capital, + wales_p.tariff_income.pensioner, + wales_p.capital_limit, + ), + tariff_amount( + capital, + scotland_p.tariff_income.pensioner, + scotland_p.capital_limit, + ), + ], + default=0, + ) + working_age_weekly = select( + [wales, scotland], + [ + tariff_amount( + capital, + wales_p.tariff_income.working_age, + wales_p.capital_limit, + ), + tariff_amount( + capital, + scotland_p.tariff_income.working_age, + scotland_p.capital_limit, + ), + ], + default=0, + ) + universal_credit_monthly = select( + [wales, scotland], + [ + tariff_amount(capital, uc_tariff, wales_p.capital_limit), + tariff_amount(capital, uc_tariff, scotland_p.capital_limit), + ], + default=0, + ) + pensioner = benunit("council_tax_reduction_pensioner", period) + # An award of Universal Credit, including one the benefit cap or + # deductions reduce to nil, selects the UC assumed yield. + universal_credit_award = benunit( + "council_tax_reduction_universal_credit_award", period + ) + income_based_benefit = benunit( + "council_tax_reduction_relevant_income_based_benefit", period + ) + tariff_income = select( + [pensioner, universal_credit_award, income_based_benefit], + [ + pensioner_weekly * WEEKS_IN_YEAR, + universal_credit_monthly * MONTHS_IN_YEAR, + 0, + ], + default=working_age_weekly * WEEKS_IN_YEAR, + ) + # The benefit unit's Pension Credit is its claimant's and partner's, not + # a household head's who applies alone + # (council_tax_reduction_head_applies_alone). + 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) + ) + return where(pension_credit_route, 0, tariff_income) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_universal_credit_award.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_universal_credit_award.py new file mode 100644 index 0000000000..90c2faeb01 --- /dev/null +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/council_tax_reduction_universal_credit_award.py @@ -0,0 +1,41 @@ +from policyengine_uk.model_api import * + + +class council_tax_reduction_universal_credit_award(Variable): + value_type = bool + entity = BenUnit + label = "Council Tax Reduction applicant has an award of Universal Credit" + documentation = ( + "Whether the Council Tax Reduction applicant or partner has an award " + "of Universal Credit: Universal Credit is paid, or the family claims " + "it and is entitled before the benefit cap and deductions, which " + "reduce an award rather than end it (UC Regs 2013 reg 81; Oxford's " + "scheme, Appendix 3, covers applicants who would be awarded it but " + "for deductions). A supplied universal_credit amount counts as an " + "award. From 1 April 2025 the Scottish scheme also counts an award " + "reduced to zero by a sanction and one whose entitlement ended after " + "a nil award due to earnings but is treated as reclaimed (SSI " + "2021/249 reg 10A); neither is modelled. The benefit unit's award " + "belongs to its claimant and partner, " + "so it is not the applicant's where the household head applies " + "alone. The schemes' working-age Universal Credit rules (the " + "Secretary of State's assessments of income and capital, and the " + "Universal Credit assumed yield) apply only to an applicant who is " + "not a pensioner (council_tax_reduction_pensioner)." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/regulation/81", + "https://www.legislation.gov.uk/uksi/2012/2886/schedule/paragraph/37", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/6/paragraph/9", + "https://www.legislation.gov.uk/ssi/2012/303/regulation/26", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/10A", + ) + + def formula(benunit, period, parameters): + paid = benunit("universal_credit", period) > 0 + entitled_claimant = benunit("claims_universal_credit", period) & benunit( + "is_uc_entitled", period + ) + head_applies_alone = benunit("council_tax_reduction_head_applies_alone", period) + return (paid | entitled_claimant) & ~head_applies_alone diff --git a/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py index 0a37929f95..4dfe07ca1c 100644 --- a/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py +++ b/policyengine_uk/variables/gov/local_authorities/kingston_upon_thames/council_tax_reduction/kingston_upon_thames_council_tax_reduction.py @@ -27,7 +27,7 @@ def formula(benunit, period, parameters): benunit("council_tax_reduction_pensioner", period), ) has_uc_award = applicant_has_universal_credit(benunit, period) - capital = household("savings", period) + capital = benunit("council_tax_reduction_assessable_capital", period) weekly_tariff_income = np.ceil( max_(0, capital - ctr.means_test.tariff_income_threshold) / ctr.means_test.tariff_income_step diff --git a/policyengine_uk/variables/gov/local_authorities/oxford/council_tax_reduction/oxford_council_tax_reduction.py b/policyengine_uk/variables/gov/local_authorities/oxford/council_tax_reduction/oxford_council_tax_reduction.py index 274ffa526f..0cee17202c 100644 --- a/policyengine_uk/variables/gov/local_authorities/oxford/council_tax_reduction/oxford_council_tax_reduction.py +++ b/policyengine_uk/variables/gov/local_authorities/oxford/council_tax_reduction/oxford_council_tax_reduction.py @@ -14,6 +14,10 @@ class oxford_council_tax_reduction(Variable): label = "Oxford Council Tax Reduction" definition_period = YEAR unit = GBP + reference = ( + "https://www.oxford.gov.uk/council-tax-reduction/council-tax-reduction-scheme-2026-27", + "https://www.oxford.gov.uk/council-tax-reduction/council-tax-reduction-scheme-2026-27/4", + ) def formula(benunit, period, parameters): ctr = parameters(period).gov.local_authorities.oxford.council_tax_reduction @@ -27,9 +31,23 @@ def formula(benunit, period, parameters): "council_tax_reduction_claimant_benunit", period ) would_claim = benunit("would_claim_council_tax_reduction", period) + # Appendix 3 covers applicants awarded Universal Credit, or who would + # be but for deductions or other adjustments to the award. has_uc_award = applicant_has_universal_credit(benunit, period) - capital = household("savings", period) + relevant_income_based_benefit = benunit( + "council_tax_reduction_relevant_income_based_benefit", + period, + ) + # Scheme paragraphs 28-29 apply the limit to capital not ignored by + # Appendix 6, which ignores capital already taken into account for + # Universal Credit, Income Support, income-based Jobseeker's Allowance + # or income-related Employment and Support Allowance. + capital = where( + has_uc_award | relevant_income_based_benefit, + 0, + benunit("council_tax_reduction_assessable_capital", period), + ) capital_eligible = capital <= ctr.means_test.capital_limit weekly_tariff_income = np.ceil( max_(0, capital - ctr.means_test.tariff_income_threshold) @@ -44,10 +62,6 @@ def formula(benunit, period, parameters): ) weekly_income = max_(0, annual_income - child_benefit) / WEEKS_IN_YEAR weekly_income += where(has_uc_award, 0, weekly_tariff_income) - relevant_income_based_benefit = benunit( - "council_tax_reduction_relevant_income_based_benefit", - period, - ) weekly_income = where( relevant_income_based_benefit & ~has_uc_award, 0, weekly_income ) diff --git a/policyengine_uk/variables/gov/local_authorities/westminster/council_tax_reduction/westminster_council_tax_reduction.py b/policyengine_uk/variables/gov/local_authorities/westminster/council_tax_reduction/westminster_council_tax_reduction.py index 6eaa8c1d74..597554d737 100644 --- a/policyengine_uk/variables/gov/local_authorities/westminster/council_tax_reduction/westminster_council_tax_reduction.py +++ b/policyengine_uk/variables/gov/local_authorities/westminster/council_tax_reduction/westminster_council_tax_reduction.py @@ -25,7 +25,7 @@ def formula(benunit, period, parameters): benunit("council_tax_reduction_pensioner", period), ) has_uc_award = applicant_has_universal_credit(benunit, period) - capital = household("savings", period) + capital = benunit("council_tax_reduction_assessable_capital", period) weekly_tariff_income = np.ceil( max_(0, capital - ctr.means_test.tariff_income_threshold) / ctr.means_test.tariff_income_step