gateway/demoData/workflows/pwg-mietzinsbestaetigung-pilot.workflow.json
2026-04-20 00:31:05 +02:00

152 lines
7.2 KiB
JSON

{
"$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": []
}