Buchungskalender: Mails an Gäste, Vermieter und Team

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
knsoandClaude Opus 5.5 committed 2026-10-07 14:12:47 +00:00
1 parent 118be44847
commit e15486263f
18 files changed
+1095 -6

No files matched your search

+37
View File
@@ -3,6 +3,8 @@ import { Query, countDocuments, createDocument, deleteDocument, getDocument, kei
import { withLocks } from '../keyedLock.js'
import { sendGuestMail } from '../mailer.js'
import { renderMail } from '../mailTemplates.js'
import { ladeRechnung } from '../unterkunft/speicher.js'
import { rechnungPdf } from '../unterkunft/rechnungPdf.js'
import { pruefeNow, pruefeText, zeitMs } from './util.js'
/**
@@ -286,6 +288,7 @@ async function sende(id, now) {
if (!platz) return 'wartet'
try {
const attachments = await baueAnhaenge(doc)
await sendGuestMail({
to: doc.an,
fromName: doc.fromName,
@@ -295,6 +298,7 @@ async function sende(id, now) {
text: doc.text,
ics: doc.ics || null,
icsMethod: doc.icsMethod || 'REQUEST',
...(attachments.length ? { attachments } : {}),
})
} catch (err) {
gibPlatzFrei(platz)
@@ -305,6 +309,39 @@ async function sende(id, now) {
})
}
/** Nach so vielen Fehlschlaegen beim Erzeugen des Anhangs geht die Mail ohne ihn raus (Buchungskalender). */
const ANHANG_VERSUCHE = 3
/**
* Anhaenge des Eintrags. Das Feld `anhang` ist JSON {art:'ukRechnung', rechnungId}: die Rechnung (ukRechnungen) wird als PDF
* gerendert (Rechnung-<nr>.pdf bzw. Stornorechnung-<nr>.pdf). Ohne `anhang` oder mit anderem Inhalt: keine Anhaenge. Scheitert das
* Laden oder Rendern, wirft die Funktion einen gewoehnlichen Fehler (der Eintrag bleibt `wartet` und wird wie jeder vorlaeufige
* Fehler wiederholt); ab dem vierten Versuch geht die Mail ohne Anhang raus. Der Fehlertext enthaelt keine Personendaten.
*/
async function baueAnhaenge(doc) {
if (!doc.anhang) return []
let verweis
try {
verweis = JSON.parse(doc.anhang)
} catch {
return []
}
if (verweis?.art !== 'ukRechnung' || typeof verweis.rechnungId !== 'string' || !verweis.rechnungId) return []
try {
const rechnung = await ladeRechnung(verweis.rechnungId)
if (!rechnung?.inhalt) throw new Error('Rechnung nicht lesbar')
const storno = rechnung.art === 'storno'
const pdf = rechnungPdf(rechnung.inhalt, { art: rechnung.art, nummer: rechnung.nummer, datum: rechnung.datum })
return [{ filename: `${storno ? 'Stornorechnung' : 'Rechnung'}-${rechnung.nummer}.pdf`, content: Buffer.from(pdf), contentType: 'application/pdf' }]
} catch (err) {
if ((Number(doc.versuche) || 0) >= ANHANG_VERSUCHE) {
console.error(`[termine-outbox] Eintrag ${doc.$id}: Rechnungs-PDF nicht erzeugt, Mail geht ohne Anhang raus (${String(err?.message).slice(0, 80)})`)
return []
}
throw new Error(`Anhang nicht erzeugt: ${String(err?.message).slice(0, 80)}`)
}
}
/**
* Ist der Bestaetigungslink dieser G01 schon verfallen? Das Halte-Fenster (config.termine.holdMinutes, bei jedem Aufruf
* gelesen) plus eine Minute Toleranz ab Einreihen; genau so alt ist noch nicht veraltet. G01 ohne Buchung (zu_viele) hat