Zahlungseingang in jedem Zustand: nie Geld ohne Spur, nie doppelt (T16/T19)

onFeaturePaid wertet den Fall aus markPaid aus. Trifft die Zahlung eine Funktion, die
schon freigeschaltet, in Einrichtung oder abgeschaltet ist, geht nur eine Team-Meldung
raus (T16 Block bereits_aktiv, bei Abo-Ende vor der Einrichtung T19), kein Ticket und
keine K15. Beide Meldungen laufen genau einmal je Dokument: unter feature-meldung:<id>
frisch lesen, Marker zahlungMeldung gemeldet erst nach gesendeter Mail. Scheitert der
Versand, wirft onFeaturePaid (Webhook 500), Stripe wiederholt und der naechste Versuch
sendet genau einmal.

meldeErstattung ist die einzige Stelle fuer T19 (Zahlung nach dem Abo-Ende und spaeter
die Meldung des Abo-Abgleichs), wirft nie. Bei Funktionen mit Wartungs-Abo-Pflicht
zeigt T16 nach der Verbuchung den Block kein_abo, wenn das Abo nicht mehr laeuft; ein
Lesefehler laesst den Block aus und blockiert nichts. customerOf und projectName sind
exportiert.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 13:25:26 +00:00
1 parent 468df49812
commit f4754f573a
3 files changed
+817 -11

No files matched your search

+3 -1
View File
@@ -353,6 +353,8 @@ test('Termine-Mails: K16 mit den Werten des Terminplaners', () => {
// -------------------------------------------------------------------- T16 je Funktion (Team-Hinweis) ---
test('Termine-T16: Betreff, Text und Knopf nennen den Terminplaner', async () => {
// c1 hat ein laufendes Wartungs-Abo: ohne es meldet T16 den Block kein_abo (Task B10b, test/featurePaid.test.js)
aw.seed('subscriptions', { $id: 'sub_w_mails', stripeSubscriptionId: 'sub_w_mails', customerId: 'c1', productKey: 'wartung', status: 'active' })
const { mail, projectId, woid, doc } = await t16Bezahlt('termine', 'Salon Haarlinie')
assert.equal(mail.subject, 'Neue Funktion bestellt: Terminplaner')
for (const teil of [mail.subject, mail.text, mail.html]) assert.doesNotMatch(teil, /News|Beitr/)
@@ -363,7 +365,7 @@ test('Termine-T16: Betreff, Text und Knopf nennen den Terminplaner', async () =>
assert.equal(link, reg.anleitungsLink('c1', projectId))
assert.ok(mail.text.includes(`Im Ticketsystem öffnen: ${link}`), mail.text)
assert.ok(mail.html.includes(`href="${link.replaceAll('&', '&amp;')}"`), mail.html)
// die Warnblöcke bleiben aus, solange B10a/D4 sie nicht füllen
// die Warnblöcke bleiben bei einem ordentlich bezahlten Kauf aus (kein_abo nur ohne laufendes Abo, bereits_aktiv nur bei einer Zahlung auf ein vorhandenes Dokument: featurePaid.test.js; gesundheit füllt D4)
for (const warnung of ['Zahlung fehlgeschlagen', 'Bezahlt, aber nicht zuzuordnen', 'Kein laufendes Wartungs-Abo', 'Gesundheitsbereich prüfen', 'Bezahlt, aber schon vorhanden']) {
assert.ok(!mail.text.includes(warnung), `kein Block "${warnung}"`)
}