|
| 1 | +from policyengine_uk.model_api import * |
| 2 | +from policyengine_core.periods import period as period_ |
| 3 | + |
| 4 | + |
| 5 | +def create_scottish_child_payment_baby_bonus_reform() -> Reform: |
| 6 | + """ |
| 7 | + Reform that implements SCP Premium for under-ones. |
| 8 | +
|
| 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. |
| 15 | +
|
| 16 | + Source: Scottish Budget 2026-27 |
| 17 | + https://www.gov.scot/publications/scottish-budget-2026-2027-finance-secretarys-statement-13-january-2026-2/ |
| 18 | + """ |
| 19 | + |
| 20 | + class scottish_child_payment(Variable): |
| 21 | + label = "Scottish Child Payment" |
| 22 | + 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." |
| 26 | + ) |
| 27 | + entity = BenUnit |
| 28 | + definition_period = YEAR |
| 29 | + value_type = float |
| 30 | + unit = GBP |
| 31 | + reference = [ |
| 32 | + "https://www.gov.scot/policies/social-security/scottish-child-payment/", |
| 33 | + "https://www.socialsecurity.gov.scot/", |
| 34 | + ] |
| 35 | + |
| 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 | + |
| 43 | + # Get SCP parameters |
| 44 | + p = parameters( |
| 45 | + period |
| 46 | + ).gov.social_security_scotland.scottish_child_payment |
| 47 | + weekly_amount = p.amount |
| 48 | + |
| 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) |
| 115 | + |
| 116 | + # 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 | + ) |
| 142 | + |
| 143 | + class reform(Reform): |
| 144 | + def apply(self): |
| 145 | + self.update_variable(scottish_child_payment) |
| 146 | + |
| 147 | + return reform |
| 148 | + |
| 149 | + |
| 150 | +def create_scottish_child_payment_reform( |
| 151 | + parameters, period, bypass: bool = False |
| 152 | +): |
| 153 | + if bypass: |
| 154 | + return create_scottish_child_payment_baby_bonus_reform() |
| 155 | + |
| 156 | + p = parameters.gov.contrib.scotland.scottish_child_payment |
| 157 | + |
| 158 | + # Check if reform is active in current period or next 5 years |
| 159 | + reform_active = False |
| 160 | + current_period = period_(period) |
| 161 | + |
| 162 | + for i in range(5): |
| 163 | + if p(current_period).in_effect: |
| 164 | + reform_active = True |
| 165 | + break |
| 166 | + current_period = current_period.offset(1, "year") |
| 167 | + |
| 168 | + if reform_active: |
| 169 | + return create_scottish_child_payment_baby_bonus_reform() |
| 170 | + else: |
| 171 | + return None |
| 172 | + |
| 173 | + |
| 174 | +scottish_child_payment_reform = ( |
| 175 | + create_scottish_child_payment_baby_bonus_reform() |
| 176 | +) |
0 commit comments