Buchungskalender: Verwaltungs-API – Einstellungen, Zustimmung, Online-Zahlung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d0ab92658a
commit
32cffb3518
5 files changed
+87
-27
No files matched your search
+25
-18
@@ -238,45 +238,53 @@ router.get('/status', route(async (req, res) => {
|
||||
antwort.onlineZahlung = einst?.onlineZahlung === true
|
||||
antwort.unterkuenfte = unterkuenfte.length
|
||||
antwort.rechnungenVorhanden = rechnungen.length > 0
|
||||
for (const u of unterkuenfte) {
|
||||
const p = await sp.ladePreise(u.$id)
|
||||
if (p?.steuerart) {
|
||||
antwort.steuerart = p.steuerart
|
||||
break
|
||||
}
|
||||
}
|
||||
const preise = await Promise.all(unterkuenfte.map((u) => sp.ladePreise(u.$id)))
|
||||
const mitArt = preise.find((p) => p?.steuerart)
|
||||
if (mitArt) antwort.steuerart = mitArt.steuerart
|
||||
res.json(antwort)
|
||||
}))
|
||||
|
||||
// ---- Einstellungen
|
||||
|
||||
function einstellungenAntwort(einst) {
|
||||
async function einstellungenAntwort(ctx, einst) {
|
||||
const e = einst ?? {}
|
||||
const ansicht = Object.fromEntries(vw.EINSTELLUNG_FELDER.map((k) => [k, e[k] ?? '']))
|
||||
ansicht.onlineZahlung = e.onlineZahlung === true
|
||||
ansicht.rechnungsPraefixFrei = vw.zaehlerLeer(e)
|
||||
ansicht.stripe = { status: stripeZustand(e) }
|
||||
return { einstellungen: ansicht, vollstaendig: vw.pruefeEinstellungen({}, e).werte !== undefined }
|
||||
ansicht.rechnungAuftrag = Boolean(e.rechnungAuftragAt)
|
||||
const [shop, rechnungen] = await Promise.all([shopMitKonto(ctx.customerId, ctx.projectId), sp.listeRechnungen(ctx.featureId)])
|
||||
return {
|
||||
einstellungen: ansicht,
|
||||
stripe: { status: stripeZustand(e), vorhandenesShopKonto: Boolean(shop) },
|
||||
rechnungenVorhanden: rechnungen.length > 0,
|
||||
}
|
||||
}
|
||||
|
||||
router.get('/einstellungen', route(async (req, res) => {
|
||||
const ctx = await mitProjekt(req)
|
||||
res.json(einstellungenAntwort(await sp.ladeEinstellungen(ctx.featureId)))
|
||||
res.json(await einstellungenAntwort(ctx, await sp.ladeEinstellungen(ctx.featureId)))
|
||||
}))
|
||||
|
||||
router.put('/einstellungen', ...schreib, route(async (req, res) => {
|
||||
const ctx = await mitProjekt(req, { schreiben: true })
|
||||
const eingabe = body(req).einstellungen && typeof body(req).einstellungen === 'object' ? body(req).einstellungen : body(req)
|
||||
const neu = await withLocks(['uk-einst:' + ctx.featureId], async () => {
|
||||
const neu = await withLocks(['uk-einst:' + ctx.featureId, 'uk-rechnungsnr:' + ctx.featureId], async () => {
|
||||
const vorher = (await sp.ladeEinstellungen(ctx.featureId)) ?? {}
|
||||
const r = vw.pruefeEinstellungen(eingabe, vorher)
|
||||
const { rechnungAuftrag, ...rest } = eingabe
|
||||
if (rechnungAuftrag !== undefined && typeof rechnungAuftrag !== 'boolean') throw ungueltig({ rechnungAuftrag: 'Ungültige Eingabe.' })
|
||||
const r = vw.pruefeEinstellungen(rest, vorher)
|
||||
if (r.fehler) throw ungueltig(r.fehler)
|
||||
if (r.werte.onlineZahlung === true && stripeZustand(vorher) !== 'aktiv') {
|
||||
throw new UkFehler(409, 'stripe_nicht_aktiv', { onlineZahlung: 'Online-Zahlung ist erst möglich, wenn dein Stripe-Konto aktiv ist.' })
|
||||
}
|
||||
if (r.werte.rechnungsPraefix !== undefined && r.werte.rechnungsPraefix !== (vorher.rechnungsPraefix ?? '') && !vw.zaehlerLeer(vorher)) {
|
||||
throw new UkFehler(409, 'praefix_gesperrt', { rechnungsPraefix: 'Das Präfix kann nach der ersten Rechnung nicht mehr geändert werden.' })
|
||||
}
|
||||
return sp.speichereEinstellungen(ctx.featureId, r.werte)
|
||||
const werte = { ...r.werte }
|
||||
if (rechnungAuftrag === true && !vorher.rechnungAuftragAt) werte.rechnungAuftragAt = new Date().toISOString()
|
||||
if (rechnungAuftrag === false) werte.rechnungAuftragAt = null
|
||||
return sp.speichereEinstellungen(ctx.featureId, werte)
|
||||
})
|
||||
res.json(einstellungenAntwort(neu))
|
||||
res.json(await einstellungenAntwort(ctx, neu))
|
||||
}))
|
||||
|
||||
// ---- Unterkuenfte
|
||||
@@ -535,9 +543,8 @@ router.get('/rechnungen', route(async (req, res) => {
|
||||
art: r.art ?? 'rechnung',
|
||||
datum: r.datum ?? '',
|
||||
bruttoCent: r.bruttoCent ?? 0,
|
||||
anfrageId: r.anfrageId ?? '',
|
||||
anfrageNummer: r.inhalt?.anfrageNummer ?? '',
|
||||
empfaenger: r.inhalt?.empfaenger?.firma || r.inhalt?.empfaenger?.name || '',
|
||||
gastName: r.inhalt?.empfaenger?.firma || r.inhalt?.empfaenger?.name || '',
|
||||
})),
|
||||
})
|
||||
}))
|
||||
|
||||
@@ -49,6 +49,11 @@ function fuerFeature(ctx, a) {
|
||||
return a
|
||||
}
|
||||
|
||||
/** Ohne Rechnungsauftrag (Zustimmung des Vermieters) darf nichts freigegeben oder verbindlich gebucht werden. */
|
||||
function brauchtZustimmung(ctx) {
|
||||
if (!ctx?.einstellungen?.rechnungAuftragAt) throw new UkFehler(409, 'zustimmung_fehlt')
|
||||
}
|
||||
|
||||
const text = (v, max) => (typeof v === 'string' ? v.trim().slice(0, max) : '')
|
||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/
|
||||
|
||||
@@ -115,6 +120,7 @@ export async function legeAnfrageAn(ctx, eingabe, { now = new Date(), ipHash = '
|
||||
|
||||
export async function gibFrei(ctx, anfrageId, { posten, fristTage, nachricht, now = new Date() } = {}) {
|
||||
const pre = fuerFeature(ctx, await ladeAnfrage(anfrageId))
|
||||
brauchtZustimmung(ctx)
|
||||
const ergebnis = await withLocks(withLocksKey(pre.unterkunftId), async () => {
|
||||
const a = fuerFeature(ctx, await ladeAnfrage(anfrageId))
|
||||
if (a.status !== 'neu') throw new UkFehler(409, 'status_ungueltig')
|
||||
@@ -192,6 +198,7 @@ export async function bucheVerbindlich(ctx, anfrageId, token, { rechnungsadresse
|
||||
if (a.status === 'gebucht' || a.status === 'bezahlt') {
|
||||
return { anfrage: a, rechnung: a.rechnungId ? await ladeRechnung(a.rechnungId) : null, neu: false }
|
||||
}
|
||||
brauchtZustimmung(ctx)
|
||||
if (a.status === 'abgelaufen') throw new UkFehler(410, 'frist_abgelaufen')
|
||||
if (a.status !== 'freigegeben') throw new UkFehler(409, 'status_ungueltig')
|
||||
if (!(Date.parse(a.fristAt) > ms(now))) throw new UkFehler(410, 'frist_abgelaufen')
|
||||
|
||||
Reference in new issue
Block a user