money: tag interest/dividend payouts on bank sync and Revolut import (category interest|dividend, never overwrites a set category)
All checks were successful
Deploy production / deploy (push) Successful in 1m14s

This commit is contained in:
2026-10-26 07:48:47 +00:00
parent 0121071af2
commit d3b9bb9ba2
8 changed files with 171 additions and 5 deletions

View File

@@ -15,6 +15,8 @@
// category 'transfer' (e.g. Personal <-> Joint legs)
// --tag-matched-transfers with --transfer-pattern: also set category 'transfer' on the
// existing tracker rows those statement rows matched
// Interest/dividend payouts (src/lib/server/investment-income.ts) get category 'interest' /
// 'dividend' on insert; matched existing rows get it only when their category is empty.
// --apply write (needs a money-schema backup in ~/backups from the last 2 hours)
// --drop-start-balance with --apply: delete the account's "Start balance" row(s), only if the
// statement opens at €0 and, after the import, the only difference
@@ -38,6 +40,7 @@ import {
planImport,
rowsFromTable,
selectRows,
statementCategory,
statementExternalId,
type StatementRow,
type TrackerRow
@@ -293,12 +296,23 @@ try {
insert into money.transactions
(user_id, account_id, date, value_date, description, amount_cents, external_id, source, booking_status, category, raw)
values (${account.user_id}, ${account.id}, ${r.date}, ${r.startedDate}, ${r.description.slice(0, 500)},
${r.amountCents}, ${statementExternalId(r, hash)}, 'csv', 'BOOK', ${isTransfer(r) ? 'transfer' : null},
${r.amountCents}, ${statementExternalId(r, hash)}, 'csv', 'BOOK', ${isTransfer(r) ? 'transfer' : statementCategory(r)},
${q.json({ revolut: { type: r.type, product: r.product, started: r.startedDate, completed: r.completedAt, description: r.description, fee_cents: r.feeCents, currency: r.currency, balance_cents: r.balanceCents, file_line: r.line } })})
on conflict do nothing`;
inserted += res.count;
}
console.log(`Inserted ${inserted} rows into ${account.name}.`);
// Interest/dividend payouts that matched an existing row: tag it, unless it already
// has a category (hand-set categories are never overwritten).
let income = 0;
for (const d of plan.duplicates) {
const category = isTransfer(d.row) ? null : statementCategory(d.row);
if (!category) continue;
const res = await q`update money.transactions set category = ${category}
where id = ${d.match.id} and account_id = ${account.id} and category is null`;
income += res.count;
}
if (income) console.log(`Tagged ${income} existing interest/dividend rows.`);
if (transferRe && flag('--tag-matched-transfers')) {
const ids = plan.duplicates.filter((d) => isTransfer(d.row)).map((d) => d.match.id);
const tagged = ids.length