From df0c7a05e884e4f6d634344bc2e75489ca913b58 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 17:22:02 +0000 Subject: [PATCH] Tickets: Startdatum als TT.MM.JJJJ, Frist gleich (R5) Co-Authored-By: Claude Sonnet 5.5 --- server/services/ticketAdmin.js | 26 ++++++++++++++++++++++++-- test/ticketAdmin.test.js | 31 ++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/server/services/ticketAdmin.js b/server/services/ticketAdmin.js index 24ef862..dbfe03c 100644 --- a/server/services/ticketAdmin.js +++ b/server/services/ticketAdmin.js @@ -1,4 +1,5 @@ import { config } from '../config.js' +import { berlinDateTime } from './berlinTime.js' import { createDocument, deleteDocument, @@ -111,7 +112,7 @@ export async function createFeatureTicket({ customerId, project, featureKey, sit * Legt ein Ticket fuer ein Projekt an (Zuordnen-Flow, erst beim Abschliessen). * Unbekannter Kunde => Fehler mit status 400. */ -export async function createTicketForProject({ customerId, topic, type, requestedBy, startDate, details }) { +export async function createTicketForProject({ customerId, topic, type, requestedBy, startDate, details }, { now = new Date() } = {}) { const customer = customerId ? await getDocument(config.collections.customers, customerId).catch(() => null) : null @@ -121,6 +122,26 @@ export async function createTicketForProject({ customerId, topic, type, requeste throw err } + // WOMS speichert Ticket-Daten als 'TT.MM.JJJJ'; leer = heute (Berlin). + let date + if (!startDate) { + date = berlinDateTime(now).date + } else { + const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(startDate)) + const valid = + m && + (() => { + const d = new Date(Date.UTC(+m[1], +m[2] - 1, +m[3])) + return d.getUTCFullYear() === +m[1] && d.getUTCMonth() === +m[2] - 1 && d.getUTCDate() === +m[3] + })() + if (!valid) { + const err = new Error('Das Startdatum ist ungültig (erwartet: JJJJ-MM-TT).') + err.status = 400 + throw err + } + date = `${m[3]}.${m[2]}.${m[1]}` + } + const woid = await generateNextWoid() const ticket = await createDocument( config.collections.workorders, @@ -135,7 +156,8 @@ export async function createTicketForProject({ customerId, topic, type, requeste customerName: customer.name || '', customerLocation: customer.location || '', requestedBy: requestedBy || '', - startDate: startDate || '', + startDate: date, + deadline: date, details: details || '', woid, createdAt: new Date().toISOString(), diff --git a/test/ticketAdmin.test.js b/test/ticketAdmin.test.js index 2cde982..febec36 100644 --- a/test/ticketAdmin.test.js +++ b/test/ticketAdmin.test.js @@ -47,7 +47,8 @@ test('createTicketForProject legt ein offenes Ticket mit Kundendaten und nächst assert.equal(d.customerLocation, 'Berlin') assert.equal(d.woid, '100121') assert.equal(d.requestedBy, 'Max') - assert.equal(d.startDate, '2026-10-05') + assert.equal(d.startDate, '05.10.2026') + assert.equal(d.deadline, '05.10.2026') assert.equal(d.details, 'Details') assert.ok(d.createdAt) }) @@ -66,3 +67,31 @@ test('deleteTicket löscht das Ticket', async () => { assert.equal(aw.get('workorders', 't2'), undefined) assert.ok(aw.calls.some((c) => c.method === 'DELETE' && c.path.endsWith('/documents/t2'))) }) + +test('createTicketForProject: leeres Startdatum = heute (Berlin), Start und Frist gleich', async () => { + const r = await createTicketForProject( + { customerId: 'c1', topic: 'x', type: 'Webpage', startDate: '' }, + { now: new Date('2026-12-31T23:30:00Z') } // in Berlin schon der 01.01.2027 + ) + const d = aw.get('workorders', r.$id) + assert.equal(d.startDate, '01.01.2027') + assert.equal(d.deadline, '01.01.2027') +}) + +test('createTicketForProject: ungültiges Startdatum ⇒ status 400, kein Ticket', async () => { + const n = aw.all('workorders').length + for (const bad of ['05.10.2026', '2026-13-01', '2026-02-30', 'morgen']) { + await assert.rejects( + () => createTicketForProject({ customerId: 'c1', topic: 'x', type: 'Webpage', startDate: bad }), + (err) => err.status === 400 && /Startdatum/.test(err.message) + ) + } + assert.equal(aw.all('workorders').length, n) +}) + +test('createTicketForProject: fehlende customerId ⇒ status 400', async () => { + await assert.rejects( + () => createTicketForProject({ topic: 'x', type: 'Webpage' }), + (err) => err.status === 400 + ) +})