refactoring

This commit is contained in:
2026-04-17 10:29:41 +02:00
parent 83a400a90e
commit bec0410ef4
17 changed files with 1752 additions and 432 deletions
+462
View File
@@ -43,6 +43,426 @@ Ergebnis:
- 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<SourceSystemDefinition>`
- `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.
@@ -518,3 +938,45 @@ Ergebnis:
- 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.