Projektkonto: Team-Route für das Abzeichen abgerechnet am Arbeitsblatt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
846059b455
commit
9fa965521a
2 files changed
+57
-2
No files matched your search
@@ -1,9 +1,25 @@
|
||||
/**
|
||||
* Gerüst von Strang L0: Arbeitsblätter fürs Ticketsystem. Mount: /api/team/arbeitsblaetter, in team/index.js hinter
|
||||
* requireStaffJwt (jeder Mitarbeiter, daher kein eigener Schutz). L1 ergänzt GET /abgerechnet (?ticketId=<id>).
|
||||
* Arbeitsblaetter fuers Ticketsystem. Mount: /api/team/arbeitsblaetter, in team/index.js hinter requireStaffJwt (jeder
|
||||
* Mitarbeiter, daher kein eigener Schutz).
|
||||
* GET /abgerechnet?ticketId=<id> { abgerechnet: { <Blatt-ID>: '<Rechnungsnummer>' | 'Entwurf' } }, ohne Betraege
|
||||
*/
|
||||
import { Router } from 'express'
|
||||
import { sendeFehler } from '../../services/auftraege/fehler.js'
|
||||
import { abgerechnetFuerTicket } from '../../services/auftraege/projektkonto.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
// Appwrite-UID: erst pruefen, dann an Appwrite geben
|
||||
const KENNUNG = /^[A-Za-z0-9][A-Za-z0-9._-]{0,35}$/
|
||||
|
||||
router.get('/abgerechnet', async (req, res) => {
|
||||
const ticketId = req.query.ticketId
|
||||
if (typeof ticketId !== 'string' || !KENNUNG.test(ticketId)) return res.status(400).json({ error: 'ticketId fehlt oder ist ungültig.' })
|
||||
try {
|
||||
res.json({ abgerechnet: await abgerechnetFuerTicket(ticketId) })
|
||||
} catch (err) {
|
||||
sendeFehler(res, 'Abgerechnete Arbeitsblätter laden', err)
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -131,3 +131,42 @@ test('Fehler in Appwrite: 500 mit fester Meldung, ohne Text von Appwrite', async
|
||||
assert.equal(res.status, 500)
|
||||
assert.deepEqual(res.body, { error: 'Interner Fehler.' })
|
||||
})
|
||||
|
||||
// ---------- Team-Route (Task 8) ----------
|
||||
|
||||
const ABGERECHNET = '/api/team/arbeitsblaetter/abgerechnet'
|
||||
const seedPr = (invoiceId, { arbeitsblattIds = [], ...over } = {}) =>
|
||||
aw.seed(config.collections.projektRechnungen, {
|
||||
$id: invoiceId, invoiceId, kundenId: 'c1', projektId: 'p1', auftragId: '', art: 'festbetrag', betragCents: 0,
|
||||
arbeitsblattIdsJson: JSON.stringify(arbeitsblattIds), rechnungsnummer: '', aktiv: true,
|
||||
erstelltVon: 'kenso@webklar.com', erstelltAm: '2026-10-01T10:00:00.000Z', ...over,
|
||||
})
|
||||
|
||||
test('Abzeichen-Route: ohne JWT 401, Konto ohne Label 403, Mitarbeiter und Admin dürfen', async () => {
|
||||
const path = `${ABGERECHNET}?ticketId=t1`
|
||||
assert.equal((await rawGet(path)).status, 401)
|
||||
assert.equal((await rawGet(path, ohneLabel)).status, 403)
|
||||
assert.equal((await rawGet(path, staff)).status, 200)
|
||||
assert.equal((await rawGet(path, admin)).status, 200)
|
||||
})
|
||||
|
||||
test('Abzeichen-Route: ticketId fehlt, ist leer, doppelt oder unmöglich -> 400', async () => {
|
||||
for (const query of ['', '?ticketId=', '?ticketId=t1&ticketId=t2', '?ticketId=../x', `?ticketId=${'t'.repeat(37)}`, '?ticketId[a]=b']) {
|
||||
const res = await rawGet(`${ABGERECHNET}${query}`, staff)
|
||||
assert.equal(res.status, 400, query)
|
||||
assert.deepEqual(res.body, { error: 'ticketId fehlt oder ist ungültig.' }, query)
|
||||
}
|
||||
})
|
||||
|
||||
test('Abzeichen-Route: { abgerechnet: { Blatt: Rechnungsnummer | Entwurf } } ohne Beträge, unbekanntes Ticket leer', async () => {
|
||||
seedBasis()
|
||||
seedPr('in_1', { rechnungsnummer: 'WEBKLAR-0007', arbeitsblattIds: ['w1'] })
|
||||
seedPr('in_2', { rechnungsnummer: '', arbeitsblattIds: ['w2'] })
|
||||
const res = await rawGet(`${ABGERECHNET}?ticketId=t1`, staff)
|
||||
assert.equal(res.status, 200)
|
||||
assert.deepEqual(res.body, { abgerechnet: { w1: 'WEBKLAR-0007', w2: 'Entwurf' } })
|
||||
assert.ok(!/cents|betrag|in_1|in_2/i.test(JSON.stringify(res.body)), 'weder Beträge noch Rechnungs-IDs')
|
||||
const unbekannt = await rawGet(`${ABGERECHNET}?ticketId=gibtsnicht`, staff)
|
||||
assert.equal(unbekannt.status, 200)
|
||||
assert.deepEqual(unbekannt.body, { abgerechnet: {} })
|
||||
})
|
||||
Reference in new issue
Block a user