56 lines
2.8 KiB
JavaScript
56 lines
2.8 KiB
JavaScript
/**
|
|
* Bestätigen 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 { withLocks } from '../keyedLock.js'
|
|
import { getAuftrag, updateAuftrag } from './auftragStore.js'
|
|
import { AuftragError } from './fehler.js'
|
|
import { sperreAuftrag } from './konstanten.js'
|
|
import { sendeBestaetigtMails } from './mails.js'
|
|
import { FRUEHBEGINN_FASSUNG } from './texte.js'
|
|
|
|
export const GESPERRT_MELDUNG = {
|
|
ersetzt: 'Diese Auftragsbestätigung wurde ersetzt.',
|
|
storniert: 'Diese Auftragsbestätigung wurde storniert.',
|
|
widerrufen: 'Diese Auftragsbestätigung wurde widerrufen.',
|
|
}
|
|
const NICHT_BESTAETIGBAR = 'Diese Auftragsbestätigung kann nicht bestätigt werden.'
|
|
const NICHT_GEFUNDEN = 'Auftragsbestätigung nicht gefunden.'
|
|
const GESPERRT_STATUS = ['entwurf', 'ersetzt', 'storniert', 'widerrufen']
|
|
|
|
/** 'offen' (bestätigbar), 'bestaetigt' (schon bestätigt) oder 'gesperrt' (Entwurf, ersetzt, storniert, widerrufen). */
|
|
export function bestaetigungsLage(auftrag) {
|
|
if (GESPERRT_STATUS.includes(auftrag.status)) return 'gesperrt'
|
|
return auftrag.bestaetigtAm || auftrag.status === 'bestaetigt' ? 'bestaetigt' : 'offen'
|
|
}
|
|
|
|
function pruefeZeitpunkt(jetzt) {
|
|
if (!(jetzt instanceof Date) || Number.isNaN(jetzt.getTime())) throw new TypeError('jetzt muss ein gültiges Date sein')
|
|
}
|
|
|
|
export async function bestaetigeAuftrag(auftrag, { ueber, fruehbeginn, jetzt = new Date() } = {}) {
|
|
// synchron vor der Sperre: der zuerst gestartete Aufruf bekommt die Sperre zuerst
|
|
if (ueber !== 'link' && ueber !== 'portal') throw new TypeError('bestaetigeAuftrag: ueber muss „link“ oder „portal“ sein')
|
|
pruefeZeitpunkt(jetzt)
|
|
const { aktuell, bestaetigtJetzt } = await withLocks(sperreAuftrag(auftrag.id), async () => {
|
|
const frisch = await getAuftrag(auftrag.id)
|
|
if (!frisch) throw new AuftragError(404, NICHT_GEFUNDEN)
|
|
const lage = bestaetigungsLage(frisch)
|
|
if (lage === 'gesperrt') throw new AuftragError(409, GESPERRT_MELDUNG[frisch.status] ?? NICHT_BESTAETIGBAR)
|
|
if (lage === 'bestaetigt') return { aktuell: frisch, bestaetigtJetzt: false }
|
|
const privat = frisch.kunde?.kundenart === 'privat'
|
|
const patch = {
|
|
bestaetigtAm: jetzt.toISOString(),
|
|
bestaetigtUeber: ueber,
|
|
bestaetigtPdfSha256: frisch.pdfSha256,
|
|
fruehbeginn: privat && fruehbeginn === true,
|
|
fruehbeginnFassung: privat ? FRUEHBEGINN_FASSUNG : '',
|
|
}
|
|
if (frisch.status === 'versendet') patch.status = 'bestaetigt'
|
|
return { aktuell: await updateAuftrag(frisch.id, patch), bestaetigtJetzt: true }
|
|
})
|
|
if (bestaetigtJetzt) await sendeBestaetigtMails(aktuell)
|
|
return aktuell
|
|
}
|