- The four plan-lifecycle routes (pause/resume/complete/abandon) were near
-duplicate copies returning a plain {error} shape; folded into one
transitionPlan(req,res,{allowedFrom,setSql,action,past}) helper that returns
standardizeError {message, code}, keeps the state guards and ownership scoping.
- Standardized the remaining plan endpoints' error responses (start/list/active/
patch) to standardizeError too.
- enrichPlanWithProgress fetched each snapshot bill one-by-one and wasn't user
-scoped; now a single WHERE id IN (…) AND user_id = ? batch.
Test: tests/snowballPlanRoute.test.js (transitions, INVALID_PLAN_STATE guard,
ownership 404, dollar-denominated current_debts). Server 154 pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PATCH /api/snowball/order silently skipped rows with bad ids or invalid
snowball_order values via bare 'continue' — no feedback, partial updates.
Now validates every item before touching the DB, returning 400 on the first
bad entry. Also adds deleted_at IS NULL filter so soft-deleted bills are
skipped instead of updated silently.