# TrafagSalesExporter Handoff Stand: 2026-05-05 ## Nachtrag 2026-05-08 Manual Excel/CSV / SharePoint-Ordner Aktueller Stand fuer manuelle Quellen: - `MANUAL_EXCEL` ist fachlich Manual Excel/CSV. - Unterstuetzt werden `.xlsx` und `.csv`; altes `.xls` ist nicht der Zielpfad. - Lokale Datei als Quelle: - App liest die Datei. - App erzeugt eine neue Exportdatei im selben lokalen Ordner. - SharePoint-Datei als Quelle: - App laedt die Datei temporaer herunter. - App erzeugt eine neue Exportdatei und laedt sie in denselben SharePoint-Ordner hoch. - SharePoint-Ordner als Quelle: - App waehlt automatisch die neueste passende `.xlsx`/`.csv` fuer den Standort. - Primaeres Muster: `ddMMyy_TSC.xlsx` oder `ddMMyy_TSC.csv`. - Fallback: SharePoint `LastModifiedDateTime`. England / UK: - Standort `England`, `TSC = TRUK`, `SourceSystem = MANUAL_EXCEL`. - Quelle ist ein SharePoint-Ordner: ```text https://trafagag.sharepoint.com/sites/WorldwideBIPlatform/Import/Finance/UK_B1 ``` - Beispielauswahl: - `010526_TRUK.xlsx` ist neuer als `010426_TRUK.xlsx`. - Exportdateien werden wieder in `Import/Finance/UK_B1` geschrieben. - Befund am 2026-05-08: England zeigte lokal faelschlich auf die Deutschland-Alphaplan-Datei; lokale DB wurde korrigiert. - `DatabaseSeedService` repariert kuenftig einen leeren England/TRUK-Manual-Pfad auf den UK_B1-Ordner. Spanien / Sage: - Spanien nutzt `MANUAL_EXCEL` als technischen Importpfad fuer den Sage-Export. - Die Datei `Spain_Sales_2025.csv` konnte gelesen werden (`4'341` Zeilen). - Fehler war danach der Exportpfad: die SharePoint-URL wurde als lokaler Dateipfad interpretiert. - Fix: SharePoint-Manual-Quellen liefern keinen `ReferenceFilePath` mehr, sondern erzeugen eine neue Exportdatei im Quellordner. Deutschland / Alphaplan: - Deutschland nutzt `MANUAL_EXCEL` als technischen Importpfad fuer Alphaplan-Excel. - Grafisches Mapping ist vorhanden. - Offener Punkt: konkreter Alphaplan-Datei-/SharePoint-Pfad muss im Standort hinterlegt sein, sonst kommt `Standort 'Deutschland' hat keine manuelle Excel-Datei.` Verifikation: - Tests `55/55` erfolgreich. ## Nachtrag 2026-05-08 FinanceProbe fuer mehr Laender FinanceProbe wurde erweitert: - `FinanceReferences` werden vollstaendig angezeigt, nicht nur bei aktivem Standort oder vorhandenen Ist-Daten. - Dadurch sind alle Soll-Laender aus der Finance-Konfiguration im Meeting sichtbar. - Neue Sektion `Datenabdeckung je Standort` zeigt je Standort: - Quelle/System - Manual-/SharePoint-Pfad - Aktivstatus - Anzahl 2025-Zeilen in `CentralSalesRecords` - Summe `SalesPriceValue` - Waehrungen und Datumsbereich - letzter Exportstatus/Fehler - CH/AT-Erkennung im Finance-Service wurde geschaerft, damit `ZSCHWEIZ`-Zeilen mit Land `AT` Oesterreich zugeordnet werden koennen. Wichtig: - `Keine Daten` bedeutet jetzt nicht zwingend fehlende Referenz, sondern oft: Referenz ist vorhanden, aber Ist-Daten wurden noch nicht exportiert/importiert. - Fuer neue Laender reicht es, `FinanceReferences` zu pflegen und Daten nach `CentralSalesRecords` zu bringen; die Probe zeigt sie dann automatisch. ## Nachtrag 2026-05-07 Mapper-Konsolidierung / Finance-Konfiguration Architekturstand: - `MappedSalesRecordComposer` ist die gemeinsame Engine fuer grafisches Mapping. - SAP OData und generisches HANA-Mapping nutzen denselben Composer fuer Joins und Zielfeldmapping. - SAP OData laedt weiter ueber `SapGatewayService`. - HANA-Tabellen/Views laden weiter ueber `HanaQueryService`. - Der alte B1-HANA-Pfad ohne Mapping bleibt als Legacy-Pfad fuer bestehende BI1/SAGE-Standorte erhalten. - `ConsolidatedExportService.ExportAsync()` erzeugt die zentrale Datei nur noch aus `CentralSalesRecords`; es gibt keinen zweiten Records-Parameter mehr. - Manual Excel/CSV akzeptiert im Standort-Editor und Upload `.xlsx` und `.csv`. Neue Konfigurationstabellen: - `FinanceReferences`: Soll-/check.xlsx-Referenzen je Jahr und Land/Key. - `FinanceIntercompanyRules`: IC-/2nd-party-Regeln nach Scope, Kundennummer oder Namensbestandteil. - Budgetkurse 2025 liegen als `CurrencyExchangeRates` mit `Notes = Budget 2025`. - Config-Export/-Import nimmt `FinanceReferences` und `FinanceIntercompanyRules` mit. Offen: - Manual-Excel-Import hat noch zwei Modi: Header-Automatik und grafisches Mapping. - Der alte B1-HANA-Spezialpfad ist bewusst noch vorhanden, sollte aber mittelfristig durch gepflegte HANA-Mappings abgeloest werden. Verifikation: - Hauptprojekt Build erfolgreich. - Tests `52/52` erfolgreich. ## Nachtrag 2026-05-07 SAP OData / ZSCHWEIZ / Schweiz-Oesterreich Aktueller Architekturentscheid: - `ZSCHWEIZ` wird ueber SAP OData/Gateway gelesen. - Direkter HANA-Spezialcode fuer `ZSCHWEIZ` wurde vermieden. - Der grafische Quellen- und Feldmapper wird fuer SAP OData verwendet. - Fuer direkte HANA-Tabellen/Views gibt es ebenfalls grafisches Mapping; das ist aber nicht der geplante Pfad fuer `ZSCHWEIZ`. Quellsysteme: - `SAP` = `SAP OData`, Anschlussart `SAP_GATEWAY`. - `SAP_HANA` = `SAP HANA Tables/Views`, Anschlussart `HANA`. - `BI1` und `SAGE` bleiben HANA-basierte Quellsysteme. - `MANUAL_EXCEL` bleibt Excel/CSV. ABAP/SAP: - Datei `report.abap` enthaelt Report `ZTRAFAG_SCHWEIZ_EXPORT`. - Ziel-Tabelle in SAP: `ZSCHWEIZ`. - `BUKRS 1100` wird als Schweiz (`TRCH`, `CH`) geschrieben. - `BUKRS 1200` wird als Oesterreich (`TRAT`, `AT`) geschrieben. - `CUSTOMER_LAND` enthaelt das urspruengliche Kundenland. - Der Report schreibt paketweise per Upsert. App-Seed: - Standort `ZSCHWEIZ` / `Schweiz/Oesterreich` wird inaktiv angelegt bzw. repariert. - `SourceSystem = SAP`. - Quelle `Z`, EntitySet `ZSCHWEIZSet`. - Quelle und Feldmapping werden beim App-Start per Upsert nachgezogen; eine teilweise vorhandene ZSCHWEIZ-Konfiguration bleibt dadurch nicht leer. - Initiales Mapping: - `Tsc <- Z.TSC` - `Land <- Z.LAND1` - `InvoiceNumber <- Z.VBELN` - `PositionOnInvoice <- Z.POSNR` - `SalesPriceValue <- Z.NETWR_HC` - `SalesCurrency <- Z.HWAER` - `CustomerCountry <- Z.CUSTOMER_LAND` Wichtig fuer naechsten Einstieg: - Wenn die zentrale SAP-Service-URL noch auf `ZPOWERBI_EINKAUF_SRV` zeigt, muss beim Standort `ZSCHWEIZ` ein Service-URL-Override fuer den `ZSCHWEIZ`-OData-Service gesetzt werden. - Feldinfos kommen ueber `$metadata`; manuelle Feldliste ist nur noetig, wenn Gateway/Metadata nicht funktioniert. - Nach URL-Setzung: `Entity Sets refreshen`, `Felder aus Quellen laden`, Mapping kontrollieren, Standort aktivieren, Export testen. Verifikation: - Hauptprojekt Build erfolgreich. - Tests `52/52` erfolgreich. ## Nachtrag 2026-05-05 Aktueller Handoff FinanceProbe / Laenderabgleich Der aktuelle Arbeitsstand fuer den naechsten Einstieg ist der lokale FinanceProbe: ```text http://localhost:55417/finance ``` Der FinanceProbe wurde als Meeting-Ansicht erweitert: - `Meeting Ampel 2025` - `Detail alle Laender` - `Germany Excel sample check` - `Spain CSV direct check` Ampel-Bedeutung: - Gruen: Ist/Soll passt rechnerisch gegen Referenz. - Gelb: technische Daten vorhanden, aber Differenz oder fachliche Abgrenzung offen. - Grau: keine belastbaren Ist-Daten im aktuellen Import. Wichtige Waehrungsregel fuer Management-Aussage: - Wenn die Quelle CHF liefert, kann CHF direkt als CHF gezeigt werden. - Wenn die Quelle EUR/USD/GBP/INR usw. liefert, ist es Mandanten- bzw. Originalwaehrung. - CHF-Ausweis braucht dann eine separate FX-Regel oder einen offiziell bestaetigten Kurs. ### Spanien Vorhandene finale Kandidatendatei: ```text sagespain/v2/Spain_Sales_2025.csv ``` FinanceProbe liest diese Datei direkt. Aktueller Stand: - Zeilen: `4'341` - Ist `SalesPriceValue`: `3'082'320.18` EUR - Soll aus `check.xlsx`: `3'102'333.61` - Differenz: `-20'013.43` - Status: Gelb / Pruefen Technisch: - `ManualExcelImportService` kann jetzt semikolongetrennte CSV-Dateien lesen. - Spanien-v2-CSV kann damit als `MANUAL_EXCEL` importiert werden. - In der Detailtabelle wird Spanien nicht mehr als `Keine Daten` gezeigt, sondern als `Pruefen` mit dem v2-CSV-Wert. Offen fachlich: - Periodenlogik: `FechaFactura` vs. andere Datumsfelder - Serien: `REG`, `LAT`, `PRO`, `REC` - Behandlung von Gutschriften / `REC` - offizielle Sage-Auswertung mit identischem Filter zur Sollzahl ### Deutschland Vorhandenes Beispielfile: ```text DE_Beispiel_Export_Daten.xlsx ``` Wichtig: - Das File ist ein Beispielfile, keine finale DE-Jahresdatei. - Es darf nicht als finale Ist-Zahl gegen die Jahresreferenz verwendet werden. Technischer Check: - relevante Spalte: `NettoPreisGesamtX` - Mapping-Ziel: `SalesPriceValue` - Betragszeilen: `2` - Summe: `8'290.70` EUR - Waehrung: `EUR` Interpretation: - Deutschland-Format ist technisch verstanden. - Mapping funktioniert. - Finale DE-Zahl fehlt noch. - Fuer Abschluss/Meeting wird ein vollstaendiger DE-Jahresfile 2025 oder ein bestaetigter Importlauf benoetigt. ### Geaenderte wichtige Dateien - `Tools/FinanceProbe/Program.cs` - Management-Ampel - Spanien-v2-CSV-Direktcheck - Deutschland-Beispielfile-Check - `Services/ManualExcelImportService.cs` - CSV-Support fuer manuelle Quellen - `Services/DatabaseSeedService.cs` - deaktivierter Spanien-Standort als Seed/Fallback - `TrafagSalesExporter.Tests/ManualExcelImportServiceTests.cs` - Tests fuer CSV/Mapping - `SAGE_SPAIN_EXPORT_2026-05-05.md` - Spanien-Doku - `lastchange.md` - chronologischer Abschlussstand ### Letzte Verifikation ```text dotnet build .\Tools\FinanceProbe\FinanceProbe.csproj --verbosity minimal --no-restore dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal --no-restore ``` Ergebnis: - FinanceProbe Build erfolgreich - Tests erfolgreich - `50/50` Tests gruen - FinanceProbe liefert `HTTP 200` ## Nachtrag 2026-04-29 Dashboard-Referenzcheck Net Sales 2025 Das Dashboard zeigt jetzt oberhalb der Exportaktionen einen Referenzcheck fuer `Net Sales Actuals 2025`. Zweck: - schnelle Gegenpruefung, ob die gezogenen Werte gegen `check.xlsx` / Power-BI-Referenz plausibel sind - automatische Ermittlung des Summenfelds, das am besten zum Referenzwert passt - sichtbar machen, ob aktuell `SalesPriceValue`, `DocTotalFC - VatSumFC` oder `DocTotal - VatSum` als Vergleichsbasis genutzt wird - `DocumentTotal*` wird nur dedupliziert pro Beleg verwendet, weil es ein Belegkopfwert ist und in der positionsbasierten Datei pro Position wiederholt wird Logik: - Ist-Wert = bester Kandidat aus: - Summe `CentralSalesRecords.SalesPriceValue` - Summe `DocumentTotalForeignCurrency - VatSumForeignCurrency` - Summe `DocumentTotalLocalCurrency - VatSumLocalCurrency` - Belegkopfwerte werden vor dem Summieren per `TSC` + `DocumentType` + `DocumentEntry` dedupliziert; falls `DocumentEntry` fehlt, per `InvoiceNumber` - Jahr = `InvoiceDate`, falls vorhanden, sonst `ExtractionDate` - Vergleichsjahr = `2025` - Referenzwerte sind aus `check.xlsx` / Power BI Stand 2026-04-29 im Code hinterlegt - wenn ein Power-BI-Referenzwert vorhanden ist, wird dieser als Vergleich verwendet - sonst wird der LC-Referenzwert verwendet Angezeigt werden: - Firma - Ist 2025 - Referenz - Summenfeld - Referenzquelle (`Power BI` oder `LC`) - Differenz - Waehrungen - Zeilen - Status `OK`, `Pruefen` oder `Keine Daten` Verifikation: - `dotnet build .\TrafagSalesExporter.csproj --verbosity minimal` erfolgreich - `dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal` erfolgreich - lokaler Dashboard-Start geprueft: `http://localhost:55416` antwortet mit HTTP `200` Naechster Bedienablauf, damit die korrekten Summen kommen: 1. App starten bzw. offen lassen: `http://localhost:55416` 2. Im Dashboard neue Daten ziehen: - entweder `Alle exportieren` - oder einzelne Standorte per `Export` 3. Danach `Zentrale Datei neu erzeugen` ausfuehren. 4. Oben im Dashboard den Block `Net Sales Actuals 2025 Referenz` pruefen. 5. Entscheidend ist die Spalte `Summenfeld`: - `Sales Price/Value` = Positionssumme - `DocTotalFC - VatSumFC` = Netto-Belegsumme in Belegwaehrung, dedupliziert pro Beleg - `DocTotal - VatSum` = Netto-Belegsumme in Hauswaehrung, dedupliziert pro Beleg 6. `Status = OK` bedeutet: Abweichung zur Referenz maximal 1. 7. `Status = Pruefen` bedeutet: Feld, Datenquelle, Zeitraum oder Standortkonfiguration fachlich kontrollieren. Wichtig: - Mit alten zentralen Daten bleiben die neuen B1-Felder leer bzw. `0`. - Fuer die echte Pruefung von `DocEntry`, `DocTotal*`, `VatSum*`, `DocRate` und `OADM.MainCurncy` muss zuerst neu exportiert werden. - Fuer neue Jahre ist aktuell noch kein dynamischer Referenzjahres-Schalter eingebaut; der harte Referenzcheck ist Stand jetzt auf `2025`, weil `check.xlsx` die 2025-Referenzen enthaelt. ## Nachtrag 2026-04-29 Export-all-Abbruch / SQLite-FK-Reparatur Beim Klick auf `Export all` kam: - `An error occurred while saving the entity changes. See the inner exception for details.` Ursache: - die bestehende SQLite-DB hatte in `ExportLogs`, `AppEventLogs` und `CentralSalesRecords` noch Foreign Keys auf `"Sites_repair_old"` - diese Reparatur-Zwischentabelle existiert nicht mehr - beim Speichern neuer Logs oder zentraler Datensaetze konnte SQLite deshalb nicht mehr korrekt speichern Korrektur: - `DatabaseSchemaMaintenanceService` erkennt jetzt nicht nur `Sites_old`, sondern auch alte Reparaturtabellen wie `Sites_repair_old` - betroffene Tabellen werden beim App-Start automatisch neu aufgebaut - `AppEventLogService` und `ExportLogService` fangen eigene Log-Speicherfehler ab, damit Logging-Probleme nicht den ganzen Export abbrechen - Dashboard-Fehlerausgaben zeigen jetzt auch die Inner Exception, falls vorhanden Verifikation: - App neu gestartet - DB-Schema direkt geprueft: - `AppEventLogs` -> `FOREIGN KEY (SiteId) REFERENCES Sites (Id)` - `ExportLogs` -> `FOREIGN KEY (SiteId) REFERENCES Sites (Id)` - `CentralSalesRecords` -> `FOREIGN KEY (SiteId) REFERENCES Sites (Id)` - `dotnet build .\TrafagSalesExporter.csproj --verbosity minimal` erfolgreich - `dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal` erfolgreich Direkt danach beobachtete Exportfehler: - Frankreich/Italien/USA: `invalid schema name ... line 40` durch HANA-Query-Quoting - Ursache: Query nutzte `"schema"."Tabelle"` - Korrektur: wieder `schema."Tabelle"` wie im alten funktionierenden Stand - Indien: `authentication failed` - Konfiguration/Credentials pruefen, kein Codefehler aus dieser Aenderung - England/Spanien/Deutschland: `MANUAL_EXCEL`, aber keine manuelle Excel-Datei hinterlegt - entweder Datei hinterlegen oder Standort deaktivieren/Quellsystem korrigieren ## Nachtrag 2026-04-29 B1-Belegwaehrungsfelder aus HANA Der HANA/B1-Export wurde um Beleg- und Hauswaehrungsfelder erweitert. Grund: - `p.StockPrice` muss fachlich in der B1-Hauswaehrung bewertet werden - die Hauswaehrung kommt aus `OADM.MainCurncy` - bisher wurde `StandardCostCurrency` aus `p.Currency` bzw. `h.DocCur` abgeleitet - fuer Power-BI-/Cockpit-Gegenpruefung muessen Belegwaehrung, Hauswaehrung, Netto-/Steuerbetraege und Kurs sichtbar sein Neue Felder in `SalesRecord` und `CentralSalesRecord`: - `DocumentEntry` - `DocumentCurrency` - `DocumentTotalForeignCurrency` - `DocumentTotalLocalCurrency` - `VatSumForeignCurrency` - `VatSumLocalCurrency` - `DocumentRate` - `CompanyCurrency` B1-Feldmapping: - `DocumentEntry` = `OINV/ORIN.DocEntry` - `DocumentCurrency` = `OINV/ORIN.DocCur` - `DocumentTotalForeignCurrency` = `OINV/ORIN.DocTotalFC` - `DocumentTotalLocalCurrency` = `OINV/ORIN.DocTotal` - `VatSumForeignCurrency` = `OINV/ORIN.VatSumFC` - `VatSumLocalCurrency` = `OINV/ORIN.VatSum` - `DocumentRate` = `OINV/ORIN.DocRate` - `CompanyCurrency` = `OADM.MainCurncy` - `StandardCostCurrency` = `OADM.MainCurncy` Technische Umsetzung: - `HanaQueryService` liest `OADM` jetzt per `CROSS JOIN` - Invoice- und Credit-Note-Query liefern die neuen Felder - bei Gutschriften werden Dokument- und Steuerbetraege mit negativem Vorzeichen uebernommen - `CentralSalesRecords`-Schema wurde erweitert - bestehende SQLite-DBs erhalten die neuen Spalten per `DatabaseSchemaMaintenanceService` - `CentralSalesRecordService` persistiert und liest die neuen Felder - `ExcelExportService` schreibt die neuen Spalten in Standort- und `Sales_All_*.xlsx`-Dateien - `ManualExcelImportService` kann die neuen Spalten wieder einlesen - `ConfigTransferService` erhaelt die neuen Felder beim Remapping zentraler Laufzeitdaten Wichtig fuer Power BI: - die neuen `DocumentTotal*`- und `VatSum*`-Felder sind Belegkopfwerte - sie werden in der positionsbasierten Excel pro Positionszeile wiederholt - diese Felder duerfen daher nicht blind positionsweise summiert werden - fuer Belegkopfsummen in Power BI zuerst nach `DocumentType`, `Invoice Number`, `TSC` und ggf. `Land` deduplizieren - besser: nach `TSC` + `DocumentType` + `DocumentEntry` deduplizieren, weil `DocEntry` aus B1 jetzt mitgezogen wird - positionsbasierte Auswertungen sollen weiterhin mit positionsbezogenen Feldern wie `Sales Price/Value`, `Quantity` oder `Standard cost` arbeiten Wichtig zum aktuellen Datenbestand: - alte zentrale Daten wurden vor der Erweiterung exportiert und haben fuer die neuen B1-Felder noch `0` - nach einem neuen Export/Rebuild der zentralen Daten koennen `DocEntry`, `DocTotal*`, `VatSum*`, `DocRate` und `OADM.MainCurncy` fachlich verglichen werden Verifikation: - `dotnet build .\TrafagSalesExporter.csproj --verbosity minimal` erfolgreich - `dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal` erfolgreich - `48/48` Tests gruen - `ManualExcelImportServiceTests` pruefen die neuen Excel-Spalten - `CentralSalesRecordServiceTests` pruefen Persistenz und Ruecklesen der neuen B1-Felder ## Nachtrag 2026-04-29 Clean-Code-/DI-Befund Der aktuelle Code ist DI-orientiert und deutlich besser strukturiert als zu Beginn des Refactorings, aber noch nicht durchgehend ein Clean-Code-Ideal. Positiv: - Services werden weitgehend ueber Interfaces und DI verdrahtet - `DataSourceAdapter` trennt die Quellsysteme - Page-Services reduzieren direkte DB-Logik in mehreren Razor-Seiten - `Scoped` fuer UI-nahe Services und `Singleton` fuer gemeinsame Infrastruktur/Orchestrierung ist bewusst gewaehlt - Testabdeckung fuer zentrale Fachlogik ist vorhanden und waechst Weiterhin offene Clean-Code-Risiken: - `DatabaseInitializationService` ist weiterhin produktiver Reparatur-/Migrationspfad - `Settings.razor` und `Standorte.razor` enthalten noch viel Workflow-/UI-Logik - `ManagementCockpitService` und `ConfigTransferService` sind breit und sollten spaeter weiter aufgeteilt werden - Retry-/Robustheitslayer fuer externe Systeme fehlt - Secret-Store fehlt - Auth-Rollenmodell ist aktuell pragmatisch, aber noch grob Bewertung: - Architektur: brauchbar bis gut - DI: grundsaetzlich sauber - Clean Code: mittel bis gut, mit klaren Altlasten Dieser Befund wurde bewusst nur dokumentiert. Die strukturelle Bereinigung wird spaeter priorisiert. ## Nachtrag 2026-04-29 Authentifizierung / AD-Zugriffsschutz Nach Rueckmeldung der IT wurde ein Zugriffsschutz fuer die Blazor-App eingebaut. Vorher konnte jeder Benutzer mit Netzwerkzugriff auf die App-URL die Anwendung oeffnen. Das war kritisch, weil die App Verkaufsdaten, Standort-/Quellsystemkonfiguration, SharePoint-Konfiguration, Config Import/Export und Secrets bzw. Zugangsdatenfelder beruehrt. Neuer Stand: - die App ist grundsaetzlich authentifizierungspflichtig - produktives Ziel ist Windows Authentication / Active Directory - Berechtigungen laufen ueber AD-Gruppen - es gibt keine eigene Benutzer-/Passwortverwaltung in der App - es gibt keinen versteckten produktiven Backdoor Neue Security-Dateien: - `Security/SecurityOptions.cs` - `Security/SecurityPolicies.cs` - `Security/DevelopmentAuthenticationHandler.cs` Geaenderte zentrale Dateien: - `Program.cs` - `Components/Routes.razor` - `Components/_Imports.razor` - `Components/Layout/NavMenu.razor` - `Components/Layout/MainLayout.razor` - `appsettings.json` - `appsettings.Development.json` Aktuelles Rollenmodell: - `Security:AccessGroups` steuert Zugriff auf die App - `Security:AdminGroups` steuert Admin-Berechtigung - Default-Gruppen sind `TRAFAG\\TrafagSalesExporter-Users` und `TRAFAG\\TrafagSalesExporter-Admins` - echte Gruppennamen muessen von der IT bestaetigt oder angepasst werden Admin-geschuetzte Seiten: - `Settings` - `Standorte` - `Transformations` Dashboard, Management Cockpit und Logs bleiben fuer berechtigte angemeldete Benutzer sichtbar. Development: - `appsettings.Development.json` aktiviert bei `ASPNETCORE_ENVIRONMENT=Development` einen lokalen Development-Auth-Handler - Default-User: `DEV\\TrafagDeveloper` - `DevelopmentUserIsAdmin=true`, damit lokal weiter programmiert werden kann - produktiv darf die App nicht mit `Development` laufen IIS-/IT-Hinweise: 1. Windows Authentication aktivieren 2. Anonymous Authentication deaktivieren 3. `ASPNETCORE_ENVIRONMENT` produktiv nicht auf `Development` setzen 4. AD-Gruppen fuer Benutzer und Admins anlegen oder bestehende Gruppen eintragen 5. `Security:AccessGroups` und `Security:AdminGroups` in produktiver Konfiguration korrekt setzen Verifikation: ```text dotnet build .\TrafagSalesExporter.csproj --verbosity minimal dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal ``` Ergebnis: - Build erfolgreich - Tests erfolgreich - `48/48` Tests gruen - Auth-Policy-Tests fuer AccessGroup, AdminGroup und Development-Admin vorhanden - lokaler Development-Auth-Start geprueft: `http://localhost:55416` antwortet mit HTTP `200` - bekannte MudBlazor-Analyzer-Warnungen zu `Dense` bleiben ## Nachtrag 2026-04-29 Management-Cockpit-Auswertung Seit dem letzten dokumentierten Stand vom 2026-04-17 wurde das `Management Cockpit` weiter ausgebaut. Dieser Abschnitt rekonstruiert den aktuellen Stand aus dem Code, weil die Aenderungen nach einem PC-Absturz nicht direkt nachdokumentiert wurden. ### Neue Auswertlogik Das Cockpit ist nicht mehr nur auf Umsatz als feste Kennzahl beschraenkt. Neu gibt es auswählbare Summenfelder: - `Sales Price/Value` - `Quantity` - `Standard cost` - `Quantity * Standard cost` Diese Auswahl gilt fuer: - dateibasierte Analyse vorhandener Excel-Exporte - zentrale Roh-Auswertung aus `CentralSalesRecords` ### Anzeige-Waehrung und Wechselkurse Fuer betragliche Summenfelder kann jetzt eine Anzeige-Waehrung gewaehlt werden: - `EUR` - `USD` - `Original` Die Umrechnung nutzt `CurrencyExchangeRateService`. Wichtig: - nicht-betragliche Werte wie `Quantity` werden nicht umgerechnet - bei `Original` bleiben Werte in der jeweiligen Quellwaehrung - bei fehlendem Wechselkurs wird der betroffene Wert mit `0` in die Zielwaehrung eingerechnet - fehlende Kurse werden als Anzahl `Nicht umgerechnet` bzw. in Hinweisen/Finding sichtbar gemacht - Wechselkurse werden pro Quellwaehrung, Zielwaehrung und Datum gecacht, damit grosse Auswertungen nicht unnoetig oft die gleiche Rate aufloesen ### Zusätzliche Summenfelder in der zentralen Sicht Die zentrale Roh-Auswertung kann neben dem Haupt-Summenfeld weitere Summenfelder anzeigen. Diese Zusatzwerte werden aktuell in den Zeitreihen ausgegeben: - Jahreswerte - Monatswerte - Tageswerte im gewaehlten Monat Beispiel: - Hauptwert: `Sales Price/Value` - Zusatzwerte: `Quantity`, `Quantity * Standard cost` Damit kann die zentrale Sicht Umsatz, Mengen und Kostennaeherung nebeneinander darstellen. ### UI-Stand `Components/Pages/ManagementCockpit.razor` hat neue Controls: - Summenfeld fuer Excel-Dateianalyse - Anzeige-Waehrung fuer Excel-Dateianalyse - Summenfeld fuer zentrale Roh-Auswertung - weitere Summenfelder fuer zentrale Roh-Auswertung per Mehrfachauswahl - Anzeige-Waehrung fuer zentrale Roh-Auswertung Die Tabellen wurden von festem Text `Umsatz` auf generische `Werte` / `Jahreswerte` / `Monatswerte` umgestellt. Die vorher dokumentierte Manometer-/Gauge-Sicht ist im aktuellen Arbeitsstand nicht mehr aktiv sichtbar. Stattdessen liegt der Fokus wieder auf Kennzahlen, Hinweisen und tabellarischen Auswertungen. ### Technische Umsetzung Betroffene Dateien: - `Components/Pages/ManagementCockpit.razor` - `Models/ManagementCockpitModels.cs` - `Services/IManagementCockpitService.cs` - `Services/ManagementCockpitPageService.cs` - `Services/ManagementCockpitService.cs` - `TrafagSalesExporter.Tests/ManagementCockpitServiceTests.cs` Neue bzw. erweiterte Modelle: - `ManagementCockpitValueFieldKeys` - `ManagementCockpitCurrencyOptions` - `ManagementCockpitValueFieldOption` - `ManagementCockpitAnalysisOptions` - `ManagementCockpitAggregatedFieldValue` Neue Felder in Ergebnissen: - gewaehltes Summenfeld - Anzeige-Waehrung - Anzahl fehlender Wechselkurse - Zusatzwerte pro Zeitreihe ### Testabdeckung Die `ManagementCockpitServiceTests` wurden erweitert um Tests fuer: - Umrechnung zentraler Werte in EUR - Caching von Wechselkursauflösungen - Mengen-Summe ohne Waehrungsumrechnung - Zusatz-Summenfelder in Jahres- und Monatswerten Noch offen: - UI manuell pruefen - genaue fachliche Zielwaehrung fuer Standardberichte bestaetigen - entscheiden, ob `CHF` ebenfalls als direkte Anzeige-Waehrung angeboten werden soll - klaeren, ob fehlende Wechselkurse langfristig mit `0`, Originalwert oder separater Fehlergruppe dargestellt werden sollen ## Nachtrag 2026-04-17 Refactoring- und HANA-Stand Der Stand aus den frueheren Nachtraegen ist fuer Architektur und HANA-Zugriff nicht mehr vollstaendig. Inzwischen gilt zusaetzlich: ### 1. DataSourceAdapter-Pattern ist eingefuehrt Die Quellsysteme `HANA`, `SAP_GATEWAY` und `MANUAL_EXCEL` laufen nicht mehr ueber einen grossen `if/else`-Block im `SiteExportService`. Neu: - `Services/DataSources/IDataSourceAdapter.cs` - `Services/DataSources/IDataSourceAdapterResolver.cs` - `Services/DataSources/DataSourceAdapterResolver.cs` - `Services/DataSources/DataSourceFetchContext.cs` - `Services/DataSources/DataSourceFetchResult.cs` - `Services/DataSources/DataSourceCredentials.cs` - `Services/DataSources/HanaDataSourceAdapter.cs` - `Services/DataSources/SapGatewayDataSourceAdapter.cs` - `Services/DataSources/ManualExcelDataSourceAdapter.cs` Neuer Zuschnitt: - `SiteExportService` ist jetzt deutlich schlanker und nur noch Export-Pipeline - Adapter loesen Quellsystem-spezifisches Laden auf - fuer ein weiteres Quellsystem ist kein Umbau im `SiteExportService` mehr noetig ### 2. Page-Services sind nicht mehr Singleton UI-nahe Services laufen jetzt pro Blazor-Circuit als `Scoped`. Betroffen: - `ISettingsPageService` - `IStandortePageService` - `IStandorteSapEditorService` - `IManagementCockpitPageService` - `IDashboardPageService` - `ILogsPageService` - `ITransformationsPageService` Wichtig: - `ExportOrchestrationService` bleibt bewusst `Singleton`, weil Exportstatus ueber Circuits geteilt werden muss - stateless Infrastruktur-Services bleiben weiter `Singleton` ### 3. Datenbank-Initialisierung ist aufgeteilt Der fruehere monolithische `DatabaseInitializationService` ist inzwischen in grobe Verantwortungsbloecke getrennt: - `DatabaseInitializationService` als Orchestrator - `DatabaseSchemaMaintenanceService` fuer Schema-/Repair-Logik - `DatabaseSeedService` fuer Defaultdaten und Stammdaten-Seeding - `DatabaseInitializationService.SchemaSql.cs` als SQL-Definitionsblock Das reduziert das groesste Architektur-Risiko deutlich, auch wenn die Startmigrationen weiterhin ein sensibler Teil des Systems bleiben. ### 4. Weitere Razor-Seiten sind entlastet Neben den frueher bereits entlasteten Seiten laufen jetzt auch diese Seiten ueber Page-Services statt direkten `DbContext`-Zugriffen: - `Dashboard.razor` ueber `DashboardPageService` - `Logs.razor` ueber `LogsPageService` - `Transformations.razor` ueber `TransformationsPageService` Der Rest an direkter Persistenzlogik in Razor ist damit deutlich kleiner geworden. ### 5. Kritische HANA-Risiken wurden entschärft #### SQL-Injection-Schutz Im `HanaQueryService` wurden die kritischen interpolierten SQL-Stellen bereinigt: - `tsc` und `dateFilter` laufen jetzt parametriert in `HanaCommand` - `schema` wird als Identifier streng validiert und gequotet Damit ist der akute Injection-Pfad in den HANA-Verkaufsabfragen geschlossen. #### Async statt `.GetAwaiter().GetResult()` Die blockierenden HANA-Aufrufe wurden auf echte Async-Methoden umgestellt: - `IHanaQueryService` ist jetzt async-basiert - `HanaQueryService` nutzt `OpenAsync`, `ExecuteReaderAsync`, `ReadAsync`, `ExecuteScalarAsync` - Aufrufer wie `HanaDataSourceAdapter`, `StandortePageService` und `SettingsPageService` verwenden keine `Task.Run`-Workarounds mehr fuer HANA Damit ist das fruehere Deadlock-/Blocking-Risiko in diesem Pfad deutlich reduziert. ### 6. Test- und Build-Stand Verifiziert wurde zuletzt mit: ```text dotnet build .\TrafagSalesExporter.csproj --verbosity minimal dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal ``` Ergebnis: - Projekt-Build erfolgreich - `36/36` Tests gruen Bekannt: - `dotnet build .\TrafagSalesExporter.sln` endet in dieser Umgebung weiterhin mit Exitcode `1` ohne konkrete Compilerfehler - das Hauptprojekt und das Testprojekt bauen aber erfolgreich - bekannte Warnungen bleiben: - `MSB3270` wegen HANA-Assembly-Architektur - MudBlazor-Analyzer zu `Dense` ### 7. Aktuelles Architektururteil Der Zustand ist jetzt deutlich professioneller als zu Beginn des Refactorings: - Datenquellen sauberer getrennt - UI konsistenter ueber Page-Services geschnitten - groesster Start-/Schema-Block zerlegt - HANA-Pfad sicherer und sauberer asynchron Aber noch nicht vollendet: - keine gezielten Adapter-/Resolver-Unit-Tests - keine Retry-Strategie fuer SharePoint / SAP / HANA-Netzpfade - kein Secret-Store - `DatabaseInitializationService` bleibt trotz Zerlegung ein sensibler produktiver Migrationspfad ## Nachtrag 2026-04-17 Der dokumentierte Stand in diesem Handoff war bei der Waehrungslogik nicht mehr aktuell. Inzwischen gilt: - Kurstabellen fuer `CurrencyExchangeRates` sind im System vorhanden - `Settings` enthaelt bereits eine Pflegeoberflaeche fuer Wechselkurse - `ExchangeRateImportService` importiert ECB-Tageskurse nach `CurrencyExchangeRates` - `NormalizeCurrencyCode` ist als Value-Transformation vorhanden - `ConvertCurrency` ist als Record-Transformation vorhanden - `Program.cs` registriert beide Strategien sowie `CurrencyExchangeRateService` und `ExchangeRateImportService` Wichtig: - die Roh-Auswertung im `Management Cockpit` rechnet Stand heute weiterhin bewusst **nicht** in CHF um - dort bleibt der Umsatz weiterhin in `Sales Currency` - die Waehrungsumrechnung ist aktuell Teil des allgemeinen Transformations-/Mapping-Systems, nicht der Cockpit-Rohsicht Zusatzlich wurden am 2026-04-17 fehlende Unit-Tests fuer die Waehrungslogik nachgezogen: - `CurrencyExchangeRateServiceTests` - `ExchangeRateImportServiceTests` - Erweiterungen in - `TransformationStrategiesTests` - `RecordTransformationServiceTests` - `TransformationCatalogTests` Aktueller Teststatus nach diesem Nachtrag: ```text dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal ``` Ergebnis: - erfolgreich - `31/31` Tests gruen - bekannte Warnung bleibt: - SAP HANA Architekturwarnung `MSB3270` ## Architekturpruefung 2026-04-17 Es wurde eine erneute Gesamtpruefung der Architektur gemacht, ausdruecklich ohne neue Implementierung. ### Gesamturteil Die Grundrichtung ist weiterhin sinnvoll: - klare Trennung der Quellsysteme `SAP`, `BI1`, `SAGE`, `MANUAL_EXCEL` - zentrales fachliches Zielschema ueber `SalesRecord` - zentrale technische Ablage ueber `CentralSalesRecords` - separater Orchestrator fuer Standort- und Konsolidierungsexport - Transformationssystem als eigener Layer Aber: - die Architektur ist **noch nicht stabil genug**, um sie als "fertig sauber" zu betrachten - die groessten Risiken liegen aktuell nicht in SAP oder Waehrungen, sondern in - Start-/Schema-Initialisierung - Config-Import - Verteilung von Logik zwischen Razor-Seiten und Services ### Wichtigste Architektur-Risiken #### 1. Start-/Schema-Initialisierung ist fragil `DatabaseInitializationService` mischt derzeit: - `EnsureCreated` - manuelle `ALTER TABLE`-Pflege - FK-Reparaturlogik - Seeding - empfohlenes Regel-Seeding Das ist funktional hilfreich, aber architektonisch gefaehrlich, weil: - die App-Initialisierung dadurch viel implizite Datenmigration enthaelt - Verhalten schwer vorhersehbar wird - Fehler im Migrationspfad sofort produktive Daten treffen Wichtiger konkreter Befund aus der Pruefung: - beim Kopieren von `Sites_old` nach `Sites` ist die Spaltenreihenfolge im SQL inkonsistent - dadurch koennen Werte wie `ManualImportFilePath`, `SapServiceUrl`, `SapEntitySet` verschoben gespeichert werden - das ist eine reale Datenkorruptionsgefahr und kein reines Architekturthema ### 2. Config-Import ist destruktiv und nicht atomar `ConfigTransferService.ImportJsonAsync` loescht aktuell zuerst grosse Teile der Konfiguration und Daten: - Sites - HanaServers - Transformation Rules - SAP-Konfiguration - Wechselkurse - sogar `CentralSalesRecords` und baut danach mit mehreren `SaveChangesAsync()`-Zwischenschritten neu auf. Risiko: - wenn der Import in der Mitte scheitert, bleibt das System teilweise geloescht zurueck - `CentralSalesRecords` gehoeren fachlich ohnehin nicht sauber in einen normalen Config-Import ### 3. Zu viel Fach- und Persistenzlogik in Razor-Seiten `Settings.razor` und `Standorte.razor` machen aktuell sehr viel direkt: - `DbContext` oeffnen - Daten laden und speichern - Konfigurationsimport/-export anstossen - SAP-Refresh - Upload-Handling - Teile der Validierung / Persistenzlogik Das funktioniert momentan, fuehrt aber langfristig zu: - schwer testbarer UI-Logik - verstreuten Regeln - hoeherem Seiteneffekt-Risiko bei Erweiterungen ### 4. Vertrag zwischen Orchestrator und konsolidiertem Export ist unscharf `ExportOrchestrationService` sammelt bei `ExportAllAsync` bereits `consolidatedRecords`, uebergibt sie weiter, aber `ConsolidatedExportService` ignoriert diesen Parameter und liest erneut aus `CentralSalesRecords`. Das zeigt ein offenes Architekturthema: - Soll die zentrale Datei aus dem Live-Exportlauf gebaut werden? - oder immer nur aus dem persistenten Read Model `CentralSalesRecords`? Aktuell ist beides halb vorhanden. ### 5. Reporting-/Cockpit-Logik ist noch nicht voll verallgemeinert Bei der Pruefung wurde gesehen: - `ManagementCockpitService` enthaelt noch hartcodierte Jahreslogik fuer `2025` und `2026` - die Rohsicht bleibt bewusst ohne CHF-Umrechnung Das ist fuer den aktuellen Stand akzeptabel, zeigt aber: - Reporting ist noch kein voll abstrahierter fachlicher Layer ## Empfohlenes Sollbild Die naechste Architektur-Stufe sollte in diese Richtung gehen: ### 1. Klare Schichten - UI: - Razor nur fuer Interaktion, Anzeige, Formularzustand - Application: - Use Cases / Commands / Queries fuer Export, Config, SAP-Refresh, Wechselkurse, Standortpflege - Domain / Fachlogik: - Transformationen, Mappingregeln, Waehrungsumrechnung, Cockpit-Berechnungen - Infrastructure: - HANA, SAP Gateway, SQLite, SharePoint, Dateisystem ### 2. Versionierte Migrationen statt manueller Start-Reparaturen Statt immer mehr Reparaturlogik beim App-Start: - Schema-Aenderungen versionieren - Migrationspfade testbar machen - Startlogik nur noch fuer minimale Bootstrap-Aufgaben behalten ### 3. Config-Import als atomarer Vorgang Ziel: - alles in einer Transaktion oder bewusst in klar getrennten Phasen - kein halb geloeschter Zustand bei Fehlern - `CentralSalesRecords` aus normalem Config-Import eher herausnehmen ### 4. Zentrale Export-Semantik entscheiden Explizit festlegen: - zentrale Datei immer aus `CentralSalesRecords` oder - zentrale Datei aus dem aktuellen Export-Snapshot Danach die doppelte Semantik entfernen. ## Priorisierung aus Architektursicht Wenn nach Stabilitaet priorisiert wird, dann in dieser Reihenfolge: 1. `DatabaseInitializationService` / Migrationspfad absichern 2. `ConfigTransferService.ImportJsonAsync` atomar und weniger destruktiv machen 3. Logik aus `Settings.razor` und `Standorte.razor` in Anwendungsservices verschieben 4. Export-Semantik fuer Konsolidierung vereinheitlichen 5. erst danach weitere Fachfeatures wie Cockpit-CHF, Budget, Gruppenlogik ## Kurzfazit Die Architektur ist nicht schlecht. Das Grundmodell traegt. Aber: - sie ist noch nicht robust genug fuer ruhigen weiteren Ausbau ohne technische Konsolidierung - die aktuelle Hauptgefahr liegt in Infrastruktur- und Persistenzlogik, nicht in den Fachfeatures Fuer den naechsten Einstieg nach Absturz gilt daher: 1. zuerst diesen Architektur-Nachtrag lesen 2. dann `DatabaseInitializationService` und `ConfigTransferService` als Risikobloecke ansehen 3. neue Fachfeatures erst nach dieser technischen Konsolidierung beginnen ## Nachtrag HANA-/Standort-Workflow 2026-04-17 Nach der Architekturpruefung wurde der doppelte HANA-Workflow bereinigt. ### Altes Problem Vorher gab es zwei konkurrierende Stellen fuer HANA-Konfiguration: - oben eine eigene `HANA Server`-Verwaltung - unten im Standortdialog noch einmal eine fast vollstaendige HANA-Verbindung Dadurch war unklar: - was die zentrale Wahrheit ist - wann ein zentraler Server geaendert wird - wann still ein separater Server pro Standort entsteht ### Neue Logik Oben gilt jetzt: - `HANA Server` ist zentrale HANA-Konfiguration pro Quellsystem - aktuell relevant fuer: - `BI1` - `SAGE` Unten im Standort gilt jetzt: - Standort pflegt nur noch standortspezifische Daten - `Schema` - `TSC` - `Land` - `SourceSystem` - optionale Username-/Password-Overrides - die technische HANA-Verbindung kommt aus der zentralen Konfiguration des Quellsystems ### Technische Umsetzung - `HanaServer` hat jetzt zusaetzlich `SourceSystem` - `DatabaseInitializationService` stellt zentrale Eintraege fuer `BI1` und `SAGE` sicher - bestehende verknuepfte HANA-Server werden dabei moeglichst auf `BI1` / `SAGE` gemappt - `SiteExportService` baut HANA-Verbindungen jetzt aus der zentralen HANA-Konfiguration des Quellsystems - `Settings.razor` testet BI1/SAGE nicht mehr ueber einen Beispiel-Standort, sondern ueber die zentrale HANA-Konfiguration - `Standorte.razor` speichert im Standort fuer HANA-basierte Systeme keine eigene Vollverbindung mehr ### Wichtige Konsequenz Fachlich gilt jetzt: - oben = Standardkonfiguration pro Quellsystem - unten = Standort + optionale Credential-Overrides Das entspricht der gewuenschten Logik: - gleiche BI1-/SAGE-Standorte koennen zentrale Verbindungswerte teilen - Ausnahmen koennen weiter ueber Username-/Password-Overrides reagieren ### UI-Nachtrag Die frueher doppelte und dadurch verwirrende UI wurde danach auch sichtbar bereinigt. Aktueller UI-Stand: - oben heisst der Bereich jetzt klar `Zentrale HANA-Konfiguration` - im Standortdialog gibt es fuer HANA keine zweite technische Eingabestrecke mehr - dort wird nur noch die aktive Zentralverbindung angezeigt - Host, Port, SSL und technische Parameter werden explizit nach oben verwiesen - der zentrale Verbindungstest in `Settings.razor` meldet jetzt sauber die zentrale HANA-Verbindung ## Nachtrag Quellsystem-Verwaltung 2026-04-17 Die bisher noch hart codierten Quellsystem-Listen wurden entfernt und durch echte Stammdaten ersetzt. ### Neuer Stand - neues Modell `SourceSystemDefinition` - Quellsysteme werden jetzt zentral in der DB gehalten statt in Razor-Arrays - pro Quellsystem werden gepflegt: - `Code` - `DisplayName` - `ConnectionKind` - `IsActive` - `CentralUsername` - `CentralPassword` ### Neue GUI-Logik - `Settings.razor` enthaelt jetzt eine pflegbare Quellsystem-Tabelle - dort koennen Quellsysteme per GUI angelegt, bearbeitet und gespeichert werden - Anschlussart ist nicht mehr implizit im Code, sondern pro Quellsystem konfigurierbar - zentrale Zugangsdaten haengen jetzt am Quellsystem selbst ### Anschlussarten Aktuell technisch vorgesehen: - `HANA` - `SAP_GATEWAY` - `MANUAL_EXCEL` Damit gilt: - HANA-Konfiguration oben in `Standorte.razor` nur noch fuer Quellsysteme mit Anschlussart `HANA` - Standort-Dropdown zieht seine Quellsysteme jetzt aus `SourceSystemDefinitions` - Transformationsregeln ziehen ihre Quellsystem-Auswahl ebenfalls aus `SourceSystemDefinitions` ### Technische Umsetzung - `AppDbContext` hat jetzt `DbSet` - `DatabaseInitializationService` erzeugt und seedet `SourceSystemDefinitions` - `SiteExportService` loest zentrale Credentials jetzt ueber `SourceSystemDefinition` - `ConfigTransferService` exportiert/importiert jetzt auch `SourceSystemDefinitions` ### Verifikation Nach dieser Umstellung geprueft: ```text dotnet build .\TrafagSalesExporter.csproj -v minimal dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal ``` Ergebnis: - Build erfolgreich - Tests erfolgreich - `31/31` Tests gruen ### Bereinigung der Legacy-Credentials Danach wurden auch die alten zentralen Credential-Felder technisch bereinigt. Aktueller Stand: - `ExportSettings` enthaelt keine alten Felder mehr fuer `SapUsername`, `Bi1Username`, `SageUsername` usw. - der Config-Export schreibt zentrale Zugangsdaten nur noch ueber `SourceSystemDefinitions` - `ConfigTransferService` hat keinen aktiven Legacy-Credential-Pfad mehr - die fruehere Temp-Datei `standorte_numbered.tmp` wurde entfernt Wichtig: - bestehende DB-Spalten koennen physisch noch vorhanden sein, sind aber kein aktiver Codepfad mehr - fuehrende Wahrheit fuer zentrale Zugangsdaten ist jetzt ausschliesslich `SourceSystemDefinition` ### Schema-Bereinigung Danach wurde auch die SQLite-Schemabereinigung nachgezogen. Aktueller Stand: - `DatabaseInitializationService` erkennt alte Credential-Spalten in `ExportSettings` - wenn diese Legacy-Spalten noch existieren, wird `ExportSettings` beim Start auf das neue Schema rekonstruiert - erhalten bleiben nur die noch gueltigen Felder: - `DateFilter` - `TimerHour` - `TimerMinute` - `TimerEnabled` - `DebugLoggingEnabled` - `LocalSiteExportFolder` - `LocalConsolidatedExportFolder` Damit gilt jetzt: - alte zentrale SAP/BI1/SAGE-Credentials sind nicht nur logisch entfernt - sie werden bei bestehender DB auch aktiv aus dem `ExportSettings`-Schema entfernt ### Letzte Bereinigung HANA-Credentials Danach wurde auch die letzte doppelte Credential-Stelle in der HANA-Verwaltung entfernt. Aktueller Stand: - zentrale HANA-Konfiguration speichert nur noch technische Verbindungsdaten - `Host` - `Port` - `DatabaseName` - `UseSsl` - `ValidateCertificate` - `AdditionalParams` - Username/Password werden nicht mehr in der zentralen HANA-UI gepflegt - HANA-Verbindungstests in `Standorte.razor` verwenden jetzt die zentralen Credentials aus `SourceSystemDefinition` - `SiteExportService` faellt bei HANA nicht mehr auf in `HanaServer` gespeicherte Credentials zurueck - `ConfigTransferService` exportiert/importiert fuer `HanaServer` keine Username-/Password-Werte mehr - `DatabaseInitializationService` bereinigt bei bestehender DB auch das `HanaServers`-Schema und entfernt die Altspalten `Username` / `Password` Die fachliche Reihenfolge ist jetzt eindeutig: 1. zentrale Credentials aus `SourceSystemDefinition` 2. optionale Override-Credentials am `Site` 3. technische HANA-Verbindung aus der zentralen HANA-Konfiguration ### EF-/SQLite-Fix Beim ersten Lauf nach der Schema-Bereinigung trat noch ein Mapping-Fehler auf: - `SQLite Error 1: 'no such column: h.Password'` Ursache: - `HanaServers`-Schema war bereits ohne `Username` / `Password` - das EF-Modell `HanaServer` hat diese Properties aber noch als normale Spalten behandelt Fix: - `HanaServer.Username` und `HanaServer.Password` sind jetzt `[NotMapped]` - damit bleiben sie fuer Laufzeit-Verbindungsaufbau und Tests nutzbar - EF erwartet sie aber nicht mehr als Datenbankspalten ## Nachtrag Zentrale SAP-Steuerung 2026-04-17 Der verbleibende Architekturbruch bei SAP wurde ebenfalls bereinigt. ### Neuer Stand - `SourceSystemDefinition` enthaelt jetzt auch `CentralServiceUrl` - zentrale SAP-Service-URL wird damit am Quellsystem gepflegt, nicht mehr primaer am Standort - `Standorte.razor` behandelt `SapServiceUrl` jetzt als Override - wenn kein Override gesetzt ist, zieht SAP die URL zentral aus dem Quellsystem ### UI - `Settings.razor` hat fuer Quellsysteme jetzt eine Dialogbearbeitung statt nur Inline-Tabellenfelder - dadurch ist das Quellsystem sauber editierbar - fuer `SAP_GATEWAY` wird dort die zentrale SAP-Service-URL gepflegt - `Standorte.razor` zeigt bei SAP jetzt: - zentrale SAP Service URL - optionales `SAP Service URL Override` ### Laufzeitlogik - `SiteExportService` verwendet bei SAP die effektive URL aus - Standort-Override - sonst `SourceSystemDefinition.CentralServiceUrl` - SAP-Verbindungstest in `Settings.razor` testet die zentrale URL direkt aus dem Quellsystem - Dashboard zeigt fuer SAP jetzt ebenfalls die effektive zentrale bzw. ueberschriebene URL ### Verifikation Nach der Umstellung geprueft: ```text dotnet build .\TrafagSalesExporter.csproj -v minimal dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --verbosity minimal ``` Ergebnis: - Build erfolgreich - Tests erfolgreich - `31/31` Tests gruen ## Nachtrag 2026-04-16 Seit dem letzten Handoff wurden weitere Funktionen umgesetzt, die unten im alten Stand noch nicht voll enthalten sind. ## Zielbild Die App wurde von einem reinen BI1/HANA-Exporter zu einer kombinierten Plattform erweitert: - `BI1` und `SAGE` bleiben auf direktem HANA-Zugriff - `SAP` laeuft separat ueber SAP Gateway / OData - SAP-Quellen koennen gelesen, gejoint und auf das zentrale `SalesRecord`-Schema gemappt werden - Standort-Exporte werden lokal als Excel geschrieben - zusaetzlich werden Datensaetze in eine zentrale SQLite-Tabelle geschrieben - ein konsolidierter Export liest aus dieser zentralen Tabelle ## Wichtigste umgesetzte Funktionen ### 1. Zentrale Credentials pro Quellsystem Es gibt zentrale Zugangsdaten in `ExportSettings` fuer: - `SAP` - `BI1` - `SAGE` Zusaetzlich gibt es pro Standort optionale Overrides: - `UsernameOverride` - `PasswordOverride` Aufloesungsreihenfolge: 1. Standort-Override 2. zentrale Credentials des Quellsystems 3. bei HANA zusaetzlich Fallback auf alten `HanaServer.Username/Password` ### 2. SAP von BI1/HANA getrennt `SAP` nutzt nicht mehr den HANA-Pfad, sondern eine eigene Gateway/OData-Strecke. Pro SAP-Standort gibt es: - `SapServiceUrl` - `SapEntitySet` - `SapEntitySetsCache` - `SapEntitySetsRefreshedAtUtc` Refresh der SAP-Quellen erfolgt nur auf Knopfdruck. Beispiel Service URL: ```text http://travt762.sap.trafag.com:8000/sap/opu/odata/sap/ZPOWERBI_EINKAUF_SRV/ ``` Wichtig: - Service URL immer nur bis zum Service - Entity Set separat auswaehlen ### 3. SAP-Quellen, Joins und Feldmappings Fuer SAP gibt es mehrere neue Modelle: - `SapSourceDefinition` - `SapJoinDefinition` - `SapFieldMapping` Unterstuetzt wird: - mehrere SAP-Quellen pro Standort - Alias pro Quelle - Primaerquelle - Join-Definitionen - Mapping von `Alias.Feldname` auf zentrales Schema UI-Erweiterungen: - `Quellen refreshen` - `Felder aus Quellen laden` - Join-Key-Auswahl aus Metadaten - `Auto-Match` fuer gleiche Feldnamen zwischen Primaerquelle und anderen Quellen ### 4. Zentrale Datenspeicherung Neue Tabelle: - `CentralSalesRecords` Verwendung: - pro Standort werden alte zentrale Saetze dieses Standorts ersetzt - konsolidierte Excel liest aus `CentralSalesRecords` Wichtig: - zentrale Excel wird nicht appendet - sie wird aus dem aktuellen Zustand der zentralen Tabelle neu erstellt ### 5. Exportpfade Neue Konfigurationsmoeglichkeiten: Zentral in `Settings`: - `LocalSiteExportFolder` - `LocalConsolidatedExportFolder` Pro Standort: - `LocalExportFolderOverride` Fallback wenn leer: ```text ./output ``` relativ zum App-Verzeichnis. ### 6. SharePoint SharePoint-Upload ist optional. Wenn keine vollstaendige SharePoint-Konfiguration vorhanden ist: - Excel wird trotzdem lokal erzeugt - kein Upload nach SharePoint Benoetigte SharePoint-Werte: - `Tenant ID` - `Client ID` - `Client Secret` Das sind Entra App Registration Werte, nicht normale Benutzer-Credentials. ### 7. Config Import/Export Es gibt JSON-Import/Export der Konfiguration mit Checkbox: - mit Secrets - ohne Secrets Enthalten sind u. a.: - SharePoint Config - ExportSettings - HanaServers - Sites - Transformation Rules - SAP-Quellen - SAP-Joins - SAP-Mappings ### 8. Logging und Live-Status Neue technische Logs ueber `AppEventLogs`. Sichtbar: - auf `/logs` - im Dashboard als `Live-Status` Geloggt werden u. a.: - HANA-Query Start - SAP Refresh - SAP Reads - Transformationen - Excel-Erstellung - zentrale Tabellenspeicherung - Export erfolgreich / fehlgeschlagen ### 9. Excel oeffnen Im Dashboard gibt es neben `Export` den Button: - `Excel oeffnen` Dieser nutzt `ExportLogs.FilePath`. Voraussetzungen: - letzter Export erfolgreich - `FilePath` gespeichert - Datei existiert lokal ### 10. Management Cockpit Es gibt einen neuen Menuepunkt: - `Management Cockpit` Funktion: - Auswahl vorhandener Excel-Dateien - Analyse einer exportierten Standort-Datei - Kennzahlen fuer Geschaeftsinhaber / Management Aktuell enthalten: - Umsatz - geschaetzte Kosten - geschaetzte Marge - Rechnungsanzahl - Kundenanzahl - Top Kunden - Top Produktgruppen - Top Sales Owner - Datenqualitaetshinweise - automatische Management-Aussagen ### 11. Manueller Excel-Import pro Standort Es gibt jetzt einen vierten `SourceSystem`-Typ: - `MANUAL_EXCEL` Gedanke: - Standort ohne Netz-/Systemanbindung liefert nur Excel - Datei wird im Standort hochgeladen - Export liest diese Datei statt SAP/HANA - Daten werden in `CentralSalesRecords` fuer diesen Standort ersetzt - der zentrale Export liest weiter nur aus `CentralSalesRecords` Neue Site-Felder: - `ManualImportFilePath` - `ManualImportLastUploadedAtUtc` Wichtig: - das ist kein Excel-zu-Excel-Merge - die App importiert ins zentrale Schema und erzeugt danach die zentrale Datei neu ### 12. Dashboard erweitert Im Dashboard gibt es jetzt zusaetzlich: - separaten Bereich `Zentrale Datei` - `Excel oeffnen` fuer die neueste zentrale Datei `Sales_All_*.xlsx` - Button `Alle exportieren` - Button `Zentrale Datei neu erzeugen` Bedeutung: - `Alle exportieren` liest alle Quellen neu und erzeugt danach die zentrale Datei - `Zentrale Datei neu erzeugen` schreibt nur aus `CentralSalesRecords` eine neue zentrale Excel ### 13. Management Cockpit Roh-Auswertung aus Zentraldaten Zusaetzlich zur dateibasierten Cockpit-Analyse gibt es jetzt eine Roh-Auswertung direkt aus `CentralSalesRecords`. Aktuell umgesetzt: - Auswahl Jahr - optional Auswahl Monat - Jahresumsatz - Monatsumsatz - Tagesumsatz im gewaehlten Monat - Umsatz nach Quelle - Umsatz nach Land - Periodenabdeckung / Zeilen / Rechnungen / Standorte / Laender / Waehrungen Bewusst noch nicht enthalten: - kein Intercompany-Filter - keine CHF-Umrechnung - kein Budgetvergleich - keine Spartenlogik - keine Gruppenlogik - keine Margenlogik ### 14. Transformationssystem erweitert Das Transformationssystem kann jetzt zwei Ebenen: - `Value` fuer einfache feldweise Regeln aus der GUI - `Record` fuer komplexere C#-Strategien per Strategy Pattern Umgesetzt: - neues Feld `RuleScope` auf `FieldTransformationRule` - dynamischer Strategiekatalog - GUI liest verfuegbare Typen aus dem Katalog - erste `Record`-Strategie: `FirstNonEmpty` Beispiel: - `TargetField = CustomerName` - `TransformationType = FirstNonEmpty` - `Argument = CustomerName|SupplierName|Name` ### 15. Schema-Lookup fuer HANA-Standorte Im Standortdialog fuer HANA-basierte Standorte gibt es jetzt: - Button `Schemas laden` - Lookup mit gueltigen Schemas aus HANA Die Liste wird nicht blind aus allen Schemas gelesen, sondern auf typische B1-Schemas eingeschraenkt, in denen z. B. Tabellen wie - `OINV` - `INV1` - `ORIN` - `RIN1` - `OCRD` - `OITM` vorhanden sind. Wichtig: - manuelle Eingabe bleibt moeglich - fuer `BI1` und `SAGE` werden beim Lookup die effektiven Credentials inkl. zentraler Zugangsdaten / Overrides verwendet - das reduziert Fehler wie `invalid schema name` ### 16. Testabdeckung ausgebaut Es gibt jetzt ein separates Testprojekt: - `TrafagSalesExporter.Tests` Automatisiert getestet werden aktuell: - Transformationsstrategien - `RecordTransformationService` - `TransformationCatalog` - `ManualExcelImportService` - `ManagementCockpitService` - `ConfigTransferService` Wichtiger bereits gefundener Bug: - deutsches Dezimalformat wie `1,50` wurde im manuellen Excel-Import falsch interpretiert - Parsing wurde korrigiert ## Wichtige Dateien ### Modelle - `Models/Site.cs` - `Models/ExportSettings.cs` - `Models/ExportLog.cs` - `Models/CentralSalesRecord.cs` - `Models/SapSourceDefinition.cs` - `Models/SapJoinDefinition.cs` - `Models/SapFieldMapping.cs` - `Models/ManagementCockpitModels.cs` - `Models/ConfigTransferPackage.cs` - `Models/FieldTransformationRule.cs` ### Services - `Services/SiteExportService.cs` - `Services/ConsolidatedExportService.cs` - `Services/CentralSalesRecordService.cs` - `Services/SapGatewayService.cs` - `Services/SapCompositionService.cs` - `Services/ConfigTransferService.cs` - `Services/AppEventLogService.cs` - `Services/ManagementCockpitService.cs` - `Services/DatabaseInitializationService.cs` - `Services/ExportOrchestrationService.cs` - `Services/ManualExcelImportService.cs` - `Services/TransformationCatalog.cs` - `Services/RecordTransformationService.cs` - `Services/TransformationStrategies.cs` ### UI - `Components/Pages/Standorte.razor` - `Components/Pages/Settings.razor` - `Components/Pages/Dashboard.razor` - `Components/Pages/Logs.razor` - `Components/Pages/ManagementCockpit.razor` - `Components/Pages/Transformations.razor` - `Components/Layout/NavMenu.razor` ### Tests - `TrafagSalesExporter.Tests/TransformationStrategiesTests.cs` - `TrafagSalesExporter.Tests/RecordTransformationServiceTests.cs` - `TrafagSalesExporter.Tests/TransformationCatalogTests.cs` - `TrafagSalesExporter.Tests/ManualExcelImportServiceTests.cs` - `TrafagSalesExporter.Tests/ManagementCockpitServiceTests.cs` - `TrafagSalesExporter.Tests/ConfigTransferServiceTests.cs` ## Datenbank / Migrationen Viele Aenderungen laufen ueber `DatabaseInitializationService`. Wichtige neue oder erweiterte Tabellen/Felder: - `Sites` - `UsernameOverride` - `PasswordOverride` - `SapServiceUrl` - `SapEntitySet` - `SapEntitySetsCache` - `SapEntitySetsRefreshedAtUtc` - `LocalExportFolderOverride` - `ManualImportFilePath` - `ManualImportLastUploadedAtUtc` - `ExportSettings` - zentrale SAP/BI1/SAGE Credentials - `LocalSiteExportFolder` - `LocalConsolidatedExportFolder` - `DebugLoggingEnabled` - `FieldTransformationRules` - `RuleScope` - `ExportLogs` - `FilePath` - neue Tabellen: - `AppEventLogs` - `CentralSalesRecords` - SAP-Konfigtabellen ## Letztes Hauptproblem und Loesung ### Export hing nach zentraler Speicherung Der Export blieb zuletzt nach - `Zentrale Tabelle: 20106 Datensaetze gespeichert.` haengen. Die eigentliche Ursache war am Ende nicht mehr der Batch-Insert selbst, sondern ein kaputter SQLite-Schemazustand: - mindestens eine Tabelle referenzierte per FK noch `main.Sites_old` - dadurch scheiterte `SaveChangesAsync()` spaeter beim Schreiben in `AppEventLogs` oder `ExportLogs` - die alte Tabelle `Sites_old` existierte nicht mehr Beobachteter Fehler: - `SQLite Error 1: 'no such table: main.Sites_old'` ## Umgesetzte Korrekturen - `Components/Pages/Dashboard.razor` - Live-Status pollt waehrend laufendem Export nicht mehr permanent `AppEventLogs` - stattdessen Anzeige ueber den In-Memory-Status aus `ExportOrchestrationService` - `Program.cs` - SQLite `Default Timeout` von `10` auf `60` erhoeht - `Services/CentralSalesRecordService.cs` - nach abgeschlossenem Batch-Insert wird explizit `Zentrale Tabelle aktualisiert` gesetzt - `Services/DatabaseInitializationService.cs` - automatische Reparaturlogik fuer Tabellen, deren `CREATE TABLE`-SQL noch `Sites_old` referenziert - betroffene Tabellen werden beim Start neu aufgebaut und Daten rueberkopiert Danach wurde der Export erfolgreich getestet und geht jetzt wieder durch. ## Was bei einer naechsten Stoerung zuerst zu pruefen ist 1. Tritt beim App-Start die Schema-Reparatur sauber durch? 2. Gibt es noch weitere Tabellen mit FK-Referenz auf `Sites_old`? 3. Erst danach wieder Insert-/Commit-Batches der zentralen Speicherung untersuchen ## Build-Status Letzter Build: ```text dotnet build TrafagSalesExporter.sln ``` Ergebnis: - erfolgreich - bekannte Warnungen bleiben: - SAP HANA Architekturwarnung `MSB3270` - MudBlazor Analyzer `Dense` ## Nachtrag 2026-04-17 UI-Klarstellung HANA vs. SAP - `Components/Pages/Standorte.razor` - Bereich oben heisst jetzt bewusst `Zentrale HANA-Technik` - Hinweistext stellt klar: dort erscheinen nur Quellsysteme mit Anschlussart `HANA` - `SAP` wird zentral unter `Settings -> Quellsysteme` gepflegt und gehoert nicht in diese Box - der irrefuehrende Button `Server hinzufuegen` wurde entfernt - neue HANA-Zeilen entstehen aus den Quellsystem-Stammdaten, nicht mehr aus einer zweiten UI-Erfassung - Dialogtitel fuer HANA wurde auf reine Bearbeitung der zentralen Technik reduziert Fachliche Regel jetzt: - `Quellsysteme` verwalten die zentralen Systeme und deren Anschlussart - `Standorte` zeigen fuer HANA nur noch die technische Zentralverbindung - `SAP` wird nicht mehr implizit in der HANA-Box erwartet ## Nachtrag 2026-04-17 Pruefung Config-Import/Export Der aktuelle Config-Transfer wurde nach den Umbauten nochmals geprueft. Status: - Das aktuelle Import-/Exportformat passt zum neuen Modell. - `SourceSystemDefinitions` werden mit `ConnectionKind`, `CentralServiceUrl`, `CentralUsername`, `CentralPassword` importiert/exportiert. - `HanaServers` enthalten nur noch technische HANA-Verbindungsdaten und keine Credentials mehr. - Standort-Overrides fuer Username/Password sowie SAP Service URL gehen weiterhin mit. - Die vorhandenen `ConfigTransferServiceTests` laufen grün. Weiterhin offene Architekturpunkte: - `ConfigTransferService.ImportJsonAsync` ist weiterhin destruktiv und nicht atomar. - Erst werden bestehende Daten geloescht, danach wird in mehreren Schritten neu aufgebaut. - Wenn der Import in der Mitte scheitert, bleibt ein teilweiser Zustand zurueck. - Altformat-Risiko bei `ConnectionKind`: - Wenn ein aelteres JSON bereits `SourceSystemDefinitions` enthaelt, aber noch ohne `ConnectionKind`, faellt der DTO-Default auf `HANA`. - Dadurch koennte ein altes `SAP` beim Import falsch als `HANA` landen. Fazit: - Fuer Exporte aus dem aktuellen Stand ist der Config-Transfer konsistent. - Fuer aeltere JSON-Staende braucht der Import noch eine explizite Migrations-/Fallback-Logik.