Skip to content

Finalisierungsablauf

Der Pfad für Kundensignatur und Finalisierung umfasst customer-view/signatures, den route-basierten Finalize-Start und die Composables der Finalisierungsseite.

Die vorgeschalteten Signatur-/Finalize-Guards sind zentral in app/utils/protocolWorkflow.ts gebündelt. Signaturseite, Middleware und Editor verwenden dadurch denselben Pfad für Setup-Load, Kündigungsgrund-Blockade und Step-Zielpfade.

Signaturseite

app/pages/customer-view/signatures.vue ist der letzte bearbeitbare Schritt vor der Finalisierung.

Aufgaben:

  • rendert Signaturen von Mieter, Vermieter und dynamischen Vertragspartnern
  • speichert den Signaturzustand über signatureStore.$saveToServer()
  • wechselt zwischen handschriftlichem Signaturmodus und manuellem Signaturmodus
  • validiert den Kündigungsgrund vor der Freigabe für Finalize über den gemeinsamen Workflow-Guard
  • übergibt den gewählten Finalize-Modus als finalizeMode-Query, bevor nach /finalize umgeleitet wird

Der persistente Signaturzustand ist dafür in app/composables/media/pdf/useCustomerSignatureSession.ts gekapselt und nicht mehr mit der PDF-Erzeugung vermischt.

Ablaufdiagramm

Finalize-Routen- und Acceptance-Zustand

Der fachliche Finalize-Zustand wird aus den Acceptance-Metadaten abgeleitet:

  • lockedAt: finalisiert und für Bearbeitung gesperrt
  • uploadPendingAt: gesperrt, aber der Upload steht noch aus
  • ohne beide Werte: weiter editierbar

app/utils/acceptanceStatus.ts bündelt diese Ableitung über getAcceptanceFinalizeState(...). Browser Storage enthält keinen fachlichen Finalisierungsstatus.

app/utils/finalizeRoute.ts hält nur den expliziten Startmodus aus der Route:

  • finalizeMode=auto: automatische Finalisierung starten
  • finalizeMode=manual: Protokoll sperren und Upload später manuell starten

Ohne gesperrte Acceptance und ohne gültigen finalizeMode leitet die Middleware /finalize zurück nach /customer-view/signatures.

Aufbau der Finalize-Seite

app/pages/finalize.vue bleibt eine schlanke Page-Shell: Sie delegiert das Verhalten an useFinalizePage() und setzt die großen Präsentationsblöcke zusammen.

Die wichtigsten Orchestrierungsbausteine sind:

  • useFinalizePage.ts
  • useFinalizePageFlow.ts
  • useAcceptanceFinalize.ts
  • useFinalizePagePreview.ts
  • useFinalizePageArchive.ts
  • useFinalizePageUnlock.ts

Die Präsentation ist in fokussierte Komponenten ausgelagert:

  • app/components/Finalize/FinalizeStatusHero.vue: Status, Fortschritt, Retry-Hinweis und Hauptaktionen
  • app/components/Finalize/FinalizeDispatchSummary.vue: deklarative Versandzusammenfassung nach erfolgreicher Finalisierung
  • app/components/Finalize/FinalizePdfPreviewSection.vue: Preview-Tabs und Versandart-Auswahl
  • app/components/Finalize/FinalizePdfPreviewPane.vue: gemeinsamer Wrapper über PdfPreviewFrame und PdfPageCanvas für externes PDF und Zählerstands-PDF

Finalisierungs-, Upload-, Archivierungs- und Unlock-Logik gehört weiter in die Composables, nicht in die Präsentationskomponenten.

Preflight-Verhalten

useFinalizePageFlow.ts führt einen Preflight aus, bevor die eigentliche Finalisierung startet.

Geprüft werden:

  • gültige Acceptance-ID
  • aktuelle Acceptance-Metadaten
  • ob die Acceptance bereits finalisiert ist
  • ob die Acceptance bereits auf manuellen Upload wartet
  • ob der Client offline ist

Wenn sich die Acceptance bereits im Pending-Upload-Zustand befindet, wechselt die Finalize-Seite in einen manuellen Vorschauzustand, statt die komplette Pipeline erneut auszuführen.

Automatische Finalisierung

useAcceptanceFinalize.ts führt die komplette Finalisierungspipeline in dieser Reihenfolge aus:

Für die PDF-Erzeugung verwendet der Composable app/composables/media/pdf/useCustomerPdfPreview.ts, also denselben Generierungspfad wie die Kundenansicht, aber ohne den Signatur-Session-Code mitzuschleppen.

  1. lokale Änderungen auf den Server speichern
  2. internes PDF erzeugen
  3. externes PDF erzeugen
  4. beide PDFs mit Retry-Unterstützung hochladen
  5. Acceptance erneut synchronisieren
  6. die Finalize-Stufe auf done setzen

Im Code verfolgte Finalize-Stufen:

  • idle
  • syncing
  • generatingIntern
  • generatingExtern
  • uploading
  • finalSync
  • done
  • error

Manuelle Finalisierung

Manuelle Finalisierung ist nicht nur ein UI-Label. Dafür existiert ein eigener Implementierungspfad.

useFinalizePageFlow.ts:

  • speichert lokale Änderungen auf den Server
  • ruft acceptanceApi.markPendingUpload(acceptanceId) auf
  • synchronisiert den Acceptance-Zustand erneut
  • bereitet eine externe Vorschau vor, ohne PDFs hochzuladen

Dadurch entsteht eine Acceptance, die für Bearbeitung gesperrt und als wartend auf Upload markiert ist.

Retry-Verhalten beim Upload

app/composables/protocol/finalizeUpload.ts lädt das Finalize-Payload per XHR hoch.

Retry-Verhalten:

  • wiederholt Fehler ohne numerischen Status
  • wiederholt 408, 429 und 5xx
  • stoppt nach maxRetries
  • markiert das Ausschöpfen der Retries mit uploadRetryAbort

maxRetries wird aus runtimeConfig.public.finalizeUploadRetryLimit abgeleitet.

Verhalten bei gesperrten Acceptances

Sobald die Acceptance gesperrt ist, wird die Finalize-Seite zum kanonischen Ziel dieser Acceptance.

  • finalisierte Acceptances zeigen den gespeicherten Abschlusszustand
  • Acceptances im Pending-Upload-Zustand zeigen manuellen Bereitschaftszustand und Vorschau
  • /customer-view* und / werden von der Middleware weg umgeleitet