new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 13:08:19 +01:00
parent 83b84664ce
commit 5032e1593b
41 changed files with 5157 additions and 40 deletions

View File

@@ -0,0 +1,75 @@
import pool from '../config/database';
import notificationService from '../services/notification.service';
import logger from '../utils/logger';
const INTERVAL_MS = 15 * 60 * 1000; // 15 minutes
let jobInterval: ReturnType<typeof setInterval> | null = null;
let isRunning = false;
async function runReminderCheck(): Promise<void> {
if (isRunning) {
logger.warn('ReminderJob: previous run still in progress — skipping');
return;
}
isRunning = true;
try {
// Find due reminders that haven't been processed
const result = await pool.query(`
SELECT e.id, e.bestellung_id, e.nachricht, e.erstellt_von,
b.bezeichnung AS bestellung_bezeichnung, b.besteller_id
FROM bestellung_erinnerungen e
JOIN bestellungen b ON b.id = e.bestellung_id
WHERE e.faellig_am <= NOW()
AND e.erledigt = FALSE
`);
for (const row of result.rows) {
// Notify the order handler (besteller_id) or the creator
const targetUserId = row.besteller_id || row.erstellt_von;
if (!targetUserId) continue;
await notificationService.createNotification({
user_id: targetUserId,
typ: 'bestellung_erinnerung',
titel: 'Bestellungs-Erinnerung',
nachricht: row.nachricht || `Erinnerung für Bestellung "${row.bestellung_bezeichnung}"`,
schwere: 'info',
link: `/bestellungen/${row.bestellung_id}`,
quell_id: `bestellung-erinnerung-${row.id}`,
quell_typ: 'bestellung_erinnerung',
});
// Mark as done
await pool.query('UPDATE bestellung_erinnerungen SET erledigt = TRUE WHERE id = $1', [row.id]);
}
if (result.rows.length > 0) {
logger.info(`ReminderJob: processed ${result.rows.length} reminders`);
}
} catch (error) {
logger.error('ReminderJob: unexpected error', {
error: error instanceof Error ? error.message : String(error),
});
} finally {
isRunning = false;
}
}
export function startReminderJob(): void {
if (jobInterval !== null) {
logger.warn('Reminder job already running — skipping duplicate start');
return;
}
// Run once after short delay, then repeat
setTimeout(() => runReminderCheck(), 45 * 1000);
jobInterval = setInterval(() => runReminderCheck(), INTERVAL_MS);
logger.info('Reminder job scheduled (every 15 minutes)');
}
export function stopReminderJob(): void {
if (jobInterval !== null) {
clearInterval(jobInterval);
jobInterval = null;
}
logger.info('Reminder job stopped');
}