Terminplaner TP2: Entwuerfe nach 90 Tagen und bei Kundenloeschung entfernen
Neu: server/services/termine/entwuerfe.js. Ein Terminplaner im Zustand off ist ein Entwurf (Fragebogen, Einstellung). loescheEntwuerfe(now) im Tagesjob (nach den abgeschalteten Funktionen, nur im vollen Lauf): letzte Aenderung = juengerer Zeitpunkt aus $updatedAt des Funktionsdokuments und termineConfig.updatedAt, aelter als 90 Tage => Einstellung weg, das Funktionsdokument nur, wenn es nie in Betrieb oder bezahlt war (sonst bleibt es wegen des siteKeys; ein von E8 zurueckgesetztes Dokument nie). Vor jedem Loeschen unter feature-order, feature-admin und termine-cfg frisch lesen (noch off, Frist, keine Buchung). Seiten zu 100 per cursorAfter, hoechstens 2000 geprueft und 100 geloescht je Lauf, der Rest folgt an Folgetagen; Einzelfehler zaehlen in fehler. Tagesbericht: Segment "Entwuerfe n geloescht (m offen)". loescheEntwuerfeVonKunde: Kundenloeschung entfernt alle off-Entwuerfe vollstaendig, Fehler werden nur protokolliert. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
29a38a9592
commit
91b1a3bcd8
6 files changed
+827
-24
No files matched your search
@@ -18,6 +18,7 @@ import {
|
||||
vergangeneAnfragen,
|
||||
zuErledigen,
|
||||
} from './buchungen.js'
|
||||
import { loescheEntwuerfe } from './entwuerfe.js'
|
||||
import { LOESCHFRIST_TAGE } from './frist.js'
|
||||
import { kontextPerFeature, ladeEinstellung } from './kontext.js'
|
||||
import { anGast } from './mails.js'
|
||||
@@ -38,7 +39,9 @@ import { gibZellenFrei, raeumeVerwaisteZellen } from './zellen.js'
|
||||
* fuenfMinutenJob alle 5 Minuten Erinnerungen (G05); bestaetigt 1 Stunde nach Ende => erledigt; Anfragen mit Beginn in
|
||||
* der Vergangenheit => abgelehnt (vom System, Zellen frei, keine Mail)
|
||||
* taeglicherJob taeglich Loeschfristen (11), Abo-Abgleich (aboAbgleich.js: der Terminplaner endet mit dem Wartungs-Abo),
|
||||
* abgeschaltete Funktionen, festgefahrene und alte Mails, verwaiste Zellen; der Abgleich laeuft VOR
|
||||
* abgeschaltete Funktionen, Entwuerfe (entwuerfe.js: Terminplaner im Zustand off, 90 Tage nach der
|
||||
* letzten Aenderung; nur im vollen Lauf, Entwuerfe sind nie bezahlt), festgefahrene und alte Mails,
|
||||
* verwaiste Zellen; der Abgleich laeuft VOR
|
||||
* der Loeschung abgeschalteter Funktionen, damit ein Terminplaner, dessen Abo heute zurueckkehrt,
|
||||
* nicht mehr geloescht wird; zuletzt die aktiven Betriebe zaehlen und den Lauf melden (Fehler,
|
||||
* Loeschdeckel in Folge, ab 20 Betrieben => Log und Team-Mail, meldeTagesjob in betrieb.js)
|
||||
@@ -759,6 +762,19 @@ const buchungenGeloescht = (loeschfristen, abgeschaltet) => Object.values(loesch
|
||||
/** Zaehler des Abo-Abgleichs, wenn der Schritt selbst scheitert (gleicheAboAb wirft nie; der Fehler steht dann schon in lauf.fehler). */
|
||||
const aboErsatz = () => ({ geprueft: 0, abgeschaltet: 0, wiederEin: 0, mails: 0, ausgenommen: 0, fehler: 0 })
|
||||
|
||||
/** Zaehler der Entwurfs-Loeschung, wenn der Schritt selbst scheitert (loescheEntwuerfe wirft nur bei ungueltiger Uhrzeit). */
|
||||
const entwuerfeErsatz = () => ({ geprueft: 0, geloescht: 0, uebrig: 0, fehler: 0 })
|
||||
|
||||
/**
|
||||
* Entwuerfe (entwuerfe.js) als Schritt des Tagesjobs: ein Fehler stoppt den Rest nicht. Die Einzelfehler der Loeschung (schon im Log)
|
||||
* kommen in lauf.fehler, damit der Tagesbericht und die Meldung ans Team sie nennen. => Zaehler { geprueft, geloescht, uebrig, fehler }
|
||||
*/
|
||||
async function entwuerfeSchritt(lauf, now) {
|
||||
const entwuerfe = await schritt(lauf, 'Entwürfe', () => loescheEntwuerfe(now), entwuerfeErsatz())
|
||||
lauf.fehler += entwuerfe.fehler
|
||||
return entwuerfe
|
||||
}
|
||||
|
||||
/**
|
||||
* Guard fuer den Modus off (fuehreAus: trotzAus): gibt es ein vom Kauf freigeschaltetes Termine-Dokument? Eine einzige Abfrage
|
||||
* (limit 1) ohne Kunden- oder Gastdaten; ein Lesefehler wirft und haelt den Tagesjob aus.
|
||||
@@ -785,15 +801,17 @@ async function aboAbgleichSchritt(lauf, now) {
|
||||
/**
|
||||
* Taeglich: festgefahrene Mails beenden (vor dem Aufraeumen, damit sie 48 Stunden lang als Zustellfehler sichtbar bleiben),
|
||||
* Loeschfristen, Abo-Abgleich (der Terminplaner endet mit dem Wartungs-Abo; VOR der Loeschung, damit ein Betrieb, dessen Abo heute
|
||||
* zurueckkehrt, nicht mehr geloescht wird), abgeschaltete Funktionen, alte Warteschlangen-Eintraege, verwaiste Zellen; zuletzt die
|
||||
* zurueckkehrt, nicht mehr geloescht wird), abgeschaltete Funktionen, Entwuerfe (entwuerfe.js; die Einzelfehler zaehlen in `fehler`),
|
||||
* alte Warteschlangen-Eintraege, verwaiste Zellen; zuletzt die
|
||||
* aktiven Betriebe zaehlen (ein nicht lesbarer Zaehler ergibt null und einen Fehler) und den Lauf ans Team melden (meldeTagesjob:
|
||||
* Fehler, Loeschdeckel an 3 Tagen in Folge, ab 20 Betrieben; wirft nie). Bricht der Job unerwartet ab, erfaehrt das Team es ebenfalls,
|
||||
* und der Fehler geht unveraendert an den Aufrufer.
|
||||
* `geloescht` = Summe aller Loeschzaehler (Buchungen aus Loeschfristen und abgeschalteten Funktionen), `aktiveBetriebe` = Zahl oder null,
|
||||
* `aboAbgleich` = Zaehler des Abgleichs { geprueft, abgeschaltet, wiederEin, mails, ausgenommen, fehler }.
|
||||
* `aboAbgleich` = Zaehler des Abgleichs { geprueft, abgeschaltet, wiederEin, mails, ausgenommen, fehler },
|
||||
* `entwuerfe` = Zaehler der Entwurfs-Loeschung { geprueft, geloescht, uebrig, fehler } (geloescht zaehlt Entwuerfe, nicht Buchungen).
|
||||
* Modus off: ohne vom Kauf freigeschaltetes Termine-Dokument { aus: true } nach genau einer Abfrage (Guard). Mit einem bezahlten
|
||||
* Dokument laeuft der eingeschraenkte Tagesjob nur mit Abo-Abgleich und Loeschung abgeschalteter Funktionen (Loeschfristen der
|
||||
* Buchungen, Warteschlange und Zellen bleiben aus; ob die uebrigen Schritte dort auch laufen sollen, ist offen). Sein Ergebnis traegt
|
||||
* Buchungen, Entwuerfe, Warteschlange und Zellen bleiben aus; ob die uebrigen Schritte dort auch laufen sollen, ist offen). Sein Ergebnis traegt
|
||||
* dieselben Felder, die meldeTagesjob und die Statusroute lesen: { eingeschraenkt: true, aboAbgleich, abgeschaltet, gedeckelt
|
||||
* { loeschfristen: 0, abgeschaltet, zellen: 0 }, geloescht, aktiveBetriebe: null, fehler }. Beide Laeufe teilen die Ueberlappungssperre.
|
||||
* @param {Date} now
|
||||
@@ -816,6 +834,7 @@ export async function taeglicherJob(now) {
|
||||
buchungen: 0,
|
||||
gedeckelt: 0,
|
||||
})
|
||||
const entwuerfe = await entwuerfeSchritt(lauf, now)
|
||||
const aufgeraeumt = await schritt(lauf, 'Warteschlange aufräumen', () => raeumeAuf(now), 0)
|
||||
const zellenErgebnis = await schritt(lauf, 'Verwaiste Zellen', () => raeumeVerwaisteZellen(now), { geloescht: 0, gedeckelt: false })
|
||||
if (zellenErgebnis.gedeckelt) {
|
||||
@@ -830,6 +849,7 @@ export async function taeglicherJob(now) {
|
||||
gedeckelt,
|
||||
abgeschaltet,
|
||||
aboAbgleich,
|
||||
entwuerfe,
|
||||
aufgeraeumt,
|
||||
zellen: zellenErgebnis.geloescht,
|
||||
geloescht: buchungenGeloescht(loeschung, abgeschaltet),
|
||||
@@ -881,10 +901,10 @@ const zahl = (wert) => (Number.isInteger(wert) && wert > 0 ? wert : 0)
|
||||
/**
|
||||
* Eine Zeile fuers Log nach dem Tagesjob: nur Zahlen, keine personenbezogenen Daten und keine Buchungs- oder Funktions-IDs
|
||||
* (Spur der unwiderruflichen Loeschungen). Reihenfolge der Segmente (verbindlich): `…, N Mails nicht zugestellt, [Löschläufe am
|
||||
* Deckel: n, Rest folgt an den nächsten Tagen, ]Abo-Abgleich g geprüft / a abgeschaltet / w wieder ein / m Mails / x ausgenommen,
|
||||
* N Fehler, n aktive Betriebe`; „n aktive Betriebe“ steht ganz am Ende und fehlt, wenn die Zahl unbekannt ist, „Abo-Abgleich“ fehlt,
|
||||
* wenn das Ergebnis keine Zaehler dafuer traegt. Der eingeschraenkte Lauf (Modus off) hat eine eigene Zeile „[termine] Tagesjob (Modus
|
||||
* off, nur Abo-Abgleich und Löschung): …“ ohne Zellen, Outbox, Mails und Betriebe.
|
||||
* Deckel: n, Rest folgt an den nächsten Tagen, ]Entwürfe n gelöscht (m offen), Abo-Abgleich g geprüft / a abgeschaltet / w wieder ein /
|
||||
* m Mails / x ausgenommen, N Fehler, n aktive Betriebe`; „n aktive Betriebe“ steht ganz am Ende und fehlt, wenn die Zahl unbekannt ist,
|
||||
* „Abo-Abgleich“ und „Entwürfe“ fehlen, wenn das Ergebnis keine Zaehler dafuer traegt. Der eingeschraenkte Lauf (Modus off) hat eine
|
||||
* eigene Zeile „[termine] Tagesjob (Modus off, nur Abo-Abgleich und Löschung): …“ ohne Entwürfe, Zellen, Outbox, Mails und Betriebe.
|
||||
* null, wenn der Job nicht gelaufen ist (Modus off ohne bezahlte Terminplaner, uebersprungen).
|
||||
* @param {object} ergebnis Rueckgabe von taeglicherJob
|
||||
* @returns {string|null}
|
||||
@@ -894,6 +914,8 @@ export function tagesbericht(ergebnis) {
|
||||
const a = ergebnis.abgeschaltet
|
||||
const amDeckel = Object.values(ergebnis.gedeckelt ?? {}).reduce((summe, n) => summe + n, 0)
|
||||
const deckel = amDeckel > 0 ? `Löschläufe am Deckel: ${amDeckel}, Rest folgt an den nächsten Tagen, ` : ''
|
||||
const e = ergebnis.entwuerfe
|
||||
const entwuerfeSegment = e === null || typeof e !== 'object' ? '' : `Entwürfe ${zahl(e.geloescht)} gelöscht (${zahl(e.uebrig)} offen), `
|
||||
const abo = ergebnis.aboAbgleich
|
||||
const aboSegment =
|
||||
abo === null || typeof abo !== 'object'
|
||||
@@ -912,7 +934,7 @@ export function tagesbericht(ergebnis) {
|
||||
`[termine] Tagesjob: ${gesamt} Buchungen gelöscht (verfallen ${l.verfallen}, abgesagt ${l.abgesagt}, abgelehnt ${l.abgelehnt}, ` +
|
||||
`erledigt ${l.erledigt}, nichterschienen ${l.nichterschienen}, abgeschaltete Funktionen ${a.buchungen}), ` +
|
||||
`${a.funktionen} Funktionen bereinigt, ${ergebnis.zellen} Zellen, ${ergebnis.aufgeraeumt} Outbox, ` +
|
||||
`${ergebnis.festgefahren} Mails nicht zugestellt, ${deckel}${aboSegment}${ergebnis.fehler} Fehler${betriebe}`
|
||||
`${ergebnis.festgefahren} Mails nicht zugestellt, ${deckel}${entwuerfeSegment}${aboSegment}${ergebnis.fehler} Fehler${betriebe}`
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user