From 59e8f4549df2ec07475f2701b7cbb6f23087e7fd Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Tue, 1 Sep 2026 21:01:53 +0200 Subject: [PATCH] fix(ui): stop showing cancelled finance-plan slices as committed PostMonthRoute's "Already committed" list filtered future schedule slices only by month, never consulting cancelledFromMonth, so a cancelled plan's remaining slices kept appearing as future obligations the fold would never actually charge. Reuse sliceAmountForMonth's existing cancellation rule instead of re-deriving it inline, to avoid a second copy of the >= boundary drifting from the domain's. Co-Authored-By: Claude Opus 5 (1M context) --- src/ui/routes/PostMonthRoute.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ui/routes/PostMonthRoute.tsx b/src/ui/routes/PostMonthRoute.tsx index c6c1ca9..115afa8 100644 --- a/src/ui/routes/PostMonthRoute.tsx +++ b/src/ui/routes/PostMonthRoute.tsx @@ -23,12 +23,17 @@ export function PostMonthRoute() { // Future finance-plan slices, for purchases split with this post, that have // not yet arrived at `monthId`. This is what surfaces a committed plan // before it lands. Strictly-after so the current month's slice stays in - // "This month" rather than also appearing here. + // "This month" rather than also appearing here. Also filtered through + // sliceAmountForMonth so a cancelled plan's remaining slices (which the + // fold will never actually charge) do not appear as future obligations — + // reusing the domain's own cancelledFromMonth rule rather than + // re-deriving it here. const committed = dataset.purchases.flatMap((purchase) => { if (!purchase.schedule) return []; if (!purchase.splits.some((s) => s.postId === postId)) return []; return purchase.schedule.slices .filter((slice) => compareMonths(slice.month, monthId) > 0) + .filter((slice) => sliceAmountForMonth(purchase, slice.month) !== null) .map((slice) => ({ purchase, slice })); });