Vertrag: „Portaldaten nicht möglich / nicht benötigt"-Opt-out
Dritter Radio-Button in der Zugangsdaten-Card des Vertragsformulars. Wenn gesetzt, unterdrückt das Cockpit die Warnung „Portal-Zugangs- daten fehlen" für diesen Vertrag – für Anbieter ohne Portal oder Kunden, die bewusst keine Zugangsdaten pflegen. Verstopft das Cockpit sonst dauerhaft. Neues Feld Contract.portalCredentialsNotRequired (Boolean, default false) + idempotente Migration (ADD COLUMN IF NOT EXISTS). Bestand bleibt auf false, Warnung greift wie bisher. Beim Umschalten auf Opt-out werden portalUsername, portalPasswordEncrypted und stressfreiEmailId server-seitig explizit auf NULL gesetzt – Datenhygiene, damit keine verwaisten Anmeldedaten in der DB stehen bleiben. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -233,6 +233,7 @@ interface ContractCreateData {
|
||||
portalUsername?: string;
|
||||
portalPassword?: string;
|
||||
stressfreiEmailId?: number;
|
||||
portalCredentialsNotRequired?: boolean;
|
||||
notes?: string;
|
||||
// Kündigungsdaten
|
||||
cancellationConfirmationDate?: Date;
|
||||
@@ -461,12 +462,26 @@ export async function updateContract(
|
||||
? encrypt(portalPassword)
|
||||
: undefined;
|
||||
|
||||
// Opt-out „Portaldaten nicht benötigt": Alte Anmeldedaten explizit
|
||||
// wegräumen, damit nach dem Umschalten kein verwaister verschlüsselter
|
||||
// Blob + Username in der DB stehen bleibt. Nur greifen, wenn das Flag
|
||||
// in diesem Update wirklich auf true gesetzt wird (nicht bei jedem PUT).
|
||||
const clearCredentials = contractData.portalCredentialsNotRequired === true;
|
||||
|
||||
// Update main contract
|
||||
await prisma.contract.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...contractData,
|
||||
...(portalPasswordEncrypted ? { portalPasswordEncrypted } : {}),
|
||||
...(clearCredentials
|
||||
? {
|
||||
portalUsername: null,
|
||||
portalPasswordEncrypted: null,
|
||||
stressfreiEmailId: null,
|
||||
}
|
||||
: portalPasswordEncrypted
|
||||
? { portalPasswordEncrypted }
|
||||
: {}),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -443,18 +443,24 @@ export async function getCockpitData(opts?: { customerIds?: number[] }): Promise
|
||||
}
|
||||
|
||||
// 3. FEHLENDE PORTAL-ZUGANGSDATEN
|
||||
// Benutzername kann entweder manuell (portalUsername) oder via Stressfrei-Wechseln E-Mail (stressfreiEmailId) gesetzt sein
|
||||
const hasUsername = contract.portalUsername || contract.stressfreiEmailId;
|
||||
const hasPassword = contract.portalPasswordEncrypted;
|
||||
// Benutzername kann entweder manuell (portalUsername) oder via Stressfrei-Wechseln E-Mail (stressfreiEmailId) gesetzt sein.
|
||||
// Vertragsseitiges Opt-out: wenn der Anbieter kein Portal hat oder der
|
||||
// Kunde bewusst keine Zugangsdaten pflegt, unterdrückt
|
||||
// `portalCredentialsNotRequired` die Warnung. So verstopft die Zeile
|
||||
// nicht dauerhaft das Cockpit.
|
||||
if (!contract.portalCredentialsNotRequired) {
|
||||
const hasUsername = contract.portalUsername || contract.stressfreiEmailId;
|
||||
const hasPassword = contract.portalPasswordEncrypted;
|
||||
|
||||
if (!hasUsername || !hasPassword) {
|
||||
issues.push({
|
||||
type: 'missing_portal_credentials',
|
||||
label: 'Portal-Zugangsdaten fehlen',
|
||||
urgency: 'warning',
|
||||
details: 'Benutzername oder Passwort für das Anbieter-Portal fehlt',
|
||||
});
|
||||
summary.byCategory.missingCredentials++;
|
||||
if (!hasUsername || !hasPassword) {
|
||||
issues.push({
|
||||
type: 'missing_portal_credentials',
|
||||
label: 'Portal-Zugangsdaten fehlen',
|
||||
urgency: 'warning',
|
||||
details: 'Benutzername oder Passwort für das Anbieter-Portal fehlt',
|
||||
});
|
||||
summary.byCategory.missingCredentials++;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. KEINE KUNDENNUMMER BEIM ANBIETER
|
||||
|
||||
Reference in New Issue
Block a user