Wiki source code of BMD_Rimo_Invoices
Version 40.2 by Patrizia Gurschka on 2026/10/05 13:43
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | |(% style="width:772px" %)((( | ||
| 2 | {{box cssClass="floatinginfobox" title="**Auf dieser Seite**"}} | ||
| 3 | {{toc/}} | ||
| 4 | {{/box}} | ||
| 5 | |||
| 6 | = **đ§Ÿ**BMD â Rimo Invoices (Rechnungsautomatisierung) = | ||
| 7 | |||
| 8 | {{info}} | ||
| 9 | **Zweck: **Automatisierte Ăbertragung von BMD-Eingangsrechnungen nach Rimo â Download, Upload und Freigabe (Approval), vollstĂ€ndig zustandsbehaftet. | ||
| 10 | |||
| 11 | **Zielgruppe: **Buchhaltung/Fibu-Team und IT/Fabric-Betrieb. | ||
| 12 | {{/info}} | ||
| 13 | ))) | ||
| 14 | |||
| 15 | == Ăberblick == | ||
| 16 | |||
| 17 | **BMD â Rimo Invoices** ist eine Fabric-Notebook-gesteuerte Automatisierung mit zwei begleitenden Data-Factory-Pipelines. Die Lösung besteht aus: | ||
| 18 | |||
| 19 | * **Notebook: **Python/PySpark (Microsoft Fabric) | ||
| 20 | * **Datenquelle: **Fabric Lakehouse (Spark SQL) | ||
| 21 | * **Orchestrierung: **2 Data-Factory-Pipelines | ||
| 22 | * **Zielsystem: **Rimo REST-API (Test/Dev) | ||
| 23 | |||
| 24 | == Architektur == | ||
| 25 | |||
| 26 | [[image:1791200276107-433.png]] | ||
| 27 | |||
| 28 | == Technologiestack == | ||
| 29 | |||
| 30 | Seit dem 25.09.2026 lĂ€uft das Notebook auf Fabric Runtime 2.0 (Spark 4, Python 3.13); die SQL-Abfragen wurden dafĂŒr von parametrisierten Abfragen auf f-Strings umgestellt. | ||
| 31 | |||
| 32 | * **Notebook/Backend:** Python, PySpark (Spark SQL), requests, notebookutils, Python-Logging mit eigenem Logger | ||
| 33 | * **Datenplattform:** Fabric Lakehouse, Delta-Tabellen bmd.fibu_erb_buchungen, bmd.fibu_erk_konto, rimo.sdmcompany, rimo.sdmcreditor, rimo.sdmaccount, rimo.sdmsalesorder, rimo.sdmprojectpurchaseorder, spl_gold_lh.bmd.rimo_processed_invoices_log | ||
| 34 | * **Orchestrierung:** Fabric Data Factory (Copy-Data, Notebook-AktivitÀt, If-Condition, Office-365-Outlook-AktivitÀt) | ||
| 35 | * **Externe API:** Rimo REST-API (multipart/form-data fĂŒr Upload, JSON fĂŒr Approvals) | ||
| 36 | |||
| 37 | == Hauptfunktionen == | ||
| 38 | |||
| 39 | Jeder Lauf durchlÀuft nach den Health-Checks drei fachliche Phasen; jede Rechnung trÀgt ihren Stand in der State-Datei, sodass ein abgebrochener Lauf beim nÀchsten Mal genau dort weitermacht. | ||
| 40 | |||
| 41 | === 1. Datenerfassung === | ||
| 42 | |||
| 43 | Buchungszeilen werden aus bmd.fibu_erb_buchungen gelesen: alle Buchungen ohne âSpesenâ im Buchungstext, einschlieĂlich Buchungen **ohne** Buchungstext, mit Erstelldatum ab 27.08.2026, 10:00 Uhr (offenes Zeitfenster). Bereits verarbeitete Zeilen werden per LEFT JOIN gegen spl_gold_lh.bmd.rimo_processed_invoices_log ausgeschlossen; bei mehreren Dateien zum selben Beleg wird die .pdf-Variante bevorzugt. Jede Zeile erhĂ€lt den SchlĂŒssel //intBelegNr_Firmennr// und wird in die Warteschlange der State-Datei ĂŒbernommen. | ||
| 44 | |||
| 45 | Buchungen ohne Buchungstext werden ohne userLabel an Rimo ĂŒbergeben; das Feld fehlt dann im Request. | ||
| 46 | |||
| 47 | === 2. Download-Phase (Belegdokument) === | ||
| 48 | |||
| 49 | Notebooks können den On-Premises Data Gateway nicht nutzen. Deshalb kopiert die vorgelagerte Copy-Data-AktivitĂ€t die Dateien vom Dateiserver (\atwotbmd01\BMDDocs\0\2...) gesammelt ins Lakehouse, anhand eines Abgleichs von bmd.fibu_erb_buchungen mit der Log-Tabelle. Die Download-Phase prĂŒft nur, ob die erwartete Datei im Lakehouse-Zielordner angekommen ist. | ||
| 50 | |||
| 51 | === 3. Upload-Phase (Rechnungsdaten) === | ||
| 52 | |||
| 53 | BMD-Felder werden auf Rimo-Felder gemappt, Firmen- und Kreditor-IDs per Lakehouse-Lookup ergĂ€nzt und Beleg plus Daten per multipart/form-data an POST /v1/invoices ĂŒbergeben. Ein erfolgreicher Upload liefert die Rimo-externalId. | ||
| 54 | |||
| 55 | === 4. Approval-Phase (Freigaben) === | ||
| 56 | |||
| 57 | Pro Buchungszeile in bmd.fibu_erk_konto (verknĂŒpft ĂŒber ErfassNr) wird eine eigene Freigabe an Rimo gesendet, mit mehrstufigem Fallback fĂŒr die Bestellnummer- und Sales-Order-Zuordnung (siehe Besondere GeschĂ€ftslogik). Die Approval-Phase lĂ€uft im Modus âallâ mit. | ||
| 58 | |||
| 59 | == Health-Checks und technische Fehlererkennung == | ||
| 60 | |||
| 61 | Vor jeder Verarbeitung prĂŒft das Notebook Verbindungen, Tabellen und die eigenen SQL-Abfragen. Ein kritischer Fehler bricht den Lauf ab, bevor eine Rechnung angefasst wird; so landen bei Systemumstellungen (z. B. Runtime-Wechsel) keine Rechnungen fĂ€lschlich in dead_letter. | ||
| 62 | |||
| 63 | |Check|Schwere|PrĂŒft | ||
| 64 | |Rimo-Token|kritisch|Token-Abruf liefert HTTP 200 und einen Token | ||
| 65 | |Rimo-API erreichbar|kritisch|API antwortet, keine 401/403/5xx | ||
| 66 | |State-Datei|kritisch|Datei lesbar und vollstĂ€ndig; fehlt sie bei befĂŒllter Log-Tabelle â Abbruch (Schutz vor Doppelverarbeitung) | ||
| 67 | |Lakehouse schreibbar|kritisch|Testdatei im Zielordner schreiben und löschen | ||
| 68 | |Stammdatentabellen|kritisch|rimo.sdmcompany, sdmcreditor, sdmaccount, sdmsalesorder, sdmprojectpurchaseorder, bmd.fibu_erk_konto nicht leer | ||
| 69 | |bmd.fibu_erb_buchungen|Warnung|nicht leer; leer ist zulÀssig, wenn keine Rechnungen anfallen | ||
| 70 | |SchlĂŒsselformat|kritisch|SchlĂŒssel entsprechen //Ziffern_Ziffern// (erkennt TypĂ€nderungen im DWH) | ||
| 71 | |BMD-Buchungen aktuell|Warnung|neueste Buchung höchstens 4 Tage alt | ||
| 72 | |Lookup Company|kritisch|echte Lookup-Funktion findet die bekannte Firma 70 | ||
| 73 | |||
| 74 | **WÀhrend des Laufs** gilt zusÀtzlich: | ||
| 75 | |||
| 76 | * **Technische Fehler:** Scheitert eine Lookup-Abfrage technisch (SQL-Fehler statt ânicht gefundenâ), wird das als technischer Fehler gesammelt und an die IT gemeldet. Ab 5 technischen Fehlern bricht der Lauf ab. | ||
| 77 | * **Lookup-Trefferquote:** Finden Company-, Kreditor-, Account-, Sales-Order- oder Purchase-Order-Lookups bei mindestens 3 Versuchen zu 80 % oder mehr nichts, wird das als vermutliches Daten- oder Abfrageproblem gemeldet. | ||
| 78 | * **Caches:** Lookup-Caches werden zu Beginn jedes Laufs geleert, damit bei wiederverwendeten Sessions keine veralteten Stammdaten verwendet werden. | ||
| 79 | |||
| 80 | == Fehler-Orchestrierung und Benachrichtigungen == | ||
| 81 | |||
| 82 | Die Pipeline trennt seit Ende September 2026 fachliche Fehler (Mail an die Buchhaltung) von technischen AuffÀlligkeiten (Mail an die IT); bricht das Notebook ab, geht ein eigener Alarm an die IT. | ||
| 83 | |||
| 84 | [[image:1791200539745-771.png]] | ||
| 85 | |||
| 86 | Fehler-Orchestrierung · drei Mails, zwei EmpfÀngergruppen | ||
| 87 | |||
| 88 | Beide If-Conditions hÀngen parallel am Erfolgspfad der Notebook-AktivitÀt und lesen Flags aus dem exitValue. | ||
| 89 | |||
| 90 | |Mail|Auslöser|Inhalt | ||
| 91 | |ErrorMailing (Buchhaltung)|hasFailures = 1|Download-, Upload-, Approval-Fehler und âLieferperiode ungĂŒltigâ, je als eigene Tabelle (Feld emailBodyHtml) | ||
| 92 | |TechnicalAlert (IT)|hasTechnicalIssues = 1|Technische Fehler, Health-Check-Warnungen, auffÀllige Lookups, unklare Uploads (Feld itEmailBodyHtml) | ||
| 93 | |NotebookStopAlert (IT)|Notebook-AktivitÀt fehlgeschlagen|Extrahierter Fehlertext aus errorValue, Pipeline, Zeitpunkt, Run-ID | ||
| 94 | |||
| 95 | * **Keine Doppelmeldungen:** Gemeldete Fehler werden in der State-Datei markiert (notified_at) und nur einmal gemailt. | ||
| 96 | * **Health-Warnungen mit Schwelle:** Eine leere bmd.fibu_erb_buchungen wird erst nach 3 LĂ€ufen in Folge gemeldet, einmal pro Serie; der ZĂ€hler steht in der State-Datei und zĂ€hlt ĂŒber Tagesgrenzen. Andere Warnungen werden beim ersten Auftreten gemeldet. | ||
| 97 | * **Lieferperiode ungĂŒltig:** bleibt in pending statt dead_letter und wird nach Korrektur in BMD automatisch neu versucht. | ||
| 98 | * **Download-Fehler** nach Erreichen der Retry-Grenze erhalten eine verstĂ€ndliche Meldung, z. B. âDatei nach Pipeline-Lauf nicht im Lakehouse gefundenâ. | ||
| 99 | |||
| 100 | == Logging, State-Datei und Backups == | ||
| 101 | |||
| 102 | Jeder Lauf wird als eigener Block oben in rimo_pipeline.log geschrieben, der neueste Lauf steht damit immer am Anfang der Datei. | ||
| 103 | |||
| 104 | === Logging === | ||
| 105 | |||
| 106 | * Das Notebook nutzt einen eigenen Logger (rimo_pipeline), unabhÀngig vom Root-Logger der Fabric-Runtime. Hintergrund: Runtime 2.0 konfiguriert den Root-Logger selbst, wodurch seit 25.09.2026 nach 07:08 Uhr keine EintrÀge mehr in der Logdatei landeten. | ||
| 107 | * WĂ€hrend des Laufs wird lokal nach /tmp geloggt; am Ende fĂŒgt das Notebook den Lauf als Block (Kopfzeile //LAUF Start bis Ende//) oben in die Lakehouse-Logdatei ein, innerhalb des Blocks chronologisch. | ||
| 108 | * Das Log wird auch bei einem Abbruch geschrieben (try/finally um den Hauptlauf). | ||
| 109 | * Zeitstempel im Log in Wiener Zeit (Europe/Vienna); Zeitstempel in der State-Datei in UTC. | ||
| 110 | |||
| 111 | === Dateien im Lakehouse === | ||
| 112 | |||
| 113 | |Datei / Ordner|Pfad|Inhalt | ||
| 114 | |State-Datei|Files/bmd/import/BMD_Invoices/rimo_processed_state.json|Warteschlange (pending), erledigt (succeeded), dead_letter, ZĂ€hler der Health-Warnungen | ||
| 115 | |Logdatei|Files/bmd/import/BMD_Invoices/rimo_pipeline.log|LÀufe als Blöcke, neuester oben | ||
| 116 | |State-Backups|Files/bmd/import/BMD_Invoices_state_backups/|TĂ€gliche Kopie der State-Datei, 5 Tage aufbewahrt | ||
| 117 | |Log-Tabelle|spl_gold_lh.bmd.rimo_processed_invoices_log|Erledigte und dead_letter-EintrĂ€ge; Basis fĂŒr den Ausschluss bei der Datenerfassung | ||
| 118 | |||
| 119 | Die State-Datei wird atomar geschrieben (Temp-Datei, PrĂŒfung, Umbenennen), damit ein Abbruch keine halbe Datei hinterlĂ€sst. Die Backups liegen bewusst auĂerhalb von BMD_Invoices, weil das Cleanup am Ende jedes Laufs dort alle Unterordner löscht; .log- und .json-Dateien bleiben dabei erhalten. | ||
| 120 | |||
| 121 | == Pipelines und Konfiguration == | ||
| 122 | |||
| 123 | Die wichtigsten Einstellungen stehen als Konstanten in der Konfig-Zelle des Notebooks; Filter und Zugangsdaten sind noch nicht parametrisiert. | ||
| 124 | |||
| 125 | |Bereich|Details | ||
| 126 | |Copy-Pipeline âBMD_Invoicesâ|Kopiert die benötigten Dateien gesammelt vom Dateiserver ins Lakehouse, vor der Notebook-AktivitĂ€t | ||
| 127 | |Orchestrierungs-Pipeline âBMD_Invoices_Error_Handlingâ|Notebook â If Condition (hasFailures) â ErrorMailing/FallbackAlert; parallel If Condition (hasTechnicalIssues) â IT-Mail; bei Abbruch NotebookStopAlert | ||
| 128 | |Rimo-API-Endpunkt|rimo-api.d-prod.spl-tele.com/v1/invoices | ||
| 129 | |State-Datei|/lakehouse/default/Files/bmd/import/BMD_Invoices/rimo_processed_state.json | ||
| 130 | |Retry-Grenzen|Download/Upload/Approval je max. 5 Versuche; HTTP-Aufrufe je 3 Versuche mit Backoff | ||
| 131 | |Technische Fehler|Abbruch ab 5 technischen Fehlern pro Lauf (MAX_TECH_ERRORS) | ||
| 132 | |Health-Warnung leere Buchungstabelle|Mail erst nach 3 LĂ€ufen in Folge, einmal pro Serie | ||
| 133 | |Exit-Details|max. 50 EintrÀge pro Kategorie im Exit-Wert (MAX_EXIT_DETAILS) | ||
| 134 | |Aktuelle Filterung|Buchungen ohne âSpesenâ (inkl. leerem Buchungstext) + Erstelldatum ab 27.08.2026, 10:00 Uhr; fest im Code. Kein Firmennr-Filter | ||
| 135 | |||
| 136 | == Sicherheit == | ||
| 137 | |||
| 138 | Die Rimo-Zugangsdaten stehen weiterhin im Klartext im Notebook; die Umstellung auf einen Key Vault ist vorbereitet, aber noch nicht umgesetzt. | ||
| 139 | |||
| 140 | === Authentifizierung === | ||
| 141 | |||
| 142 | * **Rimo-API-Token:** wird per Benutzer/Passwort ĂŒber /v1/auth/fetch-token einmal pro Lauf geholt. Der Health-Check bricht den Lauf ab, wenn der Abruf fehlschlĂ€gt. Eine automatische Token-Erneuerung bei HTTP 401 gibt es noch nicht. | ||
| 143 | * **Zugangsdaten:** Benutzer und Passwort stehen im Klartext im Notebook und damit auch im Versionsverlauf. Empfehlung: ĂŒber notebookutils.credentials.getSecret aus einem Key Vault beziehen und das Passwort Ă€ndern. | ||
| 144 | * **Fabric-API-Token:** wird nicht mehr verwendet, da der Kopiervorgang vollstÀndig in der vorgelagerten Copy-Data-AktivitÀt lÀuft. | ||
| 145 | |||
| 146 | === Datenschutz === | ||
| 147 | |||
| 148 | Zugriff auf Buchungs- und Stammdaten ausschlieĂlich ĂŒber die Fabric-Lakehouse-Berechtigungen. Das Notebook greift nicht direkt auf den On-Premises-Dateiserver zu; das lĂ€uft ausschlieĂlich ĂŒber die Gateway-Pipeline. | ||
| 149 | |||
| 150 | == Besondere GeschÀftslogik == | ||
| 151 | |||
| 152 | Vier fachliche Sonderregeln weichen bewusst von einer 1:1-Ăbernahme der BMD-Daten ab. | ||
| 153 | |||
| 154 | * **Vorzeichen-Korrektur beim Upload:** Ist der Bruttobetrag (grossAmount) positiv, der Nettobetrag (netAmount) aber negativ, wird der Betrag ohne Vorzeichen als netAmount ĂŒbergeben. Alle anderen Kombinationen bleiben unverĂ€ndert. | ||
| 155 | * **Mehrstufiger Fallback bei Approvals:** | ||
| 156 | *1. Bestellnummer-Kandidaten (Purchase-/Sales-Order-Paare) einzeln probieren | ||
| 157 | *1. bei Scheitern ein firmenbasierter Sales-Order-Kandidat ohne Bestellung | ||
| 158 | *1. sonst endgĂŒltig gescheitert (approval_dead) | ||
| 159 | * **Sales-Order-Ausnahme:** Gibt es fĂŒr eine Firma keinen Sales Order mit getsalesordernumber = '0000 {4 Ziffern}', wird ersatzweise nach dem Muster â{Firmennummer}000 0001â gesucht (Firma 68 â â68000 0001â). Dieser Fallback greift nur, wenn die regulĂ€re Suche keine Kandidaten liefert. | ||
| 160 | * **UngĂŒltige Lieferperiode:** Ist eine falsch formatierte Lieferperiode der einzige Fehler, bleibt die Rechnung in pending statt in dead_letter und wird nach Korrektur in BMD automatisch erneut versucht. | ||
| 161 | |||
| 162 | == Server / Umgebung == | ||
| 163 | |||
| 164 | Notebook und Pipelines laufen im Microsoft Fabric Workspace auf Runtime 2.0; ausgelöst wird stĂŒndlich ĂŒber die Orchestrierungs-Pipeline oder manuell. | ||
| 165 | |||
| 166 | * **Workspace:** wegen des KapazitĂ€tschecks laufen Pipeline und Notebook derzeit ĂŒber den Fabic_test_workspace, angehĂ€ngt an das im Fabric Workspace liegende bmd_invoice_execution. | ||
| 167 | * **Runtime:** Fabric Runtime 2.0 seit 25.09.2026. Bei kĂŒnftigen Runtime-Wechseln vorab in einer Kopie testen; die Health-Checks fangen grundlegende Probleme ab. | ||
| 168 | * **Erreichbarkeit Rimo-API:** ĂŒber die im Notebook hinterlegten Zugangsdaten. | ||
| 169 | * **Belegquelle:** \atwotbmd01\BMDDocs\0\2..., nur ĂŒber die On-Premises-Gateway-Pipeline erreichbar. | ||
| 170 | |||
| 171 | == Offene Punkte und bekannte EinschrÀnkungen == | ||
| 172 | |||
| 173 | Das gröĂte offene Risiko sind doppelte Rechnungen in Rimo bei Timeouts; die Lösung ist ausgearbeitet, aber noch nicht eingebaut. | ||
| 174 | |||
| 175 | * â **Schutz vor doppelten Uploads:** Bei Timeout oder 5xx wiederholt upload_invoice den Upload, obwohl Rimo die Rechnung womöglich schon angelegt hat. Geplant: Status upload_uncertain, kein automatischer Retry, Meldung an die IT, Hilfsfunktion resolve_upload_uncertain. | ||
| 176 | * â **Token-Erneuerung bei HTTP 401** fĂŒr Upload und Approval, damit lange LĂ€ufe nicht abbrechen. | ||
| 177 | * â **Zugangsdaten in Key Vault** verschieben und Passwort Ă€ndern. | ||
| 178 | * â **Leere Firmennr im SchlĂŒssel:** CONCAT mit NULL ergibt NULL; COALESCE in der Abfrage ergĂ€nzen. | ||
| 179 | * â **Copy-Data-Abfrage angleichen:** Buchungen ohne Buchungstext mĂŒssen auch dort mitkopiert werden, sonst scheitert ihr Download. | ||
| 180 | * â **Startdatum parametrisieren** statt fest im SQL. | ||
| 181 | * â **Gleichnamige PDFs** aus verschiedenen BMD-Ordnern ĂŒberschreiben sich im flachen Lakehouse-Ordner; Copy-Pipeline sollte den relativen Pfad oder den SchlĂŒssel als Dateinamen verwenden. | ||
| 182 | * â **Atomares Schreiben prĂŒfen:** Erscheint im Log âAtomares Ersetzen der State-Datei nicht möglichâ, unterstĂŒtzt der OneLake-Mount os.replace nicht. | ||
| 183 | * â **Health-Check-Werte ergĂ€nzen:** bekannten Kreditor und Kontonummer in KNOWN_LOOKUPS eintragen. | ||
| 184 | * â **Approvals bei Timeout:** submit_approval wiederholt bei Timeout und 5xx; im schlimmsten Fall entsteht eine Freigabezeile doppelt. |