Recursion is very likely not the most efficient way to do this, but it's (relatively) easy to code up. I adjusted the data so that a positive "shortage" would occur two weeks in a row to make sure the code would keep the running total and apply it correctly. The actual code first (comment out the "overage" column when you're done with your testing), then the adjusted/enhanced data:
;WITH cte_child_shortage AS (
SELECT child_1, week, pencil_in_hand, breaks,
CASE WHEN pencil_in_hand - breaks > 0 THEN 0 ELSE pencil_in_hand - breaks END AS shortage,
CASE WHEN pencil_in_hand - breaks > 0 THEN pencil_in_hand - breaks ELSE 0 END AS overage
FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY child_1 ORDER BY week) AS row_num
FROM dbo.test1
) AS derived
WHERE row_num = 1
UNION ALL
SELECT t1.child_1, t1.week, t1.pencil_in_hand, t1.breaks,
calc1.shortage,
calc1.overage
FROM cte_child_shortage ccs
INNER JOIN dbo.test1 t1 ON t1.child_1 = ccs.child_1 AND t1.week = ccs.week + 1
CROSS APPLY (
SELECT CASE WHEN t1.pencil_in_hand - t1.breaks + ccs.overage > 0 THEN 0
ELSE t1.pencil_in_hand - t1.breaks + ccs.overage END AS shortage,
CASE WHEN t1.pencil_in_hand - t1.breaks + ccs.overage > 0
THEN t1.pencil_in_hand - t1.breaks + ccs.overage ELSE 0 END AS overage
) AS calc1
)
SELECT ccs.child_1, ccs.week, ccs.pencil_in_hand, ccs.breaks, ccs.shortage
, ccs.overage
FROM cte_child_shortage ccs
ORDER BY child_1, week
truncate table test1;
insert into test1
values
(1,'ABC' , 12,10 ),
(2,'ABC' , 3,10 ),
(3,'ABC' , 7,10 ),
(4,'ABC' , 16,10 ),
(0,'DEF' , 12,10 ), /* 2 left over from this week */
(1,'DEF' , 11,10 ), /* and 1 more left over from this week */
(2,'DEF' , 3,10 ), /* this week is only 4 short now, because 2 + 1 were left over */
(3,'DEF' , 7,10 ),
(4,'DEF' , 16,10 )