Appearance
Kundenansicht und Signaturen
Die Kundenansicht besteht aus der Parent-Route app/pages/customer-view.vue, der PDF-Vorschau app/pages/customer-view/index.vue und der Signaturseite app/pages/customer-view/signatures.vue.
Navigation in die Kundenansicht
Der gemeinsame Einstieg liegt in app/composables/protocol/useCustomerViewNavigation.ts.
Dieser Flow wird aus Editor und Top-Bar verwendet und macht vor der Navigation:
- Acceptance-ID normalisieren
- gesperrte Acceptances direkt nach
/finalizeschicken - aktuelle Drafts über
persistCurrentAcceptanceDrafts()lokal sichern - Kündigungsgrund-Workflow über
resolveProtocolWorkflowBlockRedirect(...)prüfen - optional per
useFormSave().saveCurrentAcceptance(...)speichern
Die Runtime-Flags steuern das Verhalten:
autoSaveOnCustomerView: speichert vor dem Wechsel automatischallowUnsavedCustomerView: erlaubt den Wechsel trotz Save-Fehlern oder ausstehenden Änderungen
Wenn der Auto-Save erfolgreich war, hängt der Flow saved=true an die Query. customer-view.vue zeigt daraus einen Erfolgshinweis.
Parent-Route
app/pages/customer-view.vue lädt beim Wechsel der Acceptance:
- ausstehende lokale Drafts
acceptanceStore.sync(acceptanceId)- Lock-Status der Acceptance
Wenn die Acceptance gesperrt oder im manuellen Upload-Zustand ist, ersetzt die Route das Ziel durch /finalize?acceptance=<id>.
Die Parent-Route zeigt außerdem Tabs für:
- Vorschau:
/customer-view - Signaturen:
/customer-view/signatures
Bei Online-Betrieb kann sie ungespeicherte Änderungen blockieren, wenn allowUnsavedCustomerView deaktiviert ist. Offline darf die Kundenansicht weiter geöffnet werden und zeigt einen Hinweis.
PDF-Vorschau
app/pages/customer-view/index.vue erzeugt die PDF-Vorschau über useCustomerPdfPreview().
Unterstützte Varianten:
extern: Kundenvorschauintern: interne Vorschau
Die Vorschau nutzt:
PdfPreviewFrame.vuefür Toolbar, Ladezustand und ViewportPdfPageCanvas.vuefür seitenweises Rendering- Zoom, Pan-Modus, Seitennavigation, Öffnen und Download
Beim Verlassen der Route wird eine laufende PDF-Generierung über cancelPreviewGeneration() abgebrochen.
Vor dem Wechsel zur Signaturseite prüft die Vorschau erneut den gemeinsamen Workflow-Guard für den Schritt signatures.
Signaturzustand
app/composables/media/pdf/useCustomerSignatureSession.ts kapselt den persistenten Signaturzustand.
Die Signaturseite verwaltet:
- Mieter-Signatur
- Vermieter-Signatur
- dynamische Vertragspartner-Signaturen
- optionale Dienstleister-Signatur
- manuelle Signatur als Read-only-/Papiermodus
- Proxy-Signatur mit Nachweis-Upload
- optionalen Verweigerungsgrund, wenn für den Protokolltyp globale Vorlagen im Bereich
signature_refusal_reasonsgepflegt sind
Signaturänderungen werden zuerst lokal über den Signature-Store persistiert. Vor Navigation oder Auto-Save werden pending Draft-Saves geleert, damit der Acceptance-Save den aktuellen Stand sieht.
Verweigerungsgründe werden pro Protokolltyp über Einstellungen > Vorlagen im Bereich Verweigerungsgründe verwaltet. Wenn dort aktive Einträge vorhanden sind, zeigt SignatureInput.vue bei verweigerter Unterschrift eine optionale Auswahl an und speichert ID und Label im Signatur-Payload.
Dienstleister-Signatur
Die Signaturseite lädt Wohnungszuordnungen über:
ts
GET /billing-providers/flat-assignmentsEine Dienstleister-Signatur wird verlangt, wenn:
- ein aktiver Dienstleister der Wohnung zugeordnet ist
- dessen Protokolltyp-Regel
signatureRequiredaktiv ist - ein relevanter Zählertyp im Protokoll einen Wert enthält
Wenn die Signatur fehlt, blockiert die Seite die Finalisierung und zeigt einen Warnhinweis.
Finalize-Zugang
Die Signaturseite bietet zwei Wege:
manual: Protokoll sperren und später manuell hochladenauto: vollständige Finalisierung mit PDF-Upload starten
Vor dem Wechsel nach /finalize:
- Signaturen speichern
- Dienstleister-Pflicht prüfen
- Finalize-Modus als
finalizeMode=auto|manualin die Route schreiben - nach
/finalizenavigieren
Die Middleware erlaubt /finalize nur mit gesperrter Acceptance oder explizitem finalizeMode-Start. Der fachliche Sperrstatus kommt aus lockedAt und uploadPendingAt, nicht aus Browser Storage.