Unterstützung: eigene Zeilen und Gesamtzeit in den Projektdetails

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-30 15:08:16 +00:00
1 parent 7c6b0c906b
commit 7da4452bbd
8 files changed
+136 -8

No files matched your search

+54
View File
@@ -6,6 +6,7 @@ import {
isInternalTicket,
customerOrder,
customerWorkEntries,
workTotalMinutes,
} from '../server/services/customerProjectView.js'
// Commit wie listRepoCommits() ihn liefert (giteaAdmin.js)
@@ -309,3 +310,56 @@ test('Arbeit: Einträge aus getCustomerActivity (date statt endDate, Zeit als Te
{ kind: 'online', label: 'Online erledigt', date: '2026-09-18', minutes: 30, person: 'Andrej Stevanovski', text: 'Demo-Version erstellt' },
])
})
/* ---------------------------------------------------- Unterstützung --- */
const andrej = { employeeId: 'andrej', name: 'Andrej Stevanovski', task: 'Farbkonzept' }
const nico = { employeeId: 'nico', name: 'Nico Rech', task: 'Texte' }
const workSheet = (extra = {}) => ({
serviceType: 'Remote', employeeName: 'Justin Klein', totalTime: 60, startDate: '30.09.2026', endDate: '30.09.2026',
details: 'Startseite umgebaut', isComment: false, ...extra,
})
test('Unterstützung: eigene Zeile mit Vorname, Tätigkeit und halber Zeit', () => {
const [entry] = customerWorkEntries([workSheet({ supporters: JSON.stringify([andrej]) })])
assert.equal(entry.minutes, 60)
assert.deepEqual(entry.supports, [{ name: 'Andrej', task: 'Farbkonzept', minutes: 30 }])
})
test('Unterstützung: ohne supporters kein supports-Feld (bisherige Form bleibt)', () => {
const [entry] = customerWorkEntries([workSheet()])
assert.equal('supports' in entry, false)
})
test('Unterstützung: zusammengefasste Git-Tage sammeln alle Unterstützungen', () => {
const push = (sha, title, sup) => ({
...gitSheet, endDate: '24.09.2026', totalTime: 30, startTime: '1300', isComment: false, supporters: JSON.stringify([sup]),
details: `Git Push auf \`knso/ff-lack\` (Branch: main)\nCommit: ${sha}\n\n- [${sha}](https://git.webklar.com/knso/ff-lack/commit/${sha}): ${title} (knso)`,
})
const entries = customerWorkEntries([push('aaaaaaa', 'Handy-Ansicht', andrej), push('bbbbbbb', 'Icons', nico)], { includeUpdates: false })
assert.equal(entries.length, 1)
assert.equal(entries[0].minutes, 60)
assert.deepEqual(entries[0].supports, [
{ name: 'Andrej', task: 'Farbkonzept', minutes: 15 },
{ name: 'Nico', task: 'Texte', minutes: 15 },
])
})
test('Unterstützung: Kommentar mit supporters erscheint nicht', () => {
assert.deepEqual(customerWorkEntries([workSheet({ isComment: true, supporters: JSON.stringify([andrej]) })]), [])
})
test('Unterstützung: kaputtes supporters -> Eintrag ohne Unterstützung', () => {
const [entry] = customerWorkEntries([workSheet({ supporters: 'kaputt' })])
assert.equal(entry.minutes, 60)
assert.equal('supports' in entry, false)
})
test('workTotalMinutes: Summe aller Schritte inkl. Unterstützung', () => {
const entries = customerWorkEntries([
workSheet({ supporters: JSON.stringify([andrej, nico]) }),
workSheet({ totalTime: 45 }),
])
assert.equal(workTotalMinutes(entries), 60 + 30 + 30 + 45)
assert.equal(workTotalMinutes([]), 0)
})
+42
View File
@@ -0,0 +1,42 @@
import { test, after } from 'node:test'
import assert from 'node:assert/strict'
import { startAppwriteMock } from './support/appwriteMock.js'
import { startFakeStripe } from './support/fakeStripe.js'
import { useTestEnv } from './support/testEnv.js'
const aw = await startAppwriteMock()
const st = await startFakeStripe()
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
const { startTestApp, get, sessionCookie } = await import('./support/testApp.js')
const { default: projectsRouter } = await import('../server/routes/projects.js')
const app = await startTestApp({ '/api/projects': projectsRouter })
after(() => Promise.all([aw.close(), st.close(), app.close()]))
aw.seed('websiteProjects', { $id: 'p1', customerId: 'c1', ticketId: 'wo1', name: 'Website' })
aw.seed('workorders', { $id: 'wo1', woid: '100200', status: 'Open', type: 'Webpage', topic: 'Neue Website', customerId: 'c1' })
const andrej = { employeeId: 'andrej', name: 'Andrej Stevanovski', task: 'Farbkonzept' }
const sheet = (id, extra) => ({
$id: id, workorderId: 'wo1', woid: '100200', serviceType: 'Remote', employeeName: 'Justin Klein', totalTime: 60,
startDate: '30.09.2026', endDate: '30.09.2026', details: 'Arbeit', isComment: false, ...extra,
})
// Neuestes Blatt, damit es auch in getCustomerActivity (max. 20 je Ticket) dabei ist
aw.seed('worksheets', sheet('ws1', { supporters: JSON.stringify([andrej]), $createdAt: '2026-09-30T18:00:00.000Z' }))
// Mehr als 50 Blaetter: die Gesamtzeit zaehlt trotzdem alle
for (let i = 0; i < 55; i++) aw.seed('worksheets', sheet(`wsx${i}`, { totalTime: 15 }))
test('GET /:id/work liefert totalMinutes inkl. Unterstützung über alle Blätter', async () => {
const body = await get('/api/projects/p1/work', { cookie: sessionCookie({ customerId: 'c1', appwriteUserId: 'u1' }) })
assert.equal(body.totalMinutes, 60 + 30 + 55 * 15)
const withSupport = body.entries.find((e) => e.supports)
assert.deepEqual(withSupport.supports, [{ name: 'Andrej', task: 'Farbkonzept', minutes: 30 }])
})
test('getCustomerActivity reicht supporters und supportMinutes weiter (Fortschritt + Admin)', async () => {
const { getCustomerActivity } = await import('../server/services/customerActivity.js')
const [ticket] = await getCustomerActivity('c1')
const ws1 = ticket.worksheets.find((w) => w.supporters)
assert.equal(ws1.supportMinutes, 30)
const { customerWorkEntries } = await import('../server/services/customerProjectView.js')
const entry = customerWorkEntries(ticket.worksheets).find((e) => e.supports)
assert.deepEqual(entry.supports, [{ name: 'Andrej', task: 'Farbkonzept', minutes: 30 }])
})