Aufträge L5: Auftrag widerrufen (nur Privatpersonen innerhalb der Frist, unter Sperre)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-07 14:14:22 +00:00
1 parent 335ac60e54
commit 576a17bfa4
2 files changed
+107 -2

No files matched your search

+22 -1
View File
@@ -1,8 +1,9 @@
/**
* Bestätigen einer Auftragsbestätigung (Übersicht V2/V4, Strang L5): idempotent, unter der Sperre `sperreAuftrag(id)`,
* Bestätigen und Widerrufen einer Auftragsbestätigung (Übersicht V2/V4, Strang L5): idempotent, unter der Sperre `sperreAuftrag(id)`,
* Stand innerhalb der Sperre neu gelesen. K32 und T22 gehen erst nach der Freigabe der Sperre raus; Mailfehler stehen
* nur im Protokoll. Die erste Bestätigung zählt, jede weitere ändert nichts.
*/
import { withdrawalDeadline } from '../deadlines.js'
import { withLocks } from '../keyedLock.js'
import { getAuftrag, updateAuftrag } from './auftragStore.js'
import { AuftragError } from './fehler.js'
@@ -53,3 +54,23 @@ export async function bestaetigeAuftrag(auftrag, { ueber, fruehbeginn, jetzt = n
if (bestaetigtJetzt) await sendeBestaetigtMails(aktuell)
return aktuell
}
/**
* Widerruf einer Privatperson innerhalb der Frist (V2: versendet|bestaetigt → widerrufen), unter derselben Sperre.
* Verschickt selbst keine Mails (das tut abo.js nach der Rückkehr, also nach der Freigabe der Sperre).
* Ergebnis: 'widerrufen' | 'bereits_widerrufen' | 'kein_widerrufsrecht' | 'nach_frist' | 'nicht_widerrufbar'.
*/
export async function widerrufeAuftrag(auftrag, { jetzt = new Date() } = {}) {
pruefeZeitpunkt(jetzt)
return withLocks(sperreAuftrag(auftrag.id), async () => {
const frisch = await getAuftrag(auftrag.id)
if (!frisch) throw new AuftragError(404, NICHT_GEFUNDEN)
const fristEnde = frisch.gesendetAm ? withdrawalDeadline(new Date(frisch.gesendetAm)).endsAt : null
const ergebnis = (e, a = frisch) => ({ auftrag: a, ergebnis: e, fristEnde })
if (frisch.status === 'widerrufen') return ergebnis('bereits_widerrufen')
if (frisch.kunde?.kundenart !== 'privat') return ergebnis('kein_widerrufsrecht')
if (!['versendet', 'bestaetigt'].includes(frisch.status) || fristEnde === null) return ergebnis('nicht_widerrufbar')
if (jetzt.getTime() > fristEnde.getTime()) return ergebnis('nach_frist')
return ergebnis('widerrufen', await updateAuftrag(frisch.id, { status: 'widerrufen', widerrufenAm: jetzt.toISOString() }))
})
}