47 lines
1.9 KiB
TypeScript
47 lines
1.9 KiB
TypeScript
// Daily refresh of auto goal metrics (tasks.goals.metric_key):
|
|
// 1. trailing-12-month paid Moneybird sales invoices -> tasks.metric_sources
|
|
// 2. recompute every auto goal -> tasks.goals.metric_current/metric_detail (+ progress snapshot)
|
|
//
|
|
// bun --env-file=$HOME/.config/goal-metrics.env scripts/goal-metrics.ts [--dry-run]
|
|
// Env: DB_URL (app role), MONEYBIRD_API_TOKEN, MONEYBIRD_ADMINISTRATION_ID. Mode 600, never committed.
|
|
// Run by the goal-metrics.timer user unit (deploy/systemd). Page loads never call Moneybird.
|
|
import postgres from 'postgres';
|
|
import {
|
|
SIDE_INCOME_SOURCE,
|
|
fetchMoneybirdSideIncome,
|
|
persistGoalMetrics,
|
|
saveSource
|
|
} from '../src/lib/server/goal-metrics/core';
|
|
|
|
const dry = process.argv.includes('--dry-run');
|
|
const { DB_URL, MONEYBIRD_API_TOKEN, MONEYBIRD_ADMINISTRATION_ID } = process.env;
|
|
if (!DB_URL) throw new Error('Set DB_URL');
|
|
const sql = postgres(DB_URL, { max: 1, connect_timeout: 10, onnotice: () => {} });
|
|
let failed = false;
|
|
try {
|
|
if (!MONEYBIRD_API_TOKEN || !MONEYBIRD_ADMINISTRATION_ID) {
|
|
failed = true;
|
|
console.error('[goal-metrics] Moneybird env missing; keeping the cached side income');
|
|
} else {
|
|
try {
|
|
const mb = await fetchMoneybirdSideIncome(MONEYBIRD_API_TOKEN, MONEYBIRD_ADMINISTRATION_ID);
|
|
console.log(`[goal-metrics] Moneybird: ${mb.invoices} paid invoices ${mb.from}..${mb.to}`);
|
|
if (!dry) await saveSource(sql, SIDE_INCOME_SOURCE, mb.monthly, mb, null);
|
|
} catch (e) {
|
|
failed = true;
|
|
const msg = (e as Error).message.slice(0, 300);
|
|
console.error(`[goal-metrics] Moneybird failed: ${msg}`);
|
|
if (!dry) await saveSource(sql, SIDE_INCOME_SOURCE, null, null, msg);
|
|
}
|
|
}
|
|
if (!dry) {
|
|
for (const g of await persistGoalMetrics(sql))
|
|
console.log(
|
|
`[goal-metrics] goal ${g.id}: ${g.target ? ((g.value / g.target) * 100).toFixed(1) + '%' : 'no target'}`
|
|
);
|
|
}
|
|
} finally {
|
|
await sql.end();
|
|
}
|
|
if (failed) process.exit(1);
|