diff --git a/changelog.d/2011.fixed.md b/changelog.d/2011.fixed.md new file mode 100644 index 0000000000..de593718fe --- /dev/null +++ b/changelog.d/2011.fixed.md @@ -0,0 +1 @@ +The LHA size criteria now count other families' children, give foster children no bedroom of their own and add the foster-parent, adopter and overnight-care bedrooms (UC Regs 2013 Sch 4 paras 9-12 and 29(9A); HB Regs 2006 reg 13D(3)-(3B)), with new inputs for adoption placements, foster parents between placements, non-resident overnight carers and adopters who are a foster parent or close relative of the child (UC reg 89(3)(a)). Housing Benefit counts a child placed with a non-dependant, boarder or lodger in the claimant's size criteria (reg 21(3) names only the claimant or partner), and the legacy household, Income Support (Sch 1B paras 2 and 2A) and Tax-Free Childcare leave out a child placed for adoption. diff --git a/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_benefits.yaml b/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_benefits.yaml new file mode 100644 index 0000000000..a3b58e7ebd --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_benefits.yaml @@ -0,0 +1,19 @@ +description: Disability benefits whose recipients, if non-resident carers regularly stay overnight to care for them, give an additional bedroom in the LHA size criteria. The law also lists the Scottish devolved equivalents (child disability payment, adult disability payment, Scottish adult disability living allowance, pension age disability payment), which the model has no variables for. +values: + 2011-04-01: + - attendance_allowance + - armed_forces_independence_payment + - dla_sc_middle_plus + - pip_dl +metadata: + unit: list + label: LHA overnight care qualifying benefits + reference: + - title: Universal Credit Regulations 2013 Sch 4 para 12(3)(a) + href: https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12 + - title: Universal Credit Regulations 2013 reg 2, "attendance allowance" (includes armed forces independence payment) + href: https://www.legislation.gov.uk/uksi/2013/376/regulation/2 + - title: Housing Benefit Regulations 2006 reg 2(1), "person who requires overnight care" + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/2 + - title: Housing Benefit (State Pension Credit) Regulations 2006 reg 2(1), "person who requires overnight care" + href: https://www.legislation.gov.uk/uksi/2006/214/regulation/2 diff --git a/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_beyond_claimant.yaml b/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_beyond_claimant.yaml new file mode 100644 index 0000000000..d8628e728f --- /dev/null +++ b/policyengine_uk/parameters/gov/dwp/LHA/overnight_care_beyond_claimant.yaml @@ -0,0 +1,14 @@ +description: Whether the overnight care additional bedroom in the LHA size criteria covers people other than the renter or claimant and partner, such as non-dependants, other occupiers and foster children. +values: + 2011-04-01: false + 2017-04-01: true +metadata: + unit: bool + label: LHA overnight care covers the household + reference: + - title: Housing Benefit and Universal Credit (Size Criteria) (Miscellaneous Amendments) Regulations 2017 (SI 2017/213) regs 4 and 6 + href: https://www.legislation.gov.uk/uksi/2017/213/made + - title: Universal Credit Regulations 2013 Sch 4 para 12(A1) + href: https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12 + - title: Housing Benefit Regulations 2006 reg 13D(3A)(a) + href: https://www.legislation.gov.uk/uksi/2006/213/regulation/13D diff --git a/policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_exception_benefits.yaml b/policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_exception_benefits.yaml index 9f9765f986..380f03e66e 100644 --- a/policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_exception_benefits.yaml +++ b/policyengine_uk/parameters/gov/dwp/LHA/shared_accommodation_exception_benefits.yaml @@ -1,10 +1,10 @@ -description: Disability benefits whose recipients under 35 are excepted from the Universal Credit shared accommodation rate. +description: Disability benefits whose recipients under 35 are excepted from the Universal Credit shared accommodation rate. The law also lists the Scottish devolved equivalents (child disability payment, adult disability payment, Scottish adult disability living allowance), which the model has no variables for. values: 2013-04-29: - attendance_allowance + - armed_forces_independence_payment - dla_sc_middle_plus - pip_dl - - armed_forces_independence_payment metadata: unit: list label: Universal Credit shared accommodation rate disability exceptions diff --git a/policyengine_uk/parameters/household/demographic/looked_after_child_age_limit.yaml b/policyengine_uk/parameters/household/demographic/looked_after_child_age_limit.yaml new file mode 100644 index 0000000000..20223de340 --- /dev/null +++ b/policyengine_uk/parameters/household/demographic/looked_after_child_age_limit.yaml @@ -0,0 +1,11 @@ +description: Age below which a person can be a child looked after by a local authority, and so a foster child. +values: + 2010-01-01: 18 +metadata: + unit: year + label: looked-after child age limit + reference: + - title: Children Act 1989 s.22(1) (a child who is looked after by a local authority) and s.105(1) ("child" means a person under the age of eighteen) + href: https://www.legislation.gov.uk/ukpga/1989/41/section/105 + - title: Universal Credit Regulations 2013 reg 2, "foster parent" and "looked after by a local authority" + href: https://www.legislation.gov.uk/uksi/2013/376/regulation/2 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_other_families_children_and_additional_bedrooms.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_other_families_children_and_additional_bedrooms.yaml new file mode 100644 index 0000000000..c52261f487 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_other_families_children_and_additional_bedrooms.yaml @@ -0,0 +1,1548 @@ +# Who counts in the LHA size criteria beyond the claimant's own family, and +# the additional bedrooms for foster parents and overnight care. +# +# Universal Credit (UC Regs 2013 Sch 4): the renter's extended benefit unit is +# the renter, the children and qualifying young persons they are responsible +# for, and their non-dependants (para 9(1)). A non-dependant is anyone who +# normally lives with the renter except, among others, a foster child of the +# renter (9(2)(c), 9(3)), a person liable to pay for their occupation on a +# commercial basis such as a lodger (9(2)(d)), and a child or qualifying young +# person no one in the extended benefit unit is responsible for (9(2)(g)). A +# non-dependant's own child is their responsibility (reg 4(2)), so is a +# non-dependant too, and counts as a child in para 10(1)(d)-(f). No one is +# responsible for a child looked after by a local authority (reg 4(6)(a)), +# except a child placed for adoption (reg 4A(1)(c)). Para 12 gives one +# additional bedroom for each of the overnight care condition and the foster +# parent condition (12(9)). +# +# Housing Benefit (HB Regs 2006 and HB (SPC) Regs 2006 reg 13D): one bedroom +# for each category of "occupier", everyone who occupies the dwelling as +# their home except a joint tenant outside the claimant's household (13D(12)), +# so the children of a non-dependant, boarder or lodger count. A child or +# young person placed with the claimant or partner as a foster child or for +# adoption does not occupy the claimant's dwelling (reg 21(3)); the claimant +# is then a "qualifying parent or carer" (reg 2(1)) with one additional +# bedroom (13D(3A)(b)), and one more for overnight care (13D(3A)(a), (3B)). +# Every limb of reg 21(3) names a placement "with the claimant or his +# partner", so a child placed with a non-dependant, boarder or lodger +# occupies the claimant's dwelling (13D(12)): they count in the claimant's +# size criteria and, if they require overnight care, under 13D(3A)(a)(iii). +# The carer's own claim leaves them out and has the qualifying parent or +# carer's room. +# +# DWP guidance: ADM F3016, F3034, F3111-F3112, F3131-F3138; LHA Guidance +# Manual (April 2014) paras 2.030-2.031, 2.090, 2.093; HB/CTB circular A4/2012 +# paras 36-38 and 44. +# +# Rents of £200 a week (£10,400 a year) sit between the published Maidstone +# one-bedroom (B) and two-bedroom (C) rates (VOA, LHA April 2024, held for +# 2025-26: B £172.60, C £208.27 a week), so where the category is C the rent +# is met in full. + +- name: A non-dependant's child of the opposite sex needs a bedroom of their own + period: 2026 + input: + people: + renter: + age: 48 + is_household_head: true + is_male: false + son: + age: 12 + is_male: true + daughter: + age: 24 + is_male: false + granddaughter: + age: 11 + is_male: false + benunits: + renter_family: + members: [renter, son] + daughter_family: + members: [daughter, granddaughter] + households: + home: + members: [renter, son, daughter, granddaughter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_non_dependant_of_household_head: [false, false, true, true] + # UC: the renter (para 10(1)(a)), the daughter (10(1)(c)), and the son + # and the granddaughter, who are of opposite sexes and over 10 (10(1)(f)): + # 4 bedrooms. The daughter's own entitlement counts her and her child. + LHA_allowed_bedrooms: [4, 2] + LHA_category: [E, C] + # HB: the claimant, the daughter and the two children: the same four + # occupiers' categories (reg 13D(3)(b), (e)). + housing_benefit_LHA_allowed_bedrooms: [4, 2] + housing_benefit_LHA_category: [E, C] + +- name: A non-dependant's child shares with the renter's child of the same sex + period: 2026 + input: + people: + renter: + age: 48 + is_household_head: true + is_male: false + son: + age: 12 + is_male: true + daughter: + age: 24 + is_male: false + grandson: + age: 8 + is_male: true + benunits: + renter_family: + members: [renter, son] + daughter_family: + members: [daughter, grandson] + households: + home: + members: [renter, son, daughter, grandson] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # The son and the grandson share (UC para 10(1)(e); HB reg 13D(3)(c)): + # 3 bedrooms, the same as without the grandson. + LHA_allowed_bedrooms: [3, 2] + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: A non-dependant's two children under 10 share one bedroom + period: 2026 + input: + people: + renter: + age: 55 + is_household_head: true + daughter: + age: 27 + is_male: false + grandson: + age: 6 + is_male: true + granddaughter: + age: 4 + is_male: false + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, grandson, granddaughter] + households: + home: + members: [renter, daughter, grandson, granddaughter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the renter, the daughter (para 10(1)(c)) and the two grandchildren + # under 10 (10(1)(d)): 3 bedrooms, category D. + LHA_allowed_bedrooms: [3, 2] + LHA_category: [D, C] + # HB: the claimant, the daughter (reg 13D(3)(b)) and the two + # grandchildren ((d)). + housing_benefit_LHA_allowed_bedrooms: [3, 2] + housing_benefit_LHA_category: [D, C] + +- name: A non-dependant couple has a bedroom each under Universal Credit but one between them under Housing Benefit + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + son: + age: 30 + sons_partner: + age: 29 + benunits: + renter_family: + members: [renter] + son_family: + members: [son, sons_partner] + households: + home: + members: [renter, son, sons_partner] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: each is "a non-dependant who is not a child" (para 10(1)(c); ADM + # F3112 note 1): 3 bedrooms. + LHA_allowed_bedrooms: [3, 1] + # HB: the occupier couple is one category, "a couple" (reg 13D(3)(a); + # LHA Guidance Manual para 2.012): 2 bedrooms. + housing_benefit_LHA_allowed_bedrooms: [2, 1] + +- name: A lodger's child counts for Housing Benefit but not Universal Credit + period: 2026 + input: + people: + householder: + age: 60 + is_household_head: true + lodger: + age: 30 + rent_paid_as_lodger: 5_000 + lodgers_child: + age: 5 + benunits: + householder_family: + members: [householder] + lodger_family: + members: [lodger, lodgers_child] + households: + home: + members: [householder, lodger, lodgers_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_non_dependant_of_household_head: [false, false, false] + # UC: the lodger is liable to pay on a commercial basis (para 9(2)(d)), + # so is not in the householder's extended benefit unit, and the lodger's + # child is excluded by para 9(2)(g): the householder's bedroom only. + LHA_allowed_bedrooms: [1, 2] + # HB: the lodger and the lodger's child occupy the dwelling as their home + # (reg 13D(12); LHA Guidance Manual para 2.030; circular A4/2012 para + # 44): 3 bedrooms. The lodger's own claim counts their own family. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: A joint tenant's child does not count for the other joint tenant + period: 2026 + input: + people: + tenant_1: + age: 40 + is_household_head: true + tenant_2: + age: 38 + tenant_2_child: + age: 7 + benunits: + family_1: + members: [tenant_1] + family_2: + members: [tenant_2, tenant_2_child] + liable_for_share_of_household_rent: true + households: + home: + members: [tenant_1, tenant_2, tenant_2_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # A joint tenant outside the claimant's household is not an occupier (HB + # reg 13D(12)), and in the private sector each joint tenant's size + # criteria count only their own household (LHA Guidance Manual para + # 2.093; HB circular A21/2013 para 25). Under UC they are liable for + # their occupation (para 9(2)(d)), so neither they nor their children are + # in the other tenant's extended benefit unit. + LHA_allowed_bedrooms: [1, 2] + housing_benefit_LHA_allowed_bedrooms: [1, 2] + +- name: A non-dependant's foster child counts for the renter under Housing Benefit only + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + daughter: + age: 32 + is_male: false + foster_child: + age: 6 + is_looked_after_by_local_authority: true + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, foster_child] + households: + home: + members: [renter, daughter, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: no one in the renter's extended benefit unit is responsible for a + # looked-after child (reg 4(6)(a)), so the child is not a non-dependant + # (para 9(2)(g)): the renter and the daughter, 2 bedrooms. + LHA_allowed_bedrooms: [2, 2] + # HB: reg 21(3) takes out only a child placed with the claimant or + # partner, so the child placed with the daughter occupies the renter's + # dwelling as their home (13D(12)): the renter (13D(3)(b)), the daughter + # ((b)) and the child ((e)), 3 bedrooms. The daughter's own claim leaves + # the child out (reg 21(3)(a)) and has the qualifying parent or carer's + # additional bedroom (13D(3A)(b)): 1 + 1 = 2. The UC daughter's room is + # the foster parent condition's (para 12(4)(a)). + housing_benefit_LHA_allowed_bedrooms: [3, 2] + LHA_additional_bedrooms: [0, 1] + housing_benefit_LHA_additional_bedrooms: [0, 1] + +- name: Foster children have no bedrooms of their own; the foster parent has one additional bedroom + period: 2026 + input: + people: + foster_parent: + age: 45 + is_household_head: true + foster_son: + age: 12 + is_male: true + is_looked_after_by_local_authority: true + foster_daughter: + age: 11 + is_male: false + is_looked_after_by_local_authority: true + benunits: + family: + members: [foster_parent, foster_son, foster_daughter] + households: + home: + members: [foster_parent, foster_son, foster_daughter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_child_or_qualifying_young_person_for_universal_credit: [false, false, false] + is_child_or_young_person_placed_with_family: [false, true, true] + # UC: foster children are in no one's extended benefit unit (paras 9(1), + # 9(2)(c), 9(3); reg 4(6)(a)); the renter is a foster parent with one + # additional bedroom however many children are placed (para 12(4)(a), + # (9)(b); ADM F3138 example 2): 2 bedrooms, category C. + lha_renter_meets_foster_parent_condition: true + LHA_additional_bedrooms: 1 + LHA_allowed_bedrooms: 2 + LHA_category: C + # HB: the foster children, placed with the claimant, do not occupy the + # claimant's dwelling (reg 21(3)(a)); the claimant is a qualifying parent + # or carer (reg 2(1)) with one additional bedroom (reg 13D(3A)(b)). + is_housing_benefit_qualifying_parent_or_carer: true + housing_benefit_LHA_additional_bedrooms: 1 + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + uc_housing_costs_element: 10_400 + +- name: A couple fostering a child alongside their own child + period: 2026 + input: + people: + parent_1: + age: 38 + is_household_head: true + is_parent: true + parent_2: + age: 36 + is_parent: true + son: + age: 12 + is_male: true + foster_daughter: + age: 11 + is_male: false + is_looked_after_by_local_authority: true + benunits: + family: + members: [parent_1, parent_2, son, foster_daughter] + households: + home: + members: [parent_1, parent_2, son, foster_daughter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_claimant_or_partner: [true, true, false, false] + # UC: the couple, their son (para 10(1)(f)), and the foster parent's + # additional bedroom (para 12(9)(b)): 3 bedrooms. Counted as a child of + # the extended benefit unit, the foster daughter (11) could not share + # with the son (12) and would add a fourth. + LHA_allowed_bedrooms: 3 + LHA_category: D + # HB: the couple, the son (reg 13D(3)(e)) and the qualifying parent or + # carer's bedroom (13D(3A)(b)). + housing_benefit_LHA_allowed_bedrooms: 3 + housing_benefit_LHA_category: D + +- name: A single foster parent under 35 is not restricted to the shared accommodation rate + period: 2026 + input: + people: + foster_parent: + age: 28 + is_household_head: true + foster_child: + age: 7 + is_looked_after_by_local_authority: true + benunits: + family: + members: [foster_parent, foster_child] + households: + home: + members: [foster_parent, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: not responsible for the foster child (reg 4(6)(a)), who is not a + # non-dependant (para 9(2)(c)), but excepted as a renter who satisfies + # the foster parent condition (para 29(9A)). + is_responsible_for_child_or_young_person_for_uc_or_housing_benefit: false + lha_renter_has_non_dependant: false + is_lha_shared_accommodation_rate_specified_renter: false + LHA_allowed_bedrooms: 2 + LHA_category: C + # HB: a single claimant under 35, but a qualifying parent or carer is not + # a young individual (reg 2(1)). + is_housing_benefit_young_individual: false + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + +- name: An approved foster parent between placements keeps the additional bedroom + period: 2026 + input: + people: + foster_parent: + age: 30 + is_household_head: true + is_approved_foster_parent_without_placement: true + benunits: + family: + members: [foster_parent] + households: + home: + members: [foster_parent] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC Sch 4 para 12(5); HB reg 2(1), "qualifying parent or carer" (b). + lha_renter_meets_foster_parent_condition: true + is_lha_shared_accommodation_rate_specified_renter: false + LHA_allowed_bedrooms: 2 + LHA_category: C + is_housing_benefit_qualifying_parent_or_carer: true + is_housing_benefit_young_individual: false + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + uc_housing_costs_element: 10_400 + +- name: A child placed for adoption counts under Universal Credit but not Housing Benefit + period: 2026 + input: + people: + adopter: + age: 40 + is_household_head: true + child: + age: 4 + is_placed_for_adoption: true + benunits: + family: + members: [adopter, child] + households: + home: + members: [adopter, child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the adopter is responsible for the child (reg 4A(1)(c), from 1 + # April 2024), who has a bedroom (para 10(1)(f)), and as an adopter with + # whom a child is placed meets the foster parent condition (para + # 12(4)(b); ADM F3133): 3 bedrooms. + is_child_or_qualifying_young_person_for_universal_credit: [false, true] + lha_renter_meets_foster_parent_condition: true + LHA_allowed_bedrooms: 3 + LHA_category: D + # HB: the child is not a member of the household nor an occupier (reg + # 21(3)(b)-(c)); the adopter is a qualifying parent or carer: 2 bedrooms. + is_child_or_young_person_for_legacy_benefits: [false, false] + is_child_or_young_person_placed_with_family: [false, true] + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + +- name: A disabled renter with a non-resident overnight carer has an additional bedroom + period: 2026 + input: + people: + renter: + age: 62 + is_household_head: true + attendance_allowance: 5_000 + has_non_resident_overnight_carer: true + benunits: + family: + members: [renter] + households: + home: + members: [renter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC Sch 4 para 12(A1)(a), (3) (ADM F3132 example 1); HB reg + # 13D(3A)(a)(i). + meets_lha_overnight_care_condition: true + LHA_additional_bedrooms: 1 + LHA_allowed_bedrooms: 2 + LHA_category: C + housing_benefit_LHA_additional_bedrooms: 1 + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + uc_housing_costs_element: 10_400 + +- name: A disability benefit without a non-resident overnight carer gives no additional bedroom + period: 2026 + input: + people: + renter: + age: 50 + is_household_head: true + pip_dl: 5_000 + partner: + age: 49 + benunits: + couple: + members: [renter, partner] + households: + home: + members: [renter, partner] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # The carer must not live in the home (UC para 12(3)(b); ADM F3132 + # example 3; HB reg 2(1), "person who requires overnight care" (b)). + meets_lha_overnight_care_condition: [false, false] + LHA_additional_bedrooms: 0 + LHA_allowed_bedrooms: 1 + housing_benefit_LHA_allowed_bedrooms: 1 + +- name: Overnight care for a non-dependant gives the renter an additional bedroom + period: 2026 + input: + people: + renter: + age: 58 + is_household_head: true + son: + age: 30 + pip_dl: 5_000 + has_non_resident_overnight_carer: true + benunits: + renter_family: + members: [renter] + son_family: + members: [son] + households: + home: + members: [renter, son] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the son is a non-dependant (para 9(2)), in the renter's extended + # benefit unit, and meets the overnight care condition (para + # 12(A1)(b)): the renter, the son and the carer's room, 3 bedrooms. + LHA_additional_bedrooms: [1, 1] + LHA_allowed_bedrooms: [3, 2] + # HB: an occupier other than the claimant or partner who requires + # overnight care (reg 13D(3A)(a)(iii)). + housing_benefit_LHA_additional_bedrooms: [1, 1] + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: Two people needing overnight care give one additional bedroom + period: 2026 + input: + people: + partner_1: + age: 55 + is_household_head: true + dla_sc_middle_plus: true + has_non_resident_overnight_carer: true + partner_2: + age: 54 + dla_sc_middle_plus: true + has_non_resident_overnight_carer: true + benunits: + couple: + members: [partner_1, partner_2] + households: + home: + members: [partner_1, partner_2] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC para 12(9)(a) (ADM F3138 example 1); HB reg 13D(3A)(a). + LHA_additional_bedrooms: 1 + LHA_allowed_bedrooms: 2 + housing_benefit_LHA_additional_bedrooms: 1 + housing_benefit_LHA_allowed_bedrooms: 2 + +- name: Foster parents one of whom needs overnight care have two additional bedrooms + period: 2026 + input: + people: + parent_1: + age: 44 + is_household_head: true + attendance_allowance: 5_000 + has_non_resident_overnight_carer: true + parent_2: + age: 42 + foster_child_1: + age: 9 + is_looked_after_by_local_authority: true + foster_child_2: + age: 6 + is_looked_after_by_local_authority: true + benunits: + family: + members: [parent_1, parent_2, foster_child_1, foster_child_2] + households: + home: + members: [parent_1, parent_2, foster_child_1, foster_child_2] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_claimant_or_partner: [true, true, false, false] + # UC para 12(9)(a)-(b) (ADM F3138 example 2): the couple's bedroom and + # one for each condition, 3 bedrooms. + LHA_additional_bedrooms: 2 + LHA_allowed_bedrooms: 3 + # HB reg 13D(3B): two additional bedrooms where 13D(3A)(a) and (b) both + # apply. + housing_benefit_LHA_additional_bedrooms: 2 + housing_benefit_LHA_allowed_bedrooms: 3 + +- name: A single Housing Benefit claimant under 35 who needs overnight care is not a young individual + period: 2026 + input: + people: + claimant: + age: 25 + is_household_head: true + pip_dl: 5_000 + has_non_resident_overnight_carer: true + benunits: + family: + members: [claimant] + households: + home: + members: [claimant] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # HB Regs 2006 reg 2(1), "young individual": not one who requires + # overnight care. One bedroom plus the carer's. + is_housing_benefit_young_individual: false + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + # UC: excepted from shared accommodation by the daily living component + # (para 29(5)); 2 bedrooms with the carer's. + is_lha_shared_accommodation_rate_specified_renter: false + LHA_allowed_bedrooms: 2 + LHA_category: C + +- name: An armed forces independence payment excepts a renter under 35 from the shared accommodation rate + period: 2026 + input: + people: + renter: + age: 30 + is_household_head: true + armed_forces_independence_payment: 8_000 + benunits: + family: + members: [renter] + households: + home: + members: [renter] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC Sch 4 para 29(5)(b): attendance allowance, which includes armed + # forces independence payment (reg 2). + is_lha_shared_accommodation_rate_specified_renter: false + LHA_category: B + +- name: A lodger flagged as a couple without a partner still counts as one occupier + period: 2026 + input: + people: + householder: + age: 55 + is_household_head: true + lodger: + age: 40 + rent_paid_as_lodger: 3_000 + benunits: + householder_family: + members: [householder] + lodger_family: + members: [lodger] + relation_type: COUPLE + households: + home: + members: [householder, lodger] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # HB: the lodger is "a person who is not a child" (reg 13D(3)(b)); the + # couple rule (a) needs two members, so no half room: 2 bedrooms. The + # lodger, entitled to one bedroom without exclusive use of the + # accommodation, has the shared rate (reg 13D(2)(a)(ii)). + housing_benefit_LHA_allowed_bedrooms: [2, 1] + housing_benefit_LHA_category: [C, A] + +- name: A looked-after 17-year-old not in education is the renter's foster child under Universal Credit + period: 2026 + input: + people: + renter: + age: 40 + is_household_head: true + young_person: + age: 17 + current_education: NOT_IN_EDUCATION + is_looked_after_by_local_authority: true + benunits: + family: + members: [renter, young_person] + households: + home: + members: [renter, young_person] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: a person under 18 placed with the renter by a local authority + # makes the renter a foster parent (reg 2) and is their foster child + # (para 9(2)(c), 9(3); see is_lha_foster_child): no bedroom of their own, + # one foster room: 2. (Read as under 16, they would be a non-dependant + # with a bedroom and there would be no foster room: also 2.) + is_lha_foster_child: [false, true] + LHA_additional_bedrooms: 1 + LHA_allowed_bedrooms: 2 + # HB: not a "young person" (reg 19), so reg 21(3) does not apply: an + # occupier aged 16 or over with a bedroom, and no qualifying parent or + # carer room: 2. + is_child_or_young_person_placed_with_family: [false, false] + housing_benefit_LHA_additional_bedrooms: 0 + housing_benefit_LHA_allowed_bedrooms: 2 + +- name: A looked-after 17-year-old placed with a non-dependant + period: 2026 + input: + people: + renter: + age: 50 + is_household_head: true + daughter: + age: 35 + is_male: false + young_person: + age: 17 + current_education: NOT_IN_EDUCATION + is_looked_after_by_local_authority: true + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, young_person] + households: + home: + members: [renter, daughter, young_person] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: for the renter, the 17-year-old is neither a child nor a qualifying + # young person, so para 9(2)(g) does not exclude them, and they are not + # the renter's foster child: renter, daughter and young person, 3. The + # daughter's own size criteria: herself and the foster room, 2. + LHA_allowed_bedrooms: [3, 2] + # HB: not a "young person" (reg 19), so an occupier: 3. The daughter's + # own: 1 + the 17-year-old (13D(3)(b)) = 2; no carer room, since reg + # 21(3) does not apply. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: A foster child who needs overnight care gives the overnight and the foster bedrooms + period: 2026 + input: + people: + foster_parent: + age: 40 + is_household_head: true + foster_child: + age: 8 + is_looked_after_by_local_authority: true + dla_sc_middle_plus: true + has_non_resident_overnight_carer: true + benunits: + family: + members: [foster_parent, foster_child] + households: + home: + members: [foster_parent, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC para 12(A1)(c), (9)(a)-(b); HB reg 13D(3A)(a)(iv), (3B). + LHA_additional_bedrooms: 2 + LHA_allowed_bedrooms: 3 + housing_benefit_LHA_additional_bedrooms: 2 + housing_benefit_LHA_allowed_bedrooms: 3 + +- name: A looked-after qualifying young person who needs overnight care + period: 2026 + input: + people: + carer: + age: 40 + is_household_head: true + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + is_looked_after_by_local_authority: true + dla_sc_middle_plus: true + has_non_resident_overnight_carer: true + benunits: + family: + members: [carer, young_person] + households: + home: + members: [carer, young_person] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_qualifying_young_person_for_universal_credit: [false, true] + is_child_or_qualifying_young_person_for_universal_credit: [false, false] + # UC: the young person is the renter's foster child (under 18), so their + # overnight care counts under para 12(A1)(c): foster and overnight rooms, + # 3. + LHA_additional_bedrooms: 2 + LHA_allowed_bedrooms: 3 + # HB: placed under reg 21(3), so not an occupier, but within + # 13D(3A)(a)(iv); with the qualifying parent or carer room, (3B): 3. + housing_benefit_LHA_additional_bedrooms: 2 + housing_benefit_LHA_allowed_bedrooms: 3 + +- name: A lodger who needs overnight care counts for Housing Benefit only + period: 2026 + input: + people: + householder: + age: 60 + is_household_head: true + lodger: + age: 45 + rent_paid_as_lodger: 5_000 + pip_dl: 5_000 + has_non_resident_overnight_carer: true + benunits: + householder_family: + members: [householder] + lodger_family: + members: [lodger] + households: + home: + members: [householder, lodger] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the lodger is outside the extended benefit unit (para 9(2)(d)): 1. + # HB: the lodger is an occupier (13D(3)(b)) who requires overnight care + # (13D(3A)(a)(iii)): 3. The lodger's own claim: 1 + carer room = 2. + LHA_allowed_bedrooms: [1, 2] + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: A joint tenant's overnight care counts only for that tenant + period: 2026 + input: + people: + tenant_1: + age: 40 + is_household_head: true + tenant_2: + age: 38 + pip_dl: 5_000 + has_non_resident_overnight_carer: true + benunits: + family_1: + members: [tenant_1] + family_2: + members: [tenant_2] + liable_for_share_of_household_rent: true + households: + home: + members: [tenant_1, tenant_2] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the joint tenant is not in the other's extended benefit unit (para + # 9(2)(d)). HB: 13D(3A)(a)(iii) says "a person ... who occupies the + # claimant's dwelling as their home", without the defined term + # "occupiers"; the model applies 13D(12)'s joint-tenant exclusion, as + # private-sector joint tenants' size criteria rest on each tenant's own + # household (HB circular A21/2013 para 25). + LHA_allowed_bedrooms: [1, 2] + housing_benefit_LHA_allowed_bedrooms: [1, 2] + +- name: A boarder couple with a child counts as two Housing Benefit bedrooms + period: 2026 + input: + people: + householder: + age: 60 + is_household_head: true + boarder: + age: 35 + rent_paid_as_boarder: 5_000 + boarders_partner: + age: 33 + boarders_child: + age: 4 + benunits: + householder_family: + members: [householder] + boarder_family: + members: [boarder, boarders_partner, boarders_child] + households: + home: + members: [householder, boarder, boarders_partner, boarders_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # HB: the householder, the boarder couple (13D(3)(a)) and the child: 3. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + LHA_allowed_bedrooms: [1, 2] + +- name: A non-dependant's child placed for adoption + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + daughter: + age: 30 + is_male: false + child: + age: 5 + is_placed_for_adoption: true + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, child] + households: + home: + members: [renter, daughter, child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: reg 4A(1)(c) makes the daughter responsible, so the child is in + # the renter's extended benefit unit: 3. The daughter's own: herself, the + # child and the adopter's room, 3. + LHA_allowed_bedrooms: [3, 3] + # HB: reg 21(3)(c) takes out only a child placed for adoption with the + # claimant or partner, so the child placed with the daughter occupies the + # renter's dwelling (13D(12)): the renter, the daughter and the child + # (13D(3)(b), (b), (e)), 3. The daughter's own: herself and the + # qualifying parent or carer room (13D(3A)(b)), 2. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: Five or more bedrooms map to the four-bedroom category + period: 2026 + input: + people: + renter: + age: 50 + is_household_head: true + is_approved_foster_parent_without_placement: true + non_dependant_1: + age: 30 + non_dependant_2: + age: 29 + non_dependant_3: + age: 40 + benunits: + renter_family: + members: [renter] + non_dependant_family_1: + members: [non_dependant_1, non_dependant_2] + non_dependant_family_2: + members: [non_dependant_3] + households: + home: + members: [renter, non_dependant_1, non_dependant_2, non_dependant_3] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the renter, three non-dependants and the foster room: 5, capped at + # category E (para 26). HB: the claimant, the couple (13D(3)(a)), the + # other non-dependant and the carer room: 4, E. + LHA_allowed_bedrooms: [5, 1, 1] + LHA_category: [E, B, B] + housing_benefit_LHA_allowed_bedrooms: [4, 1, 1] + housing_benefit_LHA_category: [E, B, B] + +- name: Before April 2017 a non-dependant's overnight care gave no additional bedroom + period: 2016 + input: + people: + renter: + age: 58 + is_household_head: true + son: + age: 30 + pip_dl: 5_000 + has_non_resident_overnight_carer: true + benunits: + renter_family: + members: [renter] + son_family: + members: [son] + households: + home: + members: [renter, son] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC Sch 4 para 12(A1)(b) and HB reg 13D(3A)(a)(iii) came in on 1 April + # 2017 (SI 2017/213); before then only the renter or claimant and + # partner counted. The son's own claim keeps his room. + LHA_additional_bedrooms: [0, 1] + LHA_allowed_bedrooms: [2, 2] + housing_benefit_LHA_additional_bedrooms: [0, 1] + housing_benefit_LHA_allowed_bedrooms: [2, 2] + +- name: A non-dependant's foster child who needs overnight care gives the renter a Housing Benefit overnight room + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + daughter: + age: 32 + is_male: false + foster_child: + age: 6 + is_looked_after_by_local_authority: true + dla_sc_middle_plus: true + has_non_resident_overnight_carer: true + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, foster_child] + households: + home: + members: [renter, daughter, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: the foster child is in no one's extended benefit unit but the + # foster parent's (para 9(2)(g); 12(A1)(c)), so the renter gets no + # overnight room: 2. The daughter: herself, the foster room and the + # overnight room, 3. + LHA_additional_bedrooms: [0, 2] + LHA_allowed_bedrooms: [2, 3] + # HB: the child, placed with the daughter and not with the renter (reg + # 21(3)), occupies the renter's dwelling, so is "a person (other than + # the claimant or the claimant's partner) who occupies the claimant's + # dwelling as their home" (13D(3A)(a)(iii)): the renter has the + # overnight room. Renter: 1 + daughter 1 + child 1 + overnight 1 = 4. + # The daughter's own claim: herself 1, the qualifying parent or carer + # room ((3A)(b)) and the overnight room for a child for whom she is a + # qualifying parent or carer ((3A)(a)(iv)), two together ((3B)): 3. + housing_benefit_LHA_additional_bedrooms: [1, 2] + housing_benefit_LHA_allowed_bedrooms: [4, 3] + +- name: A looked-after claimant aged 17 gives no foster room + period: 2026 + input: + people: + claimant: + age: 17 + is_household_head: true + is_claimant_or_partner: true + current_education: UPPER_SECONDARY + is_looked_after_by_local_authority: true + benunits: + family: + members: [claimant] + households: + home: + members: [claimant] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # The foster parent condition needs a child placed with the renter, not + # the renter's own status (UC reg 2; HB reg 2(1), reg 21(3)). + is_lha_foster_child: false + lha_renter_meets_foster_parent_condition: false + LHA_additional_bedrooms: 0 + is_child_or_young_person_placed_with_family: false + is_housing_benefit_qualifying_parent_or_carer: false + housing_benefit_LHA_additional_bedrooms: 0 + +- name: A person aged 18 cannot be looked after, so a single renter of 30 has a qualifying young person's bedroom + period: 2026 + input: + people: + renter: + age: 30 + is_household_head: true + is_parent: true + young_person: + age: 18 + current_education: UPPER_SECONDARY + is_looked_after_by_local_authority: true + benunits: + family: + members: [renter, young_person] + households: + home: + members: [renter, young_person] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Children Act 1989 ss.22(1) and 105(1): only a person under 18 is looked + # after. UC: the renter is responsible for the qualifying young person + # (reg 4(2)), who has a bedroom (para 10(1)(b)); not a specified renter + # (para 28(3)): 2, C. HB: a member of the household aged 16 or over + # (13D(3)(b)): 2, C. No foster or carer room. + is_looked_after_child: [false, false] + is_child_or_qualifying_young_person_for_universal_credit: [false, true] + is_lha_shared_accommodation_rate_specified_renter: false + LHA_additional_bedrooms: 0 + LHA_allowed_bedrooms: 2 + LHA_category: C + is_child_or_young_person_placed_with_family: [false, false] + housing_benefit_LHA_additional_bedrooms: 0 + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C + +- name: A non-dependant parent and adult son count one Housing Benefit bedroom each + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + is_claimant_or_partner: true + parent: + age: 50 + is_claimant_or_partner: true + son: + age: 22 + is_claimant_or_partner: false + benunits: + renter_family: + members: [renter] + parent_family: + members: [parent, son] + relation_type: SINGLE + households: + home: + members: [renter, parent, son] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Not a couple, so each is "a person who is not a child" (HB reg + # 13D(3)(b)): the renter's 3. The parent's own size criteria: themself + # and the son, 2. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + +- name: An explicit single relationship stops the Housing Benefit couple rule + period: 2026 + input: + people: + renter: + age: 60 + is_household_head: true + is_claimant_or_partner: true + adult_1: + age: 40 + is_claimant_or_partner: true + adult_2: + age: 38 + is_claimant_or_partner: true + benunits: + renter_family: + members: [renter] + other_family: + members: [adult_1, adult_2] + relation_type: SINGLE + households: + home: + members: [renter, adult_1, adult_2] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # With relation_type SINGLE the family is not a couple (is_couple), so + # reg 13D(3)(a) does not merge the two adults into one bedroom for the + # renter: 3. (The inputs flag both as claimant or partner, which a + # single family cannot have, so only the renter's figure is asserted.) + is_couple: [false, false] + benunits: + renter_family: + housing_benefit_LHA_allowed_bedrooms: 3 + +- name: A child placed with the claimant is not a Housing Benefit non-dependant + period: 2026 + input: + people: + carer: + age: 40 + is_household_head: true + foster_child: + age: 10 + is_looked_after_by_local_authority: true + adopted_child: + age: 4 + is_placed_for_adoption: true + benunits: + family: + members: [carer, foster_child, adopted_child] + households: + home: + members: [carer, foster_child, adopted_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Neither child is a member of the carer's household (HB reg 21(3)(a) + # and (c)), so neither is a child or young person of the family; reg + # 3(2)(c) still takes each out of "non-dependant": the carer has none. + is_child_or_young_person_for_legacy_benefits: [false, false, false] + is_child_or_young_person_placed_with_family: [false, true, true] + housing_benefit_has_non_dependant: false + +- name: A non-dependant's foster child raises the renter's final Housing Benefit + period: 2026 + absolute_error_margin: 0.01 + input: + people: + renter: + age: 60 + is_household_head: true + housing_benefit_reported: 1 + daughter: + age: 32 + is_male: false + employment_income: 20_000 + weekly_hours: 35 + foster_child: + age: 6 + is_looked_after_by_local_authority: true + benunits: + renter_family: + members: [renter] + claims_universal_credit: false + daughter_family: + members: [daughter, foster_child] + households: + home: + members: [renter, daughter, foster_child] + rent: 15_600 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Size criteria: the renter, the daughter and the child placed with her + # (reg 21(3) takes out only a child placed with the claimant or + # partner; 13D(12)), 3 bedrooms, category D. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + housing_benefit_LHA_category: [D, C] + # Maidstone D, £276.16 a week (the VOA April 2024 rates, frozen for 2026), + # below the £300 rent: 276.16 * 52 = 14,360.32. At two bedrooms the C + # rate, £208.27, would give 10,830.04. + LHA_cap: [14_360.32, 0] + # Non-dependant deduction: the daughter works 35 hours (16 or more, so + # in remunerative work) on £20,000, 20,000 / 52 = £384.62 a week, in the + # £365 to £485 band: £105.20 a week, 105.20 * 52 = 5,470.40. + housing_benefit_non_dep_deductions: [5_470.40, 0] + # The renter has no income, below the single person's applicable amount + # (aged 25 or over, £95.55 a week), so no taper: 14,360.32 - 5,470.40 = + # 8,889.92. At two bedrooms: 10,830.04 - 5,470.40 = 5,359.64, so the + # placed child adds 3,530.28 (67.89 a week * 52). + housing_benefit: [8_889.92, 0] + +- name: A non-dependant's child placed for adoption raises the renter's final Housing Benefit + period: 2026 + absolute_error_margin: 0.01 + input: + people: + renter: + age: 60 + is_household_head: true + housing_benefit_reported: 1 + daughter: + age: 32 + is_male: false + employment_income: 20_000 + weekly_hours: 35 + child: + age: 6 + is_placed_for_adoption: true + benunits: + renter_family: + members: [renter] + claims_universal_credit: false + daughter_family: + members: [daughter, child] + households: + home: + members: [renter, daughter, child] + rent: 15_600 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # As the foster case: reg 21(3)(c) takes out only a child placed for + # adoption with the claimant or partner, so the renter has 3 bedrooms + # and the daughter's own claim 2 (herself and the qualifying parent or + # carer room). HB: 276.16 * 52 - 105.20 * 52 = 14,360.32 - 5,470.40 = + # 8,889.92. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + housing_benefit: [8_889.92, 0] + # The renter does not claim Universal Credit; "A non-dependant's child + # placed for adoption" has the Universal Credit rooms, [3, 3]. + +- name: A looked-after young person of 17 placed with a non-dependant + period: 2026 + input: + people: + renter: + age: 50 + is_household_head: true + daughter: + age: 35 + is_male: false + young_person: + age: 17 + current_education: UPPER_SECONDARY + is_looked_after_by_local_authority: true + benunits: + renter_family: + members: [renter] + daughter_family: + members: [daughter, young_person] + households: + home: + members: [renter, daughter, young_person] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + is_child_or_young_person_placed_with_family: [false, false, true] + # HB: a young person (reg 19) placed with the daughter, not with the + # renter (reg 21(3)(a)), so an occupier of the renter's dwelling + # (13D(12)) and a person who is not a child (13D(3)(b)): renter 1 + + # daughter 1 + young person 1 = 3. The daughter's own: herself and the + # qualifying parent or carer room, 2. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + # UC: a qualifying young person no one is responsible for (reg 4(6)(a)) + # is not a non-dependant (para 9(2)(g)): renter 1 + daughter 1 = 2. The + # daughter's own: herself and the foster room, 2. + LHA_allowed_bedrooms: [2, 2] + +- name: A child placed with a lodger counts for the householder under Housing Benefit only + period: 2026 + input: + people: + householder: + age: 60 + is_household_head: true + lodger: + age: 30 + rent_paid_as_lodger: 5_000 + foster_child: + age: 5 + is_looked_after_by_local_authority: true + benunits: + householder_family: + members: [householder] + lodger_family: + members: [lodger, foster_child] + households: + home: + members: [householder, lodger, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # HB: the lodger and the child placed with the lodger occupy the + # householder's dwelling (13D(12); reg 21(3) takes out only a child + # placed with the claimant or partner): householder 1 + lodger 1 + + # child 1 = 3. The lodger's own claim: the lodger and the qualifying + # parent or carer room, 2. + housing_benefit_LHA_allowed_bedrooms: [3, 2] + # UC: the lodger is outside the householder's extended benefit unit + # (para 9(2)(d)) and so is the child (9(2)(c) for the lodger's claim, + # 9(2)(g) for the householder's): 1. The lodger's own: the lodger and + # the foster room, 2. + LHA_allowed_bedrooms: [1, 2] + +- name: A child placed with a joint tenant does not count for the other tenant + period: 2026 + input: + people: + tenant_1: + age: 40 + is_household_head: true + tenant_2: + age: 38 + foster_child: + age: 7 + is_looked_after_by_local_authority: true + benunits: + family_1: + members: [tenant_1] + family_2: + members: [tenant_2, foster_child] + liable_for_share_of_household_rent: true + households: + home: + members: [tenant_1, tenant_2, foster_child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # HB: a joint tenant outside the claimant's household is not an + # occupier (13D(12)), and private-sector size criteria rest on each + # tenant's own household (circular A21/2013 para 25): 1. The second + # tenant's own: the tenant and the qualifying parent or carer room, 2. + housing_benefit_LHA_allowed_bedrooms: [1, 2] + housing_benefit_LHA_additional_bedrooms: [0, 1] + # UC: the joint tenant is liable for the rent (para 9(2)(d)): 1 and 2. + LHA_allowed_bedrooms: [1, 2] + +- name: An adopter who is a close relative of the child has no Universal Credit foster room + period: 2026 + input: + people: + adopter: + age: 40 + is_household_head: true + child: + age: 4 + is_placed_for_adoption: true + adopter_is_foster_parent_or_close_relative: true + benunits: + family: + members: [adopter, child] + households: + home: + members: [adopter, child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # UC: "adopter" (reg 2) takes the meaning in reg 89(3)(a), which + # excludes "a person who is a foster parent or close relative of the + # child", so the renter does not meet para 12(4)(b). The child is still + # placed for adoption, so the renter is responsible (reg 4A(1)(c)) and + # the child has a bedroom: 1 + 1 = 2, one fewer than an adopter who is + # not a close relative. + is_child_or_qualifying_young_person_for_universal_credit: [false, true] + lha_renter_meets_foster_parent_condition: false + LHA_additional_bedrooms: 0 + LHA_allowed_bedrooms: 2 + # HB: reg 21(3)(c) and the reg 2(1) "qualifying parent or carer" carry + # no adopter definition: the child does not occupy the dwelling and the + # claimant has the qualifying parent or carer room, 1 + 1 = 2. + is_housing_benefit_qualifying_parent_or_carer: true + housing_benefit_LHA_allowed_bedrooms: 2 + +- name: A close-relative adopter under 35 has no foster parent exception from the shared accommodation rate + period: 2026 + input: + people: + adopter: + age: 30 + is_household_head: true + child: + age: 4 + is_placed_for_adoption: true + adopter_is_foster_parent_or_close_relative: true + benunits: + family: + members: [adopter, child] + households: + home: + members: [adopter, child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Para 29(9A) excepts a renter under 35 who "satisfies the foster parent + # condition (within the meaning of paragraph 12(4))"; a close relative + # is not an "adopter" (reg 89(3)(a)), so the renter does not. The + # renter is still responsible for the child (reg 4A(1)(c)), so not a + # specified renter. UC: 1 + 1 = 2. HB: 1 + the qualifying parent or + # carer room = 2. + lha_renter_meets_foster_parent_condition: false + is_lha_shared_accommodation_rate_specified_renter: false + LHA_allowed_bedrooms: 2 + housing_benefit_LHA_allowed_bedrooms: 2 + +- name: A close-relative adopter between foster placements keeps the foster room + period: 2026 + input: + people: + adopter: + age: 30 + is_household_head: true + is_approved_foster_parent_without_placement: true + child: + age: 4 + is_placed_for_adoption: true + adopter_is_foster_parent_or_close_relative: true + benunits: + family: + members: [adopter, child] + households: + home: + members: [adopter, child] + rent: 10_400 + tenure_type: RENT_PRIVATELY + brma: MAIDSTONE + output: + # Para 12(5): an approved foster parent within 12 months of a placement + # or of approval is a foster parent for para 12(4)(a), whatever the + # adoption placement. UC: renter, child (reg 4A(1)(c)) and the foster + # room, 3. HB: 1 + the qualifying parent or carer room (reg 2(1)(a) or + # (b)) = 2. + lha_renter_meets_foster_parent_condition: true + LHA_allowed_bedrooms: 3 + housing_benefit_LHA_allowed_bedrooms: 2 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_young_person_bedroom.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_young_person_bedroom.yaml index e2da106a6d..bec2d2c77d 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_young_person_bedroom.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/LHA_young_person_bedroom.yaml @@ -117,7 +117,7 @@ housing_benefit_LHA_allowed_bedrooms: 2 housing_benefit_LHA_category: C -- name: A qualifying young person no one is responsible for has no Universal Credit bedroom +- name: A looked-after qualifying young person has no Universal Credit bedroom of their own period: 2026 input: people: @@ -143,10 +143,25 @@ output: is_qualifying_young_person_for_universal_credit: [false, true] is_child_or_qualifying_young_person_for_universal_credit: [false, false] - # Not under para 10(1)(b), and not a non-dependant (para 9(2)(g)): the - # renter's bedroom only. - LHA_allowed_bedrooms: 1 - LHA_category: B + # Not under para 10(1)(b), and not a non-dependant (para 9(2)(c) and (g)), + # so no bedroom of their own. The carer they are placed with is a foster parent + # (reg 2: a person with whom a child is placed under the care planning + # regulations, which place children under 18), so has one additional + # bedroom (para 12(4)(a), (9)(b)): 2 bedrooms, category C. The model reads + # "child" there as under 18 (see is_lha_foster_child; reg 91(2)(b)-(d) + # also speak of foster parents of qualifying young persons). Read as under + # 16 (WRA 2012 s.40), there would be no foster room and 1 bedroom. + LHA_additional_bedrooms: 1 + LHA_allowed_bedrooms: 2 + LHA_category: C + # HB: a young person placed with the claimant by a local authority does + # not occupy the dwelling (HB Regs 2006 reg 21(3)), but the claimant is a + # qualifying parent or carer (reg 2(1)) with one additional bedroom (reg + # 13D(3A)(b)): 2 bedrooms. + is_child_or_young_person_placed_with_family: [false, true] + housing_benefit_LHA_additional_bedrooms: 1 + housing_benefit_LHA_allowed_bedrooms: 2 + housing_benefit_LHA_category: C - name: A qualifying young person cannot share with a younger sibling of the same sex period: 2026 @@ -283,9 +298,13 @@ is_child_or_qualifying_young_person_for_universal_credit: [false, false, false] # The renter (para 10(1)(a)) and the carer, a non-dependant who is not a # child ((c)). The young person is no one's responsibility (reg 4(6)), so - # is not a non-dependant (para 9(2)(g)): 2 bedrooms, category C. - LHA_allowed_bedrooms: [2, 1] - LHA_category: [C, B] + # is not a non-dependant (para 9(2)(g)): 2 bedrooms, category C. The + # carer's own claim: the carer (para 10(1)(a)) and the foster parent + # condition's additional bedroom (para 12(4)(a); the young person is a + # child under 18 placed with the carer), 2. The young person, the + # carer's foster child, has none (para 9(2)(c)). + LHA_allowed_bedrooms: [2, 2] + LHA_category: [C, C] - name: A non-dependant couple has two Universal Credit bedrooms but one Housing Benefit bedroom period: 2026 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support.yaml index 091b8e9041..97a69ea985 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support.yaml @@ -23,4 +23,124 @@ child_tax_credit: 0 child_benefit: 1825 income_support_eligible: true - income_support: 0 \ No newline at end of file + income_support: 0 + +- name: A single foster carer is in an Income Support prescribed category + period: 2025 + input: + people: + carer: + age: 30 + income_support_reported: true + foster_child: + age: 3 + is_looked_after_by_local_authority: true + benunits: + family: + members: [carer, foster_child] + output: + # IS Regs 1987 Sch 1B para 2: a single claimant or lone parent with whom + # a child is placed by a local authority. The foster child is not a + # member of the household (reg 16(4)), so the carer is a single claimant. + is_single_person: true + income_support_eligible: true + +- name: A lone parent with an older child and a young foster child is in an Income Support prescribed category + period: 2025 + input: + people: + parent: + age: 30 + income_support_reported: true + child: + age: 10 + foster_child: + age: 2 + is_looked_after_by_local_authority: true + benunits: + family: + members: [parent, child, foster_child] + output: + # Sch 1B para 1 needs a child under 5 in the household, which the foster + # child is not (reg 16(4)); para 2 covers a lone parent with whom a child + # is placed. + youngest_child_age_for_legacy_benefits: 10 + income_support_eligible: true + +- name: A single adopter with a child placed for adoption is in an Income Support prescribed category + period: 2025 + input: + people: + adopter: + age: 30 + income_support_reported: true + child: + age: 3 + is_placed_for_adoption: true + benunits: + family: + members: [adopter, child] + output: + # IS Regs 1987 Sch 1B para 2A. The child is not a member of the household + # (reg 16(4)(b)-(c)), so the adopter is a single claimant. + is_single_person: true + income_support_eligible: true + +- name: A lone parent with an older child and a young child placed for adoption is in an Income Support prescribed category + period: 2025 + input: + people: + parent: + age: 30 + income_support_reported: true + child: + age: 10 + placed_child: + age: 2 + is_placed_for_adoption: true + benunits: + family: + members: [parent, child, placed_child] + output: + # Para 1 needs a child under 5 in the household, which the placed child + # is not (reg 16(4)); para 2A covers a lone parent with whom a child is + # placed for adoption. + youngest_child_age_for_legacy_benefits: 10 + income_support_eligible: true + +- name: A couple with a child placed for adoption is not in the Income Support adoption category + period: 2025 + input: + people: + adopter_1: + age: 30 + income_support_reported: true + adopter_2: + age: 31 + child: + age: 2 + is_placed_for_adoption: true + benunits: + family: + members: [adopter_1, adopter_2, child] + output: + # Sch 1B para 2A covers only a single claimant or lone parent. + income_support_eligible: false + +- name: A placement aged 16 is not a child for the Income Support adoption category + period: 2025 + input: + people: + adopter: + age: 40 + income_support_reported: true + young_person: + age: 16 + current_education: UPPER_SECONDARY + is_placed_for_adoption: true + benunits: + family: + members: [adopter, young_person] + output: + # Para 2A needs "a child", a person under 16 (SSCBA 1992 s.137(1)). + income_support_eligible: false diff --git a/policyengine_uk/tests/policy/baseline/gov/hmrc/tax_free_childcare/tax_free_childcare_qualifying_child.yaml b/policyengine_uk/tests/policy/baseline/gov/hmrc/tax_free_childcare/tax_free_childcare_qualifying_child.yaml index 7c98bbea98..30daa36fe6 100644 --- a/policyengine_uk/tests/policy/baseline/gov/hmrc/tax_free_childcare/tax_free_childcare_qualifying_child.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/hmrc/tax_free_childcare/tax_free_childcare_qualifying_child.yaml @@ -25,6 +25,17 @@ output: tax_free_childcare_qualifying_child: false +- name: A child placed for adoption is not a qualifying child + period: 2025 + input: + tax_free_childcare_child_age_eligible: true + is_parent: false + is_looked_after_by_local_authority: false + is_placed_for_adoption: true + output: + # Childcare Payments (Eligibility) Regs 2015 reg 4(2)(d). + tax_free_childcare_qualifying_child: false + - name: Age-ineligible child is not qualifying period: 2025 input: diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml index 1abdbeba87..264792dfbc 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_young_person.yaml @@ -351,3 +351,121 @@ is_council_tax_reduction_applicant_or_partner: [true, false, false] is_child_or_young_person_for_council_tax_reduction: [true, false, false] council_tax_reduction_applicable_income: 10_000 + +- name: Case 11, Scotland working age, an adopter of 23 with a child of 3 who lives with them. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + adopter: + age: 23 + employment_income: 11_000 + is_household_head: true + child: + age: 3 + is_placed_for_adoption: false + benunits: + family: + members: [adopter, child] + would_claim_uc: false + households: + home: + members: [adopter, child] + country: SCOTLAND + local_authority: CITY_OF_EDINBURGH + council_tax: 1_800 + output: + # SSI 2021/249 reg 7(2): the adopter is responsible for a child who + # normally lives with them; reg 7(8) takes out only a child placed with + # a foster carer, so an adoption placement leaves the child in the + # family and the adopter a lone parent. + is_child_or_young_person_for_council_tax_reduction: [false, true] + council_tax_reduction_pensioner: false + is_council_tax_reduction_lone_parent: true + # Lone parent aged 18 or over, £92.05 a week in 2025-26: 92.05 * 52. + council_tax_reduction_applicable_amount: 4_786.60 + # Earnings of £11,000 fall below the £12,570 personal allowance and + # National Insurance primary threshold, so no tax or contributions. The + # model counts the earnings with no earnings disregard on this route, + # plus Child Benefit for an eldest child, £26.05 a week: 11,000 + + # 26.05 * 52 = 12,354.60. + council_tax_reduction_applicable_income: 12_354.60 + # Scotland's withdrawal rate is 20%: 1,800 - 0.2 * (12,354.60 - + # 4,786.60) = 1,800 - 1,513.60 = 286.40. + council_tax_reduction: 286.40 + +- name: Case 12, Scotland working age, the same family with the child placed for adoption. + period: 2025 + absolute_error_margin: 0.01 + input: + people: + adopter: + age: 23 + employment_income: 11_000 + is_household_head: true + child: + age: 3 + is_placed_for_adoption: true + benunits: + family: + members: [adopter, child] + would_claim_uc: false + households: + home: + members: [adopter, child] + country: SCOTLAND + local_authority: CITY_OF_EDINBURGH + council_tax: 1_800 + output: + # SSI 2021/249 reg 7(2): the adopter is responsible for a child who + # normally lives with them; reg 7(8) takes out only a child placed with + # a foster carer, so an adoption placement leaves the child in the + # family and the adopter a lone parent. + is_child_or_young_person_for_council_tax_reduction: [false, true] + council_tax_reduction_pensioner: false + is_council_tax_reduction_lone_parent: true + # Lone parent aged 18 or over, £92.05 a week in 2025-26: 92.05 * 52. + council_tax_reduction_applicable_amount: 4_786.60 + # Earnings of £11,000 fall below the £12,570 personal allowance and + # National Insurance primary threshold, so no tax or contributions. The + # model counts the earnings with no earnings disregard on this route, + # plus Child Benefit for an eldest child, £26.05 a week: 11,000 + + # 26.05 * 52 = 12,354.60. + council_tax_reduction_applicable_income: 12_354.60 + # Scotland's withdrawal rate is 20%: 1,800 - 0.2 * (12,354.60 - + # 4,786.60) = 1,800 - 1,513.60 = 286.40. + council_tax_reduction: 286.40 + # Housing Benefit and Income Support still leave the child out of the + # household (HB Regs 2006 reg 21(3)(c); IS Regs 1987 reg 16(4)). + is_child_or_young_person_placed_with_family: [false, true] + is_child_or_young_person_for_legacy_benefits: [false, false] + is_responsible_for_child_or_young_person_for_legacy_benefits: false + is_lone_parent: false + +- name: Case 13, Scotland's pension-age scheme leaves out a child placed for adoption. + period: 2025 + input: + people: + adopter: + age: 70 + is_household_head: true + child: + age: 3 + is_placed_for_adoption: true + benunits: + family: + members: [adopter, child] + would_claim_uc: false + households: + home: + members: [adopter, child] + country: SCOTLAND + local_authority: CITY_OF_EDINBURGH + council_tax: 1_800 + output: + # SSI 2012/319 reg 11(2)(c): a child placed for adoption with the + # applicant is not a member of the household, so the adopter is not a + # lone parent. + council_tax_reduction_pensioner: true + is_child_or_young_person_for_council_tax_reduction: [false, false] + is_council_tax_reduction_lone_parent: false diff --git a/policyengine_uk/tests/test_child_and_adult_definitions_properties.py b/policyengine_uk/tests/test_child_and_adult_definitions_properties.py index bc6ee58fbf..7f0ef2d2e5 100644 --- a/policyengine_uk/tests/test_child_and_adult_definitions_properties.py +++ b/policyengine_uk/tests/test_child_and_adult_definitions_properties.py @@ -211,6 +211,12 @@ def qualifying_young_person(p, programme): return True +def looked_after_child(p): + # Only a person under 18 can be looked after by a local authority: + # https://www.legislation.gov.uk/ukpga/1989/41/section/105 + return p["is_looked_after_by_local_authority"] and p["age"] < 18 + + def child_or_young_person(p, programme, claimant=False): # Encoded responsibility filters, without their statutory exceptions: # https://www.legislation.gov.uk/uksi/2013/376/regulation/4 @@ -223,7 +229,7 @@ def child_or_young_person(p, programme, claimant=False): eligible = statutory_child(p["age"]) or qualifying_young_person(p, programme) if programme != "universal_credit" and claimant: return False - if programme != "child_benefit" and p["is_looked_after_by_local_authority"]: + if programme != "child_benefit" and looked_after_child(p): return False return eligible @@ -301,7 +307,7 @@ def legacy_child_or_young_person(p, claimant): # anyone placed by a local authority (IS reg16(4), HB reg21(3)): # https://www.legislation.gov.uk/uksi/1987/1967/regulation/16 # https://www.legislation.gov.uk/uksi/2006/213/regulation/21 - return not p["is_looked_after_by_local_authority"] and child_or_young_person( + return not looked_after_child(p) and child_or_young_person( p, "child_benefit", claimant ) diff --git a/policyengine_uk/tests/test_council_tax_reduction_young_person_properties.py b/policyengine_uk/tests/test_council_tax_reduction_young_person_properties.py index 1bf2efbf8f..7613a2ef3a 100644 --- a/policyengine_uk/tests/test_council_tax_reduction_young_person_properties.py +++ b/policyengine_uk/tests/test_council_tax_reduction_young_person_properties.py @@ -34,6 +34,11 @@ means test where Scotland's working-age scheme does not read them as a young person. A member who is not the applicant never counts: a young person's income is not the applicant's. +7. Adoption placements. From 2022-23, placing any member of a Scottish + working-age family for adoption leaves its lone-parent status and its + applicable amount unchanged: SSI 2021/249 reg. 7(8) takes out only a + child or young person placed with a foster carer, and the applicant is + responsible for one who normally lives with them (reg. 7(2)). The pensioner test and the claimant and partner are supplied, so these tests exercise the young person rule alone; the YAML cases use the derived tests. @@ -151,7 +156,10 @@ def assert_scheme_selection(units, year): sim = simulate(units, year) people = [p for unit in units for p in unit["members"]] claimant_or_partner = np.array([p["is_claimant_or_partner"] for p in people]) - looked_after = np.array([p["is_looked_after_by_local_authority"] for p in people]) + # Only a person under 18 can be looked after (is_looked_after_child). + looked_after = np.array( + [p["is_looked_after_by_local_authority"] and p["age"] < 18 for p in people] + ) under_16 = np.array([p["age"] < 16 for p in people]) flag = sim.calculate("is_child_or_young_person_for_council_tax_reduction", year) legacy = sim.calculate("is_child_or_young_person_for_legacy_benefits", year) @@ -459,3 +467,43 @@ def test_applicants_own_earnings_count_under_every_scheme(): # Not vacuous: a non-applicant who is the scheme's young person does not # count, nor one who is not. assert (~heads & ~young_person).any() and (~heads & young_person).any() + + +@SETTINGS +@given( + st.lists(families(), min_size=1, max_size=4), + st.sampled_from((2022, 2026)), + st.data(), +) +def test_scottish_working_age_adoption_placement_keeps_the_family(units, year, data): + # Invariant 7. + units = [dict(unit, country="SCOTLAND", pensioner=False) for unit in units] + people = [p for unit in units for p in unit["members"]] + placed = data.draw( + st.lists(st.booleans(), min_size=len(people), max_size=len(people)) + ) + + def with_placement(flags): + result, k = [], 0 + for unit in units: + members = [] + for p in unit["members"]: + members.append(dict(p, is_placed_for_adoption=flags[k])) + k += 1 + result.append(dict(unit, members=members)) + return result + + outputs = [] + for flags in ([False] * len(people), placed): + sim = simulate(with_placement(flags), year) + outputs.append( + ( + sim.calculate( + "is_child_or_young_person_for_council_tax_reduction", year + ), + sim.calculate("is_council_tax_reduction_lone_parent", year), + sim.calculate("council_tax_reduction_applicable_amount", year), + ) + ) + for before, after in zip(*outputs): + np.testing.assert_array_equal(before, after) diff --git a/policyengine_uk/tests/test_household_head_agreement_properties.py b/policyengine_uk/tests/test_household_head_agreement_properties.py index 4862578ad5..2bff2ee945 100644 --- a/policyengine_uk/tests/test_household_head_agreement_properties.py +++ b/policyengine_uk/tests/test_household_head_agreement_properties.py @@ -101,6 +101,8 @@ "housing_benefit_non_dep_deductions", "LHA_allowed_bedrooms", "housing_benefit_LHA_allowed_bedrooms", + "LHA_additional_bedrooms", + "housing_benefit_LHA_additional_bedrooms", "lha_renter_has_non_dependant", "council_tax_reduction_claimant_benunit", "council_tax_reduction_individual_non_dep_deduction_eligible", diff --git a/policyengine_uk/tests/test_lha_bedroom_young_people_properties.py b/policyengine_uk/tests/test_lha_bedroom_young_people_properties.py index 133fc95890..7d8e61425d 100644 --- a/policyengine_uk/tests/test_lha_bedroom_young_people_properties.py +++ b/policyengine_uk/tests/test_lha_bedroom_young_people_properties.py @@ -1,59 +1,104 @@ -"""Property-based tests for the bedrooms of benefit-unit members aged 16 or -over who are not the claimant or partner (UC Regs 2013 Sch 4 paras 9-10; HB -Regs 2006 and HB (SPC) Regs 2006 reg 13D(3)). +"""Property-based tests for the LHA size criteria (UC Regs 2013 Sch 4 paras +9-12; HB Regs 2006 and HB (SPC) Regs 2006 reg 13D and reg 21(3)): the +bedrooms of benefit-unit members aged 16 or over who are not the claimant or +partner, the children of other families in the household, foster and +adoption placements, and the additional bedrooms for foster parents and +overnight care. Invariants, for any generated population of households: 1. Monotonicity: adding a person aged 16 to 19 to any family never lowers any family's Universal Credit or Housing Benefit bedrooms, whether the claimant and partner are supplied or inferred. -2. Exact effect: when the added person is not the claimant or partner, their - family gains one Housing Benefit bedroom, and one Universal Credit bedroom - unless they are a qualifying young person no one is responsible for (para - 9(2)(g)) or they head the household and are not a qualifying young person - (the formula treats the household head as liable for the rent, so such - a member is neither a renter nor a non-dependant: paras 1(2), 9(1)(a) and - 9(2)(d)). If they join a non-dependant's family, the claim that counts the - household's non-dependants (uc_non_dependants_counted) gains one Universal - Credit bedroom unless they are a qualifying young person no one is - responsible for (para 9(2)(g) applies to the whole extended benefit unit), - and every family liable for the rent gains one Housing Benefit bedroom, - since they are an occupier of each such claim (reg 13D(12)). If they join - a boarder's or lodger's family, every family liable for the rent gains one - Housing Benefit bedroom. No other family's bedrooms change. -3. Reference: every family's bedrooms equal an independent count of the size - criteria. Universal Credit: one for the renter or couple; one for each - other member aged 16 or over, except a qualifying young person no one is - responsible for and a household head who is not a qualifying young - person; for the counting claim, one for each person aged 16 or - over in a non-dependant's family, with the same exception; and the - fewest rooms that hold the family's own children. Housing Benefit, for a - family liable for the rent: one for the claimant or couple; one for each - other member aged 16 or over; for each non-dependant's, boarder's or - lodger's family, one for its couple or single adult (reg 13D(3)(a), (b)) - and one for each other member aged 16 or over; and the fewest rooms that - hold the children of all those occupiers together. Any other family's - Housing Benefit claim counts only its own members. The fewest rooms hold - children under 16 two to a room, where only children of the same sex or - two children under 10 may share, found by brute force. Which claim counts - the non-dependants, and which families are liable for the rent, are read - from the model; they are tested elsewhere. Universal Credit does not yet - count other families' children (a separate change). -4. In-unit non-dependants: every member of a benefit unit aged 16 or over - who is neither the claimant nor partner nor a Universal Credit qualifying - young person nor the household head (the householder in whose name the - accommodation is rented, whom the formula reads as liable for the rent, - so that para 9(2)(d) excludes them) is a non-dependant (para 9(2)) with - a bedroom (para 10(1)(c)). So their family has one more Universal Credit - bedroom with them than without them, and making them qualifying young - persons the renter is responsible for (para 10(1)(b)) leaves every family's - Universal Credit bedrooms unchanged. This ties the bedroom to the same - definition that marks a benefit-unit member as a non-dependant for the - non-dependant deduction. +2. Exact effect of a person aged 16 to 19 who is not the claimant or + partner: + - their family gains one Universal Credit bedroom unless they are a + qualifying young person no one is responsible for (para 9(2)(g)), the + family's foster child (under 18, para 9(2)(c)), or the household head + and not a qualifying young person (the formula treats the head as + liable for the rent: paras 1(2), 9(1)(a) and 9(2)(d)); + - their family gains one Housing Benefit bedroom unless they are placed + with it as a foster child (HB reg 21(3)); + - a family they are placed with as a foster child gains the foster + parent's (UC, para 12) or qualifying parent or carer's (HB, + 13D(3A)(b)) bedroom if it did not already have it; + - if they join a non-dependant's family, the claim that counts the + household's non-dependants (uc_non_dependants_counted) gains one + Universal Credit bedroom unless no one is responsible for them; + - if they join a non-dependant's, boarder's or lodger's family, every + family liable for the rent gains one Housing Benefit bedroom, even if + they are placed with that family: reg 21(3) takes out only a child or + young person placed with the claimant or partner, so they occupy the + claimant's dwelling (reg 13D(12)); + - no other family's bedrooms change. +3. Children: adding a child under 16 who is neither fostered nor placed for + adoption to any family never lowers any family's bedrooms under either + scheme and raises each by at most one. +4. Placed children: adding a child under 16 placed with a family as a + foster child or for adoption gives that family one more bedroom under + each scheme if it did not already meet the foster parent condition (UC) + or have a qualifying parent or carer (HB), and none otherwise. If the + family is a non-dependant's, boarder's or lodger's, each family liable + for the rent gains 0 or 1 Housing Benefit bedrooms: the child occupies + its dwelling (reg 21(3) names only a placement with the claimant or + partner; reg 13D(12)) and shares a room with the other children if it + can. A foster child changes no other family's Universal Credit bedrooms: + no one is responsible for them (reg 4(6)(a); para 9(2)(g)). A child + placed for adoption counts as a child under Universal Credit (reg + 4A(1)(c)): the adopter's family and the claim counting a non-dependant + adopter's household each gain 0 or 1 more. No joint tenant's bedrooms + change, and no other family's. +5. Reference: every family's bedrooms, and its additional bedrooms, equal a + count of the size criteria made by the test itself. The added person's + status comes from the test's own predicates on the inputs (UC reg 5 + qualifying young person, the Child Benefit qualifying young person for + HB reg 19, looked after and under 18 for a foster child), not from the + model; which claim counts the non-dependants, and which families are + liable for the rent, are read from the model and tested elsewhere. + Children's rooms come from a brute-force pairing. The count applies the + same legal readings as the model, so it checks the implementation of + those readings, not the readings themselves: + - one for the claimant or couple; + - one for each other member aged 16 or over (UC: except a qualifying + young person no one is responsible for, a foster child under 18 and a + household head who is not a qualifying young person; HB: except one + placed with the family as a foster child); + - for the claim counting the non-dependants (UC), one for each person + aged 16 or over in a non-dependant's family, except one no one is + responsible for; for a family liable for the rent (HB), one for the + couple or single adult of each non-dependant's, boarder's or lodger's + family and one for each other member aged 16 or over, including one + placed with that family; + - the fewest rooms that hold the counted children under 16 two to a + room, where only children of the same sex or two children under 10 may + share, found by brute force. UC counts the family's own children other + than foster children and, for the counting claim, the non-dependants' + children other than foster children. HB counts the family's children + other than foster children and children placed for adoption and, for + a family liable for the rent, every child of each non-dependant's, + boarder's or lodger's family, placed or not; + - one additional bedroom if anyone so counted, or a child placed with + the family, has overnight care, and one if the family fosters, has a + child placed for adoption, or has an approved foster parent between + placements. +6. In-unit non-dependants: every member of a benefit unit aged 16 or over + who is neither the claimant nor partner nor a Universal Credit + qualifying young person nor the household head nor the family's foster + child is a non-dependant (para 9(2)) with a bedroom (para 10(1)(c)). So + their family has one more Universal Credit bedroom with them than + without them, and making them qualifying young persons the renter is + responsible for (para 10(1)(b)) leaves every family's Universal Credit + bedrooms unchanged. +7. Close-relative adopters: marking every child's adopter as a foster + parent or close relative of the child (UC reg 89(3)(a)) takes away the + foster parent condition exactly where an adoption placement was the + family's only route to it (para 12(4)(b)); it lowers that family's + Universal Credit bedrooms by one and changes nothing else: Universal + Credit responsibility (reg 4A(1)(c)), the Housing Benefit placement test + (reg 21(3)), the qualifying parent or carer and every family's Housing + Benefit bedrooms stay the same. """ -from itertools import combinations - import numpy as np from hypothesis import HealthCheck, example, given, settings from hypothesis import strategies as st @@ -68,17 +113,24 @@ suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], ) ROLES = ["sharer", "boarder", "lodger", "non_dependant"] -EDUCATION = ["NOT_IN_EDUCATION", "UPPER_SECONDARY", "TERTIARY"] +OCCUPIER_ROLES = ("non_dependant", "boarder", "lodger") +EDUCATION = ["NOT_IN_EDUCATION", "UPPER_SECONDARY", "UPPER_SECONDARY", "TERTIARY"] +KINDS = ["own", "own", "own", "foster", "adopted"] +OVERNIGHT = st.sampled_from([False, False, False, True]) -child = st.tuples(st.integers(0, 15), st.booleans()) # (age, is_male) +# (age, is_male, kind, has overnight care) +child = st.tuples(st.integers(0, 15), st.booleans(), st.sampled_from(KINDS), OVERNIGHT) @st.composite def family(draw, role): return dict( role=role, - adults=draw(st.lists(st.integers(20, 85), min_size=1, max_size=2)), + adults=draw( + st.lists(st.tuples(st.integers(20, 85), OVERNIGHT), min_size=1, max_size=2) + ), children=draw(st.lists(child, min_size=0, max_size=4)), + between_placements=draw(st.sampled_from([False, False, False, True])), ) @@ -92,7 +144,7 @@ def household(draw): @st.composite def young_person(draw): - return dict( + person = dict( age=draw(st.integers(16, 19)), is_male=draw(st.booleans()), current_education=draw(st.sampled_from(EDUCATION)), @@ -100,9 +152,21 @@ def young_person(draw): is_before_universal_credit_qualifying_young_person_terminal_date=draw( st.booleans() ), - is_looked_after_by_local_authority=draw(st.booleans()), - receives_benefits_in_own_right=draw(st.booleans()), + is_looked_after_by_local_authority=draw(st.sampled_from([False, True, True])), + receives_benefits_in_own_right=draw(st.sampled_from([False, False, True])), ) + if draw(OVERNIGHT): + person["dla_sc_middle_plus"] = True + person["has_non_resident_overnight_carer"] = True + return person + + +def without_overnight_care(person): + return { + k: v + for k, v in person.items() + if k not in ("dla_sc_middle_plus", "has_non_resident_overnight_carer") + } @st.composite @@ -118,9 +182,37 @@ def scenario(draw): return population, (h, f), person -def build(population, added=None, supply_roles=True): - """One situation for the population, optionally with a person added to - family ``added[0]`` = (household, family) with attributes ``added[1]``. +@st.composite +def child_scenario(draw, kinds): + population = draw(st.lists(household(), min_size=1, max_size=4)) + h = draw(st.integers(0, len(population) - 1)) + f = draw(st.integers(0, len(population[h]) - 1)) + added = ( + draw(st.integers(0, 15)), + draw(st.booleans()), + draw(st.sampled_from(kinds)), + False, + ) + return population, (h, f), added + + +def child_inputs(age, male, kind, overnight): + inputs = {"age": age, "is_male": male, "is_household_head": False} + if kind == "foster": + inputs["is_looked_after_by_local_authority"] = True + if kind == "adopted": + inputs["is_placed_for_adoption"] = True + if overnight: + inputs["dla_sc_middle_plus"] = True + inputs["has_non_resident_overnight_carer"] = True + return inputs + + +def build(population, added=None, supply_roles=True, added_child=None): + """One situation for the population, optionally with a person aged 16 to + 19 added to family ``added[0]`` = (household, family) with attributes + ``added[1]``, or a child ``added_child[1]`` = (age, is_male, kind, + overnight) added to family ``added_child[0]``. Returns the situation and, per benefit unit, its (household, family). An added person with ``is_household_head`` heads the household in place @@ -131,26 +223,33 @@ def build(population, added=None, supply_roles=True): for f, fam in enumerate(families): name = f"h{h}_f{f}" ids = [] - for i, age in enumerate(fam["adults"]): + for i, (age, overnight) in enumerate(fam["adults"]): pid = f"{name}_adult_{i}" people[pid] = {"age": age, "is_household_head": False} + if overnight: + people[pid]["dla_sc_middle_plus"] = True + people[pid]["has_non_resident_overnight_carer"] = True if supply_roles: people[pid]["is_claimant_or_partner"] = True elif fam["children"]: people[pid]["is_parent"] = True ids.append(pid) - for i, (age, male) in enumerate(fam["children"]): + if fam["between_placements"]: + people[ids[0]]["is_approved_foster_parent_without_placement"] = True + children = list(fam["children"]) + if added_child is not None and added_child[0] == (h, f): + children.append(added_child[1]) + for i, spec in enumerate(children): pid = f"{name}_child_{i}" - people[pid] = {"age": age, "is_male": male, "is_household_head": False} + people[pid] = child_inputs(*spec) if supply_roles: people[pid]["is_claimant_or_partner"] = False ids.append(pid) + added_head = False if added is not None and added[0] == (h, f): pid = f"{name}_added" - people[pid] = { - **added[1], - "is_household_head": added[1].get("is_household_head", False), - } + added_head = added[1].get("is_household_head", False) + people[pid] = {**added[1], "is_household_head": added_head} if supply_roles: people[pid]["is_claimant_or_partner"] = False ids.append(pid) @@ -159,11 +258,6 @@ def build(population, added=None, supply_roles=True): extra["liable_for_share_of_household_rent"] = True if fam["role"] in ("boarder", "lodger"): people[ids[0]][f"rent_paid_as_{fam['role']}"] = 5_000 - added_head = ( - added is not None - and added[0] == (h, f) - and added[1].get("is_household_head", False) - ) if fam["role"] == "head" and not added_head: people[ids[0]]["is_household_head"] = True benunits[name] = {"members": ids, **extra} @@ -200,23 +294,6 @@ def claim_roles(sim): return counted.astype(bool), liable -def has_own_uc_bedroom(sim, situation): - """Each person aged 16 or over who is not the claimant or partner: whether - they have a Universal Credit bedroom of their own. A qualifying young - person the renter is responsible for has one (para 10(1)(b)); one no one - is responsible for has none (para 9(2)(g)). Anyone else has one as a - non-dependant (para 10(1)(c)), unless they head the household, whom the - formula treats as liable for the rent (para 9(2)(d)).""" - qualifying = np.asarray( - sim.calculate("is_qualifying_young_person_for_universal_credit", YEAR) - ) - responsible = np.asarray( - sim.calculate("is_child_or_qualifying_young_person_for_universal_credit", YEAR) - ) - head = np.asarray(sim.calculate("is_resolved_household_head", YEAR)) - return dict(zip(situation["people"], responsible | (~qualifying & ~head))) - - def fewest_rooms_for_children(children): """Brute force: the fewest rooms holding the children two to a room, where a pair must be of the same sex or both under 10.""" @@ -237,6 +314,74 @@ def best(remaining): return best(list(children)) +def fosters(fam): + """Whether the family meets the foster parent condition (UC) or has a + qualifying parent or carer (HB) through its children or adults.""" + return fam["between_placements"] or any( + kind in ("foster", "adopted") for _, _, kind, _ in fam["children"] + ) + + +def in_qualifying_education(p, age_limit_for_entry=19): + """Full-time non-advanced education (any education short of tertiary), + entered before 19.""" + return p["current_education"] not in ("NOT_IN_EDUCATION", "TERTIARY") and ( + p["age"] < age_limit_for_entry + or p["age_started_or_accepted_current_education_or_training"] + < age_limit_for_entry + ) + + +def uc_qualifying_young_person(p): + """UC Regs 2013 reg 5: aged 16 to 19, in non-advanced education entered + before 19, before the terminal date if 19, and not receiving benefits in + their own right.""" + return ( + 16 <= p["age"] < 20 + and in_qualifying_education(p) + and ( + p["age"] < 19 + or p["is_before_universal_credit_qualifying_young_person_terminal_date"] + ) + and not p["receives_benefits_in_own_right"] + ) + + +def child_benefit_qualifying_young_person(p): + """SSCBA 1992 s.142 and the Child Benefit (General) Regulations 2006, as + HB reg 19's "young person": aged 16 to 19 in non-advanced education + entered before 19, and not receiving benefits in their own right.""" + return ( + 16 <= p["age"] < 20 + and in_qualifying_education(p) + and not p["receives_benefits_in_own_right"] + ) + + +def flags(p): + """The added person's status, from the inputs alone.""" + # Only a person under 18 can be looked after (Children Act 1989 s.105). + looked_after = p.get("is_looked_after_by_local_authority", False) and p["age"] < 18 + qualifying = uc_qualifying_young_person(p) + head = p.get("is_household_head", False) + return dict( + # A qualifying young person no one is responsible for (UC para + # 9(2)(g); reg 4(6)(a)). + unclaimed=looked_after and qualifying, + # The family's foster child: looked after and under 18 (UC reg 2, + # "foster parent"; para 9(3)). + fostered=looked_after, + # A UC bedroom of their own: a qualifying young person the renter is + # responsible for (para 10(1)(b)), or a non-dependant (para + # 10(1)(c)) who neither heads the household (para 9(2)(d)) nor is a + # foster child (para 9(2)(c)). + own_uc_room=not looked_after and (qualifying or not head), + # Placed with the family by a local authority (HB reg 21(3)). + placed=looked_after and child_benefit_qualifying_young_person(p), + overnight=p.get("has_non_resident_overnight_carer", False), + ) + + @PROPERTY_SETTINGS @given(scenario(), st.booleans()) def test_adding_a_person_aged_16_to_19_never_lowers_bedrooms(case, supply_roles): @@ -251,49 +396,32 @@ def test_adding_a_person_aged_16_to_19_never_lowers_bedrooms(case, supply_roles) assert np.all(hb_after >= hb_before) +LOOKED_AFTER_QYP = dict( + age=17, + is_male=True, + current_education="UPPER_SECONDARY", + age_started_or_accepted_current_education_or_training=16, + is_before_universal_credit_qualifying_young_person_terminal_date=True, + is_looked_after_by_local_authority=True, + receives_benefits_in_own_right=False, +) + + +def lone(role, age): + return dict(role=role, adults=[(age, False)], children=[], between_placements=False) + + @PROPERTY_SETTINGS @given(scenario()) # A qualifying young person a local authority looks after, added to the # head's family: no Universal Credit bedroom (para 9(2)(g)). -@example( - ( - [[dict(role="head", adults=[40], children=[])]], - (0, 0), - dict( - age=17, - is_male=True, - current_education="UPPER_SECONDARY", - age_started_or_accepted_current_education_or_training=16, - is_before_universal_credit_qualifying_young_person_terminal_date=True, - is_looked_after_by_local_authority=True, - receives_benefits_in_own_right=False, - ), - ) -) +@example(([[lone("head", 40)]], (0, 0), LOOKED_AFTER_QYP)) # The same young person in a non-dependant's family: no Universal Credit # bedroom in the renter's claim either (para 9(2)(g)). -@example( - ( - [ - [ - dict(role="head", adults=[40], children=[]), - dict(role="non_dependant", adults=[45], children=[]), - ] - ], - (0, 1), - dict( - age=17, - is_male=True, - current_education="UPPER_SECONDARY", - age_started_or_accepted_current_education_or_training=16, - is_before_universal_credit_qualifying_young_person_terminal_date=True, - is_looked_after_by_local_authority=True, - receives_benefits_in_own_right=False, - ), - ) -) +@example(([[lone("head", 40), lone("non_dependant", 45)]], (0, 1), LOOKED_AFTER_QYP)) def test_exact_effect_of_adding_a_person_aged_16_to_19(case): population, target, person = case + person = without_overnight_care(person) before, keys = build(population) after, _ = build(population, (target, person)) sim_before, uc_before, hb_before = bedrooms(before) @@ -304,83 +432,200 @@ def test_exact_effect_of_adding_a_person_aged_16_to_19(case): counted_before, liable_before = claim_roles(sim_before) assert np.array_equal(counted, counted_before) assert np.array_equal(liable, liable_before) - gains = has_own_uc_bedroom(sim, after)[f"h{target[0]}_f{target[1]}_added"] + added = flags(person) + fam = population[target[0]][target[1]] # 2. Exact effect. expected_uc = np.zeros(len(keys)) expected_hb = np.zeros(len(keys)) t = keys.index(target) - expected_uc[t] += 1 if gains else 0 - expected_hb[t] += 1 - role = population[target[0]][target[1]]["role"] + expected_uc[t] += int(added["own_uc_room"]) + expected_uc[t] += int(added["fostered"] and not fosters(fam)) + expected_hb[t] += 0 if added["placed"] else 1 + expected_hb[t] += int(added["placed"] and not fosters(fam)) same_household = np.array([h == target[0] for h, _ in keys]) - if role == "non_dependant" and gains: + if fam["role"] == "non_dependant" and not added["unclaimed"]: expected_uc[same_household & counted] += 1 - if role in ("non_dependant", "boarder", "lodger"): + if fam["role"] in OCCUPIER_ROLES: expected_hb[same_household & liable] += 1 assert np.array_equal(uc_after - uc_before, expected_uc) assert np.array_equal(hb_after - hb_before, expected_hb) +@PROPERTY_SETTINGS +@given(child_scenario(["own"])) +def test_adding_a_child_raises_each_family_by_at_most_one_bedroom(case): + population, target, added_child = case + before, keys = build(population) + after, _ = build(population, added_child=(target, added_child)) + _, uc_before, hb_before = bedrooms(before) + _, uc_after, hb_after = bedrooms(after) + # 3. Children. + for change in (uc_after - uc_before, hb_after - hb_before): + assert np.all((change == 0) | (change == 1)) + + +@PROPERTY_SETTINGS +@given(child_scenario(["foster", "adopted"])) +def test_a_placed_child_adds_the_carers_bedroom(case): + population, target, added_child = case + before, keys = build(population) + after, _ = build(population, added_child=(target, added_child)) + sim, uc_before, hb_before = bedrooms(before) + _, uc_after, hb_after = bedrooms(after) + counted, liable = claim_roles(sim) + # 4. Placed children. + fam = population[target[0]][target[1]] + t = keys.index(target) + new_carer = int(not fosters(fam)) + expected = np.zeros(len(keys)) + expected[t] = new_carer + same_household = np.array([h == target[0] for h, _ in keys]) + # Under Housing Benefit the child occupies the dwelling of each family + # liable for the rent if placed with a non-dependant, boarder or lodger. + hb_child_room = np.zeros(len(keys), dtype=bool) + if fam["role"] in OCCUPIER_ROLES: + hb_child_room = same_household & liable + hb_extra = hb_after - hb_before - expected + assert np.all((hb_extra == 0) | ((hb_extra == 1) & hb_child_room)) + uc_change = uc_after - uc_before + if added_child[2] == "foster": + assert np.array_equal(uc_change, expected) + else: + # The adopter's child counts as a child (reg 4A(1)(c)), in the + # adopter's family and, for a non-dependant adopter, in the claim + # counting the household's non-dependants. + child_room = np.zeros(len(keys), dtype=bool) + child_room[t] = True + if fam["role"] == "non_dependant": + child_room |= same_household & counted + extra = uc_change - expected + assert np.all((extra == 0) | ((extra == 1) & child_room)) + + @PROPERTY_SETTINGS @given(scenario()) -def test_bedrooms_match_an_independent_count_of_the_size_criteria(case): +# A non-dependant's foster child who requires overnight care: the renter's +# Housing Benefit overnight room (reg 13D(3A)(a)(iii); reg 21(3)). +@example( + ( + [ + [ + lone("head", 60), + dict( + role="non_dependant", + adults=[(32, False)], + children=[(6, False, "foster", True)], + between_placements=False, + ), + ] + ], + (0, 0), + dict(LOOKED_AFTER_QYP, is_looked_after_by_local_authority=False), + ) +) +def test_bedrooms_match_a_reference_count_of_the_size_criteria(case): population, target, person = case situation, keys = build(population, (target, person)) sim, uc, hb = bedrooms(situation) counted, liable = claim_roles(sim) - gains = has_own_uc_bedroom(sim, situation) - occupier_roles = ("non_dependant", "boarder", "lodger") - # 3. Reference count. + uc_additional = np.asarray(sim.calculate("LHA_additional_bedrooms", YEAR)) + hb_additional = np.asarray( + sim.calculate("housing_benefit_LHA_additional_bedrooms", YEAR) + ) + added = flags(person) + # 5. Reference count. for b, (h, f) in enumerate(keys): families = population[h] fam = families[f] - added = (h, f) == target - own_uc = int(added and gains[f"h{h}_f{f}_added"]) - own_hb = int(added) - outside_uc = outside_hb = 0 - hb_children = list(fam["children"]) + is_target = (h, f) == target + # Own members aged 16 or over who are not the claimant or partner. + uc_rooms = 1 + int(is_target and added["own_uc_room"]) + hb_rooms = 1 + int(is_target and not added["placed"]) + # Children: UC counts the children the family is responsible for + # (not foster children); HB counts occupiers (not children placed + # with the family as foster children or for adoption). + uc_children = [c for c in fam["children"] if c[2] != "foster"] + hb_children = [c for c in fam["children"] if c[2] == "own"] + # Overnight care: the family's own members, including a foster + # child (UC para 12(A1)(c); HB 13D(3A)(a)(iv)). + uc_overnight = hb_overnight = any(o for _, o in fam["adults"]) or any( + c[3] for c in fam["children"] + ) + if is_target and added["overnight"]: + uc_overnight |= added["fostered"] or not added["unclaimed"] + hb_overnight = True + uc_foster = fosters(fam) or (is_target and added["fostered"]) + hb_carer = fosters(fam) or (is_target and added["placed"]) for g, other in enumerate(families): if g == f: continue joins = target == (h, g) if counted[b] and other["role"] == "non_dependant": - # UC: each non-dependant who is not a child (adults are - # supplied as claimant or partner). - outside_uc += len(other["adults"]) - outside_uc += int(joins and gains[f"h{h}_f{g}_added"]) - if liable[b] and other["role"] in occupier_roles: - # HB: the occupier family's couple ((a)) or single adult - # ((b)), the added person ((b)) and its children. - outside_hb += 1 + int(joins) + uc_rooms += len(other["adults"]) + int(joins and not added["unclaimed"]) + uc_children += [c for c in other["children"] if c[2] != "foster"] + uc_overnight |= any(o for _, o in other["adults"]) or any( + c[3] for c in other["children"] if c[2] != "foster" + ) + uc_overnight |= joins and added["overnight"] and not added["unclaimed"] + if liable[b] and other["role"] in OCCUPIER_ROLES: + # HB reg 13D(3)(a), (b): the occupier family's couple or + # single adult has one bedroom, and the added person one. + # Reg 21(3) takes out only a child placed with the claimant + # or partner, so every child of the family counts. + hb_rooms += 1 + int(joins) hb_children += other["children"] - uc_children = fewest_rooms_for_children(fam["children"]) - assert uc[b] == 1 + own_uc + outside_uc + uc_children - assert hb[b] == 1 + own_hb + outside_hb + fewest_rooms_for_children(hb_children) + hb_overnight |= any(o for _, o in other["adults"]) or any( + c[3] for c in other["children"] + ) + hb_overnight |= joins and added["overnight"] + expected_uc_additional = int(uc_overnight) + int(uc_foster) + expected_hb_additional = int(hb_overnight) + int(hb_carer) + assert uc_additional[b] == expected_uc_additional + assert hb_additional[b] == expected_hb_additional + assert uc[b] == ( + uc_rooms + + fewest_rooms_for_children([c[:2] for c in uc_children]) + + expected_uc_additional + ) + assert hb[b] == ( + hb_rooms + + fewest_rooms_for_children([c[:2] for c in hb_children]) + + expected_hb_additional + ) def in_unit_non_dependants(sim): """Each person: aged 16 or over, neither the claimant nor partner, not a - Universal Credit qualifying young person, and not the household head - (UC Regs 2013 Sch 4 para 9(2), with (d) for the head, the householder - in whose name the accommodation is rented).""" + Universal Credit qualifying young person, not the household head (UC + Regs 2013 Sch 4 para 9(2), with (d) for the head, the householder in + whose name the accommodation is rented) and not the family's foster + child (para 9(2)(c)).""" age = np.asarray(sim.calculate("age", YEAR)) claimant_or_partner = np.asarray(sim.calculate("is_claimant_or_partner", YEAR)) qualifying = np.asarray( sim.calculate("is_qualifying_young_person_for_universal_credit", YEAR) ) household_head = np.asarray(sim.calculate("is_resolved_household_head", YEAR)) - return (age >= 16) & ~claimant_or_partner & ~qualifying & ~household_head + foster_child = np.asarray(sim.calculate("is_lha_foster_child", YEAR)) + return ( + (age >= 16) + & ~claimant_or_partner + & ~qualifying + & ~household_head + & ~foster_child + ) @PROPERTY_SETTINGS @given(scenario()) def test_every_in_unit_non_dependant_has_a_bedroom(case): population, target, person = case + person = without_overnight_care(person) situation, keys = build(population, (target, person)) sim, uc, _ = bedrooms(situation) marked = in_unit_non_dependants(sim) names = list(situation["people"]) - # 4. A marked member has a bedroom of their own: without them, their + # 6. A marked member has a bedroom of their own: without them, their # family has one fewer, and so does the claim counting the household's # non-dependants if they are in a non-dependant's family. Only the added # person can be marked: the generated adults are claimants or partners @@ -415,3 +660,61 @@ def test_every_in_unit_non_dependant_has_a_bedroom(case): sim_as_dependants, uc_as_dependants, _ = bedrooms(as_dependants) assert not in_unit_non_dependants(sim_as_dependants).any() assert np.array_equal(uc, uc_as_dependants) + + +def as_close_relative_adopters(situation): + return { + **situation, + "people": { + name: {**attributes, "adopter_is_foster_parent_or_close_relative": True} + for name, attributes in situation["people"].items() + }, + } + + +@PROPERTY_SETTINGS +@given(scenario()) +def test_a_close_relative_adopter_loses_only_the_foster_room(case): + population, target, person = case + situation, keys = build(population, (target, person)) + added = flags(person) + outputs = [] + for variant in (situation, as_close_relative_adopters(situation)): + sim, uc, hb = bedrooms(variant) + outputs.append( + dict( + uc=uc, + hb=hb, + foster=np.asarray( + sim.calculate("lha_renter_meets_foster_parent_condition", YEAR) + ), + **{ + name: np.asarray(sim.calculate(name, YEAR)) + for name in ( + "is_child_or_qualifying_young_person_for_universal_credit", + "is_child_or_young_person_placed_with_family", + "is_housing_benefit_qualifying_parent_or_carer", + "housing_benefit_LHA_additional_bedrooms", + ) + }, + ) + ) + before, after = outputs + # 7. The foster parent condition without the adoption route: a foster + # child, an approved foster parent between placements, or the added + # person placed as a foster child. + expected_foster = np.array( + [ + population[h][f]["between_placements"] + or any(c[2] == "foster" for c in population[h][f]["children"]) + or ((h, f) == target and added["fostered"]) + for h, f in keys + ] + ) + assert np.array_equal(after["foster"], expected_foster) + lost = before["foster"] & ~after["foster"] + assert np.array_equal(before["uc"] - after["uc"], lost.astype(float)) + assert np.array_equal(before["hb"], after["hb"]) + for name in before: + if name not in ("uc", "hb", "foster"): + assert np.array_equal(before[name], after[name]) diff --git a/policyengine_uk/tests/test_rent_of_sharers_boarders_and_lodgers_properties.py b/policyengine_uk/tests/test_rent_of_sharers_boarders_and_lodgers_properties.py index 0b68d8b3b1..37374fc9c4 100644 --- a/policyengine_uk/tests/test_rent_of_sharers_boarders_and_lodgers_properties.py +++ b/policyengine_uk/tests/test_rent_of_sharers_boarders_and_lodgers_properties.py @@ -404,7 +404,10 @@ def test_no_op_without_sharers_boarders_or_lodgers(population): head_claims = per_household(sim, claims_uc) > 0 assert np.allclose(head_deductions[head_claims], outside[head_claims], atol=0.01) # Bedrooms: what the head's family would have alone, plus one for each - # person aged 16 or over outside it. + # person aged 16 or over outside it. Non-dependants' children under 16 + # share rooms with the head's own children (UC Sch 4 para 10(1)(d)-(f)); + # test_lha_bedroom_young_people_properties.py counts those, so this check + # covers households with no child outside the head's family. alone = [dict(house, others=[]) for house in population] alone_situation, _ = build(alone) alone_sim = Simulation(situation=alone_situation) @@ -413,10 +416,14 @@ def test_no_op_without_sharers_boarders_or_lodgers(population): adults_outside = sim.map_result( aged_16_or_over & ~person_head_family, "person", "household" ) + children_outside = sim.map_result( + ~aged_16_or_over & ~person_head_family, "person", "household" + ) + checked = head_claims & (children_outside == 0) head_bedrooms = per_household(sim, calc(sim, "LHA_allowed_bedrooms") * head) assert np.allclose( - head_bedrooms[head_claims], - (bedrooms_alone + adults_outside)[head_claims], + head_bedrooms[checked], + (bedrooms_alone + adults_outside)[checked], ) # Council Tax Reduction: one claim, the household head's family's, on its # own scheme; every family's reduction is simulated or reported as that diff --git a/policyengine_uk/variables/gov/dwp/LHA_additional_bedrooms.py b/policyengine_uk/variables/gov/dwp/LHA_additional_bedrooms.py new file mode 100644 index 0000000000..22cb5296f3 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/LHA_additional_bedrooms.py @@ -0,0 +1,66 @@ +from policyengine_uk.model_api import * + + +class LHA_additional_bedrooms(Variable): + value_type = float + entity = BenUnit + label = "Additional bedrooms in the Universal Credit size criteria" + documentation = ( + "One additional bedroom if anyone in the renter's extended benefit " + "unit, or a foster child of the renter, meets the overnight care " + "condition (see meets_lha_overnight_care_condition), however many " + "people do; and one if the renter or a joint renter meets the foster " + "parent condition (see lha_renter_meets_foster_parent_condition), " + "however many children are placed. The extended benefit unit " + "includes the household's non-dependants and their children, in the " + "one Universal Credit claim that counts them (see " + "uc_non_dependants_counted). " + "Before 1 April 2017 only the renter could meet the overnight care " + "condition. " + "The disabled child and disabled person conditions, for children or " + "couples who cannot share a bedroom, are not modelled." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/9", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/10", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + ) + + def formula(benunit, period, parameters): + person = benunit.members + overnight_care = person("meets_lha_overnight_care_condition", period) + responsible = person( + "is_child_or_qualifying_young_person_for_universal_credit", period + ) + no_one_responsible = ( + person("is_child_for_universal_credit", period) + | person("is_qualifying_young_person_for_universal_credit", period) + ) & ~responsible + # UC Regs 2013 Sch 4 para 12(A1)(a)-(b): the renter and the members of + # their extended benefit unit, which excludes a child or qualifying + # young person no one is responsible for (paras 9(1) and 9(2)(g)); + # (c): a child for whom the renter meets the foster parent condition. + foster_child = person("is_lha_foster_child", period) + own = overnight_care & (~no_one_responsible | foster_child) + # Para 9(1)(c): non-dependants from other families, and their + # children. + other = ( + overnight_care + & person("is_non_dependant_of_household_head", period) + & ~no_one_responsible + ) + # Universal Credit counts the household's non-dependants in one claim + # only (para 9(2)(f); see uc_non_dependants_counted). + counted = benunit("uc_non_dependants_counted", period) + others = counted * benunit.max(person.household.sum(other)) + # Before 1 April 2017 (SI 2017/213 reg 6) only the renter could meet + # the overnight care condition. + p = parameters(period).gov.dwp.LHA + renter = person("is_claimant_or_partner", period) + own = where(p.overnight_care_beyond_claimant, own, overnight_care & renter) + others = others * p.overnight_care_beyond_claimant + # Para 12(9)(a)-(b): one bedroom for each condition met. + overnight_room = benunit.any(own) | (others > 0) + foster_room = benunit("lha_renter_meets_foster_parent_condition", period) + return 1.0 * overnight_room + 1.0 * foster_room diff --git a/policyengine_uk/variables/gov/dwp/LHA_allowed_bedrooms.py b/policyengine_uk/variables/gov/dwp/LHA_allowed_bedrooms.py index 00fdbd6fe2..7d60763c28 100644 --- a/policyengine_uk/variables/gov/dwp/LHA_allowed_bedrooms.py +++ b/policyengine_uk/variables/gov/dwp/LHA_allowed_bedrooms.py @@ -2,11 +2,11 @@ def child_bedrooms(boys_under_10, boys_10_to_15, girls_under_10, girls_10_to_15): - """Bedrooms for children under 16, given counts by sex and age band. + """The fewest bedrooms that hold children two to a room, where two + children may share if they are of the same sex or both under 10. - Children must share rooms in pairs unless they are opposite-sex and one - is 10 or over. This is the minimum number of bedrooms that allocates them - under those rules. + The arguments count children under 16: boys and girls under 10, and boys + and girls aged 10 to 15. """ # First, have over-10s share where possible over_10_rooms = (boys_10_to_15 + 1) // 2 + (girls_10_to_15 + 1) // 2 @@ -21,19 +21,42 @@ def child_bedrooms(boys_under_10, boys_10_to_15, girls_under_10, girls_10_to_15) return over_10_rooms + under_10_rooms -def bedrooms_for_children(benunit, period): - """Bedrooms for the family's own children under 16.""" +def bedrooms_for_children( + benunit, period, own_child=None, other_child=None, counts_other_children=None +): + """Bedrooms for the children under 16 in the family's size criteria. + + ``own_child`` marks the family's members counted as its children (by + default, every member under 16). ``other_child`` marks people under 16 in + other families of the household who count in this family's size + criteria, such as a non-dependant's child; they share rooms with the + family's own children. ``counts_other_children`` marks the families that + count them (by default, every family). The children are allotted to the + fewest bedrooms with child_bedrooms. + """ person = benunit.members age = person("age", period) male = person("is_male", period) under_16 = age < 16 under_10 = age < 10 - child_over_10 = ~under_10 & under_16 + if own_child is None: + own_child = under_16 + own_child = own_child & under_16 + + def count(group): + own = benunit.sum(own_child & group) + if other_child is None: + return own + others = benunit.max(person.household.sum(other_child & under_16 & group)) + if counts_other_children is None: + return own + others + return own + where(counts_other_children, others, 0) + return child_bedrooms( - benunit.sum(under_10 & male), - benunit.sum(child_over_10 & male), - benunit.sum(under_10 & ~male), - benunit.sum(child_over_10 & ~male), + count(under_10 & male), + count(~under_10 & under_16 & male), + count(under_10 & ~male), + count(~under_10 & under_16 & ~male), ) @@ -42,27 +65,37 @@ class LHA_allowed_bedrooms(Variable): entity = BenUnit label = "The number of bedrooms covered by LHA for the benefit unit" documentation = ( - "Universal Credit size criteria: one bedroom for the renter or " - "couple, one for each qualifying young person the renter is " - "responsible for, one for each other member of the benefit unit aged " - "16 or over who is not the claimant, partner or household head, one " - "for each non-dependant aged 16 or over from another family, and the " - "children's bedrooms. The formula treats the household head as liable " - "for the rent, so a head who does not claim is not a non-dependant " - "(para 9(2)(d)); a head who is a qualifying young person the renter is " - "responsible for keeps their bedroom. A qualifying " - "young person no one is responsible for, such as one looked after by " - "a local authority, is not a non-dependant and has no bedroom, in " - "this family or another. Joint tenants and other sharers of the rent, " - "boarders and lodgers are not non-dependants, so they add no bedroom " - "to anyone's entitlement; the household's non-dependants count in one " + "Universal Credit size criteria for the renter's extended benefit " + "unit: one bedroom for the renter or couple, one for each qualifying " + "young person the renter is responsible for, one for each other " + "member of the benefit unit aged 16 or over who is not the claimant, " + "partner, household head or a foster child, one for each " + "non-dependant aged 16 or over from another family, the children's " + "bedrooms, and the additional bedrooms for overnight care and foster " + "parents (see LHA_additional_bedrooms). The formula treats the " + "household head as liable for the rent, so a head who does not claim " + "is not a non-dependant (para 9(2)(d)); a head who is a qualifying " + "young person the renter is responsible for keeps their bedroom. The " + "children are the renter's own children and the children of the " + "household's non-dependants, such as a grandchild whose parent lives " + "with the renter; they share rooms with each other. A child or " + "qualifying young person no one is responsible for, such as a foster " + "child or another child looked after by a local authority, is not a " + "non-dependant and has no bedroom, in this family or another; a " + "child placed for adoption is the adopter's responsibility (reg " + "4A(1)(c)) and counts. Joint tenants and other sharers of the rent, " + "boarders and lodgers are not non-dependants, so neither they nor " + "their children add a bedroom to anyone's entitlement; the " + "household's non-dependants and their children count in one " "Universal Credit claim only (see uc_non_dependants_counted)." ) definition_period = YEAR reference = ( "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/9", "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/10", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", "https://www.legislation.gov.uk/uksi/2013/376/regulation/4", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/4A", "https://www.legislation.gov.uk/uksi/2013/376/regulation/5", ) @@ -72,38 +105,66 @@ def formula(benunit, period, parameters): aged_16_or_over = person("age", period) >= 16 family_member = aged_16_or_over & ~person("is_claimant_or_partner", period) qualifying = person("is_qualifying_young_person_for_universal_credit", period) + # UC Regs 2013 reg 4: a person is responsible for a child or + # qualifying young person who normally lives with them, but no one is + # responsible for one looked after by a local authority (reg 4(6)(a)), + # such as a foster child, unless reg 4A applies (for example (1)(c), a + # child placed for adoption). responsible = person( "is_child_or_qualifying_young_person_for_universal_credit", period ) - # UC Regs 2013 Sch 4 para 9(2)(g): a qualifying young person for whom - # no one is responsible (reg 4(6), such as one looked after by a local - # authority) is not a non-dependant, in this family or another. - no_one_responsible = qualifying & ~responsible + # Sch 4 para 9(2)(g): a child or qualifying young person for whom no + # one is responsible is not a non-dependant, in this family or + # another. + no_one_responsible = ( + person("is_child_for_universal_credit", period) | qualifying + ) & ~responsible # Para 10(1)(b): a qualifying young person for whom the renter is # responsible (regs 4 and 5). qualifying_young_person = family_member & responsible # Para 10(1)(c) with para 9(2): any other member aged 16 or over is a - # non-dependant with a bedroom, unless they head the household. The - # formula reads the household head (is_resolved_household_head, the - # householder in whose name the accommodation is rented) as liable to - # make payments on a commercial basis for their occupation, so para - # 9(2)(d) stops them being a non-dependant. A head who does not claim - # is not a renter either (paras 1(2) and 9(1)(a)). A head who is a - # qualifying young person the renter is responsible for keeps the - # para 10(1)(b) bedroom above (para 9(1)(b)). + # non-dependant with a bedroom, unless they head the household or are + # the renter's foster child (para 9(2)(c), 9(3); see + # is_lha_foster_child). The formula reads the household head + # (is_resolved_household_head, the householder in whose name the + # accommodation is rented) as liable to make payments on a commercial + # basis for their occupation, so para 9(2)(d) stops them being a + # non-dependant. A head who does not claim is not a renter either + # (paras 1(2) and 9(1)(a)). A head who is a qualifying young person + # the renter is responsible for keeps the para 10(1)(b) bedroom above + # (para 9(1)(b)). family_non_dependant = ( - family_member & ~qualifying & ~person("is_resolved_household_head", period) + family_member + & ~qualifying + & ~person("is_resolved_household_head", period) + & ~person("is_lha_foster_child", period) ) family_rooms = benunit.sum(qualifying_young_person | family_non_dependant) - # Para 10(1)(c): a non-dependant from another family who is not a - # child. + # Para 9(1)(c) and 9(2): people of other families who are + # non-dependants. A non-dependant's own child is their responsibility + # (reg 4(2)) and so a non-dependant too; para 9(2)(g) excludes a + # child or qualifying young person no one is responsible for, such as + # a non-dependant's foster child. non_dependant = ( - aged_16_or_over - & ~no_one_responsible - & person("is_non_dependant_of_household_head", period) + person("is_non_dependant_of_household_head", period) & ~no_one_responsible ) counted = benunit("uc_non_dependants_counted", period) - non_dependants = counted * benunit.max(person.household.sum(non_dependant)) - return ( - 1 + family_rooms + non_dependants + bedrooms_for_children(benunit, period) + # Para 10(1)(c): a non-dependant from another family who is not a + # child. + non_dependants = counted * benunit.max( + person.household.sum(non_dependant & aged_16_or_over) + ) + # Para 10(1)(d)-(f): the children in the extended benefit unit, the + # renter's own and their non-dependants', allotted to the fewest + # bedrooms (para 10(2)). A foster child is in no one's extended + # benefit unit (paras 9(1)(b), 9(2)(c) and 9(3); reg 4(6)(a)). + children = bedrooms_for_children( + benunit, + period, + own_child=responsible, + other_child=non_dependant, + counts_other_children=counted, ) + # Para 10(3)(b) and para 12: additional bedrooms. + additional = benunit("LHA_additional_bedrooms", period) + return 1 + family_rooms + non_dependants + children + additional diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_has_non_dependant.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_has_non_dependant.py index a5904137be..9880fa79f2 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_has_non_dependant.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_has_non_dependant.py @@ -7,7 +7,8 @@ class housing_benefit_has_non_dependant(Variable): label = "Has a non-dependant residing with them (Housing Benefit)" documentation = ( "Someone in this benefit unit who is neither a claimant or partner " - "nor a child or young person, or, for a family liable for the " + "nor a child or young person (including one placed with the family " + "as a foster child or for adoption), or, for a family liable for the " "household's rent (the household head's or a sharer's), anyone in " "the household who is a non-dependant (see " "is_non_dependant_of_household_head). A non-dependant normally " @@ -18,6 +19,7 @@ class housing_benefit_has_non_dependant(Variable): definition_period = YEAR reference = ( "https://www.legislation.gov.uk/uksi/2006/213/regulation/3", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", "https://www.legislation.gov.uk/uksi/2006/213/regulation/74", ) @@ -26,9 +28,15 @@ def formula(benunit, period, parameters): person = benunit.members claimant_or_partner = person("is_claimant_or_partner", period) age = person("age", period) - child_or_young_person = person( - "is_child_or_young_person_for_legacy_benefits", period - ) | ((age >= 16) & (age < 17)) + # Reg 3(2)(c): a child or young person living with the claimant who + # is not a member of the household by virtue of reg 21, such as one + # placed with the claimant or partner as a foster child or for + # adoption (reg 21(3)), is not a non-dependant. + child_or_young_person = ( + person("is_child_or_young_person_for_legacy_benefits", period) + | person("is_child_or_young_person_placed_with_family", period) + | ((age >= 16) & (age < 17)) + ) within_benefit_unit = benunit.any(~claimant_or_partner & ~child_or_young_person) liable_family = benunit.any(person("is_liable_for_household_rent", period)) non_dependants = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_severe_disability_premium_applies.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_severe_disability_premium_applies.py index 0e0ac10e22..aa247a5dcb 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_severe_disability_premium_applies.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_severe_disability_premium_applies.py @@ -45,7 +45,12 @@ def formula(benunit, period, parameters): # housing_benefit_has_non_dependant. age = person("age", period) adult_non_dependant = (age >= 18) & ~qualifying & ~blind - young_person = person("is_child_or_young_person_for_legacy_benefits", period) + # A child or young person placed with the family as a foster child or + # for adoption is not a non-dependant either (reg 3(2)(c) with reg + # 21(3)). + young_person = person( + "is_child_or_young_person_for_legacy_benefits", period + ) | person("is_child_or_young_person_placed_with_family", period) within = benunit.any(adult_non_dependant & ~claimant_or_partner & ~young_person) liable_family = benunit.any(person("is_liable_for_household_rent", period)) outside = benunit.max( diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_additional_bedrooms.py b/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_additional_bedrooms.py new file mode 100644 index 0000000000..6d0b7bce5e --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_additional_bedrooms.py @@ -0,0 +1,69 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_LHA_additional_bedrooms(Variable): + value_type = float + entity = BenUnit + label = "Additional bedrooms in the Housing Benefit size criteria" + documentation = ( + "One additional bedroom if the claimant, partner, another occupier " + "or a child placed with the claimant needs overnight care (see " + "meets_lha_overnight_care_condition), and one if the claimant or " + "partner is a qualifying parent or carer (see " + "is_housing_benefit_qualifying_parent_or_carer): two if both. " + "Occupiers outside the family count for a family liable for the " + "rent: non-dependants, boarders and lodgers and their children, " + "including a child placed with one of them as a foster child or for " + "adoption, but not a sharer of the rent. A child placed with the " + "claimant or partner counts as one for whom they are a qualifying " + "parent or carer. Before 1 April 2017 only the claimant and partner " + "counted for overnight care. The definitions require a bedroom in " + "the dwelling for " + "the carer or the foster child; the model does not observe the " + "dwelling's bedrooms and assumes there is one. Children and couples " + "who cannot share a bedroom because of disability are not modelled." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/13D", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/13D", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + ) + + def formula(benunit, period, parameters): + person = benunit.members + overnight_care = person("meets_lha_overnight_care_condition", period) + # HB Regs 2006 reg 13D(3A)(a)(iii): "a person (other than the + # claimant or the claimant's partner) who occupies the claimant's + # dwelling as their home". The model counts the occupiers of the + # size criteria (13D(12); see housing_benefit_LHA_allowed_bedrooms): + # for a claim by a family liable for the rent, everyone in the + # families not liable for it (non-dependants, boarders and lodgers + # and their children), including a child placed with one of them as + # a foster child or for adoption, since reg 21(3) takes out only a + # child placed with the claimant or partner. A joint tenant outside + # the claimant's household is not counted: A21/2013 para 25 bases + # private-sector joint tenants' size criteria on each tenant's own + # household. A boarder's or lodger's own claim counts only their own + # family. + liable_family = person.benunit.any( + person("is_liable_for_household_rent", period) + ) + other = overnight_care & ~liable_family + is_liable_claim = benunit.any(person("is_liable_for_household_rent", period)) + others = where(is_liable_claim, benunit.max(person.household.sum(other)), 0) + # Reg 13D(3A)(a)(i)-(iv): the claimant, partner, other members of the + # family, and a child or young person for whom the claimant or + # partner is a qualifying parent or carer. Before 1 April 2017 (SI + # 2017/213 reg 4) only the claimant and partner. + p = parameters(period).gov.dwp.LHA + claimant = person("is_claimant_or_partner", period) + own = where( + p.overnight_care_beyond_claimant, overnight_care, overnight_care & claimant + ) + others = others * p.overnight_care_beyond_claimant + overnight_room = benunit.any(own) | (others > 0) + # Reg 13D(3A)(b). + carer_room = benunit("is_housing_benefit_qualifying_parent_or_carer", period) + # Reg 13D(3B): two additional bedrooms where both apply. + return 1.0 * overnight_room + 1.0 * carer_room diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_allowed_bedrooms.py b/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_allowed_bedrooms.py index a5b667f8d0..baa3b8e976 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_allowed_bedrooms.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit_LHA_allowed_bedrooms.py @@ -11,20 +11,31 @@ class housing_benefit_LHA_allowed_bedrooms(Variable): documentation = ( "Housing Benefit size criteria over the claim's occupiers: one " "bedroom for each couple, one for each other occupier aged 16 or " - "over, and the children's bedrooms, pairing children across all the " - "occupiers. Occupiers are everyone who lives in the dwelling as their " - "home except a joint tenant outside the claimant's household. For " - "the household head's family or a sharer's, that is its own family, " - "the household's non-dependants and anyone paying the householder " - "rent (but not the other families liable for the rent). A boarder's " - "or lodger's own claim counts only their own family. Couples who " - "cannot share a bedroom and the additional bedrooms for overnight " - "care or foster parents are not modelled." + "over, the children's bedrooms, pairing children across all the " + "occupiers, and the additional bedrooms for overnight care and " + "qualifying parents or carers (see " + "housing_benefit_LHA_additional_bedrooms). Occupiers are everyone " + "who lives in the dwelling as their home except a joint tenant " + "outside the claimant's household. For the household head's family " + "or a sharer's, that is its own family, the household's " + "non-dependants and anyone paying the householder rent, with their " + "children (but not the other families liable for the rent). A " + "boarder's or lodger's own claim counts only their own family. A " + "child or young person placed with the claimant or partner as a " + "foster child or for adoption does not occupy the claimant's " + "dwelling, so the claimant's own claim leaves them out; a child " + "placed with a non-dependant, boarder or lodger occupies the " + "claimant's dwelling and counts in the claimant's size criteria. " + "Couples and children who cannot share a bedroom are not modelled." ) definition_period = YEAR reference = ( "https://www.legislation.gov.uk/uksi/2006/213/regulation/13D", "https://www.legislation.gov.uk/uksi/2006/214/regulation/13D", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/21", ) def formula(benunit, period, parameters): @@ -39,24 +50,35 @@ def formula(benunit, period, parameters): # non-dependants and people paying the householder. other = ~liable_family is_liable_claim = benunit.any(person("is_liable_for_household_rent", period)) + # HB Regs 2006 reg 21(3): a child or young person placed with the + # claimant or partner as a foster child or for adoption does not + # occupy the claimant's dwelling. Every limb names a placement "with + # the claimant or his partner", so a child placed with a + # non-dependant, boarder or lodger is one of the persons who occupy + # the claimant's dwelling as their home (13D(12)) and counts in the + # claimant's size criteria, while the carer's own claim leaves them + # out. + placed = person("is_child_or_young_person_placed_with_family", period) def occupiers_total(values): - own = benunit.sum(values) - others = benunit.max(person.household.sum(values * other)) + own = benunit.sum(values & ~placed) + others = benunit.max(person.household.sum(values & other)) return own + where(is_liable_claim, others, 0) - # 13D(3)(zb), (a): one bedroom for each couple or single claimant. + # 13D(3)(zb), (a): one bedroom for each couple or single claimant. A + # family counts as a couple only where both members are present and + # it is a couple (is_couple), so the halves always pair. + couple = (person.benunit.sum(claimant_or_partner) == 2) & person.benunit( + "is_couple", period + ) adult_units = ( - occupiers_total( - claimant_or_partner & (person.benunit.sum(claimant_or_partner) > 0) - ) - - occupiers_total( - claimant_or_partner & (person.benunit.sum(claimant_or_partner) == 2) - ) - / 2 + occupiers_total(claimant_or_partner) + - occupiers_total(claimant_or_partner & couple) / 2 ) # 13D(3)(b): any other person who is not a child. other_adults = occupiers_total((age >= 16) & ~claimant_or_partner) + # 13D(3)(c)-(e): the occupiers' children, the claimant's own and + # other families', share rooms with each other. under_16 = age < 16 male = person("is_male", period) under_10 = age < 10 @@ -66,4 +88,6 @@ def occupiers_total(values): occupiers_total(under_10 & ~male), occupiers_total(~under_10 & under_16 & ~male), ) - return max_(adult_units, 1) + other_adults + rooms_for_children + # 13D(3A) and (3B): additional bedrooms. + additional = benunit("housing_benefit_LHA_additional_bedrooms", period) + return max_(adult_units, 1) + other_adults + rooms_for_children + additional diff --git a/policyengine_uk/variables/gov/dwp/income_support_eligible.py b/policyengine_uk/variables/gov/dwp/income_support_eligible.py index 480ae5f2bf..2eae2ed91c 100644 --- a/policyengine_uk/variables/gov/dwp/income_support_eligible.py +++ b/policyengine_uk/variables/gov/dwp/income_support_eligible.py @@ -18,7 +18,8 @@ class income_support_eligible(Variable): "claimant must be under the " "qualifying age for State Pension Credit, fall within a prescribed " "category the model covers (a carer, a lone parent of a young child, " - "or a single claimant with a child placed by a local authority), not " + "or a single claimant with a child placed by a local authority or " + "for adoption), not " "be engaged in remunerative work (16 hours a week or more, unless a " "carer) and not be entitled to Employment and Support Allowance or " "Jobseeker's Allowance. The partner must not be engaged in " @@ -52,6 +53,8 @@ class income_support_eligible(Variable): "https://www.legislation.gov.uk/uksi/1987/1967/regulation/5", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/6", "https://www.legislation.gov.uk/uksi/1987/1967/schedule/1B", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/1B/paragraph/2", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/1B/paragraph/2A", "https://www.legislation.gov.uk/uksi/1987/1968/regulation/4", "https://www.legislation.gov.uk/uksi/2014/1230/regulation/6A", ) @@ -79,9 +82,12 @@ def formula(benunit, period, parameters): # says "under 5", and the model retains the existing inclusive # comparison pending a separate decision on the annual-age model. # Para 2 is "a single claimant or a lone parent with whom a child is - # placed" by a local authority or voluntary organisation. A child is - # under 16 (SSCBA s.137(1)). The model's proxy is a member under 16 - # flagged is_looked_after_by_local_authority; the flag also marks a + # placed" by a local authority or voluntary organisation, and para 2A + # the same where an adoption agency places the child for adoption. A + # child is under 16 (SSCBA s.137(1)). The model's test is a member + # under 16 placed with the family + # (is_child_or_young_person_placed_with_family): a looked-after child + # or one placed for adoption. The looked-after flag also marks a # child living away in a local authority's care, whom para 2 does not # cover, and the model cannot tell the two apart. Para 4 is a carer. youngest_child_5_or_under = ( @@ -92,7 +98,7 @@ def formula(benunit, period, parameters): benunit("is_lone_parent", period) & youngest_child_5_or_under ) placed_child = ( - person("is_looked_after_by_local_authority", period) + person("is_child_or_young_person_placed_with_family", period) & person("is_child_for_child_benefit", period) & ~claimant_or_partner ) diff --git a/policyengine_uk/variables/gov/dwp/is_child_or_qualifying_young_person_for_child_tax_credit.py b/policyengine_uk/variables/gov/dwp/is_child_or_qualifying_young_person_for_child_tax_credit.py index fd0a472e49..ebada49218 100644 --- a/policyengine_uk/variables/gov/dwp/is_child_or_qualifying_young_person_for_child_tax_credit.py +++ b/policyengine_uk/variables/gov/dwp/is_child_or_qualifying_young_person_for_child_tax_credit.py @@ -42,5 +42,5 @@ def formula(person, period, parameters): return ( child_or_qualifying_young_person & ~person("is_claimant_or_partner", period) - & ~person("is_looked_after_by_local_authority", period) + & ~person("is_looked_after_child", period) ) diff --git a/policyengine_uk/variables/gov/dwp/is_child_or_young_person_for_legacy_benefits.py b/policyengine_uk/variables/gov/dwp/is_child_or_young_person_for_legacy_benefits.py index 7091a57918..b456a6ba9c 100644 --- a/policyengine_uk/variables/gov/dwp/is_child_or_young_person_for_legacy_benefits.py +++ b/policyengine_uk/variables/gov/dwp/is_child_or_young_person_for_legacy_benefits.py @@ -11,8 +11,10 @@ class is_child_or_young_person_for_legacy_benefits(Variable): (SSCBA 1992 s.142), excluding young persons entitled to a benefit in their own right. That is the Child Benefit child or qualifying young person test, restricted to members who are not the claimant or partner. - A child or young person placed with the claimant by a local authority is - not a member of the claimant's household (IS reg 16(4); HB reg 21(3)). + A child or young person placed with the claimant by a local authority, + such as a foster child, or placed for adoption is not a member of the + claimant's household (IS reg 16(4); JSA reg 78(4); ESA reg 156(5); HB reg + 21(3)). """ value_type = bool @@ -28,11 +30,13 @@ class is_child_or_young_person_for_legacy_benefits(Variable): "https://www.legislation.gov.uk/uksi/2012/2885/regulation/2", "https://www.legislation.gov.uk/uksi/1987/1967/regulation/16", "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + "https://www.legislation.gov.uk/uksi/1996/207/regulation/78", + "https://www.legislation.gov.uk/uksi/2008/794/regulation/156", ) def formula(person, period, parameters): return ( person("is_child_or_qualifying_young_person_for_child_benefit", period) & ~person("is_claimant_or_partner", period) - & ~person("is_looked_after_by_local_authority", period) + & ~person("is_child_or_young_person_placed_with_family", period) ) diff --git a/policyengine_uk/variables/gov/dwp/is_child_or_young_person_placed_with_family.py b/policyengine_uk/variables/gov/dwp/is_child_or_young_person_placed_with_family.py new file mode 100644 index 0000000000..4512a69058 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/is_child_or_young_person_placed_with_family.py @@ -0,0 +1,54 @@ +from policyengine_uk.model_api import * + + +class is_child_or_young_person_placed_with_family(Variable): + value_type = bool + entity = Person + label = "Child or young person placed with the family (foster or adoption)" + documentation = ( + "A child or young person (the Child Benefit definition) who is not " + "the claimant or partner and is placed with their benefit unit by a " + "local authority, such as a foster child (see " + "is_looked_after_by_local_authority), or placed for adoption (see " + "is_placed_for_adoption). Under Income Support, income-based " + "Jobseeker's Allowance, income-related Employment and Support " + "Allowance and Housing Benefit they are not a member of the " + "claimant's household, and under Housing Benefit they do not occupy " + "the claimant's dwelling. Since SI 2017/901, HB reg 21(3)(a) refers " + "to a placement under section 22C(2) of the Children Act 1989, " + "which is placement with a parent; foster placements are under " + "s.22C(5)-(6), and the earlier text referred to s.23(2)(a). The " + "model treats foster placements as within reg 21(3), as the " + "'qualifying parent or carer' definition presupposes and as the " + "English pensioner and Welsh council tax reduction rules say " + "expressly ('section 22C'; 'section 22C or 23(2)(a)'). HB reg " + "19(2)(c) excludes from 'young person' anyone to whom the Children " + "(Leaving Care) Act 2000 s.6 applies, such as an eligible child aged " + "16 or 17 who has been looked after for 13 weeks since age 14; such " + "a person is an occupier, not placed. The model has no input for " + "that and treats every looked-after qualifying young person as " + "placed." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/21", + "https://www.legislation.gov.uk/uksi/1987/1967/regulation/16", + "https://www.legislation.gov.uk/uksi/1996/207/regulation/78", + "https://www.legislation.gov.uk/uksi/2008/794/regulation/156", + "https://www.legislation.gov.uk/uksi/2012/2885/regulation/8", + "https://www.legislation.gov.uk/wsi/2013/3029/regulation/8", + "https://assets.publishing.service.gov.uk/media/5a758238ed915d6faf2b38a2/lha-guidance-manual.pdf", + ) + + def formula(person, period, parameters): + # HB Regs 2006 reg 21(3)(a)-(c); IS Regs 1987 reg 16(4); JSA Regs + # 1996 reg 78(4); ESA Regs 2008 reg 156(5). + placed = person("is_looked_after_child", period) | person( + "is_placed_for_adoption", period + ) + return ( + placed + & person("is_child_or_qualifying_young_person_for_child_benefit", period) + & ~person("is_claimant_or_partner", period) + ) diff --git a/policyengine_uk/variables/gov/dwp/is_housing_benefit_qualifying_parent_or_carer.py b/policyengine_uk/variables/gov/dwp/is_housing_benefit_qualifying_parent_or_carer.py new file mode 100644 index 0000000000..d958787359 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/is_housing_benefit_qualifying_parent_or_carer.py @@ -0,0 +1,37 @@ +from policyengine_uk.model_api import * + + +class is_housing_benefit_qualifying_parent_or_carer(Variable): + value_type = bool + entity = BenUnit + label = "Housing Benefit claimant or partner is a qualifying parent or carer" + documentation = ( + "Whether the claimant or partner has a child or young person placed " + "with them as a foster child or for adoption (see " + "is_child_or_young_person_placed_with_family), or is an approved " + "foster parent who has had no child placed with them for at most 52 " + "weeks (is_approved_foster_parent_without_placement). The claimant " + "gets one additional bedroom, and is not a young individual for the " + "shared accommodation rate. The definition also requires a bedroom " + "in the dwelling additional to those the occupiers use; the model " + "does not observe the dwelling's bedrooms and assumes there is one." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/13D", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + ) + + def formula(benunit, period, parameters): + person = benunit.members + # HB Regs 2006 reg 2(1), "qualifying parent or carer", (a): a child + # or young person placed with them as mentioned in reg 21(3). + placed = person("is_child_or_young_person_placed_with_family", period) + # (b): an approved foster parent with no placement for at most 52 + # weeks. + between_placements = person("is_claimant_or_partner", period) & person( + "is_approved_foster_parent_without_placement", period + ) + return benunit.any(placed | between_placements) diff --git a/policyengine_uk/variables/gov/dwp/is_housing_benefit_young_individual.py b/policyengine_uk/variables/gov/dwp/is_housing_benefit_young_individual.py index f66e7af8ee..d54721850a 100644 --- a/policyengine_uk/variables/gov/dwp/is_housing_benefit_young_individual.py +++ b/policyengine_uk/variables/gov/dwp/is_housing_benefit_young_individual.py @@ -7,17 +7,29 @@ class is_housing_benefit_young_individual(Variable): label = "Young individual (Housing Benefit)" documentation = ( "A single claimant (no partner and not a lone parent) under the " - "shared accommodation age threshold. The exceptions for a housing " - "association landlord, care leavers, former hostel residents, " - "offenders under multi-agency management, people who need overnight " - "care, qualifying parents or carers, victims of domestic violence " - "and of modern slavery are not identified." + "shared accommodation age threshold, other than one who requires " + "overnight care (see meets_lha_overnight_care_condition) or is a " + "qualifying parent or carer (see " + "is_housing_benefit_qualifying_parent_or_carer). The exceptions for " + "a housing association landlord, care leavers, former hostel " + "residents, offenders under multi-agency management, and victims of " + "domestic violence and of modern slavery are not identified." ) definition_period = YEAR reference = "https://www.legislation.gov.uk/uksi/2006/213/regulation/2" def formula(benunit, period, parameters): threshold = parameters(period).gov.dwp.LHA.shared_accommodation_age_threshold - return benunit("is_single_person", period) & ( - benunit("eldest_claimant_or_partner_age", period) < threshold + person = benunit.members + # HB Regs 2006 reg 2(1), "young individual": not a claimant who is a + # person who requires overnight care or a qualifying parent or carer. + requires_overnight_care = benunit.any( + person("is_claimant_or_partner", period) + & person("meets_lha_overnight_care_condition", period) + ) + return ( + benunit("is_single_person", period) + & (benunit("eldest_claimant_or_partner_age", period) < threshold) + & ~requires_overnight_care + & ~benunit("is_housing_benefit_qualifying_parent_or_carer", period) ) diff --git a/policyengine_uk/variables/gov/dwp/is_lha_foster_child.py b/policyengine_uk/variables/gov/dwp/is_lha_foster_child.py new file mode 100644 index 0000000000..aeb6da3f1b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/is_lha_foster_child.py @@ -0,0 +1,33 @@ +from policyengine_uk.model_api import * + + +class is_lha_foster_child(Variable): + value_type = bool + entity = Person + label = "Foster child in the Universal Credit size criteria" + documentation = ( + "A person under 18 looked after by a local authority and placed with " + "the claimant or partner of their benefit unit. The renter is their " + "foster parent (UC Regs 2013 reg 2, a person with whom a child is " + "placed under the care planning regulations, where a child is a " + 'person under 18). The model reads "foster child" in Sch 4 para ' + '9(3) and "a child" in para 12(A1)(c) the same way, so a foster ' + "child aged 16 or 17 is not a non-dependant and has no bedroom of " + "their own, and their overnight care counts for the renter. The " + "narrower reading, under 16 as in the Welfare Reform Act 2012 s.40, " + "would instead make such a person a non-dependant with a bedroom " + "and give the renter no foster room. The guidance does not settle " + "which applies." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/regulation/2", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/9", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/ukpga/1989/41/section/105", + ) + + def formula(person, period, parameters): + return person("is_looked_after_child", period) & ~person( + "is_claimant_or_partner", period + ) diff --git a/policyengine_uk/variables/gov/dwp/is_lha_shared_accommodation_rate_specified_renter.py b/policyengine_uk/variables/gov/dwp/is_lha_shared_accommodation_rate_specified_renter.py index e858bd8826..e95ee179ed 100644 --- a/policyengine_uk/variables/gov/dwp/is_lha_shared_accommodation_rate_specified_renter.py +++ b/policyengine_uk/variables/gov/dwp/is_lha_shared_accommodation_rate_specified_renter.py @@ -14,12 +14,13 @@ class is_lha_shared_accommodation_rate_specified_renter(Variable): "as a single person (reg. 3(3)), who is under the shared " "accommodation age threshold and not excepted by a disability benefit " "(para 29(5); armed forces independence payment counts as attendance " - "allowance, reg. 2); not responsible for a child or qualifying young " - "person; and with no non-dependant under the household composition " - "proxy. The age and the exception are the renter's own: the other " - "member of a couple claiming as a single person is neither the " - "renter nor a non-dependant (para 9(2)(b)). Other paragraph 29 " - "exceptions are not modelled. Housing Benefit has its own test: see " + "allowance, reg. 2) or as a foster parent or adopter (para 29(9A)); " + "not responsible for a child or qualifying young person; and with no " + "non-dependant under the household composition proxy. The age and " + "the exceptions are the renter's own: the other member of a couple " + "claiming as a single person is neither the renter nor a " + "non-dependant (para 9(2)(b)). Other paragraph 29 exceptions are not " + "modelled. Housing Benefit has its own test: see " "is_housing_benefit_young_individual and housing_benefit_LHA_category." ) definition_period = YEAR @@ -47,14 +48,19 @@ def formula(benunit, period, parameters): renter = person("is_claimant_or_partner", period) & ~other_member renter_age = benunit.max(where(renter, person("age", period), -np.inf)) # UC Sch 4 para 29(5): a renter under 35 receiving - # attendance allowance, DLA care at the middle or highest rate, or the - # PIP daily living component is excepted. Other para 29 exceptions - # (care leavers, hostel residents, MAPPA, domestic abuse, modern - # slavery, foster parents) are not observed. + # attendance allowance (which includes armed forces independence + # payment, reg 2), DLA care at the middle or highest rate, or the PIP + # daily living component is excepted. Other para 29 exceptions (care + # leavers, hostel residents, MAPPA, domestic abuse, modern slavery) + # are not observed. excepted_disabled_renter = benunit.any( renter & (add(person, period, p.shared_accommodation_exception_benefits) > 0) ) + # Para 29(9A): a renter who satisfies the foster parent condition. + excepted_foster_parent = benunit( + "lha_renter_meets_foster_parent_condition", period + ) return ( (~benunit("is_couple", period) | claims_as_single_person) & (renter_age < p.shared_accommodation_age_threshold) @@ -68,4 +74,5 @@ def formula(benunit, period, parameters): ) & ~benunit("lha_renter_has_non_dependant", period) & ~excepted_disabled_renter + & ~excepted_foster_parent ) diff --git a/policyengine_uk/variables/gov/dwp/is_non_dependant_of_household_head.py b/policyengine_uk/variables/gov/dwp/is_non_dependant_of_household_head.py index 109ede8fe2..a7be330d94 100644 --- a/policyengine_uk/variables/gov/dwp/is_non_dependant_of_household_head.py +++ b/policyengine_uk/variables/gov/dwp/is_non_dependant_of_household_head.py @@ -15,8 +15,12 @@ class is_non_dependant_of_household_head(Variable): "lodger's. Universal Credit counts a non-dependant in one claim only " "(uc_non_dependants_counted); Housing Benefit and Council Tax " "Reduction apportion a non-dependant of several joint occupiers " - "between them. Foster children and carers engaged through a charity " - "are not identified." + "between them. The flag covers every member of such a family, " + "including children. A non-dependant's own children are " + "non-dependants too, but a child or qualifying young person looked " + "after by a local authority is not (UC Sch 4 para 9(2)(g)); the " + "size criteria apply that exclusion (see LHA_allowed_bedrooms). " + "Carers engaged through a charity are not identified." ) definition_period = YEAR reference = ( diff --git a/policyengine_uk/variables/gov/dwp/lha_renter_has_non_dependant.py b/policyengine_uk/variables/gov/dwp/lha_renter_has_non_dependant.py index b832db4ac4..eb1a6ab455 100644 --- a/policyengine_uk/variables/gov/dwp/lha_renter_has_non_dependant.py +++ b/policyengine_uk/variables/gov/dwp/lha_renter_has_non_dependant.py @@ -11,13 +11,16 @@ class lha_renter_has_non_dependant(Variable): "that counts the household's non-dependants (see " "uc_non_dependants_counted), a claimant or partner of a family not " "liable for rent. Joint tenants and other sharers of the rent, " - "boarders and lodgers are not non-dependants. Foster children are not " - "identified. Housing Benefit uses housing_benefit_has_non_dependant." + "boarders and lodgers are not non-dependants. A child or young " + "person placed with the family as a foster child or for adoption is " + "not a non-dependant. Housing Benefit uses " + "housing_benefit_has_non_dependant." ) definition_period = YEAR reference = ( "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/9", "https://www.legislation.gov.uk/uksi/2006/213/regulation/3", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", ) def formula(benunit, period, parameters): @@ -26,9 +29,13 @@ def formula(benunit, period, parameters): # A child or young person under either scheme (UC reg 5; HB reg 19) # is a dependant, not a non-dependant. age = person("age", period) + # A foster child or a child placed for adoption is not a + # non-dependant either (UC Sch 4 para 9(2)(c) and (g); HB reg 3(2)(c) + # and reg 21(3)). child_or_qyp = ( person("is_child_or_qualifying_young_person_for_universal_credit", period) | person("is_child_or_young_person_for_legacy_benefits", period) + | person("is_child_or_young_person_placed_with_family", period) | ((age >= 16) & (age < 17)) ) within_benefit_unit = benunit.any(~claimant_or_partner & ~child_or_qyp) diff --git a/policyengine_uk/variables/gov/dwp/lha_renter_meets_foster_parent_condition.py b/policyengine_uk/variables/gov/dwp/lha_renter_meets_foster_parent_condition.py new file mode 100644 index 0000000000..b352144bfe --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/lha_renter_meets_foster_parent_condition.py @@ -0,0 +1,52 @@ +from policyengine_uk.model_api import * + + +class lha_renter_meets_foster_parent_condition(Variable): + value_type = bool + entity = BenUnit + label = "Universal Credit renter meets the foster parent condition" + documentation = ( + "Whether the renter or a joint renter is a foster parent or an " + "adopter with whom a child has been placed for adoption. An adopter " + "(UC Regs 2013 reg 89(3)(a)) is not a foster parent or close " + "relative of the child (see " + "adopter_is_foster_parent_or_close_relative). A foster parent has " + "a child under 18 looked after by a local authority " + "placed with them (a member of the benefit unit flagged " + "is_looked_after_by_local_authority), or is an approved foster " + "parent whose last placement ended, or who was approved, within 12 " + "months (is_approved_foster_parent_without_placement). The renter " + "gets one additional bedroom however many children are placed, and " + "is excepted from the shared accommodation rate." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/29", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/2", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/89", + ) + + def formula(benunit, period, parameters): + person = benunit.members + claimant_or_partner = person("is_claimant_or_partner", period) + # UC Regs 2013 reg 2, "foster parent": a person with whom a child + # (under 18) is placed under the care planning regulations. Sch 4 + # para 12(4)(b): an adopter with whom a child is placed for adoption, + # where "adopter" (reg 2, reg 89(3)(a)) excludes a foster parent or + # close relative of the child. + age_limit = parameters( + period + ).household.demographic.looked_after_child_age_limit + placed_for_adoption = ( + person("is_placed_for_adoption", period) + & ~person("adopter_is_foster_parent_or_close_relative", period) + & (person("age", period) < age_limit) + & ~claimant_or_partner + ) + placed = person("is_lha_foster_child", period) | placed_for_adoption + # UC Regs 2013 Sch 4 para 12(4)(a)-(b) and (5). + between_placements = claimant_or_partner & person( + "is_approved_foster_parent_without_placement", period + ) + return benunit.any(placed | between_placements) diff --git a/policyengine_uk/variables/gov/dwp/meets_lha_overnight_care_condition.py b/policyengine_uk/variables/gov/dwp/meets_lha_overnight_care_condition.py new file mode 100644 index 0000000000..f9da22caf9 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/meets_lha_overnight_care_condition.py @@ -0,0 +1,39 @@ +from policyengine_uk.model_api import * + + +class meets_lha_overnight_care_condition(Variable): + value_type = bool + entity = Person + label = "Meets the LHA overnight care condition" + documentation = ( + "Whether this person receives a qualifying disability benefit " + "(attendance allowance or armed forces independence payment, the " + "care component of Disability Living Allowance at the middle or " + "highest rate, or the daily living component of Personal " + "Independence Payment) and has non-resident carers who regularly " + "stay overnight to care for them. This is the Universal Credit " + "overnight care condition and the Housing Benefit 'person who " + "requires overnight care'. The law also lists the Scottish child " + "disability payment, adult disability payment, Scottish adult " + "disability living allowance and pension age disability payment; " + "the model has no variables for those, so they count only where the " + "data records them as the DWP equivalents. Two Housing Benefit " + "routes are not " + "modelled: a person without a qualifying benefit whose need the " + "local authority accepts on other evidence, and the requirement that " + "the carers have the use of a bedroom additional to the occupiers'." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/2", + ) + + def formula(person, period, parameters): + p = parameters(period).gov.dwp.LHA + # UC Regs 2013 Sch 4 para 12(3)(a); HB Regs 2006 reg 2(1), "person + # who requires overnight care", (a)(i)-(iib). + qualifying_benefit = add(person, period, p.overnight_care_benefits) > 0 + # UC para 12(3)(b)-(c); HB reg 2(1), (b). + return qualifying_benefit & person("has_non_resident_overnight_carer", period) diff --git a/policyengine_uk/variables/gov/dwp/pension_credit/guarantee_credit/minimum_guarantee/additional/is_child_or_qualifying_young_person_for_pension_credit.py b/policyengine_uk/variables/gov/dwp/pension_credit/guarantee_credit/minimum_guarantee/additional/is_child_or_qualifying_young_person_for_pension_credit.py index 2876ddb1f1..4760a5e16d 100644 --- a/policyengine_uk/variables/gov/dwp/pension_credit/guarantee_credit/minimum_guarantee/additional/is_child_or_qualifying_young_person_for_pension_credit.py +++ b/policyengine_uk/variables/gov/dwp/pension_credit/guarantee_credit/minimum_guarantee/additional/is_child_or_qualifying_young_person_for_pension_credit.py @@ -33,5 +33,5 @@ def formula(person, period, parameters): return ( child_or_qualifying_young_person & ~person("is_claimant_or_partner", period) - & ~person("is_looked_after_by_local_authority", period) + & ~person("is_looked_after_child", period) ) diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/child_element/is_child_or_qualifying_young_person_for_universal_credit.py b/policyengine_uk/variables/gov/dwp/universal_credit/child_element/is_child_or_qualifying_young_person_for_universal_credit.py index b75cb06d25..6e89ee6f7a 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/child_element/is_child_or_qualifying_young_person_for_universal_credit.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/child_element/is_child_or_qualifying_young_person_for_universal_credit.py @@ -15,6 +15,9 @@ def formula(person, period, parameters): child_or_qualifying_young_person = person( "is_child_for_universal_credit", period ) | person("is_qualifying_young_person_for_universal_credit", period) + # UC Regs 2013 reg 4(6)(a): no one is responsible for a child or + # qualifying young person looked after by a local authority, which + # only a person under 18 can be. return child_or_qualifying_young_person & ~person( - "is_looked_after_by_local_authority", period + "is_looked_after_child", period ) diff --git a/policyengine_uk/variables/gov/dwp/youngest_child_age_for_legacy_benefits.py b/policyengine_uk/variables/gov/dwp/youngest_child_age_for_legacy_benefits.py index b50b668733..b9745f6539 100644 --- a/policyengine_uk/variables/gov/dwp/youngest_child_age_for_legacy_benefits.py +++ b/policyengine_uk/variables/gov/dwp/youngest_child_age_for_legacy_benefits.py @@ -8,11 +8,11 @@ class youngest_child_age_for_legacy_benefits(Variable): documentation = ( "Youngest child under 16 in the family for the legacy means-tested " "benefits (is_child_or_young_person_for_legacy_benefits). This " - "excludes the claimant and partner, and a child flagged " - "is_looked_after_by_local_authority: the model's proxy for a child " - "placed with the family by a local authority, or living away in its " - "care, who is not treated as a member of the claimant's household " - "(IS Regs 1987 reg 16(4)-(6)). SSCBA sections 137(1) and 142(1) use " + "excludes the claimant and partner, and a child placed with the " + "family by a local authority or for adoption " + "(is_child_or_young_person_placed_with_family), who is not treated " + "as a member of the claimant's household (IS Regs 1987 reg " + "16(4)-(6)). SSCBA sections 137(1) and 142(1) use " "the same child age definition. Infinity if the benefit unit contains " "no such child." ) diff --git a/policyengine_uk/variables/gov/hmrc/tax_free_childcare/conditions/tax_free_childcare_qualifying_child.py b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/conditions/tax_free_childcare_qualifying_child.py index 0e7ecdb297..da49637338 100644 --- a/policyengine_uk/variables/gov/hmrc/tax_free_childcare/conditions/tax_free_childcare_qualifying_child.py +++ b/policyengine_uk/variables/gov/hmrc/tax_free_childcare/conditions/tax_free_childcare_qualifying_child.py @@ -21,4 +21,13 @@ def formula(person, period, parameters): "is_looked_after_by_local_authority", period, ) - return meets_age_condition & ~is_parent & ~looked_after_by_local_authority + # Childcare Payments (Eligibility) Regs 2015 reg 4(2)(c)-(d): no one is + # responsible for a child looked after by a local authority, or placed + # for adoption in the home of a person proposing to adopt them. + placed_for_adoption = person("is_placed_for_adoption", period) + return ( + meets_age_condition + & ~is_parent + & ~looked_after_by_local_authority + & ~placed_for_adoption + ) diff --git a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/is_child_or_young_person_for_council_tax_reduction.py b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/is_child_or_young_person_for_council_tax_reduction.py index 476e395c44..e8eaf00d26 100644 --- a/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/is_child_or_young_person_for_council_tax_reduction.py +++ b/policyengine_uk/variables/gov/local_authorities/council_tax_reduction/is_child_or_young_person_for_council_tax_reduction.py @@ -25,7 +25,15 @@ class is_child_or_young_person_for_council_tax_reduction(Variable): local authority, as the Universal Credit and legacy flags do. That is broader than Scotland's working-age rule, which names only a child or young person placed with a foster carer under the Looked After Children - (Scotland) Regulations 2009 (reg. 7(8)). + (Scotland) Regulations 2009 (reg. 7(8)). The Child Benefit branch also + leaves out a child placed for adoption with the applicant or partner + (SI 2012/2885 reg. 8(2); SI 2012/2886 Sch para. 8(2); WSI 2013/3029 + reg. 8(2); SSI 2012/319 reg. 11(2)). The Universal Credit branch keeps them, since the Universal + Credit flag leaves out only looked-after children, so on Scotland's + working-age scheme from 1 April 2022 the applicant is responsible for a + child placed for adoption who normally lives with them (reg. 7(2)). + Before 1 April 2022 Scotland's working-age scheme follows the Child + Benefit branch. """ value_type = bool diff --git a/policyengine_uk/variables/household/demographic/adopter_is_foster_parent_or_close_relative.py b/policyengine_uk/variables/household/demographic/adopter_is_foster_parent_or_close_relative.py new file mode 100644 index 0000000000..e92263584b --- /dev/null +++ b/policyengine_uk/variables/household/demographic/adopter_is_foster_parent_or_close_relative.py @@ -0,0 +1,32 @@ +from policyengine_uk.model_api import * + + +class adopter_is_foster_parent_or_close_relative(Variable): + value_type = bool + entity = Person + label = "adopter is a foster parent or close relative of the child" + documentation = ( + "Whether the person with whom this child is placed for adoption is " + "a foster parent or close relative of the child. Universal Credit's " + "'adopter' (UC Regs 2013 reg 2, taking the meaning in reg 89(3)(a)) " + "excludes such a person, so they do not meet the foster parent " + "condition through the adoption placement (Sch 4 para 12(4)(b)), " + "nor the shared accommodation rate exception that follows it (para " + "29(9A)). A close relative (reg 2) is a parent, parent-in-law, son, " + "son-in-law, daughter, daughter-in-law, step-parent, step-son, " + "step-daughter, brother or sister, or the other member of a couple " + "with any of them. The adopter remains responsible for the child " + "(reg 4A(1)(c)), and Housing Benefit's placement rule (HB Regs 2006 " + "reg 21(3)) and qualifying parent or carer carry no such words, so " + "neither changes. A foster parent keeps the foster parent condition " + "as a foster parent (para 12(4)(a), (5)): flag their placements or " + "set is_approved_foster_parent_without_placement. Set this on the " + "child; it has no effect unless is_placed_for_adoption is true." + ) + definition_period = YEAR + default_value = False + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/regulation/2", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/89", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + ) diff --git a/policyengine_uk/variables/household/demographic/has_non_resident_overnight_carer.py b/policyengine_uk/variables/household/demographic/has_non_resident_overnight_carer.py new file mode 100644 index 0000000000..4ce8137c67 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/has_non_resident_overnight_carer.py @@ -0,0 +1,25 @@ +from policyengine_uk.model_api import * + + +class has_non_resident_overnight_carer(Variable): + value_type = bool + entity = Person + label = "has a non-resident overnight carer" + documentation = ( + "Whether one or more people who do not live in the home are engaged, " + "under arrangements made for that purpose, to provide this person " + "with overnight care and to stay overnight in the home on a regular " + "basis. With a qualifying disability benefit, this can give an " + "additional bedroom in the Universal Credit and Housing Benefit size " + "criteria (see meets_lha_overnight_care_condition): to the renter " + "whose extended benefit unit the person is in, or who fosters them " + "(UC), or to the claimant whose dwelling they occupy (HB). A " + "lodger's or joint tenant's carer gives the household head's family " + "nothing under Universal Credit." + ) + definition_period = YEAR + default_value = False + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + ) diff --git a/policyengine_uk/variables/household/demographic/is_approved_foster_parent_without_placement.py b/policyengine_uk/variables/household/demographic/is_approved_foster_parent_without_placement.py new file mode 100644 index 0000000000..402cfae680 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/is_approved_foster_parent_without_placement.py @@ -0,0 +1,22 @@ +from policyengine_uk.model_api import * + + +class is_approved_foster_parent_without_placement(Variable): + value_type = bool + entity = Person + label = "approved foster parent between placements" + documentation = ( + "Whether this person is an approved foster parent (in Scotland, a " + "foster carer or kinship carer) with no child currently placed with " + "them, whose last placement ended, or who was approved and has had " + "no placement since, no more than 12 months ago. Housing Benefit's " + "limit is 52 weeks. Such a person keeps the foster parent's " + "additional bedroom (UC Regs 2013 Sch 4 para 12(5); HB Regs 2006 " + "reg 2(1), 'qualifying parent or carer')." + ) + definition_period = YEAR + default_value = False + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/2", + ) diff --git a/policyengine_uk/variables/household/demographic/is_looked_after_by_local_authority.py b/policyengine_uk/variables/household/demographic/is_looked_after_by_local_authority.py index d2a18247a4..f4a29dc9c4 100644 --- a/policyengine_uk/variables/household/demographic/is_looked_after_by_local_authority.py +++ b/policyengine_uk/variables/household/demographic/is_looked_after_by_local_authority.py @@ -5,6 +5,30 @@ class is_looked_after_by_local_authority(Variable): value_type = bool entity = Person label = "looked after by a local authority" + documentation = ( + "Whether this child or young person is looked after by a local " + "authority. Only a person under 18 can be (see " + "is_looked_after_child), so the flag has no effect at 18 or over. A looked-after child who lives in the household, such as " + "a foster child, is placed with the family whose benefit unit they " + "are in: no one in it is responsible for them under Universal Credit " + "(UC Regs 2013 reg 4(6)(a)), they are not a member of the claimant's " + "household under Housing Benefit and the other legacy schemes (HB " + "Regs 2006 reg 21(3)), they have no bedroom of their own in the size " + "criteria, and their carer meets the foster parent condition for an " + "additional bedroom. Leave it false for a child placed for adoption " + "(see is_placed_for_adoption) or placed with their own parent, for " + "whom Universal Credit treats the carer as responsible (reg 4A). " + "Under Housing Benefit and the other legacy schemes, a child placed " + "with a parent by a local authority under Children Act 1989 s.22C(2) " + "is outside the household (HB Regs 2006 reg 21(3)(a)); one flag " + "cannot represent both, and the model treats such a child as a " + "household member." + ) definition_period = YEAR default_value = False - reference = "https://www.legislation.gov.uk/uksi/2015/448/regulation/4" + reference = ( + "https://www.legislation.gov.uk/uksi/2015/448/regulation/4", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/4", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/4A", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + ) diff --git a/policyengine_uk/variables/household/demographic/is_looked_after_child.py b/policyengine_uk/variables/household/demographic/is_looked_after_child.py new file mode 100644 index 0000000000..8cef423468 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/is_looked_after_child.py @@ -0,0 +1,30 @@ +from policyengine_uk.model_api import * + + +class is_looked_after_child(Variable): + value_type = bool + entity = Person + label = "Child looked after by a local authority" + documentation = ( + "Whether this person is flagged is_looked_after_by_local_authority " + "and is under 18. Only a child, a person under 18, can be looked " + "after by a local authority (Children Act 1989 ss.22(1) and 105(1); " + "the Scottish and Welsh definitions are also limited to children), " + "so the flag has no effect at 18 or over: Universal Credit treats " + "the carer as responsible for a qualifying young person aged 18 or " + "19, and Housing Benefit counts them as a household member." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/ukpga/1989/41/section/22", + "https://www.legislation.gov.uk/ukpga/1989/41/section/105", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/2", + ) + + def formula(person, period, parameters): + age_limit = parameters( + period + ).household.demographic.looked_after_child_age_limit + return person("is_looked_after_by_local_authority", period) & ( + person("age", period) < age_limit + ) diff --git a/policyengine_uk/variables/household/demographic/is_placed_for_adoption.py b/policyengine_uk/variables/household/demographic/is_placed_for_adoption.py new file mode 100644 index 0000000000..73e9361808 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/is_placed_for_adoption.py @@ -0,0 +1,50 @@ +from policyengine_uk.model_api import * + + +class is_placed_for_adoption(Variable): + value_type = bool + entity = Person + label = "placed for adoption" + documentation = ( + "Whether this child is placed for adoption with the claimant or " + "partner of their benefit unit under the Adoption and Children Act " + "2002 or the Adoption and Children (Scotland) Act 2007. Put the child " + "in the adopter's benefit unit and leave " + "is_looked_after_by_local_authority false. A fostering-for-adoption " + "placement (Children Act 1989 s.22C(9A)-(9B)) is a foster placement: " + "flag that child as looked after instead. Universal Credit treats the " + "adopter as responsible for the child (UC Regs 2013 reg 4A(1)(c)), " + "and the adopter satisfies the foster parent condition for an " + "additional bedroom (Sch 4 para 12(4)(b)) and the shared " + "accommodation rate exception (para 29(9A)), unless the adopter is " + "a foster parent or close relative of the child (reg 89(3)(a); see " + "adopter_is_foster_parent_or_close_relative). " + "Pension Credit also treats the adopter as responsible (SPC Regs 2002 " + "Sch IIA para 4(3)(c)). Under Housing Benefit, Income Support, " + "income-based Jobseeker's Allowance, income-related Employment and " + "Support Allowance and the English pensioner, Welsh and Scottish " + "pension-age council tax reduction schemes, the child is not a " + "member of the claimant's household; a single claimant or lone " + "parent with such a child is in an Income Support prescribed " + "category (IS Regs 1987 Sch 1B para 2A). Tax-Free Childcare does not " + "count them (Childcare Payments (Eligibility) Regs 2015 reg " + "4(2)(d)). Child Tax Credit excludes them only while the local " + "authority pays for their keep (CTC Regs 2002 reg 3, rule 4 case B), " + "which is not modelled. Scottish working-age council tax reduction " + "excludes only foster placements (SSI 2021/249 reg 7(8)), so from 1 " + "April 2022 the child counts in the adopter's family there (see " + "is_child_or_young_person_for_council_tax_reduction)." + ) + definition_period = YEAR + default_value = False + reference = ( + "https://www.legislation.gov.uk/uksi/2013/376/regulation/4A", + "https://www.legislation.gov.uk/uksi/2013/376/schedule/4/paragraph/12", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/21", + "https://www.legislation.gov.uk/uksi/2012/2885/regulation/8", + "https://www.legislation.gov.uk/uksi/2015/448/regulation/4", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/IIA", + "https://www.legislation.gov.uk/uksi/2002/2007/regulation/3", + "https://www.legislation.gov.uk/ssi/2021/249/regulation/7", + "https://www.legislation.gov.uk/uksi/2013/376/regulation/89", + )