Files
Webklar-Kundenbereich/server/services/unterkunft/schema.js
T

159 lines
5.2 KiB
JavaScript

/**
* Buchungskalender: Appwrite-Schema der sechs Collections (Spezifikation 2026-10-07-buchungskalender-design.md, Abschnitt 3).
* Reine Daten, absichtlich ohne Import von server/config.js (wie shop/schema.js: test/support/schema.js liest sie vor
* useTestEnv()). Die Collection-IDs stehen in config.collections.<Name>; scripts/unterkunft-setup.mjs legt alles an.
* Kein Feld heisst data; JSON-Felder sind Text. ukEinstellungen: Dokument-ID = featureId.
*
* Attribut: { key, type: 'string' | 'integer' | 'boolean' | 'datetime', size (nur Text), required: false }
* Index: { key, type: 'key', attributes: [...] }
* Datumswerte (dt) sind UTC (toISOString()); Kalendertage (von, bis, datum) sind Text YYYY-MM-DD (Berlin).
*/
const str = (key, size) => ({ key, type: 'string', size, required: false })
const int = (key) => ({ key, type: 'integer', required: false })
const bool = (key) => ({ key, type: 'boolean', required: false })
const dt = (key) => ({ key, type: 'datetime', required: false })
const index = (key, ...attributes) => ({ key, type: 'key', attributes })
export const UNTERKUNFT_COLLECTIONS = {
ukUnterkuenfte: {
attributes: [
str('featureId', 36),
str('customerId', 36),
str('projectId', 36),
str('name', 120),
str('beschreibung', 500),
int('maxPersonen'),
int('mindestNaechte'),
str('checkIn', 5),
str('checkOut', 5),
int('sort'),
bool('aktiv'),
str('icalImporte', 4000),
str('icalExportToken', 64),
],
indexes: [index('idx_feature', 'featureId'), index('idx_export_token', 'icalExportToken')],
},
ukPreise: {
attributes: [
str('unterkunftId', 36),
str('featureId', 36),
str('staffeln', 2000),
int('reinigungCent'),
int('personenInklusive'),
int('aufpreisPersonNachtCent'),
int('direktrabattProzent'),
str('steuerart', 20),
int('ustUebernachtung'),
int('ustReinigung'),
int('fristTage'),
str('stornobedingungen', 5000),
],
indexes: [index('idx_unterkunft', 'unterkunftId')],
},
ukSperren: {
attributes: [
str('unterkunftId', 36),
str('featureId', 36),
str('von', 10),
str('bis', 10),
str('quelle', 60),
str('notiz', 200),
],
indexes: [index('idx_unterkunft', 'unterkunftId'), index('idx_unterkunft_quelle', 'unterkunftId', 'quelle')],
},
ukAnfragen: {
attributes: [
str('featureId', 36),
str('customerId', 36),
str('projectId', 36),
str('unterkunftId', 36),
str('nummer', 12),
str('von', 10),
str('bis', 10),
int('personen'),
str('status', 12),
str('gast', 3000),
str('rechnungsadresse', 1500),
str('posten', 8000),
str('summen', 1000),
str('nachrichtVermieter', 2000),
dt('fristAt'),
str('tokenHash', 64),
str('zahlart', 8),
str('bezahltVia', 8),
dt('bezahltAt'),
str('stripeSessionId', 100),
str('stripePaymentIntentId', 100),
int('erstattetCent'),
str('stornoGrund', 500),
str('stornobedingungenText', 5000),
str('rechtstexteFassung', 20),
str('ipHash', 16),
dt('freigegebenAt'),
dt('gebuchtAt'),
dt('abgelehntAt'),
dt('abgelaufenAt'),
dt('storniertAt'),
str('rechnungId', 36),
dt('anonymisiertAt'),
],
indexes: [
index('idx_feature', 'featureId'),
index('idx_unterkunft', 'unterkunftId'),
index('idx_unterkunft_status', 'unterkunftId', 'status'),
index('idx_status', 'status'),
],
},
ukRechnungen: {
attributes: [
str('featureId', 36),
str('anfrageId', 36),
str('art', 8),
str('nummer', 24),
str('datum', 10),
int('bruttoCent'),
str('inhalt', 20000),
],
indexes: [index('idx_feature', 'featureId'), index('idx_anfrage', 'anfrageId'), { key: 'uniq_feature_nummer', type: 'unique', attributes: ['featureId', 'nummer'] }],
},
ukEinstellungen: {
attributes: [
str('featureId', 36),
str('firma', 150),
str('inhaber', 150),
str('strasse', 150),
str('plz', 10),
str('ort', 100),
str('email', 200),
str('telefon', 50),
str('steuernummer', 30),
str('ustId', 20),
str('iban', 34),
str('bic', 11),
str('bank', 100),
str('rechnungsPraefix', 8),
str('rechnungZaehler', 100),
str('akzentfarbe', 7),
str('stripeAccountId', 40),
str('stripeStatus', 4000),
bool('onlineZahlung'),
dt('rechnungAuftragAt'),
str('anfrage', 2000),
str('anfrageStatus', 16),
dt('anfrageAt'),
dt('anfrageEntschiedenAt'),
str('anfrageEntschiedenVon', 120),
str('anfrageBegruendung', 1000),
dt('icalFehlerMailAt'),
],
// idx_account: account.updated des Connect-Webhooks findet die Einstellungen eines Kontos
indexes: [index('idx_feature', 'featureId'), index('idx_account', 'stripeAccountId')],
},
}
/** Je Collection die datetime-Attribute (der Appwrite-Nachbau der Tests normalisiert sie). */
export const UNTERKUNFT_DATETIMES = Object.fromEntries(
Object.entries(UNTERKUNFT_COLLECTIONS).map(([name, { attributes }]) => [name, attributes.filter((a) => a.type === 'datetime').map((a) => a.key)]),
)