Kundenansicht neu: Pilot-Schalter (off/pilot/on) mit Randfall-Tests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f573d49f0a
commit
7c4a4a567d
3 files changed
+157
No files matched your search
@@ -34,6 +34,7 @@ const shopEnabled = (process.env.SHOP_ENABLED || '').trim().toLowerCase()
|
||||
const unterkunftEnabled = (process.env.UNTERKUNFT_ENABLED || '').trim().toLowerCase()
|
||||
const zeitenEnabled = (process.env.ZEITEN_ENABLED || '').trim().toLowerCase()
|
||||
const auftraegeEnabled = (process.env.AUFTRAEGE_ENABLED || '').trim().toLowerCase()
|
||||
const kundenansichtNeuEnabled = (process.env.KUNDENANSICHT_NEU || '').trim().toLowerCase()
|
||||
|
||||
/** Komma-Liste aus einer Umgebungsvariablen: getrimmt, klein geschrieben, ohne Leereintraege; leer ergibt den Vorgabewert. */
|
||||
function commaList(raw, fallback) {
|
||||
@@ -1123,6 +1124,15 @@ export const config = {
|
||||
keinNeubau: commaList(process.env.ZEITEN_KEIN_NEUBAU, ['emmas-schatzkiste']),
|
||||
},
|
||||
|
||||
// Neue Kundenansicht (Spec 2026-10-15): Schalter fuer die neue Oberflaeche; wird bei jedem Aufruf gelesen, siehe
|
||||
// server/services/kundenansicht/schalter.js. Der Modus off schlaegt jede Liste.
|
||||
kundenansichtNeu: {
|
||||
// off (Vorgabe) | pilot (nur KUNDENANSICHT_NEU_PILOT_EMAILS und die Mitarbeiter-Kundenansicht) | on (alle Kunden)
|
||||
mode: ['pilot', 'on'].includes(kundenansichtNeuEnabled) ? kundenansichtNeuEnabled : 'off',
|
||||
// Kunden-E-Mails fuer den Pilotbetrieb; '*' = alle
|
||||
pilotEmails: commaList(process.env.KUNDENANSICHT_NEU_PILOT_EMAILS, []),
|
||||
},
|
||||
|
||||
// Aufträge und Rechnungen: Schalter nur für die AB-Funktionen und die Rechnungsarten anzahlung/schluss; wird bei
|
||||
// jedem Aufruf gelesen, siehe server/services/auftraege/schalter.js
|
||||
auftraege: {
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { config } from '../../config.js'
|
||||
import { parsePortalSession } from '../../middleware/session.js'
|
||||
|
||||
/**
|
||||
* Pilot-Schalter der neuen Kundenansicht: KUNDENANSICHT_NEU = off (Vorgabe) | pilot | on, dazu die Komma-Liste
|
||||
* KUNDENANSICHT_NEU_PILOT_EMAILS ('*' = alle). Liest config.kundenansichtNeu bei jedem Aufruf. Der Modus off
|
||||
* schlaegt jede Liste; eine leere Liste im Pilot laesst nur die Mitarbeiter-Kundenansicht durch.
|
||||
*/
|
||||
|
||||
/** 'off' | 'pilot' | 'on'; alles andere (leer, unbekannt) gilt als off. */
|
||||
export function neueAnsichtModus() {
|
||||
const mode = config.kundenansichtNeu.mode
|
||||
return mode === 'pilot' || mode === 'on' ? mode : 'off'
|
||||
}
|
||||
|
||||
/** Nicht-leerer Text nach dem Trimmen? */
|
||||
const istText = (wert) => typeof wert === 'string' && wert.trim() !== ''
|
||||
|
||||
/** Listenvergleich im Pilot: '*' oder die getrimmte, klein geschriebene E-Mail steht in der Liste; ein Nicht-Text zaehlt als leer. */
|
||||
function stehtInPilotListe(email) {
|
||||
const erlaubt = config.kundenansichtNeu.pilotEmails
|
||||
if (erlaubt.includes('*')) return true
|
||||
const adresse = typeof email === 'string' ? email.trim().toLowerCase() : ''
|
||||
return adresse !== '' && erlaubt.includes(adresse)
|
||||
}
|
||||
|
||||
const istObjekt = (wert) => wert !== null && typeof wert === 'object' && !Array.isArray(wert)
|
||||
|
||||
/** Mitarbeiter-Kundenansicht ("Als Kunde ansehen") mit Kennung. */
|
||||
const istKundenansicht = (s) => s.viewAs === true && istText(s.viewId)
|
||||
|
||||
/** Angemeldeter Kunde (keine alte Mitarbeiter-Sitzung). */
|
||||
const istKundenSitzung = (s) => istText(s.customerId) && istText(s.appwriteUserId) && s.role !== 'admin'
|
||||
|
||||
/** Sieht diese Sitzung die neue Kundenansicht? Ungueltige Sitzungen: nie. */
|
||||
export function neueAnsichtFuerSession(session) {
|
||||
const modus = neueAnsichtModus()
|
||||
if (modus === 'off') return false
|
||||
if (!istObjekt(session)) return false
|
||||
const kundenansicht = istKundenansicht(session)
|
||||
if (!kundenansicht && !istKundenSitzung(session)) return false
|
||||
if (modus === 'on') return true
|
||||
return kundenansicht || stehtInPilotListe(session.email)
|
||||
}
|
||||
|
||||
/** Sieht diese Anfrage die neue Kundenansicht? req.session hat Vorrang, sonst das signierte Cookie. */
|
||||
export function neueAnsicht(req) {
|
||||
return neueAnsichtFuerSession(req?.session ?? parsePortalSession(req))
|
||||
}
|
||||
|
||||
/**
|
||||
* Fuer Jobs und Dienste ohne Cookie: gleiche Modus- und Listenregeln, aber ohne Sitzungspruefung und ohne
|
||||
* Mitarbeiter-Regel. Ohne nicht-leere customerId ist die Antwort in jedem Modus false.
|
||||
*/
|
||||
export function neueAnsichtFuerKunde(kunde) {
|
||||
const modus = neueAnsichtModus()
|
||||
if (modus === 'off') return false
|
||||
if (!istObjekt(kunde) || !istText(kunde.customerId)) return false
|
||||
if (modus === 'on') return true
|
||||
return stehtInPilotListe(kunde.email)
|
||||
}
|
||||
Reference in new issue
Block a user