Terminplaner: Verfuegbarkeit, Abwesenheit schlaegt Sonderoeffnung, waehleRessource ignoriert abgelaufene Haltungen

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-03 08:17:43 +00:00
1 parent cce6e64dd1
commit 4def5c735d
2 files changed
+48 -10

No files matched your search

+37 -2
View File
@@ -244,18 +244,41 @@ test('Sonderoeffnung mit leerer Liste: an diesem Tag geschlossen', () => {
assert.ok(frei(e, '2026-10-13').length > 0)
})
test('Sonderoeffnung gilt fuer alle Ressourcen und schlaegt die Abwesenheit (Rangfolge Sonderoeffnung > Abwesenheit > Feiertag > Plan)', () => {
test('Sonderoeffnung gilt fuer alle Ressourcen, auch fuer solche ohne Plan an diesem Tag', () => {
const e = einstellung({
ressourcen: [ressource(R1, wochenplan(TAG)), ressource(R2, wochenplan([['08:00', '09:00']]))],
raster: 60,
sonderoeffnungen: { [MO]: [['10:00', '12:00']] },
abwesenheiten: [{ id: 'a_cccccccc', ressourceId: R1, von: MO, bis: MO, titel: 'Urlaub' }],
})
const liste = frei(e, MO)
assert.deepEqual(uhrzeiten(liste), ['10:00', '11:00'])
assert.deepEqual(liste[0].ressourceIds, [R1, R2])
})
test('Person im Urlaub ist an einem Sonderoeffnungstag nicht buchbar', () => {
const e = einstellung({
ressourcen: [ressource(R1, wochenplan(TAG)), ressource(R2, wochenplan(TAG))],
raster: 60,
sonderoeffnungen: { [MO]: [['10:00', '12:00']] },
abwesenheiten: [{ id: 'a_cccccccc', ressourceId: R1, von: MO, bis: MO, titel: 'Urlaub' }],
})
assert.deepEqual(frei(e, MO, { ressourceId: R1 }), [])
assert.deepEqual(frei(e, MO, { ressourceId: R2 }).map((z) => [z.uhrzeit, z.ressourceIds]), [['10:00', [R2]], ['11:00', [R2]]])
assert.deepEqual(frei(e, MO).map((z) => z.ressourceIds), [[R2], [R2]], 'egal: nur die anwesende Person')
})
test('Betriebsurlaub schlaegt Sonderoeffnung', () => {
const e = einstellung({
ressourcen: [ressource(R1, wochenplan(TAG)), ressource(R2, wochenplan(TAG))],
raster: 60,
sonderoeffnungen: { [MO]: [['10:00', '12:00']], '2026-10-13': [['10:00', '12:00']] },
abwesenheiten: [{ id: 'a_dddddddd', ressourceId: null, von: MO, bis: MO, titel: 'Betriebsurlaub' }],
})
assert.deepEqual(frei(e, MO), [])
assert.deepEqual(frei(e, MO, { ressourceId: R1 }), [])
assert.deepEqual(uhrzeiten(frei(e, '2026-10-13')), ['10:00', '11:00'], 'ohne Abwesenheit gilt die Sonderoeffnung')
})
// ---------------------------------------------------------------- Belegung
test('Belegung blockiert Ueberlappung, angrenzende Zeiten bleiben frei', () => {
@@ -520,6 +543,18 @@ test('waehleRessource: bei Gleichstand gilt die Reihenfolge der Liste, abgesagte
assert.equal(waehleRessource([R2, R1], [{ ressourceId: R1, status: 'erledigt' }], e), R2, 'erledigte Termine des Tages zaehlen mit')
})
test('waehleRessource: mit now zaehlt eine abgelaufene Haltung nicht, eine gueltige schon', () => {
const e = einstellung({ ressourcen: [ressource(R1, {}), ressource(R2, {})] })
const now = new Date('2026-10-12T08:00:00Z')
const haltung = (ressourceId, heldUntil) => ({ ressourceId, status: 'gehalten', heldUntil: heldUntil && appwrite(new Date(heldUntil)) })
const abgelaufen = [haltung(R1, '2026-10-12T07:59:00Z'), haltung(R1, '2026-10-12T08:00:00Z'), haltung(R1, undefined)]
assert.equal(waehleRessource([R1, R2], abgelaufen, e), R2, 'ohne now zaehlt jede Haltung')
assert.equal(waehleRessource([R2, R1], abgelaufen, e, now), R1, 'mit now: Gleichstand 0:0, Reihenfolge der Einstellung')
assert.equal(waehleRessource([R1, R2], [haltung(R1, '2026-10-12T08:00:01Z')], e, now), R2, 'gueltige Haltung zaehlt')
assert.equal(waehleRessource([R1, R2], [...abgelaufen, { ressourceId: R1, status: 'bestaetigt' }], e, now), R2, 'andere Status zaehlen weiter')
assert.throws(() => waehleRessource([R1], [], e, 'gestern'), TypeError)
})
test('waehleRessource: keine Kandidaten ergibt null, fremde Ressourcen werden nicht gezaehlt', () => {
const e = einstellung()
assert.equal(waehleRessource([], [], e), null)