From f0ad89a6820373238d645ad8a4983d7e669a9602 Mon Sep 17 00:00:00 2001 From: Param Harrison Date: Tue, 13 Oct 2026 16:27:34 +0300 Subject: [PATCH 1/3] factory: claim #186 by runner-59290-1791898054497 From 75fe03c6b8e9635e8412193f63358404521f3ae5 Mon Sep 17 00:00:00 2001 From: Param Harrison Date: Tue, 13 Oct 2026 16:32:06 +0300 Subject: [PATCH 2/3] factory: build #186 --- src/csv.ts | 14 ++++------- tests/csv.test.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 tests/csv.test.ts diff --git a/src/csv.ts b/src/csv.ts index bbb9f3a..2f4361c 100644 --- a/src/csv.ts +++ b/src/csv.ts @@ -1,4 +1,5 @@ import type { Database } from "bun:sqlite"; +import { formatCents } from "./money/index.ts"; interface ExpenseRow { createdAt: string; @@ -25,20 +26,13 @@ function fetchExpenseRows(db: Database, groupId: string): ExpenseRow[] { .all(groupId) as ExpenseRow[]; } -/** - * Build the CSV export for a group's expenses. - * - * SEEDED DEFECT (issue #3): the amount column prints the raw integer cents - * (e.g. "1000") instead of a formatted amount ("10.00"). Baseline tests - * only check the header row and the row count, not the amount column's - * formatting, so this ships undetected. The fix should reuse - * `formatCents` from src/money (see .claude/skills/handling-money). - */ +/** Build the CSV export for a group's expenses; amounts are formatted as decimals ("10.00"). */ export function exportCsv(db: Database, groupId: string): string { const rows = fetchExpenseRows(db, groupId); const header = "date,payer,description,amount\n"; const lines = rows.map( - (r) => `${r.createdAt},${csvEscape(r.payerName)},${csvEscape(r.description)},${r.amountCents}`, + (r) => + `${r.createdAt},${csvEscape(r.payerName)},${csvEscape(r.description)},${formatCents(r.amountCents)}`, ); return header + lines.join("\n") + (lines.length > 0 ? "\n" : ""); } diff --git a/tests/csv.test.ts b/tests/csv.test.ts new file mode 100644 index 0000000..3661741 --- /dev/null +++ b/tests/csv.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, test } from "bun:test"; +import { Database } from "bun:sqlite"; +import { initSchema } from "../src/db.ts"; +import { seedDemoData } from "../src/seed.ts"; +import { createExpense } from "../src/expenses.ts"; +import { exportCsv } from "../src/csv.ts"; + +function setupDb() { + const db = new Database(":memory:"); + initSchema(db); + seedDemoData(db); + return db; +} + +function dataRows(csv: string): string[][] { + return csv + .trim() + .split("\n") + .slice(1) + .map((line) => line.split(",")); +} + +describe("exportCsv", () => { + test("exportCsv formats the amount column as a decimal", () => { + const rows = dataRows(exportCsv(setupDb(), "flat-4b")); + expect(rows.map((r) => r[3])).toEqual(["45.00", "12.00", "30.00"]); + }); + + test("exportCsv keeps two decimal places", () => { + const db = setupDb(); + const flatIds = ["flat-priya-id", "flat-imran-id", "flat-sara-id"]; + createExpense(db, { + groupId: "flat-4b", + payerId: "flat-priya-id", + amountCents: 1005, + description: "Milk", + splitAmong: flatIds, + createdAt: "2026-09-10T09:00:00.000Z", + }); + createExpense(db, { + groupId: "flat-4b", + payerId: "flat-imran-id", + amountCents: 1050, + description: "Bread", + splitAmong: flatIds, + createdAt: "2026-09-11T09:00:00.000Z", + }); + const rows = dataRows(exportCsv(db, "flat-4b")); + expect(rows.slice(-2).map((r) => r[3])).toEqual(["10.05", "10.50"]); + }); + + test("exportCsv keeps header and row count", () => { + const csv = exportCsv(setupDb(), "flat-4b"); + const lines = csv.trim().split("\n"); + expect(lines[0]).toBe("date,payer,description,amount"); + expect(lines).toHaveLength(4); + expect(lines[1]).toBe("2026-09-01T09:00:00.000Z,Priya,Electricity bill,45.00"); + }); +}); From 51c6f65b71c783494987d9cad92a400d3d4f4731 Mon Sep 17 00:00:00 2001 From: Param Harrison Date: Tue, 13 Oct 2026 16:48:42 +0300 Subject: [PATCH 3/3] factory: build #186 --- tests/csv.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/csv.test.ts b/tests/csv.test.ts index 3661741..a8be1ee 100644 --- a/tests/csv.test.ts +++ b/tests/csv.test.ts @@ -49,6 +49,20 @@ describe("exportCsv", () => { expect(rows.slice(-2).map((r) => r[3])).toEqual(["10.05", "10.50"]); }); + test("exportCsv formats an amount under one dollar with a leading zero", () => { + const db = setupDb(); + createExpense(db, { + groupId: "flat-4b", + payerId: "flat-priya-id", + amountCents: 5, + description: "Sticker", + splitAmong: ["flat-priya-id"], + createdAt: "2026-09-12T09:00:00.000Z", + }); + const rows = dataRows(exportCsv(db, "flat-4b")); + expect(rows.at(-1)?.[3]).toBe("0.05"); + }); + test("exportCsv keeps header and row count", () => { const csv = exportCsv(setupDb(), "flat-4b"); const lines = csv.trim().split("\n");