import { listeAnfragenNachStatus, listeSperren } from './speicher.js' /** Status, die die Unterkunft endgueltig belegen. 'freigegeben' blockiert nur bis fristAt. */ export const AKTIVE_STATUS = ['gebucht', 'bezahlt'] /** Halboffene Intervalle [von,bis) auf Tagesstrings: Abreisetag gleich Anreisetag ueberschneidet nicht. */ export const ueberschneidet = (a, b) => a.von < b.bis && b.von < a.bis /** * Belegte Bereiche einer Unterkunft im Fenster [von,bis), auf das Fenster zugeschnitten, nach von sortiert. * Quellen: manuell, ical (Sperre mit quelle 'ical:'), gebucht (gebucht|bezahlt), reserviert (freigegeben mit fristAt in der Zukunft). * ohneAnfrage: ID einer Anfrage, die nicht zaehlt (z. B. beim Freigeben der Anfrage selbst). now: Date oder ms. */ export async function belegteBereiche(unterkunftId, von, bis, { ohneAnfrage, now = Date.now() } = {}) { const jetzt = now instanceof Date ? now.getTime() : now const fenster = { von, bis } const roh = [] // nur was nach dem Fensteranfang endet (Index auf bis): alles andere kann das Fenster nicht beruehren for (const s of await listeSperren(unterkunftId, { bisNach: von })) { roh.push({ von: s.von, bis: s.bis, quelle: String(s.quelle ?? '').startsWith('ical') ? 'ical' : 'manuell' }) } for (const a of await listeAnfragenNachStatus(unterkunftId, [...AKTIVE_STATUS, 'freigegeben'], { bisNach: von })) { if (ohneAnfrage && a.$id === ohneAnfrage) continue if (a.status === 'freigegeben') { const frist = Date.parse(a.fristAt) if (!(frist > jetzt)) continue roh.push({ von: a.von, bis: a.bis, quelle: 'reserviert' }) } else { roh.push({ von: a.von, bis: a.bis, quelle: 'gebucht' }) } } return roh .filter((r) => r.von && r.bis && ueberschneidet(r, fenster)) .map((r) => ({ von: r.von > von ? r.von : von, bis: r.bis < bis ? r.bis : bis, quelle: r.quelle })) .sort((a, b) => (a.von < b.von ? -1 : a.von > b.von ? 1 : 0)) } export async function istFrei(unterkunftId, von, bis, opts = {}) { return (await belegteBereiche(unterkunftId, von, bis, opts)).length === 0 }