From f8afdcf4ab183af1414add6074dec8887368772e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:02:08 -0500 Subject: [PATCH 1/7] Count Maternity Allowance in the benefit cap Parliament lists maternity allowance among the welfare benefits the cap covers (Welfare Reform Act 2012 s.96(10)(i)); UC Regs 2013 regs 79-80 and HB Regs 2006 regs 75A and 75C count the claimant's and partner's own awards at the amount each scheme counts as income, which is all of it. benefit_cap_welfare_benefits left it out, so a capped family's Universal Credit fell by the allowance before the cap and the cap's reduction fell by the same amount. Add maternity_allowance to CLAIMANT_OR_PARTNER_BENEFITS, correct the documentation (the model has no variable for bereavement allowance, widow's pension or widowed mother's allowance), and add YAML cases and Hypothesis properties: exchange with another counted benefit, coefficient one, a reference written from the regulations, and the whole-model pound-for-pound response inside the cap. Fixes #2784. Co-Authored-By: Claude Opus 5.5 --- changelog.d/2784.fixed.md | 1 + .../benefit_cap/benefit_cap_capped_total.yaml | 228 +++++++++ ...efit_cap_maternity_allowance_properties.py | 479 ++++++++++++++++++ .../gov/dwp/benefit_cap_welfare_benefits.py | 9 +- 4 files changed, 714 insertions(+), 3 deletions(-) create mode 100644 changelog.d/2784.fixed.md create mode 100644 policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py diff --git a/changelog.d/2784.fixed.md b/changelog.d/2784.fixed.md new file mode 100644 index 0000000000..509ddc6dc1 --- /dev/null +++ b/changelog.d/2784.fixed.md @@ -0,0 +1 @@ +The benefit cap now counts the claimant's and partner's Maternity Allowance, which Parliament lists among the welfare benefits the cap covers (Welfare Reform Act 2012 s.96(10)(i)). A capped family receiving it loses that much more Universal Credit or Housing Benefit, as it does for its other capped benefits; a non-dependent adult's allowance still does not count (#2784). diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml index eebe419700..7c4f451118 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml @@ -327,3 +327,231 @@ is_uc_benefit_cap_single_claimant_rate: false uc_benefit_cap: 22_020 benefit_cap_reduction: 0 + +# Maternity Allowance is a welfare benefit (WRA 2012 s.96(10)(i)). It belongs +# to the woman entitled to it (SSCBA 1992 s.35(1)), so the cap counts it when +# she is the claimant or partner and leaves it out when she is a +# non-dependent adult. UC Regs +# 2013 reg 80(4) and HB Regs 2006 reg 75C(4) take the amount each scheme +# counts as income: all of it, as unearned income for Universal Credit (reg +# 66(1)(b)(viii)) and as income other than earnings for Housing Benefit (reg +# 40, with no disregard in Sch 5). + +- name: The claimant's own Maternity Allowance is in the capped total + period: 2025 + input: + people: + claimant: + age: 30 + maternity_allowance_reported: 3_000 + benunits: + family: + members: [claimant] + universal_credit_pre_benefit_cap: 15_000 + households: + home: + members: [claimant] + region: NORTH_EAST + output: + maternity_allowance: 3_000 + benefit_cap_welfare_benefits: 18_000 + # Maternity Allowance starts as early as the 11th week before the + # expected week of confinement (SSCBA 1992 s.35(1)(a)), so a claimant + # can receive it before she is responsible for a child. A single + # claimant with no child outside London: 14,753 (UC Regs 2013 reg + # 80A(2)(c)). Reg 81: max(15,000 + 3,000 - 14,753 - 0 childcare, 0) + # = 3,247, which leaves 15,000 - 3,247 = 11,753. + uc_benefit_cap: 14_753 + uc_benefit_cap_reduction: 3_247 + housing_benefit_benefit_cap_reduction: 0 + benefit_cap_reduction: 3_247 + universal_credit: 11_753 + +- name: A partner's Maternity Allowance is in the capped total + period: 2025 + input: + people: + claimant: + age: 32 + partner: + age: 30 + maternity_allowance_reported: 4_000 + benunits: + family: + members: [claimant, partner] + universal_credit_pre_benefit_cap: 20_000 + households: + home: + members: [claimant, partner] + region: NORTH_EAST + output: + is_uc_assessed_claimant: [true, true] + maternity_allowance: [0, 4_000] + benefit_cap_welfare_benefits: 24_000 + # Joint claimants outside London: 22,020 (UC Regs 2013 reg 80A(2)(d)(i)). + # Reg 81: max(20,000 + 4,000 - 22,020 - 0 childcare, 0) = 1,980, which + # leaves 20,000 - 1,980 = 18,020. + uc_benefit_cap: 22_020 + uc_benefit_cap_reduction: 1_980 + housing_benefit_benefit_cap_reduction: 0 + benefit_cap_reduction: 1_980 + universal_credit: 18_020 + +- name: A non-dependent adult's Maternity Allowance is not in the family's capped total + period: 2025 + input: + people: + claimant: + age: 40 + is_claimant_or_partner: true + adult: + age: 30 + is_claimant_or_partner: false + current_education: NOT_IN_EDUCATION + maternity_allowance_reported: 5_000 + benunits: + family: + members: [claimant, adult] + universal_credit_pre_benefit_cap: 20_000 + households: + home: + members: [claimant, adult] + region: NORTH_EAST + output: + maternity_allowance: [0, 5_000] + benefit_cap_welfare_benefits: 20_000 + # UC reg 81: max(20,000 - 14,753 - 0 childcare, 0) = 5,247. The adult's + # 5,000 is their own, not the family's. + uc_benefit_cap_reduction: 5_247 + housing_benefit_benefit_cap_reduction: 0 + benefit_cap_reduction: 5_247 + universal_credit: 14_753 + +- name: The claimant's own Maternity Allowance reduces Housing Benefit for a family without Universal Credit + period: 2025 + input: + people: + claimant: + age: 30 + maternity_allowance_reported: 6_000 + benunits: + family: + members: [claimant] + would_claim_uc: false + would_claim_housing_benefit: true + housing_benefit_pre_benefit_cap: 9_000 + households: + home: + members: [claimant] + region: NORTH_EAST + output: + universal_credit_pre_benefit_cap: 0 + benefit_cap_welfare_benefits: 15_000 + # A single claimant outside London: 14,753 (HB Regs 2006 reg 75CA(2)(c)). + # Reg 75D: min(9,000 + 6,000 - 14,753, 9,000 - 0.50 * 52) = 247, which + # leaves 9,000 - 247 = 8,753. No UC award: UC reg 78(1) gives no UC + # reduction. + housing_benefit_benefit_cap: 14_753 + uc_benefit_cap_reduction: 0 + housing_benefit_benefit_cap_reduction: 247 + benefit_cap_reduction: 247 + housing_benefit: 8_753 + +# Issue #2784's family through the whole Universal Credit award, 2026-27: a +# lone parent of 30 with children of 1, 4 and 7 renting privately for 1,500 a +# month in Tyneside, the North East's default Broad Rental Market Area. +# +# Universal Credit before the cap, monthly (DWP, Benefit and pension rates +# 2026 to 2027): +# standard allowance, single 25 or over 424.90 +# child element, 3 x 303.94 (SI 2026/148 Sch 13; reg 24A, the two-child +# limit, revoked from 6 April 2026 by the Universal Credit (Removal of +# Two Child Limit) Act 2026 s.1(3)(a)) 911.82 +# housing costs element: the lower of the rent, 1,500, and the cap rent +# (UC Regs 2013 Sch 4 para 22), the three-bedroom rate of 650.00 (DWP, +# Universal Credit LHA monthly rates 2026 to 2027, Tyneside): one bedroom +# for the parent, one for two children under 10, one for the third child +# (Sch 4 para 10(1)(a), (d), (f)) 650.00 +# maximum amount 1,986.72, or 23,840.64 a year +# less Maternity Allowance in full (reg 66(1)(b)(viii)), so 23,840.64 - 6,000 +# = 17,840.64 a year. +# +# Child Benefit: (27.05 + 2 x 17.90) x 52 = 3,268.20 a year (Child Benefit +# (Rates) Regulations 2006 reg 2(1), as SI 2026/232 art. 2 sets them). +# The family's limit is 22,020 (reg 80A(2)(d)(ii)); no exception applies. + +- name: Issue 2784 family with no Maternity Allowance loses the excess over the cap + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 30 + child1: + age: 1 + child2: + age: 4 + child3: + age: 7 + benunits: + family: + members: [parent, child1, child2, child3] + households: + home: + members: [parent, child1, child2, child3] + region: NORTH_EAST + brma: TYNESIDE + tenure_type: RENT_PRIVATELY + rent: 18_000 + output: + uc_standard_allowance: 5_098.80 + uc_child_element: 10_941.84 + uc_housing_costs_element: 7_800 + universal_credit_pre_benefit_cap: 23_840.64 + child_benefit: 3_268.20 + # 23,840.64 + 3,268.20 = 27,108.84. + benefit_cap_welfare_benefits: 27_108.84 + uc_benefit_cap: 22_020 + is_uc_benefit_cap_exempt: false + # Reg 81: 27,108.84 - 22,020 - 0 childcare = 5,088.84, which leaves + # 23,840.64 - 5,088.84 = 18,751.80. + uc_benefit_cap_reduction: 5_088.84 + universal_credit: 18_751.80 + +- name: Issue 2784 family's Maternity Allowance stays inside the cap, so Universal Credit falls by the allowance + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 30 + maternity_allowance_reported: 6_000 + child1: + age: 1 + child2: + age: 4 + child3: + age: 7 + benunits: + family: + members: [parent, child1, child2, child3] + households: + home: + members: [parent, child1, child2, child3] + region: NORTH_EAST + brma: TYNESIDE + tenure_type: RENT_PRIVATELY + rent: 18_000 + output: + uc_maximum_amount: 23_840.64 + uc_unearned_income: 6_000 + universal_credit_pre_benefit_cap: 17_840.64 + # 17,840.64 + 3,268.20 Child Benefit + 6,000 Maternity Allowance + # = 27,108.84, the same total as without the allowance. + benefit_cap_welfare_benefits: 27_108.84 + # Reg 81: 27,108.84 - 22,020 - 0 childcare = 5,088.84, which leaves + # 17,840.64 - 5,088.84 = 12,751.80. With the allowance, 12,751.80 + + # 6,000 = 18,751.80: what the family keeps from Universal Credit alone + # without it. + uc_benefit_cap_reduction: 5_088.84 + universal_credit: 12_751.80 diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py new file mode 100644 index 0000000000..8de0a9fff6 --- /dev/null +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -0,0 +1,479 @@ +"""The benefit cap counts Maternity Allowance like the other welfare benefits. + +Parliament lists maternity allowance among the welfare benefits the cap +applies to (Welfare Reform Act 2012 s.96(10)(i)), and the woman entitled to it +receives it (Social Security Contributions and Benefits Act 1992 s.35(1)). UC +Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A count the welfare +benefits "to which the single person or couple is entitled". Regs 80(4) and +75C(4) take the amount each scheme counts as income, which for Maternity +Allowance is all of it (UC Regs 2013 reg 66(1)(b)(viii); HB Regs 2006 reg 40, +whose Sch 5 disregards none of it). + +Invariants, for families on Universal Credit or on Housing Benefit alone, and +a holder who is a single claimant, either member of a couple, or a +non-dependent adult: + +1. Exchange: moving an amount between the holder's Maternity Allowance and + an equal amount of another welfare benefit of theirs that the cap counts + in the same way (contribution-based JSA or ESA, incapacity benefit, severe + disablement allowance or widowed parent's allowance) leaves the cap's + total, both exemptions and both reductions unchanged. +2. Coefficient one: with each award before the cap entered, so that + Universal Credit does not taper, raising the holder's allowance by d + raises the total by exactly d when the holder is the claimant or partner, + and leaves it unchanged when the holder is a non-dependent adult. The + total therefore never falls as the allowance rises, and nor does either + reduction. +3. Differential: the total equals a reference written from s.96(10) and + those regulations: the listed benefits of the claimant and partner, plus + the family's Child Benefit, Child Tax Credit, Income Support, and + Universal Credit and Housing Benefit before the cap. Each reduction is + the excess over the statutory limit (UC reg 80A(2); HB reg 75CA(2)), less + Housing Benefit for Universal Credit (reg 80(2A)), and for Housing Benefit + no more than leaves 50p a week (reg 75D(2)). +4. Pound for pound, through the whole model: where the model works out + Universal Credit and the award before the cap stays above nil, raising + the mother's allowance by d lowers that award by d (reg 66(1)(b)(viii)), + so the total does not move. Where the cap reduces the award at both + amounts, Universal Credit after the cap plus the allowance does not move + either: the cap holds the family's capped benefits at its limit whichever + of them the allowance replaces. + +Each example fills fixed benefit units in one simulation per module, so the +draws set amounts while each family's members stay fixed. +""" + +import numpy as np +import pytest +from hypothesis import HealthCheck, event, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +pytestmark = pytest.mark.usefixtures("cloned_uk_tax_benefit_system") + +YEAR = 2025 +# Outside London, 2025-26 (UC Regs 2013 reg 80A(2)(c), (d); HB Regs 2006 reg +# 75CA(2)(c), (d)). +SINGLE_LIMIT, COUPLE_LIMIT = 14_753, 22_020 +# HB Regs 2006 reg 75: Housing Benefit is not paid below 50p a week. +HOUSING_BENEFIT_MINIMUM = 0.50 * 52 + +# The holder's other welfare benefits that the cap counts as theirs (WRA 2012 +# s.96(10)(d), (f), (h), (j), (n)), each entered as an award. +OTHER_BENEFITS = [ + "jsa_contrib", + "esa_contrib", + "incapacity_benefit", + "sda", + "widowed_parents_allowance", +] +FAMILY_AWARDS = ["child_benefit", "child_tax_credit", "income_support"] + +# Families by structure: whether each member is the claimant or partner. +STRUCTURES = { + "single": [True], + "couple": [True, True], + "non_dependant": [True, False], +} +# Who holds the moved allowance: a structure and a member of it. +HOLDERS = [ + ("single", 0), + ("couple", 0), + ("couple", 1), + ("non_dependant", 0), + ("non_dependant", 1), +] +SCHEMES = ["uc", "hb"] +VARIANTS = ["base", "allowance", "other", "split"] +ROWS = 3 +# The benefit units of one row, in order. +UNITS = [ + (holder, scheme, variant) + for holder in HOLDERS + for scheme in SCHEMES + for variant in VARIANTS +] + + +def entered_situation(): + people, benunits, households = {}, {}, {} + for row in range(ROWS): + for i, ((structure, _), scheme, variant) in enumerate(UNITS): + unit = f"r{row}_u{i}" + members = [] + for j, counted in enumerate(STRUCTURES[structure]): + name = f"{unit}_p{j}" + members.append(name) + people[name] = { + "age": {YEAR: 40 - 2 * j}, + "is_claimant_or_partner": {YEAR: counted}, + "current_education": {YEAR: "NOT_IN_EDUCATION"}, + # No ESA support component, so contribution-based ESA + # does not lift the cap (UC reg 83(1)(a); HB reg + # 75F(1)(a)). + "esa_includes_support_component": {YEAR: False}, + "jsa_income_reported": {YEAR: 0}, + "esa_income_reported": {YEAR: 0}, + } + benunits[unit] = { + "members": members, + # Entered as nil, the LCWRA and carer elements are not in the + # award (UC reg 83(1)(a), (j)). + "uc_LCWRA_element": {YEAR: 0}, + "uc_carer_element": {YEAR: 0}, + } + if structure == "couple": + benunits[unit]["relation_type"] = {YEAR: "COUPLE"} + households[f"{unit}_home"] = { + "members": members, + "region": {YEAR: "NORTH_EAST"}, + } + return {"people": people, "benunits": benunits, "households": households} + + +@pytest.fixture(scope="module") +def entered(): + return Simulation(situation=entered_situation()) + + +PERSON_AMOUNTS = ["maternity_allowance_reported", *OTHER_BENEFITS] +pounds = st.integers(0, 1_200_000).map(lambda pence: pence / 100) + + +@st.composite +def rows(draw): + """One row's amounts: the amount moved and its split, the other benefit + it moves to, every member's own benefits before the move, and the + family's awards.""" + moved = draw(pounds) + split = round(moved * draw(st.integers(0, 100)) / 100, 2) + return { + "moved": moved, + "split": split, + "other": draw(st.sampled_from(OTHER_BENEFITS)), + # Benefits before the move, for the first and second member. + "own": [ + { + name: draw(st.sampled_from([0.0, 0.0, 1_000.0]) | pounds) + for name in PERSON_AMOUNTS + } + for _ in range(2) + ], + "family": {name: draw(st.integers(0, 4_000)) for name in FAMILY_AWARDS}, + "universal_credit": draw(st.integers(1, 35_000)), + "housing_benefit": draw(st.integers(1, 25_000)), + } + + +def holder_amounts(row, variant): + """The holder's Maternity Allowance and other benefit after the move.""" + allowance = row["own"][0]["maternity_allowance_reported"] + other = row["own"][0][row["other"]] + added_to_allowance = { + "base": 0, + "allowance": row["moved"], + "other": 0, + "split": row["split"], + }[variant] + added_to_other = { + "base": 0, + "allowance": 0, + "other": row["moved"], + "split": row["moved"] - row["split"], + }[variant] + return allowance + added_to_allowance, other + added_to_other + + +def fill(sim, drawn): + """Enter each row's amounts into the fixed families and recalculate.""" + person_inputs = {name: [] for name in PERSON_AMOUNTS} + unit_inputs = { + name: [] + for name in [ + *FAMILY_AWARDS, + "universal_credit_pre_benefit_cap", + "housing_benefit_pre_benefit_cap", + ] + } + for row in drawn: + for (structure, holder), scheme, variant in UNITS: + for j, _ in enumerate(STRUCTURES[structure]): + # The holder takes the first member's benefits before the + # move; any other member takes the second's. + own = dict(row["own"][0 if j == holder else 1]) + if j == holder: + allowance, other = holder_amounts(row, variant) + own["maternity_allowance_reported"] = allowance + own[row["other"]] = other + for name in PERSON_AMOUNTS: + person_inputs[name].append(own[name]) + for name in FAMILY_AWARDS: + unit_inputs[name].append(row["family"][name]) + unit_inputs["universal_credit_pre_benefit_cap"].append( + row["universal_credit"] if scheme == "uc" else 0 + ) + unit_inputs["housing_benefit_pre_benefit_cap"].append( + row["housing_benefit"] if scheme == "hb" else 0 + ) + for name, values in {**person_inputs, **unit_inputs}.items(): + sim.set_input(name, YEAR, np.array(values, dtype=float)) + sim.reset_calculations() + + +OUTPUTS = [ + "benefit_cap_welfare_benefits", + "is_uc_benefit_cap_exempt", + "is_housing_benefit_benefit_cap_exempt", + "uc_benefit_cap", + "housing_benefit_benefit_cap", + "uc_benefit_cap_reduction", + "housing_benefit_benefit_cap_reduction", +] + + +def results(sim, drawn): + """Each output by row and unit: {name: array of shape (rows, units)}.""" + fill(sim, drawn) + out = {} + for name in OUTPUTS: + values = np.asarray(sim.calculate(name, YEAR)).astype(float) + out[name] = values.reshape(ROWS, len(UNITS)) + return out + + +def column(holder, scheme, variant): + return UNITS.index((holder, scheme, variant)) + + +def tolerance(*values): + """A penny plus float32 rounding on the amounts involved.""" + return 0.01 + 1e-6 * sum(abs(float(v)) for v in values) + + +def reference_total(row, structure, holder, scheme, variant): + """WRA 2012 s.96(10); UC Regs 2013 regs 79(1), 80(1); HB Regs 2006 reg + 75A: the claimant's and partner's own welfare benefits and the family's + awards. A non-dependent adult's benefits are their own.""" + total = 0.0 + for j, counted in enumerate(STRUCTURES[structure]): + if not counted: + continue + own = dict(row["own"][0 if j == holder else 1]) + if j == holder: + allowance, other = holder_amounts(row, variant) + own["maternity_allowance_reported"] = allowance + own[row["other"]] = other + total += sum(own[name] for name in PERSON_AMOUNTS) + total += sum(row["family"].values()) + if scheme == "uc": + return total + row["universal_credit"] + return total + row["housing_benefit"] + + +SETTINGS = settings( + max_examples=25, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +DRAWS = st.lists(rows(), min_size=ROWS, max_size=ROWS) + + +@SETTINGS +@given(DRAWS) +def test_moving_income_between_maternity_allowance_and_another_counted_benefit( + entered, drawn +): + out = results(entered, drawn) + for r, row in enumerate(drawn): + event(f"moved to {row['other']}") + for holder in HOLDERS: + for scheme in SCHEMES: + columns = [column(holder, scheme, v) for v in VARIANTS[1:]] + for name in OUTPUTS: + values = out[name][r, columns] + assert np.all(np.abs(values - values[0]) <= tolerance(*values)), ( + name, + holder, + scheme, + row, + values, + ) + + +@SETTINGS +@given(DRAWS) +def test_total_rises_by_the_couples_allowance_and_never_falls(entered, drawn): + out = results(entered, drawn) + for r, row in enumerate(drawn): + for structure, holder in HOLDERS: + counted = STRUCTURES[structure][holder] + for scheme in SCHEMES: + base = column((structure, holder), scheme, "base") + raised = column((structure, holder), scheme, "allowance") + total = out["benefit_cap_welfare_benefits"][r] + rise = total[raised] - total[base] + expected = row["moved"] if counted else 0 + assert abs(rise - expected) <= tolerance(total[base], total[raised]), ( + structure, + holder, + scheme, + row, + rise, + ) + for name in [ + "uc_benefit_cap_reduction", + "housing_benefit_benefit_cap_reduction", + ]: + before, after = out[name][r, base], out[name][r, raised] + assert after >= before - tolerance(before, after), ( + name, + structure, + holder, + scheme, + row, + ) + + +@SETTINGS +@given(DRAWS) +def test_total_and_reductions_match_the_regulations(entered, drawn): + out = results(entered, drawn) + for r, row in enumerate(drawn): + for (structure, holder), scheme, variant in UNITS: + i = column((structure, holder), scheme, variant) + total = out["benefit_cap_welfare_benefits"][r, i] + expected = reference_total(row, structure, holder, scheme, variant) + context = (structure, holder, scheme, variant, row) + assert abs(total - expected) <= tolerance(total, expected), context + # None of these benefits lifts either cap (UC Regs 2013 reg 83; + # HB Regs 2006 regs 75E, 75F). + limit = COUPLE_LIMIT if structure == "couple" else SINGLE_LIMIT + if scheme == "uc": + assert not out["is_uc_benefit_cap_exempt"][r, i], context + assert out["uc_benefit_cap"][r, i] == limit, context + # UC reg 81, with no childcare costs element and no Housing + # Benefit to count as nil (reg 80(2A)). + reduction = max(expected - limit, 0) + actual = out["uc_benefit_cap_reduction"][r, i] + else: + assert not out["is_housing_benefit_benefit_cap_exempt"][r, i], context + assert out["housing_benefit_benefit_cap"][r, i] == limit, context + # HB reg 75D(2). + reduction = min( + max(expected - limit, 0), + max(row["housing_benefit"] - HOUSING_BENEFIT_MINIMUM, 0), + ) + actual = out["housing_benefit_benefit_cap_reduction"][r, i] + event(f"{scheme} capped: {reduction > 0}") + assert abs(actual - reduction) <= tolerance(expected, limit), context + + +# Invariant 4: Universal Credit worked out by the model, 2026-27, for families +# renting privately in Tyneside. The mother is the claimant of a lone-parent +# family and the partner in a couple. +MODEL_YEAR = 2026 +MODEL_FAMILIES = { + "lone_parent_1": [30, 2], + "lone_parent_3": [30, 1, 4, 7], + "couple_2": [33, 30, 3, 6], + "couple_3": [33, 30, 1, 5, 9], +} +MOTHER = {"lone_parent_1": 0, "lone_parent_3": 0, "couple_2": 1, "couple_3": 1} +POINTS = ["lower", "higher"] +MODEL_UNITS = [(family, point) for family in MODEL_FAMILIES for point in POINTS] + + +def model_situation(): + people, benunits, households = {}, {}, {} + for i, (family, _) in enumerate(MODEL_UNITS): + unit = f"m{i}" + members = [f"{unit}_p{j}" for j in range(len(MODEL_FAMILIES[family]))] + for name, age in zip(members, MODEL_FAMILIES[family]): + people[name] = {"age": {MODEL_YEAR: age}} + benunits[unit] = {"members": members} + if family.startswith("couple"): + benunits[unit]["relation_type"] = {MODEL_YEAR: "COUPLE"} + households[f"{unit}_home"] = { + "members": members, + "region": {MODEL_YEAR: "NORTH_EAST"}, + "brma": {MODEL_YEAR: "TYNESIDE"}, + "tenure_type": {MODEL_YEAR: "RENT_PRIVATELY"}, + } + return {"people": people, "benunits": benunits, "households": households} + + +@pytest.fixture(scope="module") +def modelled(): + return Simulation(situation=model_situation()) + + +@st.composite +def model_draws(draw): + """Each family's rent, the mother's allowance and the rise in it.""" + return { + family: { + "rent": draw(st.integers(3_000, 24_000)), + # Up to 39 weeks at the 2026-27 standard rate, 194.32 a week. + "allowance": draw(st.integers(0, 7_578)), + "rise": draw(st.integers(1, 3_000)), + } + for family in MODEL_FAMILIES + } + + +@settings( + max_examples=20, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow], +) +@given(model_draws()) +def test_universal_credit_falls_by_the_allowance_inside_the_cap(modelled, drawn): + allowance, rent = [], [] + for family, point in MODEL_UNITS: + d = drawn[family] + amount = d["allowance"] + (d["rise"] if point == "higher" else 0) + for j in range(len(MODEL_FAMILIES[family])): + allowance.append(amount if j == MOTHER[family] else 0) + rent.append(d["rent"]) + modelled.set_input( + "maternity_allowance_reported", MODEL_YEAR, np.array(allowance, float) + ) + modelled.set_input("rent", MODEL_YEAR, np.array(rent, float)) + modelled.reset_calculations() + value = { + name: np.asarray(modelled.calculate(name, MODEL_YEAR)).astype(float) + for name in [ + "universal_credit_pre_benefit_cap", + "benefit_cap_welfare_benefits", + "uc_benefit_cap_reduction", + "universal_credit", + ] + } + for f, family in enumerate(MODEL_FAMILIES): + lower, higher = 2 * f, 2 * f + 1 + d = drawn[family] + before = value["universal_credit_pre_benefit_cap"] + if not (before[lower] > 0 and before[higher] > 0): + event("award before the cap reaches nil") + continue + context = (family, d, {k: v[[lower, higher]] for k, v in value.items()}) + assert abs(before[lower] - before[higher] - d["rise"]) <= tolerance( + before[lower], before[higher] + ), context + total = value["benefit_cap_welfare_benefits"] + assert abs(total[higher] - total[lower]) <= tolerance( + total[lower], total[higher] + ), context + reduction = value["uc_benefit_cap_reduction"] + capped = reduction[lower] > 0 and reduction[higher] > 0 + event(f"capped at both amounts: {capped}") + if capped: + paid = value["universal_credit"] + kept_lower = paid[lower] + d["allowance"] + kept_higher = paid[higher] + d["allowance"] + d["rise"] + assert abs(kept_higher - kept_lower) <= tolerance( + kept_lower, kept_higher + ), context diff --git a/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py b/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py index dc0af1081b..f80f61d5a2 100644 --- a/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py +++ b/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py @@ -29,6 +29,8 @@ "esa_contrib", "incapacity_benefit", "sda", + # s. 96(10)(i). + "maternity_allowance", # s. 96(10)(n). "widowed_parents_allowance", ] @@ -60,9 +62,10 @@ class benefit_cap_welfare_benefits(Variable): "housing_benefit_pre_benefit_cap). Universal Credit counts Housing " "Benefit as nil (UC Regs 2013 reg. 80(2A)), so " "uc_benefit_cap_reduction subtracts it; an entered total should " - "include it. Widowed parent's allowance counts; maternity allowance " - "and the other bereavement benefits, also welfare benefits, are not " - "modelled here." + "include it. Maternity Allowance and widowed parent's allowance " + "count. The model has no variable for three other welfare benefits " + "Parliament lists in Welfare Reform Act 2012 s. 96(10): bereavement " + "allowance, widow's pension and widowed mother's allowance." ) definition_period = YEAR unit = GBP From 4524a28ab120f31167d3f4965eb448692d5a75c0 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 03:39:55 -0500 Subject: [PATCH 2/7] Name who counts Maternity Allowance in the cap's tests and notes The comments, case names and changelog now say that DWP and councils count the claimant's and partner's allowance, and that Parliament lists it among the welfare benefits regulations may cap. No test value changes. Co-Authored-By: Claude Opus 5.5 --- changelog.d/2784.fixed.md | 2 +- .../benefit_cap/benefit_cap_capped_total.yaml | 38 +++++++++---------- ...efit_cap_maternity_allowance_properties.py | 22 +++++------ .../gov/dwp/benefit_cap_welfare_benefits.py | 9 +++-- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/changelog.d/2784.fixed.md b/changelog.d/2784.fixed.md index 509ddc6dc1..6bd5228559 100644 --- a/changelog.d/2784.fixed.md +++ b/changelog.d/2784.fixed.md @@ -1 +1 @@ -The benefit cap now counts the claimant's and partner's Maternity Allowance, which Parliament lists among the welfare benefits the cap covers (Welfare Reform Act 2012 s.96(10)(i)). A capped family receiving it loses that much more Universal Credit or Housing Benefit, as it does for its other capped benefits; a non-dependent adult's allowance still does not count (#2784). +PolicyEngine now counts the claimant's and partner's Maternity Allowance in the benefit cap, as Parliament lists it among the welfare benefits regulations may cap (Welfare Reform Act 2012 s.96(10)(i)). DWP and councils now take the allowance off a capped family's Universal Credit or Housing Benefit, as they do the family's other capped benefits, and still leave a non-dependent adult's allowance out (#2784). diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml index 7c4f451118..0bf5a00dfe 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml @@ -328,16 +328,16 @@ uc_benefit_cap: 22_020 benefit_cap_reduction: 0 -# Maternity Allowance is a welfare benefit (WRA 2012 s.96(10)(i)). It belongs -# to the woman entitled to it (SSCBA 1992 s.35(1)), so the cap counts it when -# she is the claimant or partner and leaves it out when she is a -# non-dependent adult. UC Regs -# 2013 reg 80(4) and HB Regs 2006 reg 75C(4) take the amount each scheme -# counts as income: all of it, as unearned income for Universal Credit (reg -# 66(1)(b)(viii)) and as income other than earnings for Housing Benefit (reg -# 40, with no disregard in Sch 5). +# Parliament lists Maternity Allowance among the welfare benefits +# regulations may cap (WRA 2012 s.96(10)(i)). The woman entitled to it +# receives it (SSCBA 1992 s.35(1)), so DWP and councils count it when she is +# the claimant or partner and leave it out when she is a non-dependent adult. +# Under UC Regs 2013 reg 80(4) and HB Regs 2006 reg 75C(4) they use the amount +# each scheme counts as income: all of it, as unearned income for Universal +# Credit (reg 66(1)(b)(viii)) and as income other than earnings for Housing +# Benefit (reg 40, with no disregard in Sch 5). -- name: The claimant's own Maternity Allowance is in the capped total +- name: DWP counts the claimant's own Maternity Allowance in the capped total period: 2025 input: people: @@ -355,9 +355,9 @@ output: maternity_allowance: 3_000 benefit_cap_welfare_benefits: 18_000 - # Maternity Allowance starts as early as the 11th week before the - # expected week of confinement (SSCBA 1992 s.35(1)(a)), so a claimant - # can receive it before she is responsible for a child. A single + # A woman can become entitled to Maternity Allowance from the 11th week + # before the expected week of confinement (SSCBA 1992 s.35(1)(a)), so a + # claimant can receive it before she is responsible for a child. A single # claimant with no child outside London: 14,753 (UC Regs 2013 reg # 80A(2)(c)). Reg 81: max(15,000 + 3,000 - 14,753 - 0 childcare, 0) # = 3,247, which leaves 15,000 - 3,247 = 11,753. @@ -367,7 +367,7 @@ benefit_cap_reduction: 3_247 universal_credit: 11_753 -- name: A partner's Maternity Allowance is in the capped total +- name: DWP counts a partner's Maternity Allowance in the capped total period: 2025 input: people: @@ -397,7 +397,7 @@ benefit_cap_reduction: 1_980 universal_credit: 18_020 -- name: A non-dependent adult's Maternity Allowance is not in the family's capped total +- name: DWP leaves a non-dependent adult's Maternity Allowance out of the family's capped total period: 2025 input: people: @@ -420,14 +420,14 @@ output: maternity_allowance: [0, 5_000] benefit_cap_welfare_benefits: 20_000 - # UC reg 81: max(20,000 - 14,753 - 0 childcare, 0) = 5,247. The adult's - # 5,000 is their own, not the family's. + # UC reg 81: max(20,000 - 14,753 - 0 childcare, 0) = 5,247. The adult + # receives the 5,000 in their own right. uc_benefit_cap_reduction: 5_247 housing_benefit_benefit_cap_reduction: 0 benefit_cap_reduction: 5_247 universal_credit: 14_753 -- name: The claimant's own Maternity Allowance reduces Housing Benefit for a family without Universal Credit +- name: A council counts the claimant's own Maternity Allowance when it caps Housing Benefit for a family without Universal Credit period: 2025 input: people: @@ -480,7 +480,7 @@ # (Rates) Regulations 2006 reg 2(1), as SI 2026/232 art. 2 sets them). # The family's limit is 22,020 (reg 80A(2)(d)(ii)); no exception applies. -- name: Issue 2784 family with no Maternity Allowance loses the excess over the cap +- name: DWP takes the excess over the cap off the issue 2784 family's Universal Credit when it has no Maternity Allowance period: 2026 absolute_error_margin: 0.01 input: @@ -518,7 +518,7 @@ uc_benefit_cap_reduction: 5_088.84 universal_credit: 18_751.80 -- name: Issue 2784 family's Maternity Allowance stays inside the cap, so Universal Credit falls by the allowance +- name: DWP takes the issue 2784 family's Maternity Allowance off its capped Universal Credit pound for pound period: 2026 absolute_error_margin: 0.01 input: diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py index 8de0a9fff6..dd4dd40b6d 100644 --- a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -1,13 +1,13 @@ -"""The benefit cap counts Maternity Allowance like the other welfare benefits. +"""DWP and councils count Maternity Allowance in the benefit cap. -Parliament lists maternity allowance among the welfare benefits the cap -applies to (Welfare Reform Act 2012 s.96(10)(i)), and the woman entitled to it -receives it (Social Security Contributions and Benefits Act 1992 s.35(1)). UC -Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A count the welfare -benefits "to which the single person or couple is entitled". Regs 80(4) and -75C(4) take the amount each scheme counts as income, which for Maternity -Allowance is all of it (UC Regs 2013 reg 66(1)(b)(viii); HB Regs 2006 reg 40, -whose Sch 5 disregards none of it). +Parliament lists maternity allowance among the welfare benefits regulations +may cap (Welfare Reform Act 2012 s.96(10)(i)), and the woman entitled to it +receives it (Social Security Contributions and Benefits Act 1992 s.35(1)). +Under UC Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A, DWP and +councils count the welfare benefits "to which the single person or couple is +entitled". Under regs 80(4) and 75C(4) they use the amount each scheme counts +as income: all of a Maternity Allowance (UC Regs 2013 reg 66(1)(b)(viii); HB +Regs 2006 reg 40, whose Sch 5 disregards none of it). Invariants, for families on Universal Credit or on Housing Benefit alone, and a holder who is a single claimant, either member of a couple, or a @@ -36,8 +36,8 @@ the mother's allowance by d lowers that award by d (reg 66(1)(b)(viii)), so the total does not move. Where the cap reduces the award at both amounts, Universal Credit after the cap plus the allowance does not move - either: the cap holds the family's capped benefits at its limit whichever - of them the allowance replaces. + either: DWP holds the family's capped benefits at the limit whichever of + them the allowance replaces. Each example fills fixed benefit units in one simulation per module, so the draws set amounts while each family's members stay fixed. diff --git a/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py b/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py index f80f61d5a2..800013f66a 100644 --- a/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py +++ b/policyengine_uk/variables/gov/dwp/benefit_cap_welfare_benefits.py @@ -62,10 +62,11 @@ class benefit_cap_welfare_benefits(Variable): "housing_benefit_pre_benefit_cap). Universal Credit counts Housing " "Benefit as nil (UC Regs 2013 reg. 80(2A)), so " "uc_benefit_cap_reduction subtracts it; an entered total should " - "include it. Maternity Allowance and widowed parent's allowance " - "count. The model has no variable for three other welfare benefits " - "Parliament lists in Welfare Reform Act 2012 s. 96(10): bereavement " - "allowance, widow's pension and widowed mother's allowance." + "include it. The total includes Maternity Allowance and widowed " + "parent's allowance. The model has no variable for three other " + "welfare benefits Parliament lists in Welfare Reform Act 2012 s. " + "96(10): bereavement allowance, widow's pension and widowed mother's " + "allowance." ) definition_period = YEAR unit = GBP From 1a3509a32b0bc9f6c38ba55ed222bc6740b0f73a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 08:30:07 -0500 Subject: [PATCH 3/7] Test the Maternity Allowance cap against each scheme's own amounts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Councils disregard £15 a week of widowed parent's allowance (HB Regs 2006 Sch 5 para 16(b)) and any tax paid on incapacity benefit (Sch 5 para 1), so the Housing Benefit exchange now draws only contribution-based JSA or ESA and severe disablement allowance, and the written reference sums only the benefits each scheme counts at the award. The Universal Credit exchange keeps all five (UC Regs 2013 regs 66(1)(b), 80(1), (4)). Invariant 4 now holds only where the award absorbs the whole reduction at both amounts, and a named test for a mother of 16 shows what happens once the cap takes Universal Credit to nil. Three YAML cases check the final award input, the 2024-25 year and an entered joint claimant who is not the Housing Benefit partner. Co-Authored-By: Claude Opus 5.5 --- .../benefit_cap/benefit_cap_capped_total.yaml | 161 ++++++++++--- ...efit_cap_maternity_allowance_properties.py | 213 ++++++++++++++---- 2 files changed, 298 insertions(+), 76 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml index 0bf5a00dfe..1a4b5dff21 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml @@ -328,14 +328,14 @@ uc_benefit_cap: 22_020 benefit_cap_reduction: 0 -# Parliament lists Maternity Allowance among the welfare benefits -# regulations may cap (WRA 2012 s.96(10)(i)). The woman entitled to it -# receives it (SSCBA 1992 s.35(1)), so DWP and councils count it when she is -# the claimant or partner and leave it out when she is a non-dependent adult. -# Under UC Regs 2013 reg 80(4) and HB Regs 2006 reg 75C(4) they use the amount -# each scheme counts as income: all of it, as unearned income for Universal -# Credit (reg 66(1)(b)(viii)) and as income other than earnings for Housing -# Benefit (reg 40, with no disregard in Sch 5). +# Parliament lists Maternity Allowance among the welfare benefits whose +# total the Secretary of State may cap by regulations (WRA 2012 s.96(1), +# (10)(i)). The woman entitled to it receives it (SSCBA 1992 s.35(1)), so DWP +# and councils count it when she is the claimant or partner and leave it out +# when she is a non-dependent adult. Under UC Regs 2013 reg 80(4) and HB Regs +# 2006 reg 75C(4) they use the amount each scheme counts as income. DWP +# counts all of it as unearned income (reg 66(1)(b)(viii)), and councils +# disregard none of it under HB Regs 2006 reg 40 and Schedule 5. - name: DWP counts the claimant's own Maternity Allowance in the capped total period: 2025 @@ -356,11 +356,12 @@ maternity_allowance: 3_000 benefit_cap_welfare_benefits: 18_000 # A woman can become entitled to Maternity Allowance from the 11th week - # before the expected week of confinement (SSCBA 1992 s.35(1)(a)), so a - # claimant can receive it before she is responsible for a child. A single - # claimant with no child outside London: 14,753 (UC Regs 2013 reg - # 80A(2)(c)). Reg 81: max(15,000 + 3,000 - 14,753 - 0 childcare, 0) - # = 3,247, which leaves 15,000 - 3,247 = 11,753. + # before the expected week of confinement (SSCBA 1992 s.35(1)(a)), so she + # can receive it before she is responsible for a child. DWP applies the + # limit for a single claimant with no child outside London, 14,753 (UC + # Regs 2013 reg 80A(2)(c)). Under reg 81 it reduces her Universal Credit + # by max(15,000 + 3,000 - 14,753 - 0 childcare, 0) = 3,247 and pays + # 15,000 - 3,247 = 11,753. uc_benefit_cap: 14_753 uc_benefit_cap_reduction: 3_247 housing_benefit_benefit_cap_reduction: 0 @@ -388,9 +389,10 @@ is_uc_assessed_claimant: [true, true] maternity_allowance: [0, 4_000] benefit_cap_welfare_benefits: 24_000 - # Joint claimants outside London: 22,020 (UC Regs 2013 reg 80A(2)(d)(i)). - # Reg 81: max(20,000 + 4,000 - 22,020 - 0 childcare, 0) = 1,980, which - # leaves 20,000 - 1,980 = 18,020. + # DWP applies the limit for joint claimants outside London, 22,020 (UC + # Regs 2013 reg 80A(2)(d)(i)). Under reg 81 it reduces their Universal + # Credit by max(20,000 + 4,000 - 22,020 - 0 childcare, 0) = 1,980 and + # pays 20,000 - 1,980 = 18,020. uc_benefit_cap: 22_020 uc_benefit_cap_reduction: 1_980 housing_benefit_benefit_cap_reduction: 0 @@ -420,8 +422,9 @@ output: maternity_allowance: [0, 5_000] benefit_cap_welfare_benefits: 20_000 - # UC reg 81: max(20,000 - 14,753 - 0 childcare, 0) = 5,247. The adult - # receives the 5,000 in their own right. + # Under UC reg 81 DWP reduces the claimant's Universal Credit by + # max(20,000 - 14,753 - 0 childcare, 0) = 5,247. The adult receives the + # 5,000 in their own right. uc_benefit_cap_reduction: 5_247 housing_benefit_benefit_cap_reduction: 0 benefit_cap_reduction: 5_247 @@ -447,10 +450,11 @@ output: universal_credit_pre_benefit_cap: 0 benefit_cap_welfare_benefits: 15_000 - # A single claimant outside London: 14,753 (HB Regs 2006 reg 75CA(2)(c)). - # Reg 75D: min(9,000 + 6,000 - 14,753, 9,000 - 0.50 * 52) = 247, which - # leaves 9,000 - 247 = 8,753. No UC award: UC reg 78(1) gives no UC - # reduction. + # The council applies the limit for a single claimant outside London, + # 14,753 (HB Regs 2006 reg 75CA(2)(c)). Under reg 75D it reduces her + # Housing Benefit by min(9,000 + 6,000 - 14,753, 9,000 - 0.50 * 52) = 247 + # and pays 9,000 - 247 = 8,753. She has no Universal Credit award for DWP + # to reduce (UC reg 78(1)). housing_benefit_benefit_cap: 14_753 uc_benefit_cap_reduction: 0 housing_benefit_benefit_cap_reduction: 247 @@ -464,9 +468,9 @@ # Universal Credit before the cap, monthly (DWP, Benefit and pension rates # 2026 to 2027): # standard allowance, single 25 or over 424.90 -# child element, 3 x 303.94 (SI 2026/148 Sch 13; reg 24A, the two-child -# limit, revoked from 6 April 2026 by the Universal Credit (Removal of -# Two Child Limit) Act 2026 s.1(3)(a)) 911.82 +# child element, 3 x 303.94 (SI 2026/148 Sch 13; Parliament revoked +# reg 24A, the two-child limit, from 6 April 2026 through the Universal +# Credit (Removal of Two Child Limit) Act 2026 s.1(3)(a)) 911.82 # housing costs element: the lower of the rent, 1,500, and the cap rent # (UC Regs 2013 Sch 4 para 22), the three-bedroom rate of 650.00 (DWP, # Universal Credit LHA monthly rates 2026 to 2027, Tyneside): one bedroom @@ -513,8 +517,8 @@ benefit_cap_welfare_benefits: 27_108.84 uc_benefit_cap: 22_020 is_uc_benefit_cap_exempt: false - # Reg 81: 27,108.84 - 22,020 - 0 childcare = 5,088.84, which leaves - # 23,840.64 - 5,088.84 = 18,751.80. + # Under reg 81 DWP reduces the award by 27,108.84 - 22,020 - 0 childcare + # = 5,088.84 and pays 23,840.64 - 5,088.84 = 18,751.80. uc_benefit_cap_reduction: 5_088.84 universal_credit: 18_751.80 @@ -549,9 +553,104 @@ # 17,840.64 + 3,268.20 Child Benefit + 6,000 Maternity Allowance # = 27,108.84, the same total as without the allowance. benefit_cap_welfare_benefits: 27_108.84 - # Reg 81: 27,108.84 - 22,020 - 0 childcare = 5,088.84, which leaves - # 17,840.64 - 5,088.84 = 12,751.80. With the allowance, 12,751.80 + - # 6,000 = 18,751.80: what the family keeps from Universal Credit alone - # without it. + # Under reg 81 DWP reduces the award by 27,108.84 - 22,020 - 0 childcare + # = 5,088.84 and pays 17,840.64 - 5,088.84 = 12,751.80. With the + # allowance the family keeps 12,751.80 + 6,000 = 18,751.80, the same as + # it keeps from Universal Credit alone without it. uc_benefit_cap_reduction: 5_088.84 universal_credit: 12_751.80 + +# Each of the next three cases holds the award before the cap fixed, so the +# total and the reduction follow from the Maternity Allowance alone. + +- name: DWP counts the Maternity Allowance the claimant is entitled to, not the amount she reported + period: 2025 + input: + people: + claimant: + age: 30 + maternity_allowance_reported: 999 + maternity_allowance: 3_000 + benunits: + family: + members: [claimant] + universal_credit_pre_benefit_cap: 15_000 + households: + home: + members: [claimant] + region: NORTH_EAST + output: + # Her award is 3,000 (UC Regs 2013 reg 80(1), (4)), so 15,000 + 3,000. + benefit_cap_welfare_benefits: 18_000 + uc_benefit_cap: 14_753 + # Under reg 81 DWP reduces her Universal Credit by max(18,000 - 14,753 + # - 0 childcare, 0) = 3,247 and pays 15,000 - 3,247 = 11,753. + uc_benefit_cap_reduction: 3_247 + universal_credit: 11_753 + +- name: DWP counted the claimant's own Maternity Allowance in the capped total in 2024-25 + period: 2024 + input: + people: + claimant: + age: 30 + maternity_allowance_reported: 3_000 + benunits: + family: + members: [claimant] + universal_credit_pre_benefit_cap: 15_000 + households: + home: + members: [claimant] + region: NORTH_EAST + output: + maternity_allowance: 3_000 + # The Secretary of State included Maternity Allowance in UC Regs 2013 + # reg 79(4)(g) as made, and Parliament has listed it in WRA 2012 + # s.96(10)(i) since 2016. + benefit_cap_welfare_benefits: 18_000 + # SI 2023/335 reg 3(c) set the limit for a single claimant with no child + # outside London at 14,753 from 1 April 2023 (reg 80A(2)(c)). Under reg + # 81 DWP reduces her Universal Credit by max(15,000 + 3,000 - 14,753 - 0 + # childcare, 0) = 3,247 and pays 15,000 - 3,247 = 11,753. + uc_benefit_cap: 14_753 + uc_benefit_cap_reduction: 3_247 + universal_credit: 11_753 + +- name: On Universal Credit, DWP counts an entered joint claimant's own Maternity Allowance though she is not the Housing Benefit partner + period: 2025 + input: + people: + claimant: + age: 40 + is_claimant_or_partner: true + is_uc_claimant: true + adult: + age: 30 + is_claimant_or_partner: false + is_uc_claimant: true + current_education: NOT_IN_EDUCATION + maternity_allowance_reported: 4_000 + benunits: + family: + members: [claimant, adult] + universal_credit_pre_benefit_cap: 20_000 + housing_benefit_pre_benefit_cap: 0 + households: + home: + members: [claimant, adult] + region: NORTH_EAST + output: + is_uc_assessed_claimant: [true, true] + maternity_allowance: [0, 4_000] + # DWP counts the joint claimants' welfare benefits (UC Regs 2013 regs + # 78(2)(a), 80(1)): 20,000 + 4,000. + benefit_cap_welfare_benefits: 24_000 + # DWP applies the limit for joint claimants outside London, 22,020 (reg + # 80A(2)(d)(i)). Under reg 81 it reduces their Universal Credit by + # max(24,000 - 22,020 - 0 childcare, 0) = 1,980 and pays 20,000 - 1,980 + # = 18,020. + uc_benefit_cap: 22_020 + uc_benefit_cap_reduction: 1_980 + housing_benefit_benefit_cap_reduction: 0 + universal_credit: 18_020 diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py index dd4dd40b6d..69a69acf4e 100644 --- a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -6,18 +6,29 @@ Under UC Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A, DWP and councils count the welfare benefits "to which the single person or couple is entitled". Under regs 80(4) and 75C(4) they use the amount each scheme counts -as income: all of a Maternity Allowance (UC Regs 2013 reg 66(1)(b)(viii); HB -Regs 2006 reg 40, whose Sch 5 disregards none of it). +as income. DWP counts all of a Maternity Allowance as unearned income (UC Regs +2013 reg 66(1)(b)(viii)), and councils disregard none of it under HB Regs 2006 +reg 40 and Schedule 5. Invariants, for families on Universal Credit or on Housing Benefit alone, and a holder who is a single claimant, either member of a couple, or a non-dependent adult: 1. Exchange: moving an amount between the holder's Maternity Allowance and - an equal amount of another welfare benefit of theirs that the cap counts - in the same way (contribution-based JSA or ESA, incapacity benefit, severe - disablement allowance or widowed parent's allowance) leaves the cap's - total, both exemptions and both reductions unchanged. + an equal amount of another welfare benefit of theirs that the scheme + counts in the same way leaves the cap's total, both exemptions and both + reductions unchanged. For Universal Credit the other benefit is + contribution-based JSA or ESA, incapacity benefit, severe disablement + allowance or widowed parent's allowance. DWP counts JSA, ESA and widowed + parent's allowance in full as unearned income (UC Regs 2013 regs + 66(1)(b)(i), (ii), (vi) and 80(4)), and the other two at the amount of the + award (reg 80(1)). For Housing Benefit it is contribution-based JSA or ESA, + which councils count at the amount of the award (HB Regs 2006 reg 75C(1), + (4)), or severe disablement allowance, which no paragraph of Schedule 5 + disregards and which bears no income tax (ITEPA 2003 s.677(1)). Councils + disregard £15 a week of widowed parent's allowance (Sch 5 para 16(b)) and + any tax paid on incapacity benefit (Sch 5 para 1; ITEPA 2003 s.660(1)), so + the families on Housing Benefit receive neither. 2. Coefficient one: with each award before the cap entered, so that Universal Credit does not taper, raising the holder's allowance by d raises the total by exactly d when the holder is the claimant or partner, @@ -34,10 +45,15 @@ 4. Pound for pound, through the whole model: where the model works out Universal Credit and the award before the cap stays above nil, raising the mother's allowance by d lowers that award by d (reg 66(1)(b)(viii)), - so the total does not move. Where the cap reduces the award at both - amounts, Universal Credit after the cap plus the allowance does not move - either: DWP holds the family's capped benefits at the limit whichever of - them the allowance replaces. + so the total does not move. Where DWP reduces the award at both + amounts, and the award absorbs the whole reduction at each, Universal + Credit after the cap plus the allowance does not move either: DWP holds + the family's capped benefits at the limit whichever of them the allowance + replaces. That needs an award large enough to take the whole excess and no + protected floor that limits the reduction. Once the reduction takes the + award to nil, DWP has nothing left to reduce, and each further pound of + allowance adds a pound to what the family keeps: the test for a mother of + 16 children shows it. Each example fills fixed benefit units in one simulation per module, so the draws set amounts while each family's members stay fixed. @@ -60,14 +76,19 @@ HOUSING_BENEFIT_MINIMUM = 0.50 * 52 # The holder's other welfare benefits that the cap counts as theirs (WRA 2012 -# s.96(10)(d), (f), (h), (j), (n)), each entered as an award. -OTHER_BENEFITS = [ - "jsa_contrib", - "esa_contrib", - "incapacity_benefit", - "sda", - "widowed_parents_allowance", -] +# s.96(10)(d), (f), (h), (j), (n)), each entered as an award. Each scheme's +# list holds those it counts at the amount of the award, as it does +# Maternity Allowance (invariant 1). +OTHER_BENEFITS = { + "uc": [ + "jsa_contrib", + "esa_contrib", + "incapacity_benefit", + "sda", + "widowed_parents_allowance", + ], + "hb": ["jsa_contrib", "esa_contrib", "sda"], +} FAMILY_AWARDS = ["child_benefit", "child_tax_credit", "income_support"] # Families by structure: whether each member is the claimant or partner. @@ -137,21 +158,30 @@ def entered(): return Simulation(situation=entered_situation()) -PERSON_AMOUNTS = ["maternity_allowance_reported", *OTHER_BENEFITS] +PERSON_AMOUNTS = ["maternity_allowance_reported", *OTHER_BENEFITS["uc"]] +# The benefits each scheme's families receive. Families on Housing Benefit +# receive none of the others, which councils count at less than the award. +SCHEME_AMOUNTS = { + scheme: ["maternity_allowance_reported", *others] + for scheme, others in OTHER_BENEFITS.items() +} pounds = st.integers(0, 1_200_000).map(lambda pence: pence / 100) @st.composite def rows(draw): """One row's amounts: the amount moved and its split, the other benefit - it moves to, every member's own benefits before the move, and the - family's awards.""" + it moves to under each scheme, every member's own benefits before the + move, and the family's awards.""" moved = draw(pounds) split = round(moved * draw(st.integers(0, 100)) / 100, 2) return { "moved": moved, "split": split, - "other": draw(st.sampled_from(OTHER_BENEFITS)), + "other": { + scheme: draw(st.sampled_from(others)) + for scheme, others in OTHER_BENEFITS.items() + }, # Benefits before the move, for the first and second member. "own": [ { @@ -166,10 +196,10 @@ def rows(draw): } -def holder_amounts(row, variant): +def holder_amounts(row, scheme, variant): """The holder's Maternity Allowance and other benefit after the move.""" allowance = row["own"][0]["maternity_allowance_reported"] - other = row["own"][0][row["other"]] + other = row["own"][0][row["other"][scheme]] added_to_allowance = { "base": 0, "allowance": row["moved"], @@ -185,6 +215,26 @@ def holder_amounts(row, variant): return allowance + added_to_allowance, other + added_to_other +def member_amounts(row, structure, holder, scheme, variant): + """Each member's own benefits after the move, by member: the holder takes + the first member's benefits before the move, any other member the + second's, and a benefit the scheme's families don't receive is nil.""" + members = [] + for j, _ in enumerate(STRUCTURES[structure]): + own = dict(row["own"][0 if j == holder else 1]) + if j == holder: + allowance, other = holder_amounts(row, scheme, variant) + own["maternity_allowance_reported"] = allowance + own[row["other"][scheme]] = other + members.append( + { + name: own[name] if name in SCHEME_AMOUNTS[scheme] else 0.0 + for name in PERSON_AMOUNTS + } + ) + return members + + def fill(sim, drawn): """Enter each row's amounts into the fixed families and recalculate.""" person_inputs = {name: [] for name in PERSON_AMOUNTS} @@ -198,14 +248,7 @@ def fill(sim, drawn): } for row in drawn: for (structure, holder), scheme, variant in UNITS: - for j, _ in enumerate(STRUCTURES[structure]): - # The holder takes the first member's benefits before the - # move; any other member takes the second's. - own = dict(row["own"][0 if j == holder else 1]) - if j == holder: - allowance, other = holder_amounts(row, variant) - own["maternity_allowance_reported"] = allowance - own[row["other"]] = other + for own in member_amounts(row, structure, holder, scheme, variant): for name in PERSON_AMOUNTS: person_inputs[name].append(own[name]) for name in FAMILY_AWARDS: @@ -254,17 +297,13 @@ def tolerance(*values): def reference_total(row, structure, holder, scheme, variant): """WRA 2012 s.96(10); UC Regs 2013 regs 79(1), 80(1); HB Regs 2006 reg 75A: the claimant's and partner's own welfare benefits and the family's - awards. A non-dependent adult's benefits are their own.""" + awards. A non-dependent adult's benefits are their own. Each scheme's + families receive only benefits it counts at the amount of the award.""" + members = member_amounts(row, structure, holder, scheme, variant) total = 0.0 - for j, counted in enumerate(STRUCTURES[structure]): - if not counted: - continue - own = dict(row["own"][0 if j == holder else 1]) - if j == holder: - allowance, other = holder_amounts(row, variant) - own["maternity_allowance_reported"] = allowance - own[row["other"]] = other - total += sum(own[name] for name in PERSON_AMOUNTS) + for own, counted in zip(members, STRUCTURES[structure]): + if counted: + total += sum(own[name] for name in SCHEME_AMOUNTS[scheme]) total += sum(row["family"].values()) if scheme == "uc": return total + row["universal_credit"] @@ -287,9 +326,9 @@ def test_moving_income_between_maternity_allowance_and_another_counted_benefit( ): out = results(entered, drawn) for r, row in enumerate(drawn): - event(f"moved to {row['other']}") for holder in HOLDERS: for scheme in SCHEMES: + event(f"{scheme}: moved to {row['other'][scheme]}") columns = [column(holder, scheme, v) for v in VARIANTS[1:]] for name in OUTPUTS: values = out[name][r, columns] @@ -449,6 +488,7 @@ def test_universal_credit_falls_by_the_allowance_inside_the_cap(modelled, drawn) "universal_credit_pre_benefit_cap", "benefit_cap_welfare_benefits", "uc_benefit_cap_reduction", + "uc_benefit_cap_reduction_after_floor", "universal_credit", ] } @@ -468,12 +508,95 @@ def test_universal_credit_falls_by_the_allowance_inside_the_cap(modelled, drawn) total[lower], total[higher] ), context reduction = value["uc_benefit_cap_reduction"] + applied = value["uc_benefit_cap_reduction_after_floor"] capped = reduction[lower] > 0 and reduction[higher] > 0 - event(f"capped at both amounts: {capped}") - if capped: + # The award takes the whole reduction at both amounts: it doesn't + # reach nil first, and no protected floor limits the reduction. + absorbed = all( + abs(applied[i] - reduction[i]) <= tolerance(reduction[i]) + for i in (lower, higher) + ) + event(f"capped at both amounts: {capped}; award absorbs it: {absorbed}") + if capped and absorbed: paid = value["universal_credit"] kept_lower = paid[lower] + d["allowance"] kept_higher = paid[higher] + d["allowance"] + d["rise"] assert abs(kept_higher - kept_lower) <= tolerance( kept_lower, kept_higher ), context + + +# The edge of invariant 4. A mother of 40 with 16 children (aged 1 to 15, and +# another of 7) owns her home outright outside London and has no earnings, +# 2026-27. Monthly Universal Credit before her allowance (DWP, Benefit and +# pension rates 2026 to 2027; UC Regs 2013 reg 24A revoked from 6 April 2026 +# by the Universal Credit (Removal of Two Child Limit) Act 2026 s.1(3)(a)): +# standard allowance, single 25 or over 424.90 +# child element, first child born before 6 April 2017 351.88 +# child element, 15 more children, 15 x 303.94 4,559.10 +# maximum amount 5,335.88, or 64,030.56 +# a year +# Child Benefit: (27.05 + 15 x 17.90) x 52 = 15,368.60 a year (Child Benefit +# (Rates) Regulations 2006 reg 2(1)). Her family's limit is 22,020 (reg +# 80A(2)(d)(ii)). +EDGE_CHILD_AGES = [*range(1, 16), 7] +EDGE_ALLOWANCES = [6_000, 7_000] + + +def test_a_mother_of_16_keeps_more_once_the_cap_takes_universal_credit_to_nil(): + people, benunits, households = {}, {}, {} + for i, amount in enumerate(EDGE_ALLOWANCES): + mother = f"e{i}_mother" + children = [f"e{i}_child{j}" for j in range(len(EDGE_CHILD_AGES))] + people[mother] = { + "age": {MODEL_YEAR: 40}, + "maternity_allowance_reported": {MODEL_YEAR: amount}, + } + for child, age in zip(children, EDGE_CHILD_AGES): + people[child] = {"age": {MODEL_YEAR: age}} + benunits[f"e{i}"] = {"members": [mother, *children]} + households[f"e{i}_home"] = { + "members": [mother, *children], + "region": {MODEL_YEAR: "NORTH_EAST"}, + "tenure_type": {MODEL_YEAR: "OWNED_OUTRIGHT"}, + } + sim = Simulation( + situation={"people": people, "benunits": benunits, "households": households} + ) + value = { + name: np.asarray(sim.calculate(name, MODEL_YEAR)).astype(float) + for name in [ + "uc_maximum_amount", + "child_benefit", + "universal_credit_pre_benefit_cap", + "benefit_cap_welfare_benefits", + "uc_benefit_cap", + "uc_benefit_cap_reduction", + "uc_benefit_cap_reduction_after_floor", + "universal_credit", + ] + } + expected = { + "uc_maximum_amount": [64_030.56, 64_030.56], + "child_benefit": [15_368.60, 15_368.60], + # Less the allowance in full (reg 66(1)(b)(viii)): both stay above nil. + "universal_credit_pre_benefit_cap": [58_030.56, 57_030.56], + # 58,030.56 + 15,368.60 + 6,000 = 57,030.56 + 15,368.60 + 7,000. + "benefit_cap_welfare_benefits": [79_399.16, 79_399.16], + "uc_benefit_cap": [22_020, 22_020], + # Reg 81: 79,399.16 - 22,020 - 0 childcare = 57,379.16 at both amounts. + "uc_benefit_cap_reduction": [57_379.16, 57_379.16], + # At 7,000 the award before the cap, 57,030.56, is all DWP can take. + "uc_benefit_cap_reduction_after_floor": [57_379.16, 57_030.56], + # 58,030.56 - 57,379.16 = 651.40, and nil. + "universal_credit": [651.40, 0], + } + for name, amounts in expected.items(): + assert np.allclose(value[name], amounts, rtol=0, atol=0.01), ( + name, + value[name], + ) + # Universal Credit plus the allowance rises from 6,651.40 to 7,000: by + # 348.60 of the 1,000 more allowance, the part the award could not absorb. + kept = value["universal_credit"] + np.array(EDGE_ALLOWANCES) + assert np.allclose(kept, [6_651.40, 7_000], rtol=0, atol=0.01), kept From af5ee8eda27831b2e1603f383e71f770ffe27945 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 08:58:06 -0500 Subject: [PATCH 4/7] Say who counts Maternity Allowance in the changelog PolicyEngine changed its calculation; DWP and councils counted the allowance all along. Co-Authored-By: Claude Opus 5.5 --- changelog.d/2784.fixed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/2784.fixed.md b/changelog.d/2784.fixed.md index 6bd5228559..f0771e044b 100644 --- a/changelog.d/2784.fixed.md +++ b/changelog.d/2784.fixed.md @@ -1 +1 @@ -PolicyEngine now counts the claimant's and partner's Maternity Allowance in the benefit cap, as Parliament lists it among the welfare benefits regulations may cap (Welfare Reform Act 2012 s.96(10)(i)). DWP and councils now take the allowance off a capped family's Universal Credit or Housing Benefit, as they do the family's other capped benefits, and still leave a non-dependent adult's allowance out (#2784). +PolicyEngine now includes the claimant's and partner's Maternity Allowance when it calculates the benefit cap on Universal Credit and Housing Benefit, and leaves a non-dependent adult's allowance out (#2784). Parliament lists the allowance among the welfare benefits whose total the Secretary of State may cap (Welfare Reform Act 2012 s.96(10)(i)). From 69152574196cb1a43d41ce3d22a59b345edddedc Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 09:02:00 -0500 Subject: [PATCH 5/7] Name DWP and councils as the actors in the cap tests' comments The comments and docstrings now give the counting, exempting and paying to DWP and councils rather than to the cap or the scheme, and two YAML case names and the mother-of-16 test name follow. Co-Authored-By: Claude Opus 5.5 --- .../benefit_cap/benefit_cap_capped_total.yaml | 30 ++--- ...efit_cap_maternity_allowance_properties.py | 107 ++++++++++-------- 2 files changed, 73 insertions(+), 64 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml index 1a4b5dff21..2e168540f1 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml @@ -331,10 +331,10 @@ # Parliament lists Maternity Allowance among the welfare benefits whose # total the Secretary of State may cap by regulations (WRA 2012 s.96(1), # (10)(i)). The woman entitled to it receives it (SSCBA 1992 s.35(1)), so DWP -# and councils count it when she is the claimant or partner and leave it out -# when she is a non-dependent adult. Under UC Regs 2013 reg 80(4) and HB Regs -# 2006 reg 75C(4) they use the amount each scheme counts as income. DWP -# counts all of it as unearned income (reg 66(1)(b)(viii)), and councils +# and councils count the allowance of a claimant or partner and leave out +# that of a non-dependent adult in the household. Under UC Regs 2013 reg +# 80(4) and HB Regs 2006 reg 75C(4) they use the amount they count as income. +# DWP counts all of it as unearned income (reg 66(1)(b)(viii)), and councils # disregard none of it under HB Regs 2006 reg 40 and Schedule 5. - name: DWP counts the claimant's own Maternity Allowance in the capped total @@ -356,12 +356,12 @@ maternity_allowance: 3_000 benefit_cap_welfare_benefits: 18_000 # A woman can become entitled to Maternity Allowance from the 11th week - # before the expected week of confinement (SSCBA 1992 s.35(1)(a)), so she - # can receive it before she is responsible for a child. DWP applies the - # limit for a single claimant with no child outside London, 14,753 (UC - # Regs 2013 reg 80A(2)(c)). Under reg 81 it reduces her Universal Credit - # by max(15,000 + 3,000 - 14,753 - 0 childcare, 0) = 3,247 and pays - # 15,000 - 3,247 = 11,753. + # before the expected week of confinement (SSCBA 1992 s.35(1)(a)), so DWP + # can pay it to a woman with no child yet. DWP applies the limit for a + # single claimant with no child outside London, 14,753 (UC Regs 2013 reg + # 80A(2)(c)). Under reg 81 it reduces her Universal Credit by max(15,000 + + # 3,000 - 14,753 - 0 childcare, 0) = 3,247 and pays 15,000 - 3,247 = + # 11,753. uc_benefit_cap: 14_753 uc_benefit_cap_reduction: 3_247 housing_benefit_benefit_cap_reduction: 0 @@ -482,7 +482,8 @@ # # Child Benefit: (27.05 + 2 x 17.90) x 52 = 3,268.20 a year (Child Benefit # (Rates) Regulations 2006 reg 2(1), as SI 2026/232 art. 2 sets them). -# The family's limit is 22,020 (reg 80A(2)(d)(ii)); no exception applies. +# DWP applies the family limit of 22,020 (reg 80A(2)(d)(ii)) and grants no +# exception. - name: DWP takes the excess over the cap off the issue 2784 family's Universal Credit when it has no Maternity Allowance period: 2026 @@ -563,7 +564,7 @@ # Each of the next three cases holds the award before the cap fixed, so the # total and the reduction follow from the Maternity Allowance alone. -- name: DWP counts the Maternity Allowance the claimant is entitled to, not the amount she reported +- name: DWP counts the claimant's Maternity Allowance award, not the amount she reported period: 2025 input: people: @@ -580,7 +581,8 @@ members: [claimant] region: NORTH_EAST output: - # Her award is 3,000 (UC Regs 2013 reg 80(1), (4)), so 15,000 + 3,000. + # DWP counts her 3,000 award (UC Regs 2013 reg 80(1), (4)): 15,000 + + # 3,000. benefit_cap_welfare_benefits: 18_000 uc_benefit_cap: 14_753 # Under reg 81 DWP reduces her Universal Credit by max(18,000 - 14,753 @@ -617,7 +619,7 @@ uc_benefit_cap_reduction: 3_247 universal_credit: 11_753 -- name: On Universal Credit, DWP counts an entered joint claimant's own Maternity Allowance though she is not the Housing Benefit partner +- name: On Universal Credit, DWP counts the Maternity Allowance of an entered joint claimant whom the council doesn't treat as the Housing Benefit partner period: 2025 input: people: diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py index 69a69acf4e..392e117b06 100644 --- a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -10,31 +10,31 @@ 2013 reg 66(1)(b)(viii)), and councils disregard none of it under HB Regs 2006 reg 40 and Schedule 5. -Invariants, for families on Universal Credit or on Housing Benefit alone, and -a holder who is a single claimant, either member of a couple, or a -non-dependent adult: +Invariants, for families on Universal Credit or on Housing Benefit alone, +whether a single claimant, either member of a couple, or a non-dependent +adult receives the allowance: 1. Exchange: moving an amount between the holder's Maternity Allowance and - an equal amount of another welfare benefit of theirs that the scheme - counts in the same way leaves the cap's total, both exemptions and both - reductions unchanged. For Universal Credit the other benefit is - contribution-based JSA or ESA, incapacity benefit, severe disablement - allowance or widowed parent's allowance. DWP counts JSA, ESA and widowed - parent's allowance in full as unearned income (UC Regs 2013 regs - 66(1)(b)(i), (ii), (vi) and 80(4)), and the other two at the amount of the - award (reg 80(1)). For Housing Benefit it is contribution-based JSA or ESA, - which councils count at the amount of the award (HB Regs 2006 reg 75C(1), - (4)), or severe disablement allowance, which no paragraph of Schedule 5 - disregards and which bears no income tax (ITEPA 2003 s.677(1)). Councils - disregard £15 a week of widowed parent's allowance (Sch 5 para 16(b)) and - any tax paid on incapacity benefit (Sch 5 para 1; ITEPA 2003 s.660(1)), so - the families on Housing Benefit receive neither. + an equal amount of another welfare benefit of theirs that DWP or the + council counts in the same way leaves the cap's total, both exemptions and + both reductions unchanged. For Universal Credit the tests draw the other + benefit from contribution-based JSA or ESA, incapacity benefit, severe + disablement allowance and widowed parent's allowance. DWP counts JSA, ESA + and widowed parent's allowance in full as unearned income (UC Regs 2013 + regs 66(1)(b)(i), (ii), (vi) and 80(4)), and the other two at the amount + of the award (reg 80(1)). For Housing Benefit the tests draw + contribution-based JSA or ESA, which councils count at the amount of the + award (HB Regs 2006 reg 75C(1), (4)), or severe disablement allowance, + which no paragraph of Schedule 5 disregards and which bears no income tax + (ITEPA 2003 s.677(1)). Councils disregard £15 a week of widowed parent's + allowance (Sch 5 para 16(b)) and any tax paid on incapacity benefit (Sch 5 + para 1; ITEPA 2003 s.660(1)), so the tests give families on Housing + Benefit neither. 2. Coefficient one: with each award before the cap entered, so that Universal Credit does not taper, raising the holder's allowance by d - raises the total by exactly d when the holder is the claimant or partner, - and leaves it unchanged when the holder is a non-dependent adult. The - total therefore never falls as the allowance rises, and nor does either - reduction. + raises the total by d for a claimant or partner, and leaves it unchanged + for a non-dependent adult. The total therefore never falls as the + allowance rises, and nor does either reduction. 3. Differential: the total equals a reference written from s.96(10) and those regulations: the listed benefits of the claimant and partner, plus the family's Child Benefit, Child Tax Credit, Income Support, and @@ -52,8 +52,9 @@ replaces. That needs an award large enough to take the whole excess and no protected floor that limits the reduction. Once the reduction takes the award to nil, DWP has nothing left to reduce, and each further pound of - allowance adds a pound to what the family keeps: the test for a mother of - 16 children shows it. + allowance adds a pound to what the family keeps. + test_a_mother_of_16_keeps_more_allowance_once_dwp_cuts_her_award_to_nil + checks that edge. Each example fills fixed benefit units in one simulation per module, so the draws set amounts while each family's members stay fixed. @@ -72,13 +73,14 @@ # Outside London, 2025-26 (UC Regs 2013 reg 80A(2)(c), (d); HB Regs 2006 reg # 75CA(2)(c), (d)). SINGLE_LIMIT, COUPLE_LIMIT = 14_753, 22_020 -# HB Regs 2006 reg 75: Housing Benefit is not paid below 50p a week. +# HB Regs 2006 reg 75: councils pay no Housing Benefit of less than 50p a +# week. HOUSING_BENEFIT_MINIMUM = 0.50 * 52 -# The holder's other welfare benefits that the cap counts as theirs (WRA 2012 -# s.96(10)(d), (f), (h), (j), (n)), each entered as an award. Each scheme's -# list holds those it counts at the amount of the award, as it does -# Maternity Allowance (invariant 1). +# The holder's other welfare benefits that DWP and councils count in the cap +# as theirs (WRA 2012 s.96(10)(d), (f), (h), (j), (n)), each entered as an +# award. Each scheme's list holds those that DWP or the council counts at the +# amount of the award, as each counts Maternity Allowance (invariant 1). OTHER_BENEFITS = { "uc": [ "jsa_contrib", @@ -91,7 +93,8 @@ } FAMILY_AWARDS = ["child_benefit", "child_tax_credit", "income_support"] -# Families by structure: whether each member is the claimant or partner. +# Families by structure: True for each member whose benefits DWP and councils +# count, the claimant or partner. STRUCTURES = { "single": [True], "couple": [True, True], @@ -130,17 +133,17 @@ def entered_situation(): "age": {YEAR: 40 - 2 * j}, "is_claimant_or_partner": {YEAR: counted}, "current_education": {YEAR: "NOT_IN_EDUCATION"}, - # No ESA support component, so contribution-based ESA - # does not lift the cap (UC reg 83(1)(a); HB reg - # 75F(1)(a)). + # With no ESA support component, DWP and councils grant + # no exemption for contribution-based ESA (UC reg + # 83(1)(a); HB reg 75F(1)(a)). "esa_includes_support_component": {YEAR: False}, "jsa_income_reported": {YEAR: 0}, "esa_income_reported": {YEAR: 0}, } benunits[unit] = { "members": members, - # Entered as nil, the LCWRA and carer elements are not in the - # award (UC reg 83(1)(a), (j)). + # The tests enter the LCWRA and carer elements as nil, so + # neither exempts the family (UC reg 83(1)(a), (j)). "uc_LCWRA_element": {YEAR: 0}, "uc_carer_element": {YEAR: 0}, } @@ -160,7 +163,7 @@ def entered(): PERSON_AMOUNTS = ["maternity_allowance_reported", *OTHER_BENEFITS["uc"]] # The benefits each scheme's families receive. Families on Housing Benefit -# receive none of the others, which councils count at less than the award. +# receive none of the others, which councils can count at less than the award. SCHEME_AMOUNTS = { scheme: ["maternity_allowance_reported", *others] for scheme, others in OTHER_BENEFITS.items() @@ -218,7 +221,8 @@ def holder_amounts(row, scheme, variant): def member_amounts(row, structure, holder, scheme, variant): """Each member's own benefits after the move, by member: the holder takes the first member's benefits before the move, any other member the - second's, and a benefit the scheme's families don't receive is nil.""" + second's, and a member receives nothing of a benefit outside the scheme's + list.""" members = [] for j, _ in enumerate(STRUCTURES[structure]): own = dict(row["own"][0 if j == holder else 1]) @@ -297,8 +301,9 @@ def tolerance(*values): def reference_total(row, structure, holder, scheme, variant): """WRA 2012 s.96(10); UC Regs 2013 regs 79(1), 80(1); HB Regs 2006 reg 75A: the claimant's and partner's own welfare benefits and the family's - awards. A non-dependent adult's benefits are their own. Each scheme's - families receive only benefits it counts at the amount of the award.""" + awards. A non-dependent adult receives their benefits in their own right. + Each scheme's families receive only the benefits DWP or the council counts + at the amount of the award.""" members = member_amounts(row, structure, holder, scheme, variant) total = 0.0 for own, counted in zip(members, STRUCTURES[structure]): @@ -386,8 +391,8 @@ def test_total_and_reductions_match_the_regulations(entered, drawn): expected = reference_total(row, structure, holder, scheme, variant) context = (structure, holder, scheme, variant, row) assert abs(total - expected) <= tolerance(total, expected), context - # None of these benefits lifts either cap (UC Regs 2013 reg 83; - # HB Regs 2006 regs 75E, 75F). + # DWP and councils grant no exemption for these benefits (UC Regs + # 2013 reg 83; HB Regs 2006 regs 75E, 75F). limit = COUPLE_LIMIT if structure == "couple" else SINGLE_LIMIT if scheme == "uc": assert not out["is_uc_benefit_cap_exempt"][r, i], context @@ -409,9 +414,9 @@ def test_total_and_reductions_match_the_regulations(entered, drawn): assert abs(actual - reduction) <= tolerance(expected, limit), context -# Invariant 4: Universal Credit worked out by the model, 2026-27, for families -# renting privately in Tyneside. The mother is the claimant of a lone-parent -# family and the partner in a couple. +# Invariant 4: the model works out Universal Credit, 2026-27, for families +# renting privately in Tyneside. The mother claims alone in a lone-parent +# family and jointly, as the second member, in a couple. MODEL_YEAR = 2026 MODEL_FAMILIES = { "lone_parent_1": [30, 2], @@ -528,22 +533,23 @@ def test_universal_credit_falls_by_the_allowance_inside_the_cap(modelled, drawn) # The edge of invariant 4. A mother of 40 with 16 children (aged 1 to 15, and # another of 7) owns her home outright outside London and has no earnings, -# 2026-27. Monthly Universal Credit before her allowance (DWP, Benefit and -# pension rates 2026 to 2027; UC Regs 2013 reg 24A revoked from 6 April 2026 -# by the Universal Credit (Removal of Two Child Limit) Act 2026 s.1(3)(a)): +# 2026-27. Parliament revoked UC Regs 2013 reg 24A, the two-child limit, from +# 6 April 2026 through the Universal Credit (Removal of Two Child Limit) Act +# 2026 s.1(3)(a). Monthly Universal Credit before her allowance (DWP, Benefit +# and pension rates 2026 to 2027): # standard allowance, single 25 or over 424.90 # child element, first child born before 6 April 2017 351.88 # child element, 15 more children, 15 x 303.94 4,559.10 # maximum amount 5,335.88, or 64,030.56 # a year # Child Benefit: (27.05 + 15 x 17.90) x 52 = 15,368.60 a year (Child Benefit -# (Rates) Regulations 2006 reg 2(1)). Her family's limit is 22,020 (reg -# 80A(2)(d)(ii)). +# (Rates) Regulations 2006 reg 2(1)). DWP applies the limit of 22,020 for a +# single claimant with a child (reg 80A(2)(d)(ii)). EDGE_CHILD_AGES = [*range(1, 16), 7] EDGE_ALLOWANCES = [6_000, 7_000] -def test_a_mother_of_16_keeps_more_once_the_cap_takes_universal_credit_to_nil(): +def test_a_mother_of_16_keeps_more_allowance_once_dwp_cuts_her_award_to_nil(): people, benunits, households = {}, {}, {} for i, amount in enumerate(EDGE_ALLOWANCES): mother = f"e{i}_mother" @@ -586,7 +592,8 @@ def test_a_mother_of_16_keeps_more_once_the_cap_takes_universal_credit_to_nil(): "uc_benefit_cap": [22_020, 22_020], # Reg 81: 79,399.16 - 22,020 - 0 childcare = 57,379.16 at both amounts. "uc_benefit_cap_reduction": [57_379.16, 57_379.16], - # At 7,000 the award before the cap, 57,030.56, is all DWP can take. + # At 7,000 DWP can take no more than the award before the cap, + # 57,030.56. "uc_benefit_cap_reduction_after_floor": [57_379.16, 57_030.56], # 58,030.56 - 57,379.16 = 651.40, and nil. "universal_credit": [651.40, 0], From 03ab8cfe70625f2c1057a581cd3c9d4f01f206a5 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 09:03:05 -0500 Subject: [PATCH 6/7] Give the cap tests' docstring its actors and the Secretary of State's power Co-Authored-By: Claude Opus 5.5 --- ...efit_cap_maternity_allowance_properties.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py index 392e117b06..fdce94589e 100644 --- a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -1,12 +1,12 @@ """DWP and councils count Maternity Allowance in the benefit cap. -Parliament lists maternity allowance among the welfare benefits regulations -may cap (Welfare Reform Act 2012 s.96(10)(i)), and the woman entitled to it -receives it (Social Security Contributions and Benefits Act 1992 s.35(1)). -Under UC Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A, DWP and -councils count the welfare benefits "to which the single person or couple is -entitled". Under regs 80(4) and 75C(4) they use the amount each scheme counts -as income. DWP counts all of a Maternity Allowance as unearned income (UC Regs +Parliament lists maternity allowance among the welfare benefits whose total +the Secretary of State may cap by regulations (Welfare Reform Act 2012 +s.96(1), (10)(i)), and the woman entitled to it receives it (Social Security +Contributions and Benefits Act 1992 s.35(1)). Under UC Regs 2013 regs 79(1) +and 80(1) and HB Regs 2006 reg 75A, DWP and councils count the welfare +benefits "to which the single person or couple is entitled". Under regs 80(4) +and 75C(4) they use the amount they count as income. DWP counts all of a Maternity Allowance as unearned income (UC Regs 2013 reg 66(1)(b)(viii)), and councils disregard none of it under HB Regs 2006 reg 40 and Schedule 5. @@ -35,13 +35,14 @@ raises the total by d for a claimant or partner, and leaves it unchanged for a non-dependent adult. The total therefore never falls as the allowance rises, and nor does either reduction. -3. Differential: the total equals a reference written from s.96(10) and +3. Differential: the total equals a reference that follows s.96(10) and those regulations: the listed benefits of the claimant and partner, plus the family's Child Benefit, Child Tax Credit, Income Support, and - Universal Credit and Housing Benefit before the cap. Each reduction is - the excess over the statutory limit (UC reg 80A(2); HB reg 75CA(2)), less - Housing Benefit for Universal Credit (reg 80(2A)), and for Housing Benefit - no more than leaves 50p a week (reg 75D(2)). + Universal Credit and Housing Benefit before the cap. DWP reduces Universal + Credit by the excess over the statutory limit (UC reg 80A(2)), counting + Housing Benefit as nil (reg 80(2A)). Councils reduce Housing Benefit by the + excess over theirs (HB reg 75CA(2)), leaving at least 50p a week (reg + 75D(2)). 4. Pound for pound, through the whole model: where the model works out Universal Credit and the award before the cap stays above nil, raising the mother's allowance by d lowers that award by d (reg 66(1)(b)(viii)), From 55e015e104f3ad0bc1c07b41e367ef78bb256511 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 1 Nov 2026 16:05:02 -0500 Subject: [PATCH 7/7] Qualify the cap tests' fourth invariant and name the actors in their notes The docstring now says Universal Credit plus the allowance holds still only while the award absorbs the whole excess, no protected floor limits the reduction and DWP deducts the same for debts, and that the tests' families carry no debt deductions. Comments give the Secretary of State and the Treasury their instruments, and DWP its exemptions. The changelog splits its first sentence. No code, input or expected value changes. Co-Authored-By: Claude Opus 5.5 --- changelog.d/2784.fixed.md | 2 +- .../benefit_cap/benefit_cap_capped_total.yaml | 15 +++-- ...efit_cap_maternity_allowance_properties.py | 57 ++++++++++--------- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/changelog.d/2784.fixed.md b/changelog.d/2784.fixed.md index f0771e044b..52bcbf7777 100644 --- a/changelog.d/2784.fixed.md +++ b/changelog.d/2784.fixed.md @@ -1 +1 @@ -PolicyEngine now includes the claimant's and partner's Maternity Allowance when it calculates the benefit cap on Universal Credit and Housing Benefit, and leaves a non-dependent adult's allowance out (#2784). Parliament lists the allowance among the welfare benefits whose total the Secretary of State may cap (Welfare Reform Act 2012 s.96(10)(i)). +PolicyEngine now includes the claimant's and partner's Maternity Allowance when it calculates the benefit cap on Universal Credit and Housing Benefit. It leaves a non-dependent adult's allowance out (#2784). Parliament lists the allowance among the welfare benefits whose total the Secretary of State may cap (Welfare Reform Act 2012 s.96(10)(i)). diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml index 2e168540f1..a6a430508f 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_capped_total.yaml @@ -334,7 +334,7 @@ # and councils count the allowance of a claimant or partner and leave out # that of a non-dependent adult in the household. Under UC Regs 2013 reg # 80(4) and HB Regs 2006 reg 75C(4) they use the amount they count as income. -# DWP counts all of it as unearned income (reg 66(1)(b)(viii)), and councils +# DWP counts it in full as unearned income (reg 66(1)(b)(viii)), and councils # disregard none of it under HB Regs 2006 reg 40 and Schedule 5. - name: DWP counts the claimant's own Maternity Allowance in the capped total @@ -481,7 +481,8 @@ # = 17,840.64 a year. # # Child Benefit: (27.05 + 2 x 17.90) x 52 = 3,268.20 a year (Child Benefit -# (Rates) Regulations 2006 reg 2(1), as SI 2026/232 art. 2 sets them). +# (Rates) Regulations 2006 reg 2(1), as the Treasury set the rates through SI +# 2026/232 art. 2). # DWP applies the family limit of 22,020 (reg 80A(2)(d)(ii)) and grants no # exception. @@ -611,10 +612,12 @@ # reg 79(4)(g) as made, and Parliament has listed it in WRA 2012 # s.96(10)(i) since 2016. benefit_cap_welfare_benefits: 18_000 - # SI 2023/335 reg 3(c) set the limit for a single claimant with no child - # outside London at 14,753 from 1 April 2023 (reg 80A(2)(c)). Under reg - # 81 DWP reduces her Universal Credit by max(15,000 + 3,000 - 14,753 - 0 - # childcare, 0) = 3,247 and pays 15,000 - 3,247 = 11,753. + # The Secretary of State set the limit for a single claimant with no + # child outside London at 14,753 from 1 April 2023 through SI 2023/335 + # reg 3(c), for assessment periods beginning on or after 10 April 2023 + # (reg 1(3); UC Regs 2013 reg 80A(2)(c)). Under reg 81 DWP reduces her + # Universal Credit by max(15,000 + 3,000 - 14,753 - 0 childcare, 0) = + # 3,247 and pays 15,000 - 3,247 = 11,753. uc_benefit_cap: 14_753 uc_benefit_cap_reduction: 3_247 universal_credit: 11_753 diff --git a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py index fdce94589e..d29f649833 100644 --- a/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py +++ b/policyengine_uk/tests/test_benefit_cap_maternity_allowance_properties.py @@ -6,9 +6,9 @@ Contributions and Benefits Act 1992 s.35(1)). Under UC Regs 2013 regs 79(1) and 80(1) and HB Regs 2006 reg 75A, DWP and councils count the welfare benefits "to which the single person or couple is entitled". Under regs 80(4) -and 75C(4) they use the amount they count as income. DWP counts all of a Maternity Allowance as unearned income (UC Regs -2013 reg 66(1)(b)(viii)), and councils disregard none of it under HB Regs 2006 -reg 40 and Schedule 5. +and 75C(4) they use the amount they count as income. DWP counts Maternity +Allowance in full as unearned income (UC Regs 2013 reg 66(1)(b)(viii)), and +councils disregard none of it under HB Regs 2006 reg 40 and Schedule 5. Invariants, for families on Universal Credit or on Housing Benefit alone, whether a single claimant, either member of a couple, or a non-dependent @@ -25,16 +25,17 @@ of the award (reg 80(1)). For Housing Benefit the tests draw contribution-based JSA or ESA, which councils count at the amount of the award (HB Regs 2006 reg 75C(1), (4)), or severe disablement allowance, - which no paragraph of Schedule 5 disregards and which bears no income tax - (ITEPA 2003 s.677(1)). Councils disregard £15 a week of widowed parent's - allowance (Sch 5 para 16(b)) and any tax paid on incapacity benefit (Sch 5 - para 1; ITEPA 2003 s.660(1)), so the tests give families on Housing - Benefit neither. -2. Coefficient one: with each award before the cap entered, so that - Universal Credit does not taper, raising the holder's allowance by d - raises the total by d for a claimant or partner, and leaves it unchanged - for a non-dependent adult. The total therefore never falls as the - allowance rises, and nor does either reduction. + which councils count in full in these cases, with no dependant's increase + (Sch 5 para 52), and on which recipients pay no income tax (ITEPA 2003 + s.677(1)). Councils disregard £15 a week of widowed parent's allowance + (Sch 5 para 16(b)) and any income tax a recipient pays on incapacity + benefit (Sch 5 para 1; ITEPA 2003 s.660(1)), so the tests give families + on Housing Benefit neither. +2. Coefficient one: the tests enter each award before the cap, so Universal + Credit does not taper. Raising the holder's allowance by d then raises + the total by d for a claimant or partner, and leaves it unchanged for a + non-dependent adult. The total therefore never falls as the allowance + rises, and nor does either reduction. 3. Differential: the total equals a reference that follows s.96(10) and those regulations: the listed benefits of the claimant and partner, plus the family's Child Benefit, Child Tax Credit, Income Support, and @@ -46,14 +47,17 @@ 4. Pound for pound, through the whole model: where the model works out Universal Credit and the award before the cap stays above nil, raising the mother's allowance by d lowers that award by d (reg 66(1)(b)(viii)), - so the total does not move. Where DWP reduces the award at both - amounts, and the award absorbs the whole reduction at each, Universal - Credit after the cap plus the allowance does not move either: DWP holds - the family's capped benefits at the limit whichever of them the allowance - replaces. That needs an award large enough to take the whole excess and no - protected floor that limits the reduction. Once the reduction takes the - award to nil, DWP has nothing left to reduce, and each further pound of - allowance adds a pound to what the family keeps. + so the total does not move. Where DWP reduces the award at both amounts, + Universal Credit after the cap plus the allowance holds still too, + provided that at each amount the award absorbs the whole excess, no + protected floor limits the reduction, and DWP deducts the same for + debts. DWP then holds the family's capped benefits at the limit whichever + of them the allowance replaces. The tests' families have no debt + deductions, because the model makes none in a household situation unless + a test enters them (uc_deduction_random_draw), so the test checks the + first two conditions. Once the reduction takes the award to nil, DWP has + nothing left to reduce, and each further pound of allowance adds a pound + to what the family keeps. test_a_mother_of_16_keeps_more_allowance_once_dwp_cuts_her_award_to_nil checks that edge. @@ -79,9 +83,9 @@ HOUSING_BENEFIT_MINIMUM = 0.50 * 52 # The holder's other welfare benefits that DWP and councils count in the cap -# as theirs (WRA 2012 s.96(10)(d), (f), (h), (j), (n)), each entered as an -# award. Each scheme's list holds those that DWP or the council counts at the -# amount of the award, as each counts Maternity Allowance (invariant 1). +# as theirs (WRA 2012 s.96(10)(d), (f), (h), (j), (n)), which the tests enter +# as awards. Each scheme's list holds those that DWP or the council counts at +# the amount of the award, as each counts Maternity Allowance (invariant 1). OTHER_BENEFITS = { "uc": [ "jsa_contrib", @@ -144,7 +148,7 @@ def entered_situation(): benunits[unit] = { "members": members, # The tests enter the LCWRA and carer elements as nil, so - # neither exempts the family (UC reg 83(1)(a), (j)). + # DWP grants neither exemption (UC reg 83(1)(a), (j)). "uc_LCWRA_element": {YEAR: 0}, "uc_carer_element": {YEAR: 0}, } @@ -517,7 +521,8 @@ def test_universal_credit_falls_by_the_allowance_inside_the_cap(modelled, drawn) applied = value["uc_benefit_cap_reduction_after_floor"] capped = reduction[lower] > 0 and reduction[higher] > 0 # The award takes the whole reduction at both amounts: it doesn't - # reach nil first, and no protected floor limits the reduction. + # reach nil first, and no protected floor limits the reduction. The + # families have no debt deductions to change with the award. absorbed = all( abs(applied[i] - reduction[i]) <= tolerance(reduction[i]) for i in (lower, higher)