81 lines
2.5 KiB
JavaScript
81 lines
2.5 KiB
JavaScript
|
|
const cron = require('node-cron');
|
||
|
|
const { getDb, getSetting } = require('../db/database');
|
||
|
|
const { buildTrackerRow, getCycleRange } = require('../services/statusService');
|
||
|
|
const { pruneExpiredSessions } = require('../services/authService');
|
||
|
|
const { runNotifications } = require('../services/notificationService');
|
||
|
|
const { runAllCleanup } = require('../services/cleanupService');
|
||
|
|
const {
|
||
|
|
markWorkerError,
|
||
|
|
markWorkerStarted,
|
||
|
|
markWorkerSuccess,
|
||
|
|
} = require('../services/statusRuntime');
|
||
|
|
|
||
|
|
const DAILY_CRON_HOUR = 6;
|
||
|
|
|
||
|
|
function nextDailyRunIso(from = new Date()) {
|
||
|
|
const next = new Date(from);
|
||
|
|
next.setHours(DAILY_CRON_HOUR, 0, 0, 0);
|
||
|
|
if (next <= from) next.setDate(next.getDate() + 1);
|
||
|
|
return next.toISOString();
|
||
|
|
}
|
||
|
|
|
||
|
|
async function runDailyTasks() {
|
||
|
|
const db = getDb();
|
||
|
|
const now = new Date();
|
||
|
|
const year = now.getFullYear();
|
||
|
|
const month = now.getMonth() + 1;
|
||
|
|
const todayStr = now.toISOString().slice(0, 10);
|
||
|
|
const { start, end } = getCycleRange(year, month);
|
||
|
|
|
||
|
|
const bills = db.prepare('SELECT * FROM bills WHERE active = 1').all();
|
||
|
|
|
||
|
|
for (const bill of bills) {
|
||
|
|
const payments = db.prepare(
|
||
|
|
'SELECT * FROM payments WHERE bill_id = ? AND paid_date BETWEEN ? AND ? AND deleted_at IS NULL'
|
||
|
|
).all(bill.id, start, end);
|
||
|
|
|
||
|
|
const row = buildTrackerRow(bill, payments, year, month, todayStr);
|
||
|
|
|
||
|
|
// Auto-mark autopay bills as assumed_paid on due date
|
||
|
|
if (
|
||
|
|
bill.autopay_enabled &&
|
||
|
|
bill.autodraft_status === 'pending' &&
|
||
|
|
todayStr >= row.due_date
|
||
|
|
) {
|
||
|
|
db.prepare("UPDATE bills SET autodraft_status = 'assumed_paid', updated_at = datetime('now') WHERE id = ?")
|
||
|
|
.run(bill.id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pruneExpiredSessions();
|
||
|
|
await runNotifications();
|
||
|
|
|
||
|
|
// Run scheduled cleanup tasks (expired import sessions, stale temp files, etc.)
|
||
|
|
await runAllCleanup().catch(err => {
|
||
|
|
console.error('[worker] Cleanup error (non-fatal):', err.message);
|
||
|
|
});
|
||
|
|
|
||
|
|
markWorkerSuccess(nextDailyRunIso());
|
||
|
|
console.log(`[worker] Daily tasks ran at ${todayStr}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
function start() {
|
||
|
|
markWorkerStarted(nextDailyRunIso());
|
||
|
|
|
||
|
|
// Run once at startup
|
||
|
|
runDailyTasks().catch(err => {
|
||
|
|
markWorkerError(err, nextDailyRunIso());
|
||
|
|
console.error('[worker] Startup task error:', err);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Run every day at 6:00 AM
|
||
|
|
cron.schedule('0 6 * * *', () => {
|
||
|
|
runDailyTasks().catch(err => {
|
||
|
|
markWorkerError(err, nextDailyRunIso());
|
||
|
|
console.error('[worker] Daily task error:', err);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = { start, runDailyTasks, nextDailyRunIso };
|