Öffnungszeiten: Schalter, Collections und Felder

ZEITEN_ENABLED/ZEITEN_PILOT_EMAILS/ZEITEN_KEIN_NEUBAU als config.zeiten (neben config.termine),
zeitenSetup (30 € einmalig), Collection-IDs oeffnungszeiten und zeitenErinnerungen, Schema der beiden
Collections plus fünf neue portalFeatures-Felder, scripts/zeiten-setup.mjs (idempotent, --check),
schemaKeys kennt die neuen Collections und Felder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-04 23:25:37 +00:00
1 parent 385f768d76
commit 4b4cd1058f
7 files changed
+649 -3

No files matched your search

+36
View File
@@ -30,6 +30,16 @@ function nonNegativeNumber(raw, fallback) {
}
const termineEnabled = (process.env.TERMINE_ENABLED || '').trim().toLowerCase()
const zeitenEnabled = (process.env.ZEITEN_ENABLED || '').trim().toLowerCase()
/** Komma-Liste aus einer Umgebungsvariablen: getrimmt, klein geschrieben, ohne Leereintraege; leer ergibt den Vorgabewert. */
function commaList(raw, fallback) {
const list = String(raw || '')
.split(',')
.map((s) => s.trim().toLowerCase())
.filter(Boolean)
return list.length ? list : fallback
}
// Abo-Produkte (Spec 2026-09-27 "Verträge, Hosting-Abo und E-Mail-Zusatzspeicher"). Preise in Cent,
// Endpreise gemäß § 19 UStG. Texte, die Kunden sehen, stimmen mit den Vertragsbedingungen überein.
@@ -116,6 +126,16 @@ const termineSetup = {
priceNickname: 'Terminplaner-Einrichtung 149 €',
}
// Oeffnungszeiten live: einmalige Einrichtung (Einmalpreis, kein Abo); im Wartungs-Abo ist die Funktion enthalten
const zeitenSetup = {
key: 'zeitenSetup',
name: 'Öffnungszeiten live – Einrichtung',
amountCents: 3000,
lookupKey: 'webklar_zeiten_einrichtung_3000',
oneTime: true,
priceNickname: 'Öffnungszeiten-Einrichtung 30 €',
}
// Ticketsystem (WOMS); eigene Konstante, weil auch die Enable-Banking-Rueckkehradresse darauf aufbaut
const womsBaseUrl = (process.env.WOMS_PUBLIC_URL || 'https://ticket.webklar.com').replace(/\/$/, '')
@@ -310,6 +330,9 @@ export const config = {
termineBookings: process.env.APPWRITE_COLLECTION_TERMINE_BOOKINGS || 'termineBookings',
termineClaims: process.env.APPWRITE_COLLECTION_TERMINE_CLAIMS || 'termineClaims',
termineOutbox: process.env.APPWRITE_COLLECTION_TERMINE_OUTBOX || 'termineOutbox',
// Oeffnungszeiten live (Einstellungen, Erinnerungsmerker; scripts/zeiten-setup.mjs)
oeffnungszeiten: process.env.APPWRITE_COLLECTION_OEFFNUNGSZEITEN || 'oeffnungszeiten',
zeitenErinnerungen: process.env.APPWRITE_COLLECTION_ZEITEN_ERINNERUNGEN || 'zeitenErinnerungen',
},
publicBaseUrl: (process.env.PORTAL_PUBLIC_URL || 'https://project.webklar.com').replace(/\/$/, ''),
@@ -326,6 +349,7 @@ export const config = {
mailStorage,
newsSetup,
termineSetup,
zeitenSetup,
ustHinweis,
// Register der kaufbaren Funktionen (siehe oben)
features,
@@ -551,6 +575,18 @@ export const config = {
minAntwortMs: nonNegativeNumber(process.env.TERMINE_MIN_ANTWORT_MS, 300),
},
// Oeffnungszeiten live (Funktionsschluessel 'zeiten'); Geschwister von termine (termineSchalter.test.js pinnt
// config.termine). Wird bei jedem Aufruf gelesen; Schalter siehe server/services/zeiten/schalter.js
zeiten: {
// off (Vorgabe) | pilot (nur ZEITEN_PILOT_EMAILS) | on (alle Kunden)
mode: ['pilot', 'on'].includes(zeitenEnabled) ? zeitenEnabled : 'off',
// Kunden-E-Mails fuer den Pilotbetrieb; '*' = alle
pilotEmails: commaList(process.env.ZEITEN_PILOT_EMAILS, []),
// Subdomains, fuer die der Neubau nie angestossen wird (Einbau von Hand); ZEITEN_KEIN_NEUBAU ist eine
// Komma-Liste, die Vorgabe ist emmas-schatzkiste
keinNeubau: commaList(process.env.ZEITEN_KEIN_NEUBAU, ['emmas-schatzkiste']),
},
invoiceNinja: {
url: (process.env.INVOICE_NINJA_URL || 'https://invoice.webklar.com').replace(/\/$/, ''),
apiToken: process.env.INVOICE_NINJA_API_TOKEN || '',