Some checks failed
Deploy production / deploy (push) Failing after 23s
- Knab statement exports: per-account ids (knab:<account>:<Referentie>), routed by IBAN, transfers between own accounts merged into one tracker account are dropped (interest kept) - Import: multiple files, hand-entered twins get the import id, hand entries equal to the sum of 2-3 payments within a day are replaced by them - bank-link --bank revolut|abn|knab with per-bank default account; ASPSP notes printed - bank-sync: longest history on an account first sync (--full to force), sum reconcile, per-session status so one bank failing does not mark the others - Timeline: 1 year / 3 years / All history range
54 lines
2.4 KiB
TypeScript
54 lines
2.4 KiB
TypeScript
// Pull booked bank transactions into money.transactions (Enable Banking).
|
|
//
|
|
// bun --env-file=$HOME/.config/money-sync.env scripts/bank-sync.ts [options]
|
|
// --dry-run fetch and report, write nothing
|
|
// --reconcile match against ALL hand-entered rows (account + amount + date ±1 day)
|
|
// and attach the bank id to them instead of inserting duplicates;
|
|
// run once after linking (with --dry-run first)
|
|
// --from YYYY-MM-DD override the start date (default: last synced date - 7 days, or the
|
|
// account's first transaction on the first run)
|
|
// --full ask for the longest history the bank serves (automatic on an
|
|
// account's first sync; only works within an hour of consent at most banks)
|
|
// --account <name> only this tracker account
|
|
//
|
|
// Dedupe: unique (account_id, external_id); re-running is always safe.
|
|
import postgres from 'postgres';
|
|
import { configFromEnv, createEnableBankingClient } from '../src/lib/server/enable-banking';
|
|
import { syncBankAccounts } from '../src/lib/server/bank-sync';
|
|
|
|
const args = process.argv.slice(2);
|
|
const value = (name: string) => {
|
|
const i = args.indexOf(name);
|
|
return i >= 0 ? args[i + 1] : undefined;
|
|
};
|
|
const from = value('--from');
|
|
if (from && !/^\d{4}-\d{2}-\d{2}$/.test(from)) throw new Error('--from must be YYYY-MM-DD');
|
|
if (!process.env.DB_URL) throw new Error('DB_URL is not set');
|
|
|
|
const client = createEnableBankingClient(configFromEnv());
|
|
const sql = postgres(process.env.DB_URL, { max: 2, connect_timeout: 10, onnotice: () => {} });
|
|
const dryRun = args.includes('--dry-run');
|
|
try {
|
|
const results = await syncBankAccounts(sql, client, {
|
|
dryRun,
|
|
reconcile: args.includes('--reconcile'),
|
|
from,
|
|
full: args.includes('--full'),
|
|
accountName: value('--account')
|
|
});
|
|
for (const r of results) {
|
|
console.log(
|
|
`${r.account}: fetched ${r.fetched}, booked ${r.booked}, new ${r.inserted}, ` +
|
|
`matched to existing ${r.matched}, replaced sum entries ${r.absorbed}, ` +
|
|
`already synced ${r.alreadyKnown}` +
|
|
(r.historyFrom ? `, history from ${r.historyFrom}` : '') +
|
|
(r.balance ? `, bank balance ${r.balance}` : '') +
|
|
(r.error ? `\n ERROR ${r.error}` : '')
|
|
);
|
|
}
|
|
if (dryRun) console.log('(dry run: nothing written)');
|
|
if (results.some((r) => r.error)) process.exitCode = 1;
|
|
} finally {
|
|
await sql.end();
|
|
}
|