diff --git a/changelog.d/hb-qualified-childcare.fixed.md b/changelog.d/hb-qualified-childcare.fixed.md new file mode 100644 index 0000000000..54b1056887 --- /dev/null +++ b/changelog.d/hb-qualified-childcare.fixed.md @@ -0,0 +1 @@ +Limited Housing Benefit childcare deductions to remaining earnings after the shared applied standard plus tax-credit payments, retaining childcare_expenses and the existing age-based cap approximation; deferred detailed qualifying-care rules without adding an input. Prevented negative overridden net earnings from producing a negative permitted-work applied standard. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml index 0f57841821..86edb6a8d1 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.yaml @@ -1,63 +1,1315 @@ -- name: One child, capped - period: 2025 - absolute_error_margin: 0.01 +# Detailed provider, charge-type and work/leave conditions are deferred. +# Aggregate childcare_expenses and age-eligible child counts retain the +# existing annual approximation. Cap inputs reproduce #1925, not another fix. +- name: "No children and no qualifying charges" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + benunits: + family: + members: ["claimant"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Existing claimant childcare_expenses are used without a new input" + period: 2024 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true childcare_expenses: 9000 + is_claimant_or_partner: true child0: age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 0 benunits: - benunit: - members: [claimant, child0] + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 1 relevant children the deduction is min(cost, weekly cap * 52). - num_relevant_children_for_housing_benefit_childcare: 1 housing_benefit_applicable_income_childcare_element: 9000 -- name: Two child, capped - period: 2025 - absolute_error_margin: 0.01 +- name: "One child below weekly cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 9000 + +- name: "One child at weekly cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9100 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 9100 + +- name: "One child above weekly cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 20000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 9100 + +- name: "Two children below multiple-child cap" + period: 2024 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 10000 + childcare_expenses: 0 + is_claimant_or_partner: true child0: - age: 8 + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 5000 child1: age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 5000 benunits: - benunit: - members: [claimant, child0, child1] + family: + members: ["claimant","child0","child1"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 2 relevant children the deduction is min(cost, weekly cap * 52). - num_relevant_children_for_housing_benefit_childcare: 2 housing_benefit_applicable_income_childcare_element: 10000 -- name: No children - period: 2025 - absolute_error_margin: 0.01 +- name: "Two children at multiple-child cap" + period: 2024 + absolute_error_margin: 0.02 input: people: claimant: age: 40 is_parent: true - childcare_expenses: 30000 + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 7800 + child1: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 7800 benunits: - benunit: - members: [claimant] + family: + members: ["claimant","child0","child1"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 15600 + +- name: "Two children above multiple-child cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + child1: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0","child1"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 15600 + +- name: "Three paid-care children do not increase the family cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 8000 + child1: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 8000 + child2: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 8000 + benunits: + family: + members: ["claimant","child0","child1","child2"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 15600 + +- name: "Age-based cap approximation counts both children when only one has recorded spending" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 20000 + child1: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 0 + benunits: + family: + members: ["claimant","child0","child1"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + # Spending attribution is not assessed: two age-eligible children give + # the multiple-child cap even when costs are recorded on only one child. + housing_benefit_applicable_income_childcare_element: 15600 + +- name: "Older child without qualifying care does not increase cap" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 20000 + child1: + age: 17 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 0 + benunits: + family: + members: ["claimant","child0","child1"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 9100 + +- name: "Charges for an excluded young person are not counted" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 17 + is_child_or_young_person_for_legacy_benefits: false + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Negative supplied charges are floored" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: -500 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Zero earnings and no tax credits give no deduction" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 0 + housing_benefit_special_earnings_disregard: 0 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Low earnings after standard disregard" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 740 + +- name: "Standard disregard exhausts earnings" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 260 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "WTC payment meets residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 500 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 1240 + +- name: "CTC payment meets residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "Both tax credit payments may meet residual under DWP W2.180" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 500 + child_tax_credit: 600 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 1840 + +- name: "Permitted work replaces standard amount before childcare" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 500 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 500 + +- name: "Accommodation disregard reduces available earnings" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 500 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 240 + +- name: "Accommodation amount is capped at earnings left" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 1000 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 output: - # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). - # With 0 relevant children the deduction is min(cost, weekly cap * 52). - num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 +- name: "Special standard amount reduces remaining earnings" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 2000 + housing_benefit_special_earnings_disregard: 1040 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 960 + +- name: "Higher lone-parent amount is retained over permitted work" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 2000 + housing_benefit_special_earnings_disregard: 1300 + housing_benefit_permitted_work_disregard: 500 + is_lone_parent: true + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 700 + +- name: "Additional disregard qualifies at exact childcare-inclusive threshold" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 1000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 2149.2 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: true + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 1000 + housing_benefit_applicable_income_disregard: 1149.2 + +- name: "Additional disregard fails just below childcare-inclusive threshold" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 1000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 2149.19 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: true + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 1000 + housing_benefit_applicable_income_disregard: 260 + +- name: "Childcare does not recurse through additional disregard with low earnings" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 1000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: true + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 740 + housing_benefit_applicable_income_disregard: 260 + +- name: "Explicit one-child cap reform wins" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 100 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 5200 + +- name: "ENGLAND pension regulations false earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "ENGLAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "ENGLAND pension regulations true earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: true + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "ENGLAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "SCOTLAND pension regulations false earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "SCOTLAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "SCOTLAND pension regulations true earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: true + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "SCOTLAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "WALES pension regulations false earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "WALES" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "WALES pension regulations true earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: true + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "WALES" + output: + housing_benefit_applicable_income_childcare_element: 1540 + +- name: "NORTHERN_IRELAND pension regulations false earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "NORTHERN_IRELAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + + + +- name: "NORTHERN_IRELAND pension regulations true earnings and CTC residual" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 2000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 1000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 800 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: true + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + households: + household: + members: ["claimant","child0"] + country: "NORTHERN_IRELAND" + output: + housing_benefit_applicable_income_childcare_element: 1540 + + +- name: "Recorded spending without age-eligible children gives no deduction" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 5000 + is_claimant_or_partner: true + benunits: + family: + members: ["claimant"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Standard age limit excludes a child aged 16" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 16 + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 0 + +- name: "Disability extends the annual child age limit to include age 16" + period: 2024 + absolute_error_margin: 0.02 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 0 + is_claimant_or_partner: true + child0: + age: 16 + is_disabled_for_benefits: true + is_child_or_young_person_for_legacy_benefits: true + childcare_expenses: 9000 + benunits: + family: + members: ["claimant","child0"] + housing_benefit_net_earnings: 20000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + is_lone_parent: false + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + meets_housing_benefit_additional_earnings_disregard_conditions: false + housing_benefit_on_passporting_benefit: false + housing_benefit_pension_age_regulations_apply: false + gov.dwp.tax_credits.working_tax_credit.elements.childcare_1: 175 + gov.dwp.tax_credits.working_tax_credit.elements.childcare_2: 300 + output: + housing_benefit_applicable_income_childcare_element: 9000 + - name: Non-disabled child aged 15 remains within annual age approximation period: 2025 absolute_error_margin: 0.01 @@ -72,6 +1324,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 1 relevant children the deduction is min(cost, weekly cap * 52). @@ -92,6 +1352,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 0 relevant children the deduction is min(cost, weekly cap * 52). @@ -112,6 +1380,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 0 relevant children the deduction is min(cost, weekly cap * 52). @@ -133,6 +1409,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 1 relevant children the deduction is min(cost, weekly cap * 52). @@ -154,6 +1438,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 1 relevant children the deduction is min(cost, weekly cap * 52). @@ -175,6 +1467,14 @@ benunits: benunit: members: [claimant, child0] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # Annual age limits are <16, or <17 if disabled/blind (HB reg 28(6)). # With 0 relevant children the deduction is min(cost, weekly cap * 52). @@ -197,6 +1497,14 @@ benunits: benunit: members: [claimant, child, young_person] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: num_relevant_children_for_housing_benefit_childcare: 1 # Reg 27(3) selects the one-child cap: min(30,000, 175 * 52). The cap is @@ -213,6 +1521,14 @@ benunits: benunit: members: [claimant] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # 0 dependants implies 0 childcare cap (HB reg 27(3)). num_relevant_children_for_housing_benefit_childcare: 0 @@ -234,8 +1550,110 @@ benunits: benunit: members: [claimant, young_person] + # Isolate reg 28 age/count and cap selection: the earnings + # residual is 20,000 - 260 = 19,740, above either child cap. + housing_benefit_net_earnings: 20_000 + housing_benefit_special_earnings_disregard: 260 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 output: # HB reg 28(6) requires a child of the family, including a qualifying # young person; the disability age extension does not create that status. num_relevant_children_for_housing_benefit_childcare: 0 housing_benefit_applicable_income_childcare_element: 0 + +- name: One relevant child and an older young person have no earnings or tax credits + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + is_parent: true + childcare_expenses: 30_000 + child: + age: 10 + young_person: + age: 17 + benunits: + benunit: + members: [claimant, child, young_person] + housing_benefit_net_earnings: 0 + housing_benefit_special_earnings_disregard: 0 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + working_tax_credit: 0 + child_tax_credit: 0 + output: + num_relevant_children_for_housing_benefit_childcare: 1 + # Reg 27(3) still selects min(30,000, 175 * 52) = 9,100. + # BW2 W2.179-W2.182: limit = max(0, 0 - 0 - 0) + 0 + 0 = 0; + # deduction = min(9,100, 0) = 0, despite the unchanged relevant-child count. + housing_benefit_childcare_earnings_limit: 0 + housing_benefit_applicable_income_childcare_element: 0 + +- name: Pre-2025 WTC disability award selects the special standard and funds childcare + period: 2024 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 70 + is_parent: true + is_claimant_or_partner: true + childcare_expenses: 2_000 + sda: 0 + attendance_allowance: 0 + dla_sc: 0 + dla_m: 0 + pip_dl: 0 + pip_m: 0 + armed_forces_independence_payment: 0 + is_blind: false + partner: + age: 70 + is_claimant_or_partner: true + sda: 0 + attendance_allowance: 0 + dla_sc: 0 + dla_m: 0 + pip_dl: 0 + pip_m: 0 + armed_forces_independence_payment: 0 + is_blind: false + child: + age: 10 + is_child_or_young_person_for_legacy_benefits: true + benunits: + family: + members: [claimant, partner, child] + housing_benefit_net_earnings: 2_000 + housing_benefit_permitted_work_disregard: 0 + housing_benefit_specified_or_temporary_accommodation_disregard: 0 + housing_benefit_pension_age_regulations_apply: true + housing_benefit_on_passporting_benefit: false + meets_housing_benefit_additional_earnings_disregard_conditions: false + disability_premium: 0 + severe_disability_premium: 0 + carer_premium: 0 + # Pre-assessed award in payment and its pre-taper disability element; + # special eligibility and both standard variables remain calculated. + working_tax_credit: 500 + WTC_disabled_element: 3_900 + WTC_severely_disabled_element: 0 + child_tax_credit: 0 + output: + # SI 2006/214 Sch 4 para 5(1)(a)(vi): WTC disability receipt selects + # 20 * 52 = 1,040 (rather than the ordinary couple's 10 * 52 = 520). + # Reg 30(1)(c), (2)-(3), with DWP BW2 W2.179-W2.182: + # residual = max(0, 2,000 - 1,040 - 0) = 960; + # limit = 960 + 500 WTC + 0 CTC = 1,460; + # capped charge = min(2,000, 175 * 52) = 2,000; + # deduction = min(2,000, 1,460) = 1,460. + housing_benefit_special_earnings_disregard_eligible: true + housing_benefit_special_earnings_disregard: 1_040 + housing_benefit_applied_standard_earnings_disregard: 1_040 + housing_benefit_childcare_earnings_limit: 1_460 + housing_benefit_applicable_income_childcare_element: 1_460 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml index ca1ab09503..bd046040ba 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applicable_income_disregard.yaml @@ -363,9 +363,10 @@ would_claim_uc: false # not on Universal Credit, which passports the means test members: [parent, child] output: - # Childcare deducted is min(£4,160, one-child maximum) = £4,160. - # £5,200 < £1,300 + £4,160 + £889.20 = £6,349.20, so only £25 a week. - housing_benefit_applicable_income_childcare_element: 4_160 + # Reg 27(1)(c): after the £1,300 standard disregard, only £3,900 of + # earnings remain. With no tax credits, min(£4,160, £3,900) = £3,900. + # £5,200 < £1,300 + £3,900 + £889.20 = £6,089.20, so only £25 a week. + housing_benefit_applicable_income_childcare_element: 3_900 housing_benefit_applicable_income_disregard: 1_300 - name: Lone parent whose earnings cover the disregards and childcare gets the additional disregard diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.yaml new file mode 100644 index 0000000000..13a6c3af85 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.yaml @@ -0,0 +1,10 @@ +- name: Negative overridden net earnings cannot produce a negative permitted-work standard + period: 2026 + input: + housing_benefit_net_earnings: -1 + housing_benefit_special_earnings_disregard: 0 + housing_benefit_permitted_work_disregard: 1 + is_lone_parent: false + output: + # min(max(-1, 0), max(1, 0 * 0)) = min(0, 1) = 0. + housing_benefit_applied_standard_earnings_disregard: 0 diff --git a/policyengine_uk/tests/test_housing_benefit_childcare_properties.py b/policyengine_uk/tests/test_housing_benefit_childcare_properties.py new file mode 100644 index 0000000000..588340beee --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_childcare_properties.py @@ -0,0 +1,274 @@ +"""Housing Benefit childcare invariants for independently assessed inputs. + +C1: the deduction is nonnegative and no greater than either the qualifying +charge cap or the childcare earnings limit. +C2: increasing private pension or maintenance income cannot increase the +deduction when earnings, tax credits and the other assessed inputs are fixed. +C3: the limit is max(0, net earnings - applied standard - accommodation) plus +WTC and CTC, reading the applied standard from the shared model variable. +C4: increasing net earnings cannot lower the limit, and increasing childcare +charges cannot lower the deduction. + +Selected standards, accommodation and tax credits are pre-assessed inputs so +these properties isolate the earnings residual. Standards, accommodation, +charges and tax credits are nonnegative; net earnings may be negative and +permitted work may be negative to exercise their zero floors. The applied +standard is always calculated by the model, never supplied as an input. +Each population contains independent benefit units with actual adult/child +members; lone-parent status is supplied consistently with those members. +""" + +import numpy as np +from hypothesis import HealthCheck, example, given, settings +from hypothesis import strategies as st +from policyengine_core.simulations import Simulation + +from policyengine_uk.system import system + + +YEAR = 2026 +TOLERANCE = 1e-6 +PROPERTY_SETTINGS = settings( + max_examples=5, + derandomize=True, + deadline=None, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +def _case(**overrides): + case = { + "net_earnings": 0, + "selected_standard": 0, + "permitted_work": 0, + "lone_parent": False, + "children": 1, + "childcare": 1_000, + "accommodation": 0, + "wtc": 0, + "ctc": 0, + "private_pension": 0, + "maintenance": 0, + } + case.update(overrides) + return case + + +CASES = st.fixed_dictionaries( + { + "net_earnings": st.integers(-100, 40_000), + "selected_standard": st.sampled_from([0, 260, 520, 1_040, 1_300]), + "permitted_work": st.sampled_from([-1, 0, 1, 1_040, 1_300, 9_542]), + "lone_parent": st.booleans(), + "children": st.integers(0, 2), + "childcare": st.integers(0, 25_000), + "accommodation": st.integers(0, 10_000), + "wtc": st.integers(0, 10_000), + "ctc": st.integers(0, 10_000), + "private_pension": st.integers(0, 20_000), + "maintenance": st.integers(0, 20_000), + } +) +POPULATIONS = st.lists(CASES, min_size=1, max_size=24) +EDGE_CASES = [ + _case(), + _case( + net_earnings=2_000, + selected_standard=1_300, + permitted_work=1, + lone_parent=True, + childcare=2_000, + ), + _case(net_earnings=-1, selected_standard=260, permitted_work=1), + _case( + selected_standard=1_040, + children=2, + childcare=25_000, + wtc=500, + ctc=1_000, + ), + _case( + net_earnings=10_000, + selected_standard=520, + children=0, + childcare=25_000, + ), + _case( + net_earnings=5_000, + selected_standard=1_040, + lone_parent=True, + childcare=25_000, + accommodation=8_000, + ), + _case( + net_earnings=30_000, + selected_standard=1_040, + children=2, + childcare=25_000, + wtc=1_000, + ), +] + + +def _evaluate(cases): + people = {} + benunits = {} + households = {} + for index, case in enumerate(cases): + # A unit with no children has no lone parent. Otherwise construct one + # adult for a lone parent and two adults for a couple. + lone_parent = case["lone_parent"] and case["children"] > 0 + members = [] + for adult_index in range(1 if lone_parent else 2): + name = f"adult_{index}_{adult_index}" + members.append(name) + people[name] = { + "age": {YEAR: 40}, + "is_claimant_or_partner": {YEAR: True}, + "is_child_or_young_person_for_legacy_benefits": {YEAR: False}, + "childcare_expenses": { + YEAR: case["childcare"] if adult_index == 0 else 0 + }, + "private_pension_income": { + YEAR: case["private_pension"] if adult_index == 0 else 0 + }, + "maintenance_income": { + YEAR: case["maintenance"] if adult_index == 0 else 0 + }, + } + for child_index in range(case["children"]): + name = f"child_{index}_{child_index}" + members.append(name) + people[name] = { + "age": {YEAR: 8}, + "is_claimant_or_partner": {YEAR: False}, + "is_child_or_young_person_for_legacy_benefits": {YEAR: True}, + } + benunits[f"benunit_{index}"] = { + "members": members, + "is_lone_parent": {YEAR: lone_parent}, + "housing_benefit_net_earnings": {YEAR: case["net_earnings"]}, + "housing_benefit_special_earnings_disregard": { + YEAR: case["selected_standard"] + }, + "housing_benefit_permitted_work_disregard": {YEAR: case["permitted_work"]}, + "housing_benefit_specified_or_temporary_accommodation_disregard": { + YEAR: case["accommodation"] + }, + "working_tax_credit": {YEAR: case["wtc"]}, + "child_tax_credit": {YEAR: case["ctc"]}, + } + households[f"household_{index}"] = {"members": members} + simulation = Simulation( + tax_benefit_system=system, + situation={ + "people": people, + "benunits": benunits, + "households": households, + }, + ) + result = { + "limit": simulation.calculate("housing_benefit_childcare_earnings_limit", YEAR), + "deduction": simulation.calculate( + "housing_benefit_applicable_income_childcare_element", YEAR + ), + "standard": simulation.calculate( + "housing_benefit_applied_standard_earnings_disregard", YEAR + ), + "count": simulation.calculate( + "num_relevant_children_for_housing_benefit_childcare", YEAR + ), + } + # The statutory charge ceiling is independent of the earnings formula. + charge_caps = np.where( + result["count"] > 1, + 300 * 52, + np.where(result["count"] == 1, 175 * 52, 0), + ) + result["capped_charge"] = np.minimum( + np.array([case["childcare"] for case in cases]), charge_caps + ) + return result + + +@PROPERTY_SETTINGS +@given(cases=POPULATIONS) +@example(cases=EDGE_CASES) +def test_c1_childcare_deduction_bounds(cases): + result = _evaluate(cases) + assert np.all(result["deduction"] >= -TOLERANCE) + assert np.all( + result["deduction"] + <= np.minimum(result["capped_charge"], result["limit"]) + TOLERANCE + ) + + +@PROPERTY_SETTINGS +@given( + cases=POPULATIONS, + increase=st.integers(1, 20_000), + income_kind=st.sampled_from(["private_pension", "maintenance"]), +) +@example(cases=EDGE_CASES, increase=1_000, income_kind="private_pension") +@example(cases=EDGE_CASES, increase=1_000, income_kind="maintenance") +def test_c2_unrelated_income_cannot_fund_childcare(cases, increase, income_kind): + baseline = _evaluate(cases) + increased = _evaluate( + [ + { + **case, + income_kind: case[income_kind] + increase, + } + for case in cases + ] + ) + assert np.all(increased["deduction"] <= baseline["deduction"] + TOLERANCE) + + +@PROPERTY_SETTINGS +@given(cases=POPULATIONS) +@example(cases=EDGE_CASES) +def test_c3_childcare_earnings_residual_identity(cases): + result = _evaluate(cases) + expected = ( + np.maximum( + 0, + np.array([case["net_earnings"] for case in cases]) + - result["standard"] + - np.array([case["accommodation"] for case in cases]), + ) + + np.array([case["wtc"] for case in cases]) + + np.array([case["ctc"] for case in cases]) + ) + np.testing.assert_allclose(result["limit"], expected, rtol=0, atol=TOLERANCE) + + +@PROPERTY_SETTINGS +@given(cases=POPULATIONS, increase=st.integers(1, 40_000)) +@example(cases=EDGE_CASES, increase=1_000) +def test_c4_net_earnings_cannot_lower_childcare_limit(cases, increase): + baseline = _evaluate(cases) + increased = _evaluate( + [ + { + **case, + "net_earnings": min(40_000, case["net_earnings"] + increase), + } + for case in cases + ] + ) + assert np.all(increased["limit"] + TOLERANCE >= baseline["limit"]) + + +@PROPERTY_SETTINGS +@given(cases=POPULATIONS, increase=st.integers(1, 25_000)) +@example(cases=EDGE_CASES, increase=1_000) +def test_c4_charges_cannot_lower_childcare_deduction(cases, increase): + baseline = _evaluate(cases) + increased = _evaluate( + [ + {**case, "childcare": min(25_000, case["childcare"] + increase)} + for case in cases + ] + ) + assert np.all(increased["deduction"] + TOLERANCE >= baseline["deduction"]) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py index aa7dd6bd65..1c91664139 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income_childcare_element.py @@ -1,29 +1,45 @@ from policyengine_uk.model_api import * +def hb_capped_childcare_charges(benunit, period, parameters): + """Aggregate childcare spending capped using the existing age-based count.""" + expenses = max_(add(benunit, period, ["childcare_expenses"]), 0) + count = benunit("num_relevant_children_for_housing_benefit_childcare", period) + p = parameters(period).gov.dwp.tax_credits.working_tax_credit.elements + cap = select([count == 1, count > 1], [p.childcare_1, p.childcare_2], default=0) + return min_(expenses, cap * WEEKS_IN_YEAR) + + class housing_benefit_applicable_income_childcare_element(Variable): value_type = float entity = BenUnit label = "Housing Benefit applicable income childcare element" definition_period = YEAR unit = GBP - reference = "https://www.legislation.gov.uk/uksi/2006/213/regulation/27" + documentation = ( + "Aggregate childcare_expenses, capped using the existing age-eligible " + "child count and limited by remaining earnings plus WTC/CTC payments. " + "Provider eligibility, excluded charge types, work/leave conditions " + "and incapacity/continuation exceptions are not assessed. The child " + "count approximates children with paid care and can overstate the " + "cap when only one of several eligible children receives paid care. " + "These qualifying-care rules are deferred in " + "https://github.com/PolicyEngine/policyengine-uk/issues/2236. " + "The annual calculation assumes constant household circumstances." + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/27", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/30", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/24", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/213/regulation/28", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/31", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/25", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/29", + ) def formula(benunit, period, parameters): - p = parameters(period).gov.dwp.tax_credits.working_tax_credit.elements - relevant_children = benunit( - "num_relevant_children_for_housing_benefit_childcare", period - ) - childcare_amount_1 = (relevant_children == 1) * p.childcare_1 - childcare_amount_2 = (relevant_children > 1) * p.childcare_2 - max_weekly_childcare_amount = childcare_amount_1 + childcare_amount_2 - # Assuming that no children leads to no childcare element - capped_max_childcare_amount = where( - relevant_children == 0, 0, max_weekly_childcare_amount - ) - max_childcare_amount = capped_max_childcare_amount * WEEKS_IN_YEAR - childcare_expenses = add(benunit, period, ["childcare_expenses"]) return min_( - max_childcare_amount, - childcare_expenses, + hb_capped_childcare_charges(benunit, period, parameters), + benunit("housing_benefit_childcare_earnings_limit", period), ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.py index a05e20dd7f..df3258a362 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applied_standard_earnings_disregard.py @@ -24,7 +24,7 @@ class housing_benefit_applied_standard_earnings_disregard(Variable): ) def formula(benunit, period, parameters): - net_earnings = benunit("housing_benefit_net_earnings", period) + net_earnings = max_(benunit("housing_benefit_net_earnings", period), 0) # Working age Sch 4 paras 3, 4, 7 and 10; pension age Sch 4 paras 2, # 4, 5 and 7. Other full-amount £20 routes are pre-assessed # (housing_benefit_special_earnings_disregard_eligible). diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_childcare_earnings_limit.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_childcare_earnings_limit.py new file mode 100644 index 0000000000..8fa5661d04 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_childcare_earnings_limit.py @@ -0,0 +1,65 @@ +from policyengine_uk.model_api import * + + +def hb_standard_earnings_disregard(benunit, period): + """Selected standard amount, including the permitted-work replacement.""" + return benunit("housing_benefit_applied_standard_earnings_disregard", period) + + +def hb_childcare_earnings_limit(benunit, period, accommodation=None): + """Remaining earnings and tax credits, without an additional-disregard loop.""" + net = max_(benunit("housing_benefit_net_earnings", period), 0) + standard = hb_standard_earnings_disregard(benunit, period) + if accommodation is None: + accommodation = benunit( + "housing_benefit_specified_or_temporary_accommodation_disregard", period + ) + accommodation = min_(max_(accommodation, 0), max_(0, net - standard)) + # DWP BW2 W2.179–W2.182 permits the residual against any WTC/CTC in + # payment, not other income. Both amounts are benefit-unit payments. + credits = max_(benunit("working_tax_credit", period), 0) + max_( + benunit("child_tax_credit", period), 0 + ) + return max_(0, net - standard - accommodation) + credits + + +class housing_benefit_childcare_earnings_limit(Variable): + value_type = float + entity = BenUnit + definition_period = YEAR + unit = GBP + label = "Housing Benefit childcare earnings and tax-credit limit" + documentation = ( + "Net claimant/partner earnings after the selected standard, permitted-work " + "and accommodation disregards, plus WTC/CTC payments. Unrelated income " + "cannot meet remaining childcare charges. The additional earnings " + "disregard is conditional on earnings covering the childcare deduction " + "as well as that disregard: when it applies the full capped childcare " + "charge already fits, so this calculation need not depend on it. This " + "avoids a circular calculation through the childcare deduction. The " + "WTC edge also runs from this limit through " + "housing_benefit_applied_standard_earnings_disregard, " + "housing_benefit_special_earnings_disregard and " + "housing_benefit_special_earnings_disregard_eligible to " + "working_tax_credit and its disability elements. With fixed earnings, " + "WTC entitlement " + "and its components (including the WTC childcare element) do not " + "read the HB childcare deduction, limit or applicable income, so " + "neither this edge nor the direct WTC addition creates a cycle. " + "Earnings are fixed when the simulation has no baseline or the " + "labour supply income and substitution elasticities are zero, as " + "they are by default. Labour supply responses can make earnings " + "depend on benefits, so this note does not cover a reform that " + "turns them on." + ) + reference = ( + "https://www.legislation.gov.uk/uksi/2006/213/regulation/27", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/30", + "https://www.legislation.gov.uk/nisr/2006/405/regulation/24", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/28", + "https://assets.publishing.service.gov.uk/media/5a7c7cf7ed915d6969f4538d/hbgm-bw2-assessment-of-income.pdf", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/4/paragraph/17", + ) + + def formula(benunit, period, parameters): + return hb_childcare_earnings_limit(benunit, period)