From 390abf2be40569298c4e1bc4a12b343ce3cd5ebc Mon Sep 17 00:00:00 2001 From: Lucas Winther Date: Tue, 29 Sep 2026 20:36:33 +0200 Subject: [PATCH] fix: keep budget sibling order distinct at numeric limit --- src/store/actions.test.ts | 15 +++++++++++++++ src/store/actions.ts | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/store/actions.test.ts b/src/store/actions.test.ts index 6f16896..e9ac285 100644 --- a/src/store/actions.test.ts +++ b/src/store/actions.test.ts @@ -2,6 +2,7 @@ import { test, expect, describe } from "bun:test"; import * as actions from "./actions.ts"; import { createSeedDataset } from "../domain/seed.ts"; import { occurrencesByMonth } from "../domain/occurrences.ts"; +import { exportDatasetJson, parseDatasetJson } from "../export/json.ts"; import type { Dataset } from "../domain/types.ts"; const billInput = (postId: string, folderId: string | null = null) => ({ @@ -83,6 +84,20 @@ describe("budget folder placement", () => { const bill = actions.addRecurringCost(data, billInput(post.id)); expect([folder.order, post.order, bill.order]).toEqual([4, 5, 6]); }); + + test("adding after the largest finite sibling order stays importable", () => { + for (const add of [ + (data: Dataset) => actions.addBudgetFolder(data, "Utilities", null), + (data: Dataset) => actions.addPost(data, "Bills", "DKK"), + (data: Dataset) => actions.addRecurringCost(data, billInput(data.posts[0]!.id)), + ]) { + const data = createSeedDataset("2026-09"); + data.posts[2]!.order = Number.MAX_VALUE; + const added = add(data); + expect(added.order).not.toBe(Number.MAX_VALUE); + expect(() => parseDatasetJson(exportDatasetJson(data))).not.toThrow(); + } + }); }); /** diff --git a/src/store/actions.ts b/src/store/actions.ts index 697b118..68a23fe 100755 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -64,7 +64,12 @@ export function budgetSiblings(draft: Dataset, parentId: FolderId | null): Budge function nextSiblingOrder(draft: Dataset, parentId: FolderId | null): number { const siblings = siblingRefs(draft, parentId); - return siblings.length ? siblings[siblings.length - 1]!.item.order + 1 : 0; + if (!siblings.length) return 0; + const highest = siblings[siblings.length - 1]!.item.order; + const next = highest + 1; + if (Number.isFinite(next) && next > highest) return next; + siblings.forEach(({ item }, order) => { item.order = order; }); + return siblings.length; } function requireFolder(draft: Dataset, id: FolderId): BudgetFolder {