import 'server-only' import { abgleichEntscheiden, zeitraumHash } from '@/lib/zeitblock' import { db } from '@/server/db' /** * Der Rückweg: Änderungen an Zeitblöcken aus dem Kalender übernehmen. * * Läuft nach jedem Abgleich eines Kontos. Für jeden Zeitblock wird verglichen, * was im Kalender steht — der örtliche Spiegel (Tabelle `termin`) ist dafür * bereits auf dem neuesten Stand. * * **Der Kalender gewinnt.** Wer dort etwas verschiebt, meint es so; der Planer * zieht nach, statt zurückzuschreiben. Sonst zöge die App dem Benutzer den * Termin unter den Händen weg. */ export type RueckwegBericht = { uebernommen: number geloest: number } export async function rueckwegAnwenden( kalenderkontoId: string, ): Promise { const zeitbloecke = await db.zeitblock.findMany({ where: { kalenderkontoId, extId: { not: null } }, select: { id: true, extId: true, beginn: true, ende: true, hash: true, aufgabeId: true, }, }) if (zeitbloecke.length === 0) return { uebernommen: 0, geloest: 0 } const extIds = zeitbloecke.map((z) => z.extId).filter((id): id is string => id !== null) const termine = await db.termin.findMany({ where: { kalenderkontoId, extId: { in: extIds } }, select: { extId: true, beginn: true, ende: true, etag: true }, }) const nachExtId = new Map(termine.map((t) => [t.extId, t])) let uebernommen = 0 let geloest = 0 for (const zeitblock of zeitbloecke) { const imKalender = nachExtId.get(zeitblock.extId as string) ?? null const entscheidung = abgleichEntscheiden( { hash: zeitblock.hash, beginn: zeitblock.beginn, ende: zeitblock.ende }, imKalender ? { beginn: imKalender.beginn, ende: imKalender.ende } : null, ) if (entscheidung.tun === 'nichts') continue if (entscheidung.tun === 'loesen') { // Im Kalender gelöscht: der Zeitblock verliert seine Verankerung. Die // Aufgabe bleibt bestehen und fällt zurück auf offen, wenn nichts // anderes mehr für sie geplant ist. await db.zeitblock.delete({ where: { id: zeitblock.id } }) geloest++ const nochGeplant = await db.zeitblock.count({ where: { aufgabeId: zeitblock.aufgabeId }, }) if (nochGeplant === 0) { await db.aufgabe.updateMany({ where: { id: zeitblock.aufgabeId, status: 'GEPLANT' }, data: { status: 'OFFEN' }, }) } continue } await db.zeitblock.update({ where: { id: zeitblock.id }, data: { beginn: entscheidung.beginn, ende: entscheidung.ende, // Den Fingerabdruck auf den übernommenen Stand setzen, damit die // nächste Runde ihn wiedererkennt und nichts mehr tut. hash: zeitraumHash(entscheidung.beginn, entscheidung.ende), etag: imKalender?.etag ?? null, letzterFehler: null, }, }) uebernommen++ } return { uebernommen, geloest } }