feat(cash): mark how a transaction was paid, exclude cash from reconciliation
ci / lint-test (push) Successful in 41s
ci / lint-test (push) Successful in 41s
getPendingReconciliations treated every unreconciled manual transaction as awaiting a matching statement row. Cash never appears on a statement, so a cash entry sat in the queue indefinitely being offered matches within 3 days and 1% on amount - and accepting one is silently destructive: reconciled manual rows are filtered out of every query, so the cash spend disappears while the card transaction it matched claims to be that same spend. Migration 0016 adds transactions.payment_method (card | cash | bank_transfer | other, NULL = unknown) with a CHECK constraint and a partial index. The notCash() fragment excludes cash from both halves of the reconciliation query - the pending list and the candidate match subquery, which aliases the manual row as m. Only cash is excluded. Bank transfers do appear on a statement now that transaction accounts are imported, and NULL means unknown, so both stay candidates and every pre-existing row behaves exactly as before. ATM withdrawals deliberately stay categorised as spend rather than transfers. Treating them as transfers is only correct if every cash purchase is logged; with partial logging it silently deletes the unlogged remainder from spend.
This commit is contained in:
@@ -42,6 +42,7 @@ export async function POST(req: NextRequest) {
|
||||
transaction_type?: string;
|
||||
merchant_normalized?: string;
|
||||
category?: string;
|
||||
payment_method?: string;
|
||||
splits?: { participant_id: number; share_percent: number }[];
|
||||
};
|
||||
|
||||
@@ -51,8 +52,8 @@ export async function POST(req: NextRequest) {
|
||||
|
||||
// Insert manual transaction with no statement (statement_id = NULL, owner_id set directly)
|
||||
const txRows = await queryRaw<{ id: number }>(
|
||||
`INSERT INTO transactions (statement_id, owner_id, transaction_date, description, amount, transaction_type, merchant_normalized, category, row_index)
|
||||
VALUES (NULL, $1, $2, $3, $4, $5, $6, $7, (
|
||||
`INSERT INTO transactions (statement_id, owner_id, transaction_date, description, amount, transaction_type, merchant_normalized, category, payment_method, row_index)
|
||||
VALUES (NULL, $1, $2, $3, $4, $5, $6, $7, $8, (
|
||||
SELECT COALESCE(MAX(row_index), -1) + 1 FROM transactions WHERE owner_id = $1 AND statement_id IS NULL
|
||||
))
|
||||
RETURNING id`,
|
||||
@@ -64,6 +65,7 @@ export async function POST(req: NextRequest) {
|
||||
body.transaction_type || "debit",
|
||||
body.merchant_normalized || null,
|
||||
body.category || null,
|
||||
body.payment_method || null,
|
||||
]
|
||||
);
|
||||
const transactionId = txRows[0].id;
|
||||
|
||||
Reference in New Issue
Block a user