AB-Kern: Admin-Routen zum Senden, Erinnern, für neue Fassungen, zum Stornieren und zum Zuordnen eines Projekts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7d3114d7a3
commit
e680ea3266
2 files changed
+130
No files matched your search
@@ -94,4 +94,52 @@ router.get('/:id/pdf', async (req, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** Antwort der Aktionen, die eine Mail auslösen: { auftrag, mailFehler }. */
|
||||||
|
const mitMail = ({ auftrag, mailFehler }) => ({ auftrag: auftragFuerTeam(auftrag), mailFehler })
|
||||||
|
|
||||||
|
router.post('/:id/senden', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await ladeMitSchalter(req.params.id)
|
||||||
|
return res.json(mitMail(await sendeAuftrag(req.params.id, { von: vonAdmin(req) })))
|
||||||
|
} catch (err) {
|
||||||
|
return sendeFehler(res, 'Auftragsbestätigung senden', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post('/:id/erinnern', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await ladeMitSchalter(req.params.id)
|
||||||
|
return res.json(mitMail(await erinnereAuftrag(req.params.id)))
|
||||||
|
} catch (err) {
|
||||||
|
return sendeFehler(res, 'Auftragsbestätigung erinnern', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post('/:id/neue-fassung', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await ladeMitSchalter(req.params.id)
|
||||||
|
return res.json({ auftrag: auftragFuerTeam(await neueFassung(req.params.id, { von: vonAdmin(req) })) })
|
||||||
|
} catch (err) {
|
||||||
|
return sendeFehler(res, 'Neue Fassung anlegen', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post('/:id/stornieren', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await ladeMitSchalter(req.params.id)
|
||||||
|
return res.json({ auftrag: auftragFuerTeam(await storniereAuftrag(req.params.id)) })
|
||||||
|
} catch (err) {
|
||||||
|
return sendeFehler(res, 'Auftragsbestätigung stornieren', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post('/:id/projekt', async (req, res) => {
|
||||||
|
try {
|
||||||
|
await ladeMitSchalter(req.params.id)
|
||||||
|
return res.json({ auftrag: auftragFuerTeam(await ordneProjektZu(req.params.id, req.body?.projektId)) })
|
||||||
|
} catch (err) {
|
||||||
|
return sendeFehler(res, 'Projekt zuordnen', err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
@@ -125,3 +125,85 @@ test('Unerwartete Fehler: 500 mit fester Meldung, nichts von Appwrite gelangt an
|
|||||||
const r = await api('GET', `/${a.id}`)
|
const r = await api('GET', `/${a.id}`)
|
||||||
assert.deepEqual([r.status, r.body], [500, { error: 'Interner Fehler.' }])
|
assert.deepEqual([r.status, r.body], [500, { error: 'Interner Fehler.' }])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('POST senden: 200 ohne Token und Dateipfad; Kundendaten-, PDF- und Statusfehler mit festen Meldungen; Mail-Fehler als mailFehler: true', async () => {
|
||||||
|
mock.method(console, 'error', () => {})
|
||||||
|
const a = await entwurfAnlegen()
|
||||||
|
aw.seed(config.collections.customers, kundeDoc({ email: '' }))
|
||||||
|
let r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.deepEqual([r.status, r.body], [400, { error: MELDUNG.keineMail }])
|
||||||
|
aw.seed(config.collections.customers, kundeDoc({ street: '' }))
|
||||||
|
r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.adresse }])
|
||||||
|
aw.seed(config.collections.customers, kundeDoc())
|
||||||
|
kontext = baueDeps({ pdfFehler: new Error('pdfkit') })
|
||||||
|
setzeDepsFuerTests(kontext.deps)
|
||||||
|
r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.deepEqual([r.status, r.body], [500, { error: MELDUNG.pdf }])
|
||||||
|
kontext = baueDeps({ mailFehler: new Error('smtp') })
|
||||||
|
setzeDepsFuerTests(kontext.deps)
|
||||||
|
r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.equal(r.status, 200)
|
||||||
|
assert.equal(r.body.mailFehler, true)
|
||||||
|
assert.deepEqual([r.body.auftrag.status, r.body.auftrag.mailStatus, r.body.auftrag.pdfVorhanden], ['versendet', 'fehler', true])
|
||||||
|
assert.match(r.body.auftrag.nummer, /^AB-\d{4}-0001$/)
|
||||||
|
for (const feld of ['tokenHash', 'pdfDatei', 'bestaetigtPdfSha256']) assert.equal(feld in r.body.auftrag, false, feld)
|
||||||
|
r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.nurEntwurfSenden }])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('POST erinnern, neue-fassung, stornieren: Antworten, Folgezustände und 409 bei falschem Status', async () => {
|
||||||
|
const a = await entwurfAnlegen()
|
||||||
|
let r = await api('POST', `/${a.id}/erinnern`)
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.keineErinnerung }])
|
||||||
|
r = await api('POST', `/${a.id}/senden`)
|
||||||
|
assert.deepEqual([r.status, r.body.mailFehler, r.body.auftrag.status], [200, false, 'versendet'])
|
||||||
|
r = await api('POST', `/${a.id}/erinnern`)
|
||||||
|
assert.deepEqual([r.status, r.body.mailFehler, r.body.auftrag.status], [200, false, 'versendet'])
|
||||||
|
assert.equal(kontext.calls.mail.at(-1).erinnerung, true)
|
||||||
|
r = await api('POST', `/${a.id}/neue-fassung`)
|
||||||
|
assert.deepEqual([r.status, r.body.auftrag.status, r.body.auftrag.ersetztId], [200, 'entwurf', a.id])
|
||||||
|
r = await api('POST', `/${a.id}/neue-fassung`)
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.schonEntwurf }])
|
||||||
|
r = await api('POST', `/${a.id}/stornieren`)
|
||||||
|
assert.deepEqual([r.status, r.body.auftrag.status], [200, 'storniert'])
|
||||||
|
r = await api('POST', `/${a.id}/stornieren`)
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.keinStorno }])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('POST projekt: ordnet einer AB ohne Projekt das Projekt zu (200, AuftragTeam); 400 ohne oder mit fremdem Projekt, 404 bei unbekannter AB, 409 bei vorhandenem Projekt oder falschem Status', async () => {
|
||||||
|
const a = await entwurfAnlegen({ projektId: '', titel: 'Beratung ohne Projekt' })
|
||||||
|
await api('POST', `/${a.id}/senden`)
|
||||||
|
let r = await api('POST', `/${a.id}/projekt`, {})
|
||||||
|
assert.deepEqual([r.status, r.body], [400, { error: MELDUNG.projektFehlt }])
|
||||||
|
r = await api('POST', `/${a.id}/projekt`)
|
||||||
|
assert.deepEqual([r.status, r.body], [400, { error: MELDUNG.projektFehlt }])
|
||||||
|
r = await api('POST', `/${a.id}/projekt`, { projektId: FREMD.projekt })
|
||||||
|
assert.deepEqual([r.status, r.body], [400, { error: MELDUNG.projektFremd }])
|
||||||
|
r = await api('POST', '/a_gibtsnicht/projekt', { projektId: PROJEKT_ID })
|
||||||
|
assert.deepEqual([r.status, r.body], [404, { error: MELDUNG.auftragFehlt }])
|
||||||
|
assert.equal((await getAuftrag(a.id)).projektId, '') // die abgelehnten Aufrufe haben nichts geändert
|
||||||
|
r = await api('POST', `/${a.id}/projekt`, { projektId: PROJEKT_ID })
|
||||||
|
assert.equal(r.status, 200)
|
||||||
|
assert.deepEqual([r.body.auftrag.projektId, r.body.auftrag.zeitquelle, r.body.auftrag.status], [PROJEKT_ID, [TICKET_ID], 'versendet'])
|
||||||
|
for (const feld of ['tokenHash', 'pdfDatei', 'bestaetigtPdfSha256']) assert.equal(feld in r.body.auftrag, false, feld)
|
||||||
|
r = await api('POST', `/${a.id}/projekt`, { projektId: PROJEKT_ID })
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.schonProjekt }])
|
||||||
|
const b = await entwurfAnlegen({ projektId: '', titel: 'Zweite Beratung ohne Projekt' })
|
||||||
|
await api('POST', `/${b.id}/senden`)
|
||||||
|
await api('POST', `/${b.id}/stornieren`)
|
||||||
|
r = await api('POST', `/${b.id}/projekt`, { projektId: PROJEKT_ID })
|
||||||
|
assert.deepEqual([r.status, r.body], [409, { error: MELDUNG.keinProjekt }])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Schalter aus: auch senden, erinnern, neue-fassung, stornieren und projekt antworten 404 mit der festen Meldung', async () => {
|
||||||
|
const a = await entwurfAnlegen({ projektId: '', titel: 'Beratung ohne Projekt' })
|
||||||
|
config.auftraege.mode = 'off'
|
||||||
|
for (const aktion of ['senden', 'erinnern', 'neue-fassung', 'stornieren', 'projekt']) {
|
||||||
|
const r = await api('POST', `/${a.id}/${aktion}`, aktion === 'projekt' ? { projektId: PROJEKT_ID } : undefined)
|
||||||
|
assert.deepEqual([r.status, r.body], [404, { error: SCHALTER_AUS_MELDUNG }], aktion)
|
||||||
|
}
|
||||||
|
const danach = await getAuftrag(a.id)
|
||||||
|
assert.deepEqual([danach.status, danach.projektId], ['entwurf', ''])
|
||||||
|
assert.equal(kontext.calls.pdf.length + kontext.calls.mail.length, 0)
|
||||||
|
})
|
||||||
Reference in new issue
Block a user