Vertrag: Auto-CANCELLED bei Kuendigungsbestaetigung + Cockpit-Filter
1) Auto-Status: Wird eine Kuendigungsbestaetigung hinzugefuegt (Datum ueber Formular und/oder Dokument-Upload), wird der Vertrag von ACTIVE auf CANCELLED gesetzt und das Vertragsende = Kuendigungsdatum. Zentrale Funktion maybeCancelOnCancellationConfirmation (idempotent, nur aus ACTIVE). Upload-Route ersetzt die alte Inline-Logik (setzt jetzt auch endDate); Update-Controller triggert nur bei neu/geaendertem Bestaetigungsdatum (manuelle Status-Korrekturen bleiben unangetastet). 2) Cockpit-Filter 'Kuendigungsbestaetigung': neue Liste cancellationConfirmations (Vertraege mit Bestaetigung in Status ACTIVE/DRAFT/CANCELLED) + Filter-Option im Cockpit-Dropdown. Eigene Liste, weil bereits CANCELLED-Vertraege mangels Issue sonst nicht in der Cockpit-Liste auftauchen. Beides lokal verifiziert (Helper: ACTIVE->CANCELLED + endDate; Cockpit: Vertrag erscheint in der Liste mit korrektem Status). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ import { logChange } from '../services/audit.service.js';
|
||||
import { sanitizeContract, sanitizeContractStrict, sanitizeContracts, sanitizeContractsStrict, stripHtml, sanitizeNotes, validateContractDocumentType, validateOptionalIsoDate, isContractIdentifierField, validateContractIdentifier, validatePortalUsername } from '../utils/sanitize.js';
|
||||
import { ApiError } from '../utils/apiError.js';
|
||||
import { canAccessContract, canAccessCustomer } from '../utils/accessControl.js';
|
||||
import { maybeActivateOnDeliveryConfirmation, withContractDocumentLock } from '../services/contractStatusScheduler.service.js';
|
||||
import { maybeActivateOnDeliveryConfirmation, maybeCancelOnCancellationConfirmation, withContractDocumentLock } from '../services/contractStatusScheduler.service.js';
|
||||
|
||||
/**
|
||||
* Walk-and-clean: strippt HTML/Script-/URI-Schemata in allen String-Werten
|
||||
@@ -232,6 +232,20 @@ export async function updateContract(req: AuthRequest, res: Response): Promise<v
|
||||
const sanitizedBody = sanitizeContractBody(req.body);
|
||||
const contract = await contractService.updateContract(contractId, sanitizedBody as any);
|
||||
|
||||
// Wenn über das Formular ein (neues/geändertes) Kündigungsbestätigungs-
|
||||
// datum gesetzt wurde: Vertrag ACTIVE → CANCELLED + Vertragsende =
|
||||
// Kündigungsdatum. Nur bei tatsächlicher Änderung des Datums auslösen,
|
||||
// damit manuelle Status-Korrekturen nicht sofort zurückgesetzt werden.
|
||||
{
|
||||
const asDay = (d: unknown) =>
|
||||
d ? new Date(d as string).toISOString().split('T')[0] : null;
|
||||
const beforeConf = asDay((before as any)?.cancellationConfirmationDate);
|
||||
const afterConf = asDay((sanitizedBody as any)?.cancellationConfirmationDate);
|
||||
if (afterConf && afterConf !== beforeConf) {
|
||||
await maybeCancelOnCancellationConfirmation(contractId, req);
|
||||
}
|
||||
}
|
||||
|
||||
// Geänderte Felder ermitteln
|
||||
const changes: Record<string, { von: unknown; nach: unknown }> = {};
|
||||
const fieldLabels: Record<string, string> = {
|
||||
|
||||
Reference in New Issue
Block a user