Kundenansicht neu E-Fix F5: Fassung 6 ohne PDF behauptet keinen Anhang, das Team bekommt den Hinweis

Die PDFs der Fassung 6 entstehen erst nach der Freigabe. Bis dahin gingen K01, K12 und K13 ohne Anhang raus, sagten aber "im Anhang" bzw.
"beigefügt", und das Team erfuhr es nicht (nur K38/T24 hatten dafür den Block anhang_fehlt).

- Neuer Helfer vertragsAnhang.js: lädt das PDF der zugestimmten Fassung und meldet fehlt nur bei Fassung 6 ohne lesbare Datei.
- K01, K12, K13: Block anhang (Anhangsaussagen) und ohne_anhang (Satz, dass die Unterlagen gesondert kommen).
- T02, T12, T13: Block anhang_fehlt "Unterlagen von Hand nachsenden" (T12 auch beim späteren Wirksamwerden, T13 auch ohne Aufgabe).
- Alte Fassungen unverändert: Hash-Pins auf die Wiedergabe der Vorlagen vor der Änderung, Anhang und Texte wie bisher.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 21:38:54 +00:00
1 parent 9c04f806eb
commit 72b5ac5265
12 files changed
+362 -66

No files matched your search

+8 -8
View File
@@ -260,11 +260,11 @@ test('Werte werden HTML-sicher eingesetzt, Zeilenumbrüche werden <br>', () => {
test('optionale Blöcke: nur eingeschaltete erscheinen', () => {
const values = { name: 'Max', produkt: 'Wartungs-Abo', preis: '50,00 € / Monat', angebot_text: 'Erste 2 Monate je 25,00 €', vertragsschluss: '01.10.2026', leistungsbeginn: '15.10.2026', mindestlaufzeit_bis: '15.10.2027', bedingungen_version: 'v3', zustimmung_zeitpunkt: '01.10.2026, 10:00' }
const early = renderMail('K01', values, { angebot: false, sofortbeginn: true, beginn_nach_widerrufsfrist: false })
const early = renderMail('K01', values, { angebot: false, sofortbeginn: true, beginn_nach_widerrufsfrist: false, anhang: true })
assert.doesNotMatch(early.html, /Ihr Angebot:/)
assert.match(early.html, /Sie haben ausdrücklich verlangt/)
assert.doesNotMatch(early.html, /erst nach Ablauf der Widerrufsfrist/)
const late = renderMail('K01', values, { angebot: true, sofortbeginn: false, beginn_nach_widerrufsfrist: true })
const late = renderMail('K01', values, { angebot: true, sofortbeginn: false, beginn_nach_widerrufsfrist: true, anhang: true })
assert.match(late.html, /Ihr Angebot:<\/strong> Erste 2 Monate je 25,00 € \(wie vereinbart\)/)
assert.doesNotMatch(late.html, /Sie haben ausdrücklich verlangt/)
assert.match(late.html, /Leistungsbeginn und erste Abbuchung: 15\.10\.2026\./)
@@ -298,7 +298,7 @@ test('Textfassung K01: alle Vertragsangaben lesbar', () => {
const mail = renderMail(
'K01',
{ name: 'Erika Musterfrau', produkt: 'Wartungs-Abo', preis: '50,00 € / Monat', angebot_text: '', vertragsschluss: '01.10.2026', leistungsbeginn: '01.10.2026', mindestlaufzeit_bis: '01.10.2027', bedingungen_version: '2026-09-25-v3', zustimmung_zeitpunkt: '01.10.2026, 10:07' },
{ sofortbeginn: true, wartung: true }
{ sofortbeginn: true, wartung: true, anhang: true }
)
assert.deepEqual(mail.problems, [])
const t = mail.text
@@ -373,7 +373,7 @@ test('K12: Block zahlung_offen wörtlich, Block lastschrift mit dem Satz aus §
assert.match(sepa.text, /Wird die Lastschrift nicht eingelöst, gilt der Wechsel als nicht erfolgt/)
assert.match(sepa.text, /Ihr Abbuchungstag bleibt der Wechseltag/)
assert.doesNotMatch(sepa.text, /sobald die Zahlung bestätigt ist/)
const plain = renderMail('K12', values, {})
const plain = renderMail('K12', values, { anhang: true }) // Vertragsunterlagen hängen an (F5: ohne PDF der Fassung 6 stattdessen ohne_anhang)
assert.doesNotMatch(plain.text, /sobald die Zahlung bestätigt ist|Wird die Lastschrift nicht eingelöst/)
// Vertragsbestaetigung: Preis mit § 19 UStG, Mindestlaufzeit, Unterlagen, Zustimmung zum Sofortbeginn
for (const text of ['gemäß § 19 UStG ohne Umsatzsteuer', 'Mindestlaufzeit 12 Monate bis Wert-mindestlaufzeit_bis.', 'Widerrufsbelehrung mit Muster-Widerrufsformular']) {
@@ -406,22 +406,22 @@ test('K13, T13: Betreff, Platzhalter und Blöcke des Zusatzspeichers', () => {
assert.deepEqual(loadTemplate('K13').placeholders, ['name', 'pakete', 'gesamt_gb', 'monatspreis_zusatz', 'wirksam_ab'])
// Fix 2 (3): plus = Einrichtung mit anteiliger Berechnung, plus_bezahlt = Plus bis zur schon bezahlten Menge,
// bestellung = Unterlagen und Widerruf (bei beiden), minus = Verringerung zum Periodenende
assert.deepEqual(loadTemplate('K13').blocks, ['plus', 'plus_bezahlt', 'bestellung', 'minus'])
assert.deepEqual(loadTemplate('K13').blocks, ['plus', 'plus_bezahlt', 'bestellung', 'minus', 'anhang', 'ohne_anhang'])
assert.equal(loadTemplate('T13').subject, '[Speicher] {{aktion}}: {{email}}')
for (const p of ['aktion', 'email', 'name', 'stripe_abo_id', 'postfaecher_hinweis', 'neue_groesse_gb', 'pakete', 'faellig']) {
assert.ok(loadTemplate('T13').placeholders.includes(p), p)
}
assert.deepEqual([...loadTemplate('T13').blocks].sort(), ['einrichten', 'nachweis_fehlt', 'periodenende', 'teilweise'])
assert.deepEqual([...loadTemplate('T13').blocks].sort(), ['anhang_fehlt', 'einrichten', 'nachweis_fehlt', 'periodenende', 'teilweise'])
const values = sampleValues(loadTemplate('K13'))
const plus = renderMail('K13', values, { plus: true, bestellung: true })
const plus = renderMail('K13', values, { plus: true, bestellung: true, anhang: true })
assert.deepEqual(plus.problems, [])
assert.match(plus.text, /gemäß § 19 UStG ohne Umsatzsteuer/)
assert.match(plus.text, /wird eingerichtet/)
assert.match(plus.text, /14 Tagen widerrufen/)
assert.match(plus.text, /Vertragsunterlagen im Anhang/)
assert.doesNotMatch(plus.text, /ohne anteilige Erstattung|keine zusätzlichen Kosten/)
const paid = renderMail('K13', values, { plus_bezahlt: true, bestellung: true })
const paid = renderMail('K13', values, { plus_bezahlt: true, bestellung: true, anhang: true })
assert.ok(paid.text.includes('Die Pakete sind für den laufenden Monat schon bezahlt; es entstehen keine zusätzlichen Kosten. Ab dem nächsten Abrechnungsmonat gelten Wert-pakete Pakete.'))
assert.match(paid.text, /14 Tagen widerrufen/)
assert.match(paid.text, /Vertragsunterlagen im Anhang/)