AB-Kern: Erinnerung mit neuem Token und geprüfter PDF-Datei
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c74f7eeea7
commit
0da5b30119
2 files changed
+158
-1
No files matched your search
@@ -5,12 +5,13 @@
|
||||
* über `deps` (L4/L5, Standard: dynamischer Import beim Aufruf). Jede Änderung an einer bestehenden AB läuft unter
|
||||
* sperreAuftrag(id) (konstanten.js), das Senden zusätzlich unter SPERRE_NUMMER; Mails gehen immer erst nach der Sperre.
|
||||
*/
|
||||
import { createHash } from 'node:crypto'
|
||||
import { config } from '../../config.js'
|
||||
import { getDocument, listDocuments, Query, updateDocument } from '../appwriteAdmin.js'
|
||||
import { getSettings } from '../finance/settings.js'
|
||||
import { withLocks } from '../keyedLock.js'
|
||||
import { kundeSnapshot } from './auftragSicht.js'
|
||||
import { entfernePdf, speicherePdf } from './ablage.js'
|
||||
import { entfernePdf, lesePdf, speicherePdf } from './ablage.js'
|
||||
import { createAuftrag, deleteAuftrag, getAuftrag, updateAuftrag } from './auftragStore.js'
|
||||
import { AuftragError } from './fehler.js'
|
||||
import { vergibNummer } from './nummern.js'
|
||||
@@ -444,3 +445,38 @@ export async function sendeAuftrag(id, { von, deps, jetzt = new Date() } = {}) {
|
||||
})
|
||||
return versendeMail(d, gespeichert, { pdf, token })
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// Erinnern („Erinnerung senden“ und „Erneut senden“)
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/** Liest die gespeicherte PDF und prüft die SHA-256-Summe: eine veränderte Datei wird nie verschickt oder angezeigt. */
|
||||
export async function ladeGespeichertesPdf(auftrag) {
|
||||
if (!hatText(auftrag.pdfDatei)) throw new AuftragError(404, 'PDF nicht gefunden.')
|
||||
const buffer = await lesePdf(auftrag.pdfDatei)
|
||||
if (createHash('sha256').update(buffer).digest('hex') !== auftrag.pdfSha256) {
|
||||
console.error('[auftraege] Prüfsumme der gespeicherten PDF stimmt nicht:', auftrag.id)
|
||||
throw new AuftragError(500, 'Die gespeicherte PDF-Datei stimmt nicht mit der Prüfsumme überein.')
|
||||
}
|
||||
return buffer
|
||||
}
|
||||
|
||||
/**
|
||||
* Neuer Bestätigungslink für eine versendete AB (der alte gilt ab dann nicht mehr) und erneute Mail mit der gespeicherten
|
||||
* PDF. Nach einem Mail-Fehler ist es eine gewöhnliche Mail ohne Erinnerungs-Hinweis; gesendetAn wird die aktuelle Adresse.
|
||||
*/
|
||||
export async function erinnereAuftrag(id, { deps, jetzt = new Date() } = {}) {
|
||||
const d = await ladeDeps(deps, ['neuerToken', 'sendeAuftragMail'])
|
||||
const { gespeichert, pdf, token, erinnerung } = await withLocks(sperreAuftrag(id), async () => {
|
||||
const alt = await ladeAuftrag(id)
|
||||
if (alt.status !== 'versendet') throw new AuftragError(409, 'Eine Erinnerung gibt es nur für versendete Auftragsbestätigungen.')
|
||||
const kundeDoc = await ladeKunde(alt.kundenId)
|
||||
if (!hatText(kundeDoc.email)) throw new AuftragError(400, 'Für den Versand fehlt die E-Mail-Adresse des Kunden.')
|
||||
// vor dem Token-Tausch: eine beschädigte Datei darf den alten Link nicht entwerten
|
||||
const pdfBytes = await ladeGespeichertesPdf(alt)
|
||||
const neu = d.neuerToken(jetzt)
|
||||
const dokument = await updateAuftrag(id, { tokenHash: neu.hash, tokenGueltigBis: neu.gueltigBis.toISOString(), gesendetAn: kundeDoc.email.trim() })
|
||||
return { gespeichert: dokument, pdf: pdfBytes, token: neu.token, erinnerung: alt.mailStatus !== 'fehler' }
|
||||
})
|
||||
return versendeMail(d, gespeichert, { pdf, token, erinnerung })
|
||||
}
|
||||
Reference in new issue
Block a user