Wiki source code of BMD_Rimo_Invoices
Version 31.2 by Patrizia Gurschka on 2026/09/10 13:33
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:1789039273400-757.png||height="388" width="571"]] | ||
| 27 | |||
| 28 | == Technologiestack == | ||
| 29 | |||
| 30 | **Notebook/Backend: **Python · PySpark (Spark SQL) · requests · notebookutils · Rimo-API-Token | ||
| 31 | |||
| 32 | **Datenplattform: **Microsoft Fabric Lakehouse · Delta-Tabellen (bmd.fibu_erb_buchungen, bmd.fibu_erk_konto, rimo.sdmcompany, rimo.sdmcreditor, rimo.sdmaccount, rimo.sdmsalesorder) | ||
| 33 | |||
| 34 | **Orchestrierung: **Microsoft Fabric Data Factory (Copy-Data-Aktivität, Notebook-Aktivität, If-Condition, Office 365 Email-Aktivität) | ||
| 35 | |||
| 36 | **Externe API: **Rimo REST-API (multipart/form-data fĂĽr Upload, JSON fĂĽr Approvals) | ||
| 37 | |||
| 38 | == Hauptfunktionen == | ||
| 39 | |||
| 40 | === 1. Datenerfassung === | ||
| 41 | |||
| 42 | Buchungszeilen werden aus bmd.fibu_erb_buchungen gelesen, gefiltert auf Buchungen ohne „Spesen“ und mit Erstelldatum ab 27.08.2026, 10:00 Uhr (offenes Zeitfenster, kein Enddatum). Eine Firmennr-Einschränkung besteht aktuell nicht mehr. Bereits verarbeitete Zeilen werden per LEFT JOIN gegen die Log-Tabelle spl_gold_lh.bmd.rimo_processed_invoices_log ausgeschlossen; bei mehreren Dateien zum selben Beleg wird bevorzugt die .pdf-Variante gewählt. Jede Zeile erhält einen eindeutigen Schlüssel aus interner Belegnummer + Firmennummer und wird in eine persistente Warteschlange gemischt. | ||
| 43 | |||
| 44 | === 2. Download-Phase (Belegdokument) === | ||
| 45 | |||
| 46 | Da Notebooks den On-Premises Data Gateway nicht direkt nutzen können, kopiert eine vorgelagerte Copy-Data-Aktivität der übergeordneten Orchestrierungs-Pipeline die Dateien vom Dateiserver (~\~\atwotbmd01\BMDDocs\0\2\...) gesammelt ins Lakehouse anhand eines Abgleichs der bmd.fibu_erb_buchungen mit der bmd.rimo_processed_invoices_log, bevor das Notebook startet. Die Download-Phase im Notebook triggert selbst keinen Kopiervorgang mehr - sie prüft nur noch, ob die erwartete Datei tatsächlich im Lakehouse-Zielordner angekommen ist. | ||
| 47 | |||
| 48 | === 3. Upload-Phase (Rechnungsdaten) === | ||
| 49 | |||
| 50 | BMD-Felder werden auf Rimo-Felder gemappt, Firmen-/Kreditor-IDs per Lakehouse-Lookup ergänzt und Beleg + Daten per multipart/form-data an POST /v1/invoices übergeben. Erfolgreiche Uploads liefern eine Rimo-externalId. | ||
| 51 | |||
| 52 | === 4. Approval-Phase (Freigaben) === | ||
| 53 | |||
| 54 | Pro Buchungszeile in bmd.fibu_erk_konto (verknĂĽpft ĂĽber ErfassNr) wird eine eigene Freigabe an Rimo gesendet, inkl. mehrstufigem Fallback fĂĽr Bestellnummer-/Sales-Order-Zuordnung. | ||
| 55 | |||
| 56 | |||
| 57 | [[image:1789039907840-302.png||height="434" width="911"]] | ||
| 58 | |||
| 59 | //Die drei fachlichen Phasen der Verarbeitung inkl. Fehlerpfade.// | ||
| 60 | |||
| 61 | == Fehler-Orchestrierung == | ||
| 62 | |||
| 63 | Die ĂĽbergeordnete Pipeline unterscheidet zwischen technischem Scheitern des Notebooks selbst und fachlichen Fehlern innerhalb eines technisch erfolgreichen Laufs: | ||
| 64 | |||
| 65 | [[image:1789019374368-405.png]] | ||
| 66 | |||
| 67 | //Steuerung ĂĽber die If-Condition anhand des exitValue (Feld hasFailures) des Notebooks.// | ||
| 68 | |||
| 69 | Die Fehler-Mail (ErrorMailing) zeigt in der Kopfzeile die Anzahl **Download-Fehler**, **Upload-Fehler** und **Approval-Fehler** getrennt an, ergänzt um eine vierte, separate Kategorie „Lieferperiode ungültig“ für Rechnungen, deren einziges Problem eine falsch formatierte Lieferperiode ist - diese landen bewusst nicht in dead_letter, sondern bleiben in pending und werden nach Korrektur in BMD automatisch neu versucht. Alle vier Kategorien werden in eigenen Tabellenabschnitten aufgelistet. Download-Fehlschläge (nach Erreichen der Retry-Grenze) erhalten dabei eine eigene, verständliche Fehlermeldung (z. B. „Datei nach Pipeline-Lauf nicht im Lakehouse gefunden“, „Zeitüberschreitung beim Pipeline-Lauf“) statt zuvor generisch unter „Upload Error“ mitgezählt zu werden. | ||
| 70 | |||
| 71 | == Pipelines & Konfiguration == | ||
| 72 | |||
| 73 | |**Bereich**|**Details** | ||
| 74 | |Copy-Pipeline „BMD_Invoices“|Kopiert die benötigten Dateien gesammelt vom Dateiserver ins Lakehouse - läuft jetzt vor der Notebook-Aktivität (nicht mehr pro Einzelbeleg aus dem Notebook heraus getriggert). | ||
| 75 | |Orchestrierungs-Pipeline|Notebook-Aktivität → If Condition (hasFailures) → ErrorMailing/FallbackAlert bzw. bei Notebook-Absturz NotebookStopAlert | ||
| 76 | |Rimo-API-Endpunkt|rimo-api.d-prod.spl-tele.com/v1/invoices | ||
| 77 | |State-Datei|/lakehouse/default/Files/bmd/import/BMD_Invoices/rimo_processed_state.json | ||
| 78 | |Retry-Grenzen|Download/Upload/Approval je max. 5 Versuche, HTTP-Aufrufe je 3 Versuche mit Backoff | ||
| 79 | |Aktuelle Filterung|Buchungen ohne „Spesen“ + Erstelldatum ab 27.08.2026, 09:00 Uhr (offenes Zeitfenster) — fest im Code der Datenerfassung, noch nicht parametrisiert. Firmennr-Filter wurde entfernt. | ||
| 80 | |||
| 81 | == Sicherheit == | ||
| 82 | |||
| 83 | === Authentifizierung === | ||
| 84 | |||
| 85 | * **Rimo-API-Token: **wird per Benutzer/Passwort über /v1/auth/fetch-token geholt und je Notebook-Lauf verwendet. Zugangsdaten (Benutzer/Passwort) sind aktuell als Klartext direkt im Notebook hinterlegt statt über einen sicheren Secret Store (z. B. Fabric Key Vault) bezogen zu werden - vor einem produktiven Einsatz empfohlen zu ändern | ||
| 86 | * **Fabric-API-Token: **früher pro Pipeline-Trigger frisch über notebookutils.credentials.getToken geholt - dieser Mechanismus wird im aktuellen Code nicht mehr verwendet, da der Datei-Kopiervorgang jetzt vollständig außerhalb des Notebooks in der vorgelagerten Copy-Data-Aktivität läuft (siehe „2. Download-Phase“). | ||
| 87 | |||
| 88 | === Datenschutz === | ||
| 89 | |||
| 90 | Zugriff auf Buchungs- und Stammdaten ausschließlich über die Fabric-Lakehouse-Berechtigungen; keine direkten Zugriffe auf den On-Premises-Dateiserver durch das Notebook (läuft ausschließlich über die Gateway-Pipeline). | ||
| 91 | |||
| 92 | == Besondere Geschäftslogik == | ||
| 93 | |||
| 94 | (% class="wikigeneratedid" id="HVorzeichen-KorrekturbeimUpload:IstderBruttobetrag28grossAmount29positiv2CderNettobetrag28netAmount29abernegativ2CwirdderpositiveBetrag28abs-Wert29fFCrnetAmountanRimoFCbergeben2CstattdennegativenWert1:1zuFCbernehmen.GreiftnurbeidiesemVorzeichen-Konflikt2CalleanderenKombinationenbleibenunverE4ndert." %) | ||
| 95 | (% style="font-size:14px" %)**Vorzeichen-Korrektur beim Upload: **Ist der Bruttobetrag (grossAmount) positiv, der Nettobetrag (netAmount) aber negativ, wird der positive Betrag (abs-Wert) für netAmount an Rimo übergeben, statt den negativen Wert 1:1 zu übernehmen. Greift nur bei diesem Vorzeichen-Konflikt, alle anderen Kombinationen bleiben unverändert. | ||
| 96 | |||
| 97 | **Mehrstufiger Fallback bei Approvals: **1) Bestellnummer-Kandidaten (Purchase-/Sales-Order-Paare) einzeln probieren → 2) bei Scheitern generischer, firmenbasierter Sales-Order-Kandidat ohne Bestellung → 3) endgültig gescheitert (approval_dead). | ||
| 98 | |||
| 99 | **Sales-Order-Ausnahme: **Gibt es für eine Firma keinen Sales Order mit getsalesordernumber = '0000 {weitere 4 Zahlen}', wird ersatzweise über getsalesordernumber nach dem Muster „{Firmennummer}000 0001“ gesucht (Beispiel: Firma 68 → „68000 0001“). Dieser Fallback greift nur, wenn die reguläre '0000'-Suche keine Kandidaten liefert. | ||
| 100 | |||
| 101 | == Server / Umgebung == | ||
| 102 | |||
| 103 | Das Notebook läuft im Microsoft Fabric Workspace (Lakehouse-Kontext); die Pipelines liegen im selben Workspace. Auslösung erfolgt über die Orchestrierungs-Pipeline (Zeitplan oder manueller Start), nicht über einen eigenständigen Docker-Server. | ||
| 104 | |||
| 105 | * **Umgebung: **derzeit wegen Kapazitätscheck läuft die Pipeline und das Notebook über den Fabic_test_workspace, angehängt an der im Fabic Workspace liegenden bmd_invoice_execution | ||
| 106 | * **Erreichbarkeit Rimo-API: **ĂĽber die im Workspace hinterlegten Zugangsdaten (Benutzer/Passwort) | ||
| 107 | * **Datenserver (Belegquelle): **~\~\atwotbmd01\BMDDocs\0\2\... — nur über die On-Premises-Gateway-Pipeline erreichbar |