TP2 Abschlussprüfung: Löschung (IP/Browser auf portalFeatures, Erstattungsspur, K22-Datum)

- markOrdered speichert IP und Browser der Bestellung nicht mehr am Funktionsdokument (nur im Nachweis featureConsents, dort mit
  Löschfrist); Altwerte werden bei einer neuen Bestellung geleert
- Aufbewahrungslauf (retention): consentIp, consentUserAgent, consentText, consentAt werden an allen Funktionsdokumenten eines fälligen
  Kunden geleert, auch an abgeschalteten; Fehlschlag hält den Kunden wie die übrigen abhängigen Daten
- Einmal-Skript scripts/feature-consent-felder-leeren.mjs (Standard Probelauf, --apply leert nur, wo featureConsents die Angabe trägt)
- 30-Tage-Reset (jobs.js): auch eine bezahlte Einrichtung mit Grund abo_ende_vor_einrichtung und noch nicht gemeldetem T19 wird nicht
  zurückgesetzt, solange zahlungMeldung nicht gemeldet ist (die Spur der Erstattung bleibt)
- K22: enddatum ist das Abo-Ende (lage.endedAt), sonst der Tag des Abschaltens; loeschdatum bleibt 30 Tage nach dem Abschalten

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-05 06:26:33 +00:00
1 parent b974b3a3ec
commit 2fc48df915
13 files changed
+425 -22

No files matched your search

+8 -3
View File
@@ -81,7 +81,7 @@ const istBewertet = (doc) =>
* Schritt 2b: bezahlte, wegen des Abo-Endes vor der Einrichtung abgeschaltete Einrichtung, deren Erstattung (T19) noch nicht beim Team ist.
* Das Abo spielt keine Rolle: die Erstattung bleibt geschuldet, auch wenn es zurueckkommt.
*/
const istErstattungOffen = (doc) =>
export const istErstattungOffen = (doc) =>
doc.state === 'disabled' && doc.disabledReason === GRUND_VOR && doc.unlockedByPurchase === true && doc.zahlungMeldung !== 'gemeldet'
/** Schritt 3: abgeschaltet wegen des Abo-Endes (nur 'abo_ende', nicht 'abo_ende_vor_einrichtung'). */
@@ -93,7 +93,8 @@ const portalFeatures = () => config.collections.portalFeatures
* Der gemeinsame Melder fuer das Ende des Terminplaners (Schritt 2, Schritt 1b und der Sofortpfad E9 rufen nur ihn, nie T19 oder
* K22 einzeln). Reihenfolge: (T19,) K22 an die E-Mail des Kundenkontos, danach der Marker aboEndeMailAt = now.
* - Grund 'abo_ende': K22 mit Block `abo_ende` (Wartungs-Abo beendet) bzw. `hosting` (lage.art 'hosting' oder 'wechsel_widerrufen':
* das Abo ist ein Hosting-Abo), dazu der Kasten `daten`. enddatum = Berliner Tag von disabledAt, loeschdatum = 30 Tage danach.
* das Abo ist ein Hosting-Abo), dazu der Kasten `daten`. enddatum = Berliner Tag des Abo-Endes (lage.endedAt), sonst von disabledAt;
* loeschdatum = 30 Tage nach disabledAt.
* - Grund 'abo_ende_vor_einrichtung': ein unbezahltes Dokument (unlockedByPurchase nicht true, die Bestellung wartet noch auf die
* Zahlung) hat nichts zu erstatten: weder T19 noch K22 noch Marker, kein Schreibzugriff (kommt die Zahlung spaeter, meldet
* siteFeatures das als T19 und der Abgleich sendet dann K22). Ein bezahltes Dokument meldet ZUERST die Erstattung an das Team
@@ -136,6 +137,10 @@ export async function meldeAboEnde(doc, { lage = null, now, onGesendet = null })
}
const projekt = (await projectName(doc.projectId)) || 'Dein Projekt'
const beginn = new Date(Number.isFinite(zeitMs(doc.disabledAt)) ? zeitMs(doc.disabledAt) : nowMs) // disabledAt fehlt nie, ausser bei Altdaten
// enddatum ist der Tag des Abo-Endes (lage.endedAt: endedAt || canceledAt des Abos), wenn bekannt - das Abschalten kann Tage danach liegen;
// sonst (Sofortpfad, Nachlauf ohne Abo-Lesen, kein lesbares Datum) der Tag des Abschaltens. loeschdatum bleibt 30 Tage nach dem Abschalten.
const aboEnde = zeitMs(lage?.endedAt)
const ende = Number.isFinite(aboEnde) ? new Date(aboEnde) : beginn
const grundBlock = vorEinrichtung
? { vor_einrichtung: true }
: { [lage?.art === 'hosting' || lage?.art === 'wechsel_widerrufen' ? 'hosting' : 'abo_ende']: true, daten: true }
@@ -144,7 +149,7 @@ export async function meldeAboEnde(doc, { lage = null, now, onGesendet = null })
values: {
kunde_name: customer.name || '',
projekt,
enddatum: datumKurz(beginn),
enddatum: datumKurz(ende),
loeschdatum: datumKurz(loeschzeit(beginn)),
preis: config.features.termine.priceLabel,
portal_url: `${config.publicBaseUrl}/dashboard.html#termine`,