diff --git a/public/buchungen-tab-anfragen.js b/public/buchungen-tab-anfragen.js index 5e411c0..92705cf 100644 --- a/public/buchungen-tab-anfragen.js +++ b/public/buchungen-tab-anfragen.js @@ -6,7 +6,8 @@ POST …/freigeben {posten,fristTage,nachricht} (=> { buchungsLink? }), …/ablehnen {text}, …/bezahlt, …/stornieren {grund,erstattungCent}. Fremdtext (Gast, Nachricht) nur ueber textContent. render(panel, ctx) wie shop-tab-*.js. */ -import { abschnitt, allgemeinerFehler, euroText, euroZuCent, fehlerKarte, feld, frage, h, zeigeFehler, datumText } from './shop-dom.js' +import { abschnitt, allgemeinerFehler, centZuEuro, euroZuCent, fehlerKarte, feld, frage, h, zeigeFehler, datumText } from './shop-dom.js' +import { fehlerFuerFormular } from './buchungen-fehler.js' import { baueEditor, euroMitVorzeichen } from './buchungen-posten.js' export const STATUS = { @@ -142,7 +143,7 @@ export async function render(panel, ctx) { feld('nachricht', 'Nachricht an den Gast (optional)', nachricht), allgemeinerFehler()) const freigeben = h('button', { - type: 'button', class: 'kb-btn', 'data-aktion': 'freigeben', disabled: ctx.nurLesen && !ctx.abwickeln, + type: 'button', class: 'kb-btn', 'data-aktion': 'freigeben', onclick: () => sendeFreigabe(a, editor, frist, nachricht, form, freigeben), }, 'Freigeben') const ablehnen = h('button', { type: 'button', class: 'kb-btn-outline', 'data-aktion': 'ablehnen', onclick: () => ablehnDialog(a, ablehnen) }, 'Ablehnen') @@ -160,12 +161,12 @@ export async function render(panel, ctx) { method: 'POST', body: { posten, fristTage: tage, nachricht: String(nachricht.value).trim() }, }) if (!ctx.aktuell()) return - ctx.zeigeMeldung('Freigegeben. Dein Gast hat den Buchungslink per Mail bekommen.', 'ok') + ctx.zeigeMeldung('Freigegeben. Der Buchungslink wurde an deinen Gast geschickt – falls die Mail nicht ankommt, kannst du ihn hier kopieren.', 'ok') zeigeLink(antwort?.buchungsLink, a) } catch (err) { knopf.disabled = false if (err.status === 409) zeigeFehler(form, { message: BELEGT, fehler: { _: BELEGT } }) - else zeigeFehler(form, err) + else zeigeFehler(form, fehlerFuerFormular(err)) } } @@ -212,7 +213,7 @@ export async function render(panel, ctx) { await zeigeListe() } catch (err) { ev.currentTarget.disabled = false - zeigeFehler(box, err) + zeigeFehler(box, fehlerFuerFormular(err)) } }, }, 'Ablehnen'), @@ -262,10 +263,10 @@ export async function render(panel, ctx) { } function stornoDialog(a, dialogEl, ausloeser) { - const online = a.bezahltVia === 'online' + const online = a.bezahltVia === 'stripe' const grund = h('textarea', { id: 'bk-a-grund', rows: '3', maxlength: '500' }) const betrag = h('input', { type: 'text', inputmode: 'decimal', id: 'bk-a-erstattung', autocomplete: 'off' }) - betrag.value = Number.isInteger(a.summen?.bruttoCent) ? `${Math.floor((a.summen.bruttoCent - (a.erstattetCent || 0)) / 100)},${String((a.summen.bruttoCent - (a.erstattetCent || 0)) % 100).padStart(2, '0')}` : '' + betrag.value = Number.isInteger(a.summen?.bruttoCent) ? centZuEuro(a.summen.bruttoCent - (a.erstattetCent || 0)) : '' const box = frage('Buchung stornieren', h('p', { class: 'sh-hinweis' }, 'Der Gast bekommt eine Stornomail und eine Storno-Rechnung.'), feld('grund', 'Grund', grund), online ? feld('erstattungCent', 'Erstattung in Euro', betrag, 'Der Betrag geht an die Karte des Gastes zurück. 0 = keine Erstattung.') : null, @@ -290,7 +291,7 @@ export async function render(panel, ctx) { knopf.disabled = false if (err.fehler === 'erstattung_fehlgeschlagen' || err.body?.fehler === 'erstattung_fehlgeschlagen') { zeigeFehler(box, { message: 'Die Buchung ist storniert, aber die Erstattung ist fehlgeschlagen. Bitte versuch die Erstattung gleich noch einmal.', fehler: {} }) - } else zeigeFehler(box, err) + } else zeigeFehler(box, fehlerFuerFormular(err)) } }, }, 'Stornieren'), diff --git a/test/buchungenUi.test.js b/test/buchungenUi.test.js index 8f88022..7264d23 100644 --- a/test/buchungenUi.test.js +++ b/test/buchungenUi.test.js @@ -151,7 +151,7 @@ test('Gebucht: Rechnung-Link, „Als bezahlt (vor Ort)“, Storno ohne Erstattun })) test('Storno bei Online-Zahlung: Erstattungsbetrag wird gesendet', mit(server({ - 'GET /api/unterkunft/anfragen/a1': () => ({ body: gebucht({ status: 'bezahlt', zahlart: 'online', bezahltVia: 'online' }) }), + 'GET /api/unterkunft/anfragen/a1': () => ({ body: gebucht({ status: 'bezahlt', zahlart: 'online', bezahltVia: 'stripe' }) }), 'POST /api/unterkunft/anfragen/a1/stornieren': () => ({ body: {} }), }), async (fx) => { const { panel } = await zeige(fx) @@ -369,3 +369,14 @@ test('iCal: Import hinzufügen (POST), entfernen mit Rückfrage, Link erneuern m await fx.ruhe() assert.equal(posts(fx).filter((a) => a.url.includes('erneuern')).length, 1) })) + +test('Freigeben: Serverfehler 400 mit felder zeigt genau den Feldtext', mit(server({ + 'POST /api/unterkunft/anfragen/a1/freigeben': () => ({ status: 400, body: { fehler: 'ungueltig', felder: { posten: 'Die Summe muss größer als 0 sein.' } } }), +}), async (fx) => { + const { panel } = await zeige(fx) + await oeffne(fx, panel) + await fx.klick(aktion(fx, panel, 'freigeben')) + await fx.ruhe() + assert.equal(fx.text(fx.finde(panel, '[data-fehler="posten"]')), 'Die Summe muss größer als 0 sein.') + assert.equal(fx.text(fx.finde(panel, '[data-fehler="_"]')), '') +}))