Commit Graph
5 Commits
Author SHA1 Message Date
siddharthd db5c9a02a7 intake: POST /api/intake router + PUT /api/transactions/[id]/line-items (plan §11 C1, C2)
One upload point, every applicable step. Persist the batch, classify each
file, ONE LiteLLM call (cloud-budget, temperature 0, strict json_schema; PDFs
as unpdf text, never pixels) with an order-item prompt that keeps names
verbatim, header (merchant, date, total), merchant pattern
(coles|woolworths|woolies|aldi|iga|foodworks|costco) -> grocery | food | ask,
exact (platform, merchant, date, total) match against transactions +
expense_metadata, then act:

- food + unique match  -> replace line_items via the C2 path, 'enriched'
- food + miss/ambiguity -> 'candidates' (same merchant ±3d) with
  intake_use_candidate / intake_create buttons; never auto-creates
- grocery              -> original files to pantry POST /api/capture with
  finance_target_transaction_id + finance_action enrich|create (C3);
  409 -> 'duplicate'
- ask / needs_header / held / duplicate / unsupported as replies, not writes

Reconciliation is against the printed item subtotal (a delivery total is
items + fees - promotions: 18.94 of Coles lines settled at 5.74),  or
2%, else 'held'. Originals are kept under INTAKE_FILE_DIR by sha256 so a later
'Groceries' tap can still forward them.

C2 is an idempotent replace on transaction_id = :id OR
matched_transaction_id = :id, accepts INTAKE_TOKEN or RECEIPT_INGEST_TOKEN,
creates the expense_metadata row when absent, 404 when the transaction does
not exist, returns {previous_line_items, line_items} so pantry's undo is the
same call with the previous list.
2026-08-21 12:10:05 +10:00
siddharthd 1296555f17 test: add unit and integration test suites
- Extract evaluateCondition + rule types into src/lib/rules.ts for testability
- 48 unit tests for evaluateCondition (all fields/operators) and formatCategory
- 21 integration tests for getTransactions filters and getParticipantBalances
- Vitest configs for unit (vitest.config.ts) and integration (vitest.integration.config.ts)
- setup-test-db.sh creates personal_test DB from production schema via pg_dump
- Use vi.doMock + dynamic import pattern to isolate test DB from Prisma singleton
2026-04-01 19:59:29 +11:00
siddharthd 30a7857d13 feat(analytics): replace budget page with spending analytics + split-adjusted amounts
- Rename 'Budget' → 'Analytics' in sidebar
- Rewrite /budget page: summary cards, recharts bar charts (monthly trend + category breakdown), 6-month trend table
- Fix analytics API to count only user's share for split transactions (CASE WHEN ts.share_percent IS NOT NULL THEN amount * share_percent / 100 ELSE amount END)
- Install recharts
2026-03-08 17:58:33 +11:00
siddharthd 35a5be97b0 feat: initial finance SPA — phases 1 & 2
Next.js 16 personal finance dashboard connected to postgres-personal.

Phase 1 (Foundation):
- API routes: GET /api/transactions (paginated, filterable, sortable),
  GET /api/statements, GET /api/merchants
- Transactions data table with date/category/bank/search filters, pagination, sort
- Statements card grid with period, due date, amount, transaction count
- Sidebar layout with nav for all planned sections

Phase 2 (Normalisation):
- PATCH /api/transactions/[id] — upsert transaction_overrides
- POST /api/transactions/bulk — bulk categorize/normalize
- Inline click-to-edit category (22 options) and merchant name
- Blue dot override indicator, bulk action bar
- Effective values via COALESCE(override, llm_value) pattern

Stack: Next.js 16 (App Router, standalone), Prisma 7.x + @prisma/adapter-pg,
TanStack Query, Tailwind CSS. Auth via Traefik chain-oauth@file.
2026-03-07 23:31:40 +11:00
siddharthd 28207b42b5 Initial commit from Create Next App 2026-03-07 19:32:57 +11:00