GET /api/team/customers/:id/stundenkonto kannte nur Produkt und Konto; WOMS (stundenkontoView.js) kann bei beendetem Abo nicht "verfällt, wird nicht berechnet" (V8, E17) statt "wird mit den nächsten Gutschriften verrechnet" zeigen, weil das Feld active fehlte. Jetzt trägt jede Antwort active (Abo läuft: Status active, trialing oder past_due, auch mit vorgemerkter Kündigung; ohne Abo false). WOMS liest antwort.active schon, nur ein ausdrückliches false ändert den Satz. Test in teamStundenkonto.test.js. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
42 lines
3.4 KiB
JavaScript
42 lines
3.4 KiB
JavaScript
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)
|
|
})
|