{ "$schemaVersion": "1.0", "$kind": "poweron.workflow", "$exportedAt": "2026-04-16T10:00:00Z", "$gatewayVersion": "demo-2026-04", "label": "PWG Pilot: Jahresmietzinsbestätigung", "description": "Verarbeitet gescannte Rückantworten der Jahresmietzinsbestätigungen: OCR, Abgleich gegen Trustee-DB (Mieter + Mietzins-Buchungen), AI-Klassifikation pro Scan und Zustellung als CSV-Anhang im Outlook-Draft an die Sachbearbeitung. Pilot-Lieferung Sommer 2026.", "tags": ["pwg", "pilot", "mietzins", "trustee", "ocr"], "templateScope": "instance", "sharedReadOnly": false, "notifyOnFailure": true, "graph": { "nodes": [ { "id": "n1", "type": "trigger.manual", "x": 50, "y": 200, "title": "Manueller Start", "parameters": {} }, { "id": "n2", "type": "sharepoint.listFiles", "x": 320, "y": 200, "title": "Scan-Ordner auflisten", "parameters": { "connectionReference": "", "pathQuery": "PWG/Mietzinsbestaetigungen/Scans-Eingang" } }, { "id": "n3", "type": "flow.loop", "x": 590, "y": 200, "title": "Pro Scan-Dokument", "parameters": { "level": 1, "concurrency": 1 } }, { "id": "n4", "type": "sharepoint.downloadFile", "x": 860, "y": 200, "title": "PDF/Bild laden", "parameters": { "connectionReference": "", "pathQuery": "{{loop.item.path}}" } }, { "id": "n5", "type": "trustee.extractFromFiles", "x": 1130, "y": 200, "title": "OCR & Felder extrahieren", "parameters": { "featureInstanceId": "", "prompt": "Extrahiere die folgenden Felder aus dieser Jahresmietzinsbestätigung und antworte als JSON: tenantName (string), tenantAddress (string), objectAddress (string), confirmedRentAmount (number|null in CHF), currency ('CHF'), period (string z.B. '2026'), tenantNotes (string|null - alle handschriftlichen Anmerkungen oder Korrekturen), hasSignature (boolean - ist eine Unterschrift vorhanden?), documentDate (ISO date|null), ocrConfidence (number 0-1)." } }, { "id": "n6", "type": "trustee.queryData", "x": 1400, "y": 200, "title": "Referenzdaten Trustee-DB", "parameters": { "featureInstanceId": "", "mode": "lookup", "entity": "tenantWithRent", "tenantNameRef": "{{n5.output.tenantName}}", "tenantAddressRef": "{{n5.output.tenantAddress}}", "period": "{{n5.output.period}}", "rentAccountPattern": "6000-6099" } }, { "id": "n7", "type": "ai.prompt", "x": 1670, "y": 200, "title": "Prüfung & Klassifikation", "parameters": { "outputFormat": "json", "simpleMode": false, "documentList": "{{n5.output}}", "context": "{{n6.output}}", "aiPrompt": "Du bist ein Sachbearbeitungs-Assistent der Stiftung PWG. Deine Aufgabe ist es, eine eingescannte und OCR-extrahierte Jahresmietzinsbestätigung gegen die Stammdaten der Buchhaltung (Trustee-Feature) abzugleichen.\n\nEingaben:\n1. SCAN_DATEN (extrahiert per OCR aus dem Rückantwort-Dokument):\n{{scan}}\n\n2. REFERENZ_DATEN (aus Trustee-DB für diesen Mieter; ggf. leer wenn nicht eindeutig zuordenbar):\n{{reference}}\n\nVorgehen:\n1. Prüfe Identität: Stimmt SCAN_DATEN.tenantName + SCAN_DATEN.tenantAddress mit einem Datensatz in REFERENZ_DATEN.contacts überein? (Toleranz: kleine Tippfehler, Umlaute, Abkürzungen).\n2. Prüfe Mietzinsbetrag: Stimmt SCAN_DATEN.confirmedRentAmount mit dem aus REFERENZ_DATEN.expectedRentAmount erwarteten Mietzins überein? (Toleranz: ±1 CHF Rundung).\n3. Prüfe Unterschrift: hasSignature muss true sein.\n4. Prüfe OCR-Qualität: ocrConfidence < 0.6 -> 'unleserlich'.\n\nKlassifiziere in EXAKT EINEN Status:\n- 'bestaetigt': Identität stimmt, Betrag stimmt, Unterschrift vorhanden.\n- 'abweichung_betrag': Identität ok, Unterschrift ok, Betrag weicht ab.\n- 'abweichung_anmerkung': tenantNotes enthält substantielle Anmerkung (nicht leer, nicht reine Bestätigung).\n- 'keine_unterschrift': hasSignature == false.\n- 'unleserlich': OCR-Qualität ungenügend ODER Pflichtfelder fehlen.\n- 'kein_match': Mieter nicht in REFERENZ_DATEN auffindbar.\n\nBei Status != 'bestaetigt': Generiere einen kurzen, höflichen Antwortvorschlag (deutsch, Sie-Form, max. 5 Sätze, PWG-Stil) für die Sachbearbeitung. Bei 'bestaetigt': antwortVorschlag = null.\n\nAntworte AUSSCHLIESSLICH als JSON nach folgendem Schema:\n{\n \"tenantName\": string,\n \"objectAddress\": string,\n \"status\": \"bestaetigt\" | \"abweichung_betrag\" | \"abweichung_anmerkung\" | \"keine_unterschrift\" | \"unleserlich\" | \"kein_match\",\n \"scanRentAmount\": number | null,\n \"expectedRentAmount\": number | null,\n \"delta\": number | null,\n \"tenantNotes\": string | null,\n \"antwortVorschlag\": string | null,\n \"matchConfidence\": number,\n \"auditEvidence\": string\n}" } }, { "id": "n8", "type": "data.aggregate", "x": 1940, "y": 200, "title": "Ergebnisse sammeln (im Loop)", "parameters": { "mode": "collect" } }, { "id": "n9", "type": "data.consolidate", "x": 2210, "y": 200, "title": "CSV bauen (nach Loop)", "parameters": { "mode": "csvJoin", "separator": "\n" } }, { "id": "n10", "type": "email.draftEmail", "x": 2480, "y": 200, "title": "Draft an Sachbearbeitung", "parameters": { "connectionReference": "", "to": "sachbearbeiter@pwg.ch", "subject": "Mietzinsbestätigungen Auswertung {{currentDate}}", "body": "Hallo,\n\nim Anhang die Auswertung der eingegangenen Jahresmietzinsbestätigungen.\nPro Scan eine Zeile mit Status, Betragsabgleich und (bei Abweichung) Antwortvorschlag.\n\nBitte die Zeilen mit Status != 'bestaetigt' manuell sichten.\n\nFreundliche Grüße,\nPWG Automation", "emailStyle": "business", "attachments": [ { "name": "mietzinsbestaetigungen-auswertung", "mimeType": "text/csv", "csvFromVariable": "n9.output" } ] } } ], "connections": [ {"source": "n1", "target": "n2", "sourceOutput": 0, "targetInput": 0}, {"source": "n2", "target": "n3", "sourceOutput": 0, "targetInput": 0}, {"source": "n3", "target": "n4", "sourceOutput": 0, "targetInput": 0}, {"source": "n4", "target": "n5", "sourceOutput": 0, "targetInput": 0}, {"source": "n5", "target": "n6", "sourceOutput": 0, "targetInput": 0}, {"source": "n6", "target": "n7", "sourceOutput": 0, "targetInput": 0}, {"source": "n7", "target": "n8", "sourceOutput": 0, "targetInput": 0}, {"source": "n8", "target": "n9", "sourceOutput": 0, "targetInput": 0}, {"source": "n9", "target": "n10", "sourceOutput": 0, "targetInput": 0} ] }, "invocations": [] }