Skip to content

Commit 732fa08

Browse files
vahid-ahmadiclaude
andauthored
Prevent children from receiving negative Marriage Allowance (#1666) (#1667)
Children in a married benefit unit are assigned MaritalStatus.MARRIED and have tax_band == NONE, so they passed the Marriage Allowance eligibility checks. The transferable amount calculation then produced a negative value (their full PA minus zero adult-summed unused PA), which flowed into earned_taxable_income and generated phantom basic-rate income tax of 20% × £12,570 per child. Guard marriage_allowance with is_adult, clamp the eligible amount at zero, and fix partners_unused_personal_allowance to subtract the person's own unused PA only when they are an adult (mirrors the inclusion in the benunit sum). Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent be8ca93 commit 732fa08

4 files changed

Lines changed: 34 additions & 4 deletions

File tree

changelog.d/1666.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Prevent children in a married benefit unit from being assigned (negative) Marriage Allowance and being taxed on phantom income.

policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/allowances/marriage_allowance.yaml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,26 @@
3939
is_married: true
4040
output:
4141
marriage_allowance: [0, 0]
42+
43+
# Regression test for issue #1666: children in a married benefit unit must not
44+
# receive (negative) Marriage Allowance and must not be taxed on phantom income.
45+
- name: Children in married benunit do not transfer Marriage Allowance
46+
period: 2026
47+
input:
48+
people:
49+
adult1:
50+
age: 42
51+
employment_income: 55_000
52+
adult2:
53+
age: 40
54+
employment_income: 35_000
55+
child1:
56+
age: 8
57+
child2:
58+
age: 3
59+
benunit:
60+
members: [adult1, adult2, child1, child2]
61+
is_married: true
62+
output:
63+
marriage_allowance: [0, 0, 0, 0]
64+
income_tax: [9_432, 4_486, 0, 0]

policyengine_uk/variables/gov/hmrc/income_tax/allowances/marriage_allowance.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,17 @@ class marriage_allowance(Variable):
2727
def formula(person, period, parameters):
2828
marital = person("marital_status", period)
2929
married = marital == marital.possible_values.MARRIED
30-
eligible = married & person(
31-
"meets_marriage_allowance_income_conditions", period
30+
is_adult = person("is_adult", period)
31+
eligible = (
32+
married
33+
& is_adult
34+
& person("meets_marriage_allowance_income_conditions", period)
3235
)
3336
transferable_amount = person("partners_unused_personal_allowance", period)
3437
allowances = parameters(period).gov.hmrc.income_tax.allowances
3538
capped_percentage = allowances.marriage_allowance.max
3639
max_amount = allowances.personal_allowance.amount * capped_percentage
37-
amount_if_eligible_pre_rounding = min_(transferable_amount, max_amount)
40+
amount_if_eligible_pre_rounding = max_(min_(transferable_amount, max_amount), 0)
3841
# Round up.
3942
rounding_increment = allowances.marriage_allowance.rounding_increment
4043
amount_if_eligible = (

policyengine_uk/variables/gov/hmrc/income_tax/allowances/partners_unused_personal_allowance.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@ class partners_unused_personal_allowance(Variable):
1515
def formula(person, period, parameters):
1616
is_adult = person("is_adult", period)
1717
pa = person("unused_personal_allowance", period)
18-
return person.benunit.sum(is_adult * pa) - pa
18+
# Subtract this person's own unused PA only if they are an adult, so
19+
# non-adults (whose PA isn't part of the adult-summed pool) cannot
20+
# produce a negative transferable amount.
21+
return person.benunit.sum(is_adult * pa) - is_adult * pa

0 commit comments

Comments
 (0)