diff --git a/docs/superpowers/specs/2026-10-02-terminplaner-design.md b/docs/superpowers/specs/2026-10-02-terminplaner-design.md index a775fe0..eba5d56 100644 --- a/docs/superpowers/specs/2026-10-02-terminplaner-design.md +++ b/docs/superpowers/specs/2026-10-02-terminplaner-design.md @@ -303,7 +303,7 @@ sinngemäß: „Bitte bestätige deinen Termin …“). G01 und G08 enthalten ke | G01 | Gast | Bitte bestätigen Sie Ihren Termin bei {betrieb} | Datum, Uhrzeit, Leistung, Knopf „Termin bestätigen“, „Das waren Sie nicht? Dann ignorieren Sie diese E-Mail.“ Nichts Werbliches. | | G02 | Gast | Ihr Termin bei {betrieb} am {datum} | Zusammenfassung, Buchungsnummer, Zahlungsart, Stornoregel (Wortlaut), Verwaltungslink, .ics (REQUEST); bei Widerrufsrecht: Widerrufsbelehrung + Muster-Widerrufsformular + Hinweis auf die Widerrufsfunktion (§ 312f Abs. 2 BGB): Bis zum Beginn des Termins über den Knopf „Vertrag widerrufen“, danach über das Formular auf der Website des Betriebs oder per E-Mail an den Betrieb | | G03 | Gast | Ihre Terminanfrage bei {betrieb} | „Der Betrieb meldet sich“, Verwaltungslink (Absage und Verschieben, R26) | -| G04 | Gast | Ihre Terminanfrage bei {betrieb} | abgelehnt, optionale Nachricht des Betriebs | +| G04 | Gast | Ihre Terminanfrage bei {betrieb} – leider abgelehnt | abgelehnt, optionale Nachricht des Betriebs | | G05 | Gast | Erinnerung: Ihr Termin am {datum} um {zeit} | Termin, Verwaltungslink; sonst nichts | | G06 | Gast | Ihr Termin am {datum} wurde abgesagt | wer abgesagt hat, Grund/Nachricht, .ics (CANCEL) | | G07 | Gast | Ihr Termin wurde verschoben | alte/neue Zeit, .ics (REQUEST, Sequenz + 1) | diff --git a/server/services/termine/mails.js b/server/services/termine/mails.js index 835f4dc..b09d939 100644 --- a/server/services/termine/mails.js +++ b/server/services/termine/mails.js @@ -72,7 +72,7 @@ export const BETREFFE = einfrieren({ }, G02: { sie: { standard: 'Ihr Termin bei {betrieb} am {datum}' }, du: { standard: 'Dein Termin bei {betrieb} am {datum}' } }, G03: { sie: { standard: 'Ihre Terminanfrage bei {betrieb}' }, du: { standard: 'Deine Terminanfrage bei {betrieb}' } }, - G04: { sie: { standard: 'Ihre Terminanfrage bei {betrieb}' }, du: { standard: 'Deine Terminanfrage bei {betrieb}' } }, + G04: { sie: { standard: 'Ihre Terminanfrage bei {betrieb} – leider abgelehnt' }, du: { standard: 'Deine Terminanfrage bei {betrieb} – leider abgelehnt' } }, G05: { sie: { standard: 'Erinnerung: Ihr Termin am {datum} um {zeit}' }, du: { standard: 'Erinnerung: Dein Termin am {datum} um {zeit}' }, diff --git a/test/termineAblaufBetrieb.test.js b/test/termineAblaufBetrieb.test.js index f0b88b3..ae93de4 100644 --- a/test/termineAblaufBetrieb.test.js +++ b/test/termineAblaufBetrieb.test.js @@ -294,7 +294,7 @@ test('ablehnen: abgelehnt, Zellen frei, G04 mit der Nachricht des Betriebs; die const neu = sink.sent.slice(vorher) assert.equal(neu.length, 1) assert.equal(neu[0].to[0].address, 'max@example.com') - assert.equal(neu[0].subject, 'Ihre Terminanfrage bei Salon Müller') + assert.equal(neu[0].subject, 'Ihre Terminanfrage bei Salon Müller – leider abgelehnt') assert.match(neu[0].text, /leider kann Salon Müller Ihre Terminanfrage nicht annehmen/) assert.match(neu[0].text, /Am Montag sind wir im Urlaub\./) assert.equal('icalEvent' in neu[0], false) diff --git a/test/termineKontext.test.js b/test/termineKontext.test.js index d3136b5..3b75bca 100644 --- a/test/termineKontext.test.js +++ b/test/termineKontext.test.js @@ -611,7 +611,7 @@ test('BETREFFE: jede Gastvorlage hat Sie- und Du-Fassung, K20/K21 die Du-Fassung assert.throws(() => (BETREFFE.G01.sie.bestaetigen = 'x'), TypeError, 'Tabelle ist eingefroren') }) -test('Betreff je Anrede: Sie-Form und Du-Form (G01, G02, G05)', () => { +test('Betreff je Anrede: Sie-Form und Du-Form (G01, G02, G03/G04, G05)', () => { const sie = ctxMit() const du = ctxMit({ anrede: 'du' }) const betreff = (art, ctx, b, extra = {}) => werteFuer(art, ctx, b, extra).values.betreff @@ -622,6 +622,11 @@ test('Betreff je Anrede: Sie-Form und Du-Form (G01, G02, G05)', () => { assert.equal(betreff('G05', sie, buchung()), 'Erinnerung: Ihr Termin am 12.10.2026 um 10:00') assert.equal(betreff('G05', du, buchung()), 'Erinnerung: Dein Termin am 12.10.2026 um 10:00') assert.equal(betreff('G06', du, buchung(), { von: 'gast' }), 'Dein Termin am 12.10.2026 wurde abgesagt') + // Eingang (G03) und Ablehnung (G04) einer Anfrage sind schon am Betreff zu unterscheiden + assert.equal(betreff('G03', sie, buchung()), 'Ihre Terminanfrage bei Salon Müller') + assert.equal(betreff('G04', sie, buchung({ status: 'abgelehnt' })), 'Ihre Terminanfrage bei Salon Müller – leider abgelehnt') + assert.equal(betreff('G04', du, buchung({ status: 'abgelehnt' })), 'Deine Terminanfrage bei Salon Müller – leider abgelehnt') + assert.notEqual(betreff('G03', sie, buchung()), betreff('G04', sie, buchung({ status: 'abgelehnt' }))) assert.equal(betreff('G08', du, buchung(), { fall: 'zugeordnet', eingang: EINGANG }), 'Eingangsbestätigung deines Widerrufs') for (const [art, b, extra] of FAELLE.filter(([a]) => a.startsWith('G'))) { assert.doesNotMatch(betreff(art, du, b, extra), /\b(Sie|Ihr\w*)\b/, `${art} Du`)