Terminplaner: Aufbewahrungs-Loeschung seitenweise (Grundlagen, verfallen/abgesagt/abgelehnt)
loeschKandidaten liest eine Seite (Standard 100, aelteste Bezugszeit zuerst, optional je Funktion) ohne Gastfelder; die Frist steht in der Abfrage. arbeiteSeiten (Seite lesen, bearbeiten, neu lesen) endet bei leerer Seite, am Deckel (config.termine.loeschDeckel, 2000 je Status und Lauf, Rest an den Folgetagen, gezaehlt als gedeckelt) oder bei einer Seite ohne Fortschritt. verfallen, abgesagt und abgelehnt laufen darueber, unter der Buchungssperre werden Status und Bezugszeit frisch geprueft. taeglicherJob liefert gedeckelt getrennt vom Loeschzaehler. Neue Indizes idx_status_ends und idx_status_updated auf termineBookings (scripts/termine-setup.mjs legt sie an). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2dd9c0dec7
commit
5c95dfc322
8 files changed
+484
-33
No files matched your search
@@ -31,6 +31,10 @@ const LOESCH_BEZUG = {
|
||||
nichterschienen: 'endsAt',
|
||||
}
|
||||
|
||||
/** Eine Seite von loeschKandidaten und die Felder, die sie liest (nie Gastfelder). */
|
||||
const LOESCH_SEITE = 100
|
||||
const LOESCH_FELDER = ['$id', 'featureId', 'status', 'endsAt', 'updatedAt', 'heldUntil']
|
||||
|
||||
const iso = (wert) => new Date(wert).toISOString()
|
||||
const kleinGetrimmt = (email) => (typeof email === 'string' ? email.trim().toLowerCase() : '')
|
||||
|
||||
@@ -181,16 +185,31 @@ export async function vergangeneAnfragen(now) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Buchungen eines Status (alle Funktionen), deren Bezugszeit vor `vor` liegt. Bezugszeit je Status: verfallen =
|
||||
* heldUntil, erledigt und nichterschienen = endsAt (Terminende), abgesagt und abgelehnt = updatedAt (letzte
|
||||
* Aenderung, also der Zeitpunkt der Absage; endgueltige Status werden danach nicht mehr geaendert). Die Frist je
|
||||
* Funktion (aufbewahrungTage) wendet der Aufrufer auf das Ergebnis an. Andere Status: TypeError.
|
||||
* Buchungen eines Status, deren Bezugszeit vor `vor` liegt (die Frist steht in der Abfrage, nie nachtraeglich im Code):
|
||||
* hoechstens `limit` (Standard 100, eine Seite), die mit der aeltesten Bezugszeit zuerst. Bezugszeit je Status: verfallen =
|
||||
* heldUntil, erledigt und nichterschienen = endsAt (Terminende), abgesagt und abgelehnt = updatedAt (letzte Aenderung, also
|
||||
* der Zeitpunkt der Absage; endgueltige Status werden danach nicht mehr geaendert). Mit featureId nur diese Funktion, sonst alle.
|
||||
* Ohne Cursor: wer loescht, liest die Liste danach neu (Geloeschtes fehlt). Die Treffer tragen nur $id, featureId, status,
|
||||
* endsAt, updatedAt und heldUntil, nie Gastfelder (Name, Adresse). Die Frist je Funktion (aufbewahrungTage) wendet der
|
||||
* Aufrufer auf das Ergebnis an. Andere Status: TypeError.
|
||||
*/
|
||||
export async function loeschKandidaten(status, vor) {
|
||||
export async function loeschKandidaten(status, vor, { featureId = null, limit = LOESCH_SEITE } = {}) {
|
||||
if (!Object.hasOwn(LOESCH_BEZUG, status)) throw new TypeError(`loeschKandidaten: Status ${status} wird nicht automatisch geloescht`)
|
||||
return listAllDocuments(col(), [Query.equal('status', status), Query.lessThan(LOESCH_BEZUG[status], iso(vor))])
|
||||
if (!Number.isInteger(limit) || limit < 1) throw new TypeError(`loeschKandidaten: limit muss eine ganze Zahl ab 1 sein, nicht ${limit}`)
|
||||
const bezug = LOESCH_BEZUG[status]
|
||||
return listDocuments(col(), [
|
||||
Query.equal('status', status),
|
||||
Query.lessThan(bezug, iso(vor)),
|
||||
...(featureId === null ? [] : [Query.equal('featureId', featureId)]),
|
||||
Query.orderAsc(bezug),
|
||||
Query.limit(limit),
|
||||
Query.select(LOESCH_FELDER),
|
||||
])
|
||||
}
|
||||
|
||||
/** Feld der Bezugszeit einer Loeschfrist (siehe loeschKandidaten); undefined fuer Status, die nicht automatisch geloescht werden. */
|
||||
export const loeschBezugsfeld = (status) => (Object.hasOwn(LOESCH_BEZUG, status) ? LOESCH_BEZUG[status] : undefined)
|
||||
|
||||
/** Zahl der offenen Anfragen (Status angefragt) einer Funktion. */
|
||||
export async function zaehleAnfragen(featureId) {
|
||||
return (await listAllDocuments(col(), [Query.equal('featureId', featureId), Query.equal('status', 'angefragt')])).length
|
||||
|
||||
Reference in new issue
Block a user