/** * Bestandsabgleich mit ApiCore als Sicherheitsnetz unter den Sofort-Wegen. * * Normalerweise geht eine Buchung direkt nach der Zahlung/Stornierung an * ApiCore, und eine Entnahme in ApiCore kommt per Webhook sofort an. Dieser * Lauf faengt alles ab, was dabei liegen blieb: ApiCore war nicht erreichbar, * ein Webhook ging verloren, der Server wurde mitten im Senden neu gestartet. * * 1. offene Buchungen senden (mit Wartezeiten 1, 5, 15, 60 Minuten), * 2. ALLE verknuepften Produkte gegen ApiCore abgleichen. * * Aufruf: pnpm stock:apicore-sync * Im Cluster laeuft er alle 10 Minuten als CronJob (k8s/07-backup-cronjob.yaml). * * Exit-Code 1, wenn ApiCore nicht erreichbar war oder Buchungen abgelehnt * hat: dann soll der Job als fehlgeschlagen sichtbar sein, nicht nur in * einer Logzeile verschwinden. */ import { prisma } from "../src/lib/prisma"; import { deliverPendingStockEvents } from "../src/lib/apicore-stock/delivery"; import { reconcileApiCoreStock } from "../src/lib/apicore-stock/reconcile"; async function main(): Promise { const delivered = await deliverPendingStockEvents(); console.log( `[apicore-stock] Buchungen: ${delivered.sent} bestaetigt, ${delivered.rejected} abgelehnt, ${delivered.failed} nicht zugestellt${delivered.error ? ` (${delivered.error})` : ""}` ); const reconciled = await reconcileApiCoreStock(); console.log( `[apicore-stock] Abgleich: ${reconciled.updated} Produkte aktualisiert, ${reconciled.missing} in ApiCore nicht gefunden${reconciled.error ? ` (${reconciled.error})` : ""}` ); const failed = delivered.failed > 0 || delivered.rejected > 0 || Boolean(reconciled.error); return failed ? 1 : 0; } main() .then(async (code) => { await prisma.$disconnect(); process.exit(code); }) .catch(async (error: unknown) => { console.error("[apicore-stock] Lauf abgebrochen:", error); await prisma.$disconnect(); process.exit(1); });