docs: update CLAUDE.md and README to reflect recent changes
- Add reconciled_with_id and created_at columns to transactions table docs - Document split_payments, expense_metadata, rule_apply_runs tables - Update /api/transactions route docs with has_split filter and all sort options - Add /api/transactions/reconcile and /api/split-payments to API table - Document import date (created_at) behaviour and reconciliation caveat - Add Prisma regeneration note to CLAUDE.md - Note schema drift for tables added without migration files
This commit is contained in:
@@ -72,6 +72,8 @@ One row per line item within a statement. Cascade-deleted when the parent statem
|
||||
| `foreign_currency_code` | text | Foreign currency code (e.g. `USD`) |
|
||||
| `category` | text | AI-assigned category (see category taxonomy below) |
|
||||
| `row_index` | int | Position in statement — used for deduplication |
|
||||
| `reconciled_with_id` | int FK → `transactions` (nullable) | Links a manually-entered transaction to its matching statement transaction after reconciliation |
|
||||
| `created_at` | timestamptz | When the row was inserted — the "import date". For reconciled transactions the UI shows the original manual/CSV `created_at`, not the statement's |
|
||||
|
||||
**Deduplication**: unique index on `(statement_id, transaction_date, description, amount, row_index)`.
|
||||
|
||||
@@ -171,6 +173,55 @@ Saved auto-categorisation rules. Applied in bulk via the Rules page.
|
||||
|
||||
---
|
||||
|
||||
### `split_payments`
|
||||
Records of actual cash settlements between participants.
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `from_participant_id` | int FK → `participants` | Who paid |
|
||||
| `to_participant_id` | int FK → `participants` | Who received |
|
||||
| `amount` | numeric | Amount settled |
|
||||
| `payment_date` | date | Date of settlement |
|
||||
| `notes` | text | Optional note (e.g. "bank transfer") |
|
||||
| `linked_transaction_id` | int FK → `transactions` (nullable) | If the payment was itself a transaction |
|
||||
|
||||
---
|
||||
|
||||
### `expense_metadata`
|
||||
Enrichment records for non-statement expenses (email receipts, manual entries). Linked to a `transaction` if one exists; otherwise a standalone record awaiting reconciliation.
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `transaction_id` | int FK → `transactions` (unique, nullable) | Linked transaction; NULL until reconciled |
|
||||
| `source` | text | Origin: `email`, `manual` |
|
||||
| `paperless_doc_id` | int | Paperless-NGX document ID |
|
||||
| `payment_method` | text | `credit_card`, `debit_card`, `paypal`, `afterpay`, `cash`, etc. |
|
||||
| `payment_method_detail` | text | Card last-4 or provider detail |
|
||||
| `order_reference` | text | Order/confirmation number |
|
||||
| `line_items` | jsonb | Array of `{description, qty, unit_price, total}` |
|
||||
| `merchant_normalized` | text | Canonical merchant for matching |
|
||||
| `amount` / `transaction_date` | numeric / date | Used for reconciliation matching when `transaction_id IS NULL` |
|
||||
| `extraction_model` | text | AI model used (`gemini-2.5-flash`) |
|
||||
|
||||
Partial index on `(merchant_normalized, transaction_date) WHERE transaction_id IS NULL` powers reconciliation queries.
|
||||
|
||||
---
|
||||
|
||||
### `rule_apply_runs`
|
||||
Audit log of bulk rule-apply operations. Each run captures which transactions were affected and a full snapshot for revert support.
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `owner_id` | int FK → `participants` | |
|
||||
| `applied_at` | timestamptz | When the run executed |
|
||||
| `split_from` | date | Optional date filter used for this run |
|
||||
| `matched` | int | Number of rules matched |
|
||||
| `transactions_affected` | int | Number of transactions changed |
|
||||
| `reverted_at` | timestamptz | Set when run was reverted |
|
||||
| `snapshot` | jsonb | Pre-run state of all affected transactions |
|
||||
|
||||
---
|
||||
|
||||
### `budgets`
|
||||
Monthly spend targets per category. Stored but currently unused in the UI (replaced by the analytics/insights views).
|
||||
|
||||
@@ -205,16 +256,19 @@ All routes require authentication via `X-Forwarded-User` header (set by Traefik)
|
||||
|--------|-------|-------------|
|
||||
| GET | `/api/statements` | All statements for current user |
|
||||
| GET / PATCH | `/api/statements/[id]` | Get statement; PATCH to reassign owner (also writes `account_owner_mappings`) |
|
||||
| GET | `/api/transactions` | Paginated transactions with filters: `from`, `to`, `category`, `merchant`, `statement_id`, `search`, `sort`, `dir` |
|
||||
| GET | `/api/transactions` | Paginated transactions. Filters: `from`, `to`, `categories`, `bank_names`, `tag_ids`, `transaction_types`, `search`, `statement_id`, `amount_min`, `amount_max`, `has_split` (`yes`/`no`). Sort: `sort_by` (`transaction_date`\|`amount`\|`created_at`), `sort_dir` (`asc`\|`desc`) |
|
||||
| POST | `/api/transactions` | Create a manual transaction (no statement) |
|
||||
| GET / PATCH | `/api/transactions/[id]` | Get transaction; PATCH to upsert override (category, merchant, notes) |
|
||||
| GET / POST | `/api/transactions/[id]/splits` | List or create splits on a transaction |
|
||||
| GET / POST | `/api/transactions/[id]/tags` | List or apply tags to a transaction |
|
||||
| POST | `/api/transactions/bulk` | Bulk update category/merchant across multiple transactions |
|
||||
| POST | `/api/transactions/reconcile` | Link manual transactions to statement transactions; copies overrides, tags, splits across |
|
||||
| GET | `/api/analytics/monthly` | Split-adjusted monthly spend by category + income + investments. Params: `months` (1–24, default 6) |
|
||||
| GET | `/api/analytics/subscriptions` | Recurring charge detection — merchants with ≥3 occurrences at consistent intervals |
|
||||
| GET | `/api/analytics/fees` | Fees and interest from statement summaries + individual fee/interest transactions |
|
||||
| GET | `/api/shared-transactions` | Transactions that have active splits |
|
||||
| GET | `/api/shared-transactions` | Transactions with active splits; sorted client-side by date/imported/amount in the UI |
|
||||
| POST | `/api/splits/settle` | Mark a split as settled |
|
||||
| GET / POST | `/api/split-payments` | List or record cash settlements between participants |
|
||||
| GET / POST | `/api/participants` | List participants; POST to create (with optional `email`) |
|
||||
| GET | `/api/participants/[id]/balance` | Net balance owed by/to a specific participant |
|
||||
| GET | `/api/participants/balances` | All participant balances |
|
||||
@@ -292,6 +346,7 @@ docker exec postgres-personal psql -U personal -d personal \
|
||||
|
||||
> `paperless_doc_id` on statements and the `uq_statements_paperless_doc_id` index were added directly (not tracked in a migration file).
|
||||
> `owner_id` on transactions and `statement_id` made nullable were applied directly (March 2026) to support manual transaction entry without a fake statement.
|
||||
> `reconciled_with_id` on transactions, `expense_metadata`, `rule_apply_runs`, `split_payments` were added directly and are covered by the Prisma schema but lack individual migration files.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user