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' // Team-Endpunkt Stundenkonto fuers Ticketsystem: Produkt, Guthaben, Vorschuss, Mehraufwand und active (Abo laeuft; E-Fix W1: WOMS zeigt bei beendetem Abo // "verfaellt, wird nicht berechnet" statt "wird mit den naechsten Gutschriften verrechnet") const aw = await startAppwriteMock() const st = await startFakeStripe() useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url }) const { startTestApp, rawGet } = await import('./support/testApp.js') const { seedFixtures } = await import('./support/fixtures.js') const { default: teamRoutes } = await import('../server/routes/team/index.js') const { updateDocument } = await import('../server/services/appwriteAdmin.js') const app = await startTestApp({ '/api/team': teamRoutes }) after(() => Promise.all([app.close(), aw.close(), st.close()])) seedFixtures(aw) const auth = { headers: { authorization: 'Bearer jwt-staff' } } test('Wartung: Guthaben, Vorschuss und Mehraufwand aus dem Stundenkonto', async () => { aw.seed('subscriptions', { $id: 'sub_t', customerId: 'c3', status: 'active', productKey: 'wartung', storageUnits: 0, startedAt: '2026-09-01T10:00:00.000Z' }) aw.seed('hourCredits', { $id: 'h1', customerId: 'c3', minutes: 60, grantedAt: '2026-09-01T00:00:00.000Z', expiresAt: '2099-01-01T00:00:00.000Z' }) aw.seed('workorders', { $id: 'wo_t', customerId: 'c3', woid: '100401', topic: 'Einrichtung', einrichtungAbrechnung: 'abo' }) aw.seed('worksheets', { $id: 'ws_t', workorderId: 'wo_t', wsid: 'ws_t', countsToPlan: true, totalTime: 90, startDate: '10.09.2026' }) const res = await rawGet('/api/team/customers/c3/stundenkonto', auth) assert.deepEqual([res.status, res.body], [200, { produkt: 'wartung', active: true, ledger: { balanceMinutes: 0, vorschussMinutes: 30, overageMinutes: 0, nextExpiry: null } }]) }) test('Hosting: kein Konto; ohne Abo null; beendetes Wartungs-Abo behält den Vorschuss, Guthaben 0; ohne JWT 401', async () => { assert.deepEqual((await rawGet('/api/team/customers/c1/stundenkonto', auth)).body, { produkt: 'hosting', active: true, ledger: null }) // c1: Hosting aus seedFixtures assert.deepEqual((await rawGet('/api/team/customers/c4/stundenkonto', auth)).body, { produkt: null, active: false, ledger: null }) await updateDocument('subscriptions', 'sub_t', { status: 'canceled' }) // aw.docs() liefert Kopien: ueber die API aendern const ende = (await rawGet('/api/team/customers/c3/stundenkonto', auth)).body assert.deepEqual([ende.produkt, ende.active, ende.ledger.vorschussMinutes, ende.ledger.balanceMinutes], ['wartung', false, 30, 0]) await updateDocument('subscriptions', 'sub_t', { status: 'active', cancelAtPeriodEnd: true }) // gekündigt, aber bis zum Periodenende noch aktiv: der Vorschuss geht noch in die Gutschriften assert.equal((await rawGet('/api/team/customers/c3/stundenkonto', auth)).body.active, true) await updateDocument('subscriptions', 'sub_t', { status: 'past_due', cancelAtPeriodEnd: false }) // offene Zahlung: das Abo läuft noch (ACTIVE_STATUSES) assert.equal((await rawGet('/api/team/customers/c3/stundenkonto', auth)).body.active, true) assert.equal((await rawGet('/api/team/customers/c3/stundenkonto')).status, 401) })