@@ -15,6 +15,9 @@ def test_slc_targets_registered():
1515 assert "slc/plan_5_borrowers_above_threshold" in targets
1616 assert "slc/plan_2_borrowers_liable" in targets
1717 assert "slc/plan_5_borrowers_liable" in targets
18+ assert "slc/student_loan_repayment/england" in targets
19+ assert "slc/student_loan_repayment/scotland" in targets
20+ assert "slc/student_loan_repayment/england/plan_2" in targets
1821
1922
2023def test_slc_snapshot_values_match_higher_education_total_rows ():
@@ -46,6 +49,54 @@ def test_liable_targets_exceed_above_threshold_targets():
4649 assert targets ["slc/plan_5_borrowers_liable" ].values [year ] > count
4750
4851
52+ def test_slc_repayment_targets_match_official_2025_values ():
53+ """Repayment amount targets should match the official 2024-25 releases."""
54+ from policyengine_uk_data .targets .registry import get_all_targets
55+
56+ targets = {t .name : t for t in get_all_targets ()}
57+
58+ assert (
59+ targets ["slc/student_loan_repayment/england" ].values [2025 ] == 5_018_231_834.95
60+ )
61+ assert (
62+ targets ["slc/student_loan_repayment/england/plan_1" ].values [2025 ]
63+ == 1_852_699_178.55
64+ )
65+ assert (
66+ targets ["slc/student_loan_repayment/england/plan_2" ].values [2025 ]
67+ == 2_778_253_361.64
68+ )
69+ assert (
70+ targets ["slc/student_loan_repayment/england/postgraduate" ].values [2025 ]
71+ == 346_409_713.95
72+ )
73+ assert (
74+ targets ["slc/student_loan_repayment/england/plan_5" ].values [2025 ]
75+ == 40_869_580.81
76+ )
77+ assert targets ["slc/student_loan_repayment/scotland" ].values [2025 ] == 203_300_000
78+ assert targets ["slc/student_loan_repayment/wales" ].values [2025 ] == 229_100_000
79+ assert (
80+ targets ["slc/student_loan_repayment/northern_ireland" ].values [2025 ]
81+ == 181_700_000
82+ )
83+
84+
85+ def test_slc_england_plan_repayments_sum_to_england_total ():
86+ """England plan-level repayment targets should reconcile to the total."""
87+ from policyengine_uk_data .targets .registry import get_all_targets
88+
89+ targets = {t .name : t for t in get_all_targets ()}
90+ england_total = targets ["slc/student_loan_repayment/england" ].values [2025 ]
91+ england_plans = (
92+ targets ["slc/student_loan_repayment/england/plan_1" ].values [2025 ]
93+ + targets ["slc/student_loan_repayment/england/plan_2" ].values [2025 ]
94+ + targets ["slc/student_loan_repayment/england/postgraduate" ].values [2025 ]
95+ + targets ["slc/student_loan_repayment/england/plan_5" ].values [2025 ]
96+ )
97+ assert england_plans == england_total
98+
99+
49100def test_slc_testing_mode_uses_snapshot_without_network (monkeypatch ):
50101 """Dataset-build CI should not depend on a live SLC endpoint."""
51102 from policyengine_uk_data .targets .sources import slc
@@ -209,3 +260,59 @@ def household_from_person(values):
209260
210261 assert above_threshold .tolist () == [1.0 , 0.0 , 0.0 , 0.0 ]
211262 assert liable .tolist () == [1.0 , 1.0 , 0.0 , 0.0 ]
263+
264+
265+ def test_student_loan_repayment_target_compute_filters_country_and_plan ():
266+ """Repayment amount targets should filter on modeled plan and country."""
267+ from policyengine_uk_data .targets .compute .other import (
268+ compute_student_loan_repayment ,
269+ )
270+
271+ class DummyCtx :
272+ class sim :
273+ @staticmethod
274+ def calculate (variable , map_to = None ):
275+ if variable == "country" and map_to == "person" :
276+ return SimpleNamespace (
277+ values = np .array (
278+ [
279+ "ENGLAND" ,
280+ "ENGLAND" ,
281+ "SCOTLAND" ,
282+ "ENGLAND" ,
283+ "WALES" ,
284+ ]
285+ )
286+ )
287+ raise AssertionError (f"Unexpected calculate call: { variable } , { map_to } " )
288+
289+ @staticmethod
290+ def pe_person (variable ):
291+ values = {
292+ "student_loan_plan" : np .array (
293+ ["PLAN_1" , "PLAN_2" , "PLAN_4" , "POSTGRADUATE" , "PLAN_1" ]
294+ ),
295+ "student_loan_repayment" : np .array ([100.0 , 200.0 , 300.0 , 400.0 , 500.0 ]),
296+ }
297+ return values [variable ]
298+
299+ @staticmethod
300+ def household_from_person (values ):
301+ return values
302+
303+ england_total = compute_student_loan_repayment (
304+ SimpleNamespace (name = "slc/student_loan_repayment/england" ),
305+ DummyCtx (),
306+ )
307+ england_plan_2 = compute_student_loan_repayment (
308+ SimpleNamespace (name = "slc/student_loan_repayment/england/plan_2" ),
309+ DummyCtx (),
310+ )
311+ scotland_total = compute_student_loan_repayment (
312+ SimpleNamespace (name = "slc/student_loan_repayment/scotland" ),
313+ DummyCtx (),
314+ )
315+
316+ assert england_total .tolist () == [100.0 , 200.0 , 0.0 , 400.0 , 0.0 ]
317+ assert england_plan_2 .tolist () == [0.0 , 200.0 , 0.0 , 0.0 , 0.0 ]
318+ assert scotland_total .tolist () == [0.0 , 0.0 , 300.0 , 0.0 , 0.0 ]
0 commit comments