Files
Webklar-Kundenbereich/test/unterkunftBelegung.test.js
T
2026-10-07 13:49:29 +00:00

163 lines
9.2 KiB
JavaScript

import { test, after, beforeEach } from 'node:test'
import assert from 'node:assert/strict'
import { startAppwriteMock } from './support/appwriteMock.js'
import { useTestEnv } from './support/testEnv.js'
import { schemaKeys } from './support/schema.js'
// Buchungskalender Task 3: Speicher (services/unterkunft/speicher.js) und Belegung (belegung.js)
const NAMEN = ['ukUnterkuenfte', 'ukPreise', 'ukSperren', 'ukAnfragen', 'ukEinstellungen']
const aw = await startAppwriteMock({
schema: Object.fromEntries(NAMEN.map((n) => [n, schemaKeys(n)])),
datetimes: { ukAnfragen: ['fristAt', 'freigegebenAt', 'gebuchtAt'] },
})
useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1/v1' })
const { config } = await import('../server/config.js')
const { listDocuments, deleteDocument } = await import('../server/services/appwriteAdmin.js')
const sp = await import('../server/services/unterkunft/speicher.js')
const bel = await import('../server/services/unterkunft/belegung.js')
after(() => aw.close())
const NOW = new Date('2026-11-01T12:00:00Z')
const ZUKUNFT = '2026-11-02T12:00:00.000+00:00'
const VERGANGENHEIT = '2026-10-31T12:00:00.000+00:00'
let n = 0
const anfrage = (felder) => {
const doc = { $id: `a${++n}`, featureId: 'f1', unterkunftId: 'u1', von: '2026-11-10', bis: '2026-11-12', status: 'neu', ...felder }
aw.seed('ukAnfragen', doc)
return doc
}
beforeEach(async () => {
for (const c of NAMEN) for (const id of aw.docs(c).keys()) await deleteDocument(c, id)
})
test('ueberschneidet: Halboffen, Abreise gleich Anreise ist frei', () => {
assert.equal(bel.ueberschneidet({ von: '2026-11-01', bis: '2026-11-05' }, { von: '2026-11-05', bis: '2026-11-07' }), false)
assert.equal(bel.ueberschneidet({ von: '2026-11-01', bis: '2026-11-05' }, { von: '2026-11-04', bis: '2026-11-07' }), true)
assert.equal(bel.ueberschneidet({ von: '2026-11-04', bis: '2026-11-07' }, { von: '2026-11-01', bis: '2026-11-05' }), true)
assert.equal(bel.ueberschneidet({ von: '2026-11-01', bis: '2026-11-10' }, { von: '2026-11-03', bis: '2026-11-04' }), true)
})
test('Sperre manuell blockiert, Abreisetag nicht', async () => {
await sp.legeSperreAn({ unterkunftId: 'u1', featureId: 'f1', von: '2026-11-10', bis: '2026-11-12', quelle: 'manuell' })
assert.equal(await bel.istFrei('u1', '2026-11-11', '2026-11-13', { now: NOW }), false)
assert.equal(await bel.istFrei('u1', '2026-11-12', '2026-11-14', { now: NOW }), true)
assert.equal(await bel.istFrei('u1', '2026-11-08', '2026-11-10', { now: NOW }), true)
assert.equal(await bel.istFrei('u2', '2026-11-11', '2026-11-13', { now: NOW }), true)
})
test('Anfragen: freigegeben mit Frist, gebucht, bezahlt blockieren; Rest nicht', async () => {
anfrage({ status: 'freigegeben', fristAt: ZUKUNFT, von: '2026-12-01', bis: '2026-12-03' })
anfrage({ status: 'freigegeben', fristAt: VERGANGENHEIT, von: '2026-12-05', bis: '2026-12-07' })
anfrage({ status: 'gebucht', von: '2026-12-10', bis: '2026-12-12' })
anfrage({ status: 'bezahlt', von: '2026-12-15', bis: '2026-12-17' })
for (const [i, s] of ['neu', 'abgelehnt', 'abgelaufen', 'storniert'].entries()) {
anfrage({ status: s, fristAt: ZUKUNFT, von: `2026-12-${20 + i}`, bis: `2026-12-${21 + i}` })
}
const frei = (v, b) => bel.istFrei('u1', v, b, { now: NOW })
assert.equal(await frei('2026-12-01', '2026-12-02'), false)
assert.equal(await frei('2026-12-05', '2026-12-06'), true)
assert.equal(await frei('2026-12-10', '2026-12-11'), false)
assert.equal(await frei('2026-12-15', '2026-12-16'), false)
assert.equal(await frei('2026-12-20', '2026-12-25'), true)
const b = await bel.belegteBereiche('u1', '2026-12-01', '2026-12-31', { now: NOW })
assert.deepEqual(b.map((x) => [x.von, x.bis, x.quelle]), [
['2026-12-01', '2026-12-03', 'reserviert'],
['2026-12-10', '2026-12-12', 'gebucht'],
['2026-12-15', '2026-12-17', 'gebucht'],
])
})
test('now als Zahl (ms) und Standard Date.now()', async () => {
anfrage({ status: 'freigegeben', fristAt: ZUKUNFT })
assert.equal(await bel.istFrei('u1', '2026-11-10', '2026-11-12', { now: NOW.getTime() }), false)
assert.equal(await bel.istFrei('u1', '2026-11-10', '2026-11-12', { now: Date.parse('2026-11-03T00:00:00Z') }), true)
anfrage({ status: 'gebucht', von: '2027-01-01', bis: '2027-01-03' })
assert.equal(await bel.istFrei('u1', '2027-01-01', '2027-01-02'), false)
})
test('ohneAnfrage ignoriert genau diese Anfrage', async () => {
const a = anfrage({ status: 'gebucht' })
anfrage({ status: 'gebucht', von: '2026-11-20', bis: '2026-11-22' })
assert.equal(await bel.istFrei('u1', '2026-11-10', '2026-11-12', { now: NOW }), false)
assert.equal(await bel.istFrei('u1', '2026-11-10', '2026-11-12', { now: NOW, ohneAnfrage: a.$id }), true)
assert.equal(await bel.istFrei('u1', '2026-11-20', '2026-11-22', { now: NOW, ohneAnfrage: a.$id }), false)
})
test('belegteBereiche: Quelle ical, Ausschnitt auf [von,bis), sortiert', async () => {
await sp.legeSperreAn({ unterkunftId: 'u1', featureId: 'f1', von: '2026-11-08', bis: '2026-11-14', quelle: 'ical:abc' })
await sp.legeSperreAn({ unterkunftId: 'u1', featureId: 'f1', von: '2026-11-20', bis: '2026-11-22', quelle: 'manuell' })
const b = await bel.belegteBereiche('u1', '2026-11-10', '2026-11-21', { now: NOW })
assert.deepEqual(b, [
{ von: '2026-11-10', bis: '2026-11-14', quelle: 'ical' },
{ von: '2026-11-20', bis: '2026-11-21', quelle: 'manuell' },
])
assert.deepEqual(bel.AKTIVE_STATUS, ['gebucht', 'bezahlt'])
})
test('Einstellungen: anlegen mit featureId als ID, JSON geparst, aendern', async () => {
assert.equal(await sp.ladeEinstellungen('f1'), null)
const e = await sp.speichereEinstellungen('f1', { firma: 'Haus am See', rechnungZaehler: { RE: 3 }, anfrage: { a: 1 } })
assert.equal(e.$id, 'f1')
assert.equal(e.featureId, 'f1')
assert.deepEqual(e.rechnungZaehler, { RE: 3 })
const roh = (await listDocuments(config.collections.ukEinstellungen))[0]
assert.equal(roh.rechnungZaehler, '{"RE":3}')
const e2 = await sp.speichereEinstellungen('f1', { ort: 'Stetten', stripeStatus: { ok: true } })
assert.equal(e2.firma, 'Haus am See')
assert.equal(e2.ort, 'Stetten')
assert.deepEqual((await sp.ladeEinstellungen('f1')).stripeStatus, { ok: true })
assert.equal(aw.docs('ukEinstellungen').size, 1)
})
test('Unterkuenfte: sortiert, nurAktive, icalImporte JSON, aendern per ID', async () => {
const b = await sp.speichereUnterkunft('f1', { name: 'B', sort: 2, aktiv: true })
const a = await sp.speichereUnterkunft('f1', { name: 'A', sort: 1, aktiv: false, icalImporte: [{ id: 'abc', url: 'https://x' }] })
await sp.speichereUnterkunft('f2', { name: 'Fremd', sort: 0, aktiv: true })
assert.deepEqual((await sp.listeUnterkuenfte('f1')).map((u) => u.name), ['A', 'B'])
assert.deepEqual((await sp.listeUnterkuenfte('f1', { nurAktive: true })).map((u) => u.name), ['B'])
assert.deepEqual((await sp.ladeUnterkunft(a.$id)).icalImporte, [{ id: 'abc', url: 'https://x' }])
const b2 = await sp.speichereUnterkunft('f1', { name: 'B2' }, b.$id)
assert.equal(b2.$id, b.$id)
assert.equal(b2.sort, 2)
assert.equal((await sp.ladeUnterkunft(b.$id)).name, 'B2')
assert.equal(await sp.ladeUnterkunft('gibtsnicht'), null)
})
test('Preise: 1:1 je Unterkunft, staffeln JSON, zweites Speichern aendert', async () => {
assert.equal(await sp.ladePreise('u1'), null)
const p = await sp.speicherePreise('u1', 'f1', { staffeln: [{ abNaechte: 1, nachtCent: 9000 }], reinigungCent: 5000 })
assert.deepEqual(p.staffeln, [{ abNaechte: 1, nachtCent: 9000 }])
const p2 = await sp.speicherePreise('u1', 'f1', { reinigungCent: 6000 })
assert.equal(p2.$id, p.$id)
assert.equal(p2.reinigungCent, 6000)
assert.deepEqual(p2.staffeln, [{ abNaechte: 1, nachtCent: 9000 }])
assert.equal(aw.docs('ukPreise').size, 1)
})
test('Sperren: liste, anlegen, loeschen', async () => {
const s = await sp.legeSperreAn({ unterkunftId: 'u1', featureId: 'f1', von: '2026-11-10', bis: '2026-11-12', quelle: 'manuell', notiz: 'Familie' })
await sp.legeSperreAn({ unterkunftId: 'u2', featureId: 'f1', von: '2026-11-10', bis: '2026-11-12', quelle: 'manuell' })
assert.equal((await sp.listeSperren('u1')).length, 1)
await sp.loescheSperre(s.$id)
assert.equal((await sp.listeSperren('u1')).length, 0)
})
test('Anfragen: anlegen, lesen, aendern, filtern, JSON geparst', async () => {
const a = await sp.legeAnfrageDokAn({ featureId: 'f1', unterkunftId: 'u1', nummer: 'A-1', von: '2026-11-10', bis: '2026-11-12', status: 'neu', gast: { name: 'Anna' }, posten: [{ t: 'x' }], summen: { brutto: 100 } })
assert.deepEqual(a.gast, { name: 'Anna' })
const roh = [...aw.docs('ukAnfragen').values()][0]
assert.equal(roh.gast, '{"name":"Anna"}')
const a2 = await sp.aktualisiereAnfrage(a.$id, { status: 'freigegeben', fristAt: ZUKUNFT, rechnungsadresse: { ort: 'X' } })
assert.equal(a2.status, 'freigegeben')
assert.deepEqual(a2.gast, { name: 'Anna' })
assert.deepEqual((await sp.ladeAnfrage(a.$id)).rechnungsadresse, { ort: 'X' })
assert.equal(await sp.ladeAnfrage('nix'), null)
anfrage({ status: 'gebucht', unterkunftId: 'u2' })
anfrage({ status: 'gebucht', featureId: 'f2' })
assert.equal((await sp.listeAnfragen('f1')).length, 2)
assert.equal((await sp.listeAnfragen('f1', { status: ['gebucht'] })).length, 1)
assert.equal((await sp.listeAnfragen('f1', { unterkunftId: 'u1' })).length, 1)
})