Buchungskalender: Mails an Gäste, Vermieter und Team
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
118be44847
commit
e15486263f
18 files changed
+1095
-6
No files matched your search
@@ -10,7 +10,7 @@ import { TERMINE_DATETIMES } from '../server/services/termine/schema.js'
|
||||
// Produktion. Der Mailtransport ist ein Fake, der Sendeversuche zaehlt und gezielt Fehler wirft (nodemailer-Fehler
|
||||
// tragen `code` und SMTP-`responseCode`). Alle Zeiten sind feste Parameter.
|
||||
const aw = await startAppwriteMock({
|
||||
schema: { termineOutbox: schemaKeys('termineOutbox') },
|
||||
schema: { termineOutbox: schemaKeys('termineOutbox'), ukRechnungen: schemaKeys('ukRechnungen') },
|
||||
datetimes: TERMINE_DATETIMES,
|
||||
defaultLimit: 25,
|
||||
})
|
||||
@@ -1290,3 +1290,39 @@ test('einreihen: optionaler Anhang-Verweis wird gespeichert (Senden unverändert
|
||||
const attribut = (await import('../server/services/termine/schema.js')).TERMINE_COLLECTIONS.termineOutbox.attributes.find((a) => a.key === 'anhang')
|
||||
assert.deepEqual(attribut, { key: 'anhang', type: 'string', size: 500, required: false })
|
||||
})
|
||||
|
||||
// Buchungskalender (Task 20): anhang {art:'ukRechnung', rechnungId} -> Rechnungs-PDF als Anhang
|
||||
const RE_INHALT = { aussteller: { firma: 'Haus' }, empfaenger: { name: 'Eva' }, unterkunft: { name: 'Wohnung' }, von: '2026-11-12', bis: '2026-11-14', naechte: 2, personen: 2, posten: [{ text: 'Übernachtung', menge: 2, einzelCent: 10000, ustProzent: 0 }], summen: { bruttoCent: 20000, nettoCent: 20000, ust: [] }, steuerart: 'kleinunternehmer' }
|
||||
const seedRechnung = (extra = {}) => aw.seed('ukRechnungen', { $id: 'r1', featureId: 'f_feature01', anfrageId: 'a1', art: 'rechnung', nummer: 'RE-2026-0001', datum: '2026-11-01', bruttoCent: 20000, inhalt: JSON.stringify(RE_INHALT), ...extra })
|
||||
|
||||
test('Anhang ukRechnung: gesendete Mail hat Rechnung-<nr>.pdf (beginnt mit %PDF); Stornorechnung heißt Stornorechnung-<nr>.pdf', async () => {
|
||||
seedRechnung()
|
||||
seedRechnung({ $id: 'r2', art: 'storno', nummer: 'RE-2026-0002' })
|
||||
await einreihen(eintrag({ bookingId: 'b_re', anhang: JSON.stringify({ art: 'ukRechnung', rechnungId: 'r1' }) }), JETZT)
|
||||
await einreihen(eintrag({ bookingId: 'b_st', anhang: JSON.stringify({ art: 'ukRechnung', rechnungId: 'r2' }) }), JETZT)
|
||||
await einreihen(eintrag({ bookingId: 'b_ohne' }), JETZT)
|
||||
await warteAufVersand()
|
||||
const namen = tr.senke.sent.map((m) => (m.attachments ?? []).map((a) => a.filename))
|
||||
assert.deepEqual(namen.map((n) => n.join()).sort(), ['', 'Rechnung-RE-2026-0001.pdf', 'Stornorechnung-RE-2026-0002.pdf'])
|
||||
const mit = tr.senke.sent.find((m) => m.attachments?.length)
|
||||
assert.equal(Buffer.from(mit.attachments[0].content, 'base64').subarray(0, 4).toString(), '%PDF')
|
||||
assert.equal(mit.attachments[0].contentType, 'application/pdf')
|
||||
})
|
||||
|
||||
test('Anhang nicht erzeugbar: Eintrag bleibt wartet (Wiederholung), nach 3 Fehlversuchen geht die Mail ohne Anhang raus', async () => {
|
||||
const doc = await einreihen(eintrag({ bookingId: 'b_fehlt', art: 'uk-G19', anhang: JSON.stringify({ art: 'ukRechnung', rechnungId: 'gibtsnicht' }) }), JETZT)
|
||||
await warteAufVersand()
|
||||
let d = await lies(doc.$id)
|
||||
assert.equal(d.status, 'wartet')
|
||||
assert.equal(d.versuche, 1)
|
||||
assert.equal(tr.aufrufe, 0)
|
||||
let jetzt = JETZT
|
||||
for (const warte of [2 * MIN, 6 * MIN, 31 * MIN]) {
|
||||
jetzt = plus(warte, jetzt)
|
||||
await sendeEintrag(doc.$id, jetzt)
|
||||
}
|
||||
d = await lies(doc.$id)
|
||||
assert.equal(d.status, 'gesendet')
|
||||
assert.equal(tr.senke.sent.length, 1)
|
||||
assert.equal(tr.senke.sent[0].attachments?.length ?? 0, 0)
|
||||
})
|
||||
Reference in new issue
Block a user