Skip to content

Commit 6b3d463

Browse files
vahid-ahmadiclaude
andauthored
fix: update SCP baby bonus reform to use Person-level variable (#1481)
The scottish_child_payment variable was refactored from BenUnit to Person entity, but the baby bonus reform was not updated to match. This caused a mismatch where applying the reform would try to replace a Person-level variable with a BenUnit-level variable. Changes: - Update reform to use Person entity instead of BenUnit - Use parameterized baby_bonus rates instead of hardcoded values - Leverage is_scp_eligible and would_claim_scp variables - Fix effective date to 2027-04-01 (fiscal year 2027-28) per Scottish Budget - Add unit tests for the reform Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 00ec6b1 commit 6b3d463

5 files changed

Lines changed: 168 additions & 114 deletions

File tree

changelog_entry.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- bump: patch
2+
changes:
3+
fixed:
4+
- Fixed Scottish Child Payment baby bonus reform to use Person-level variable structure, matching the refactored base variable. The reform now correctly uses parameterized baby bonus rates instead of hardcoded values.
5+
- Fixed SCP baby bonus effective date to 2027-04-01 (fiscal year 2027-28) per Scottish Budget 2026-27.

policyengine_uk/parameters/gov/contrib/scotland/scottish_child_payment/baby_bonus.yaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
description: Additional weekly amount for Scottish Child Payment based on child age.
1+
description: Additional weekly amount for Scottish Child Payment based on child age. Effective from 2027-28 fiscal year.
22
brackets:
33
- threshold:
44
values:
55
0001-01-01: 0
66
amount:
77
values:
8-
0001-01-01: 12.85
8+
0001-01-01: 0
9+
2027-04-01: 12.85
910
- threshold:
1011
values:
1112
0001-01-01: 1
@@ -19,5 +20,5 @@ metadata:
1920
period: week
2021
label: Scottish Child Payment baby bonus by age
2122
reference:
22-
- title: Scottish Government - Scottish Child Payment
23-
href: https://www.gov.scot/policies/social-security/scottish-child-payment/
23+
- title: Scottish Budget 2026 to 2027
24+
href: https://www.gov.scot/publications/scottish-budget-2026-2027/pages/6/
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
description: Whether the Scottish Child Payment baby bonus reform is in effect.
22
values:
33
0001-01-01: false
4+
2027-04-01: true
45
metadata:
56
unit: bool
67
period: year
78
label: Scottish Child Payment baby bonus reform in effect
9+
reference:
10+
- title: Scottish Budget 2026 to 2027
11+
href: https://www.gov.scot/publications/scottish-budget-2026-2027/pages/6/

policyengine_uk/reforms/scotland/scottish_child_payment_reform.py

Lines changed: 24 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@
44

55
def create_scottish_child_payment_baby_bonus_reform() -> Reform:
66
"""
7-
Reform that implements SCP Premium for under-ones.
7+
Reform that implements SCP baby bonus for children under 1.
88
9-
Policy: Children under 1 receive a FIXED £40/week total payment.
10-
Children 1+ receive the standard SCP rate (inflates with inflation).
11-
12-
This is NOT a fixed bonus added to the base - it's a fixed total amount.
13-
As the base SCP rate inflates, the "bonus" for under-1s effectively
14-
decreases to maintain the £40 total.
9+
Policy: Children under 1 receive an additional weekly bonus on top of
10+
the standard SCP rate. The bonus amount is parameterized at
11+
gov.contrib.scotland.scottish_child_payment.baby_bonus.
1512
1613
Source: Scottish Budget 2026-27
1714
https://www.gov.scot/publications/scottish-budget-2026-2027-finance-secretarys-statement-13-january-2026-2/
@@ -20,125 +17,42 @@ def create_scottish_child_payment_baby_bonus_reform() -> Reform:
2017
class scottish_child_payment(Variable):
2118
label = "Scottish Child Payment"
2219
documentation = (
23-
"Scottish Child Payment provides financial support to low-income "
24-
"families in Scotland. It is paid per eligible child to families "
25-
"receiving qualifying benefits such as Universal Credit."
20+
"Scottish Child Payment amount for this child. "
21+
"Paid to eligible children in families receiving qualifying benefits. "
22+
"When baby bonus reform is active, children under 1 receive additional payment."
2623
)
27-
entity = BenUnit
24+
entity = Person
2825
definition_period = YEAR
2926
value_type = float
3027
unit = GBP
28+
defined_for = "is_scp_eligible"
3129
reference = [
30+
"https://www.legislation.gov.uk/ssi/2020/351/contents",
3231
"https://www.gov.scot/policies/social-security/scottish-child-payment/",
33-
"https://www.socialsecurity.gov.scot/",
3432
]
3533

36-
def formula(benunit, period, parameters):
37-
# Check if household is in Scotland
38-
in_scotland = (
39-
benunit.household("country", period).decode_to_str()
40-
== "SCOTLAND"
41-
)
42-
34+
def formula(person, period, parameters):
4335
# Get SCP parameters
4436
p = parameters(
4537
period
4638
).gov.social_security_scotland.scottish_child_payment
4739
weekly_amount = p.amount
4840

49-
# SCP only available when amount > 0 (i.e., after Feb 2021)
50-
scp_available = weekly_amount > 0
51-
52-
# Count eligible children in the benefit unit
53-
is_eligible_child = benunit.members(
54-
"is_scp_eligible_child", period
55-
)
56-
eligible_children = benunit.sum(is_eligible_child)
57-
58-
# Get ages for baby bonus calculation
59-
age = benunit.members("age", period)
60-
61-
# Count children under 6 and 6+ for takeup rate calculation
62-
is_child = benunit.members("is_child", period)
63-
children_6_and_over = benunit.sum(
64-
is_child & (age >= 6) & (age < 16)
65-
)
66-
67-
# Check if receiving a qualifying benefit
68-
qb = p.qualifying_benefits
69-
70-
receives_uc = (
71-
benunit("universal_credit", period) > 0
72-
) & qb.universal_credit
73-
receives_ctc = (
74-
benunit("child_tax_credit", period) > 0
75-
) & qb.child_tax_credit
76-
receives_wtc = (
77-
benunit("working_tax_credit", period) > 0
78-
) & qb.working_tax_credit
79-
receives_income_support = (
80-
benunit("income_support", period) > 0
81-
) & qb.income_support
82-
receives_jsa_income = (
83-
benunit("jsa_income", period) > 0
84-
) & qb.jsa_income
85-
receives_esa_income = (
86-
benunit("esa_income", period) > 0
87-
) & qb.esa_income
88-
receives_pension_credit = (
89-
benunit("pension_credit", period) > 0
90-
) & qb.pension_credit
91-
92-
receives_qualifying_benefit = (
93-
receives_uc
94-
| receives_ctc
95-
| receives_wtc
96-
| receives_income_support
97-
| receives_jsa_income
98-
| receives_esa_income
99-
| receives_pension_credit
100-
)
101-
102-
# SCP Premium for under-ones: Fixed £40/week total (not base + bonus)
103-
# Policy: Children under 1 get £40/week, children 1+ get standard rate
104-
PREMIUM_RATE_UNDER_ONE = 40.0 # £40/week fixed total
105-
106-
# Calculate per-child weekly amount based on age
107-
per_child_weekly = where(
108-
age < 1,
109-
PREMIUM_RATE_UNDER_ONE, # £40/week for under-1s (TOTAL, not bonus)
110-
weekly_amount, # Standard SCP rate for 1+ (inflates with inflation)
111-
)
112-
113-
# Calculate total weekly payment for all eligible children
114-
total_weekly = benunit.sum(per_child_weekly * is_eligible_child)
41+
# Get baby bonus parameter (age-bracketed)
42+
baby_bonus_params = parameters(
43+
period
44+
).gov.contrib.scotland.scottish_child_payment.baby_bonus
45+
age = person("age", period)
46+
baby_bonus = baby_bonus_params.calc(age)
47+
48+
# Total weekly amount = base + baby bonus
49+
total_weekly = weekly_amount + baby_bonus
50+
51+
# Child-level take-up (generated stochastically in dataset)
52+
would_claim = person("would_claim_scp", period)
11553

11654
# Convert to annual amount
117-
annual_amount = total_weekly * WEEKS_IN_YEAR
118-
119-
# Apply age-specific take-up rates in microsimulation
120-
takeup_under_6 = p.takeup_rate.under_6
121-
takeup_6_and_over = p.takeup_rate.age_6_and_over
122-
123-
has_children_6_and_over = children_6_and_over > 0
124-
takeup_rate = where(
125-
has_children_6_and_over, takeup_6_and_over, takeup_under_6
126-
)
127-
128-
takes_up = random(benunit) < takeup_rate
129-
is_in_microsimulation = benunit.simulation.dataset is not None
130-
if is_in_microsimulation:
131-
receives_payment = takes_up
132-
else:
133-
receives_payment = True
134-
135-
return (
136-
in_scotland
137-
* scp_available
138-
* receives_qualifying_benefit
139-
* receives_payment
140-
* annual_amount
141-
)
55+
return total_weekly * WEEKS_IN_YEAR * would_claim
14256

14357
class reform(Reform):
14458
def apply(self):
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Scottish Child Payment Baby Bonus Reform tests
2+
# Tests that the SCP baby bonus reform correctly applies additional
3+
# payment for children under 1 year old.
4+
# Policy effective from 2027-28 fiscal year (April 2027).
5+
# Reform adds £12.85/week bonus for under-1s on top of standard rate.
6+
7+
- name: SCP baby bonus for child under 1 (2028)
8+
period: 2028
9+
absolute_error_margin: 10
10+
reforms:
11+
- policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform
12+
input:
13+
people:
14+
parent:
15+
age: 30
16+
baby:
17+
age: 0
18+
benunits:
19+
benunit:
20+
members: [parent, baby]
21+
universal_credit: 5000
22+
households:
23+
household:
24+
members: [parent, baby]
25+
region: SCOTLAND
26+
output:
27+
# Base: £27.15/week + Bonus: £12.85/week = £40/week total
28+
# £40/week * 52 weeks = £2,080 per year
29+
# [parent, baby]
30+
scottish_child_payment: [0, 2080]
31+
32+
- name: SCP baby bonus - child over 1 gets standard rate (2028)
33+
period: 2028
34+
absolute_error_margin: 10
35+
reforms:
36+
- policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform
37+
input:
38+
people:
39+
parent:
40+
age: 30
41+
toddler:
42+
age: 2
43+
benunits:
44+
benunit:
45+
members: [parent, toddler]
46+
universal_credit: 5000
47+
households:
48+
household:
49+
members: [parent, toddler]
50+
region: SCOTLAND
51+
output:
52+
# Standard rate only: £27.15/week * 52 = £1,411.80
53+
# [parent, toddler]
54+
scottish_child_payment: [0, 1412]
55+
56+
- name: SCP baby bonus - mixed ages (2028)
57+
period: 2028
58+
absolute_error_margin: 10
59+
reforms:
60+
- policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform
61+
input:
62+
people:
63+
parent:
64+
age: 30
65+
baby:
66+
age: 0
67+
older_child:
68+
age: 5
69+
benunits:
70+
benunit:
71+
members: [parent, baby, older_child]
72+
universal_credit: 5000
73+
households:
74+
household:
75+
members: [parent, baby, older_child]
76+
region: SCOTLAND
77+
output:
78+
# Baby (age 0): £40/week * 52 = £2,080
79+
# Older child (age 5): £27.15/week * 52 = £1,411.80
80+
# [parent, baby, older_child]
81+
scottish_child_payment: [0, 2080, 1412]
82+
83+
- name: SCP baby bonus - not in Scotland (2028)
84+
period: 2028
85+
absolute_error_margin: 1
86+
reforms:
87+
- policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform
88+
input:
89+
people:
90+
parent:
91+
age: 30
92+
baby:
93+
age: 0
94+
benunits:
95+
benunit:
96+
members: [parent, baby]
97+
universal_credit: 5000
98+
households:
99+
household:
100+
members: [parent, baby]
101+
region: NORTH_EAST
102+
output:
103+
# Not in Scotland - no SCP
104+
# [parent, baby]
105+
scottish_child_payment: [0, 0]
106+
107+
- name: SCP baby bonus - before effective date (2025)
108+
period: 2025
109+
absolute_error_margin: 10
110+
reforms:
111+
- policyengine_uk.reforms.scotland.scottish_child_payment_reform.scottish_child_payment_reform
112+
input:
113+
people:
114+
parent:
115+
age: 30
116+
baby:
117+
age: 0
118+
benunits:
119+
benunit:
120+
members: [parent, baby]
121+
universal_credit: 5000
122+
households:
123+
household:
124+
members: [parent, baby]
125+
region: SCOTLAND
126+
output:
127+
# Before 2027-04-01 - baby bonus is £0, so standard rate only
128+
# £27.15/week * 52 = £1,411.80
129+
# [parent, baby]
130+
scottish_child_payment: [0, 1412]

0 commit comments

Comments
 (0)