From 9322e7c4caefbd224583c780fd4639aa7a57a512 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 17 Apr 2026 12:18:54 +0000 Subject: [PATCH] Handoff-Dok fuer das DataSourceAdapter-Refactoring Beschreibt was geaendert wurde, wie gebaut/getestet wird und welche Themen bewusst offen gelassen wurden (SQL-Injection, Blocking-Async). --- .../HANDOFF_REFACTORING_2026-04-17.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 TrafagSalesExporter/HANDOFF_REFACTORING_2026-04-17.md diff --git a/TrafagSalesExporter/HANDOFF_REFACTORING_2026-04-17.md b/TrafagSalesExporter/HANDOFF_REFACTORING_2026-04-17.md new file mode 100644 index 0000000..e5bf6bf --- /dev/null +++ b/TrafagSalesExporter/HANDOFF_REFACTORING_2026-04-17.md @@ -0,0 +1,119 @@ +# Handoff: DataSourceAdapter-Refactoring (2026-04-17) + +**Branch:** `claude/review-trafag-tool-JONMq` +**Commit:** `82ac7df` ("DataSourceAdapter-Pattern + SiteExportService schlanker + Page-Services Scoped") +**Basis:** `main` @ `2a56ba5` (umfangreiches refactoring) + +## Kontext fuer den naechsten LLM + +Vorheriges Review hatte drei Architektur-Punkte beanstandet: +1. `SiteExportService` war zu gross (338 Zeilen, if/else auf ConnectionKind) +2. Fehlende Adapter-Abstraktion fuer Datenquellen (HANA / SAP_GATEWAY / MANUAL_EXCEL) +3. Alle Services Singleton, auch UI-nahe Page-Services + +Dieses Refactoring adressiert alle drei Punkte. **Nicht** im Scope (absichtlich offen gelassen): +- SQL-Injection-Risiko in `HanaQueryService:191,204` +- `.GetAwaiter().GetResult()` Blocking in `HanaQueryService` +- Secret-Store-Integration +- Retry/Polly + +## Was konkret geaendert wurde + +### Neu: `Services/DataSources/` +| Datei | Zweck | +|---|---| +| `IDataSourceAdapter.cs` | Interface mit `ConnectionKind` + `FetchAsync(context)` | +| `DataSourceFetchContext.cs` | Input: Site, SourceDefinition, Settings, SharePointConfig, UpdateStatus | +| `DataSourceFetchResult.cs` | Output: Records + optionaler `ReferenceFilePath` (Manual Excel liefert Quell-Datei als Referenz) | +| `IDataSourceAdapterResolver.cs` + `DataSourceAdapterResolver.cs` | Dictionary-Lookup nach ConnectionKind | +| `HanaDataSourceAdapter.cs` | Baut `HanaServer` aus zentraler Config + Site-Overrides, ruft `IHanaQueryService.GetSalesRecords` | +| `SapGatewayDataSourceAdapter.cs` | Laedt SapSources/Joins/Mappings, ruft `ISapCompositionService.BuildSalesRecordsAsync` | +| `ManualExcelDataSourceAdapter.cs` | Lokale Datei oder SharePoint-Download, ruft `IManualExcelImportService.ReadSalesRecordsAsync` | +| `DataSourceCredentials.cs` | Interner Helper (FirstNonEmpty, Resolve, ResolveSapServiceUrl) | + +### Geaendert: `Services/SiteExportService.cs` +338 -> 187 Zeilen. Jetzt reine Pipeline: +``` +1. NormalizeSourceSystem +2. LoadExportConfigAsync (settings, spConfig, sourceDefinition, rules) - 1x DbContext +3. Resolve adapter per ConnectionKind +4. adapter.FetchAsync -> records (+ optional ReferenceFilePath) +5. Transform (_transformationService.Apply) +6. Excel erzeugen (falls Adapter keine Referenzdatei liefert) +7. CentralSalesRecordService.ReplaceForSiteAsync +8. UploadToSharePointIfConfiguredAsync +``` +Entferntes Dead-Injection: `ISapGatewayService` (wurde konstruiert aber nie benutzt). + +### Geaendert: `Program.cs` +- Adapter registriert (3x `AddSingleton` + Resolver) +- **Page-Services auf Scoped** (`ISettingsPageService`, `IStandortePageService`, `IStandorteSapEditorService`, `IManagementCockpitPageService`, `IDashboardPageService`, `ILogsPageService`, `ITransformationsPageService`) — pro Blazor-Circuit +- `ExportOrchestrationService` bleibt bewusst Singleton (geteilter Export-Status ueber Circuits via `OnExportStatusChanged`) +- Stateless Connector-/Infra-Services bleiben Singleton + +## Was der naechste LLM pruefen / testen soll + +### 1. Build (ICH KONNTE NICHT BAUEN — kein dotnet SDK in der Sandbox) +```bash +cd TrafagSalesExporter +dotnet restore +dotnet build +``` +Falls Fehler: hohe Wahrscheinlichkeit, dass ich ein `using` vergessen oder einen Interface-Namen vertippt habe. Kandidaten fuer Tippfehler: `DataSourceCredentials.FirstNonEmpty` in `SiteExportService.cs:181`, Adapter-Constructoren in `Services/DataSources/*.cs`. + +### 2. Tests laufen lassen +```bash +cd TrafagSalesExporter +dotnet test +``` +Bestehende Tests in `TrafagSalesExporter.Tests/` referenzieren **keinen** der refactorierten Services direkt (siehe grep: `SiteExportService|IDataSource` liefert keine Treffer in Tests). Sollten also gruen bleiben. + +### 3. Manueller Smoke-Test der drei Quellsysteme +In der Blazor-UI (Standorte-Seite, Export-Button): +- **HANA-Standort**: Export starten — muss wie vorher Records aus HANA ziehen, Excel erzeugen, zentrale Tabelle aktualisieren, optional nach SharePoint uploaden. +- **SAP_GATEWAY-Standort**: Export starten — muss SAP-Quellen/Joins/Mappings laden, Records ueber `SapCompositionService` bauen. +- **MANUAL_EXCEL-Standort** (lokaler Pfad): Referenz-Excel wird gelesen, **keine** neue Excel-Datei erzeugt (Referenzdatei bleibt). +- **MANUAL_EXCEL-Standort** (SharePoint-Pfad, `/Shared Documents/...`): temporaerer Download, lesen, Temp-Datei wird im `finally` wieder geloescht. + +**Verhaltens-Aequivalenz** zur vorherigen Implementierung ist das Pruefkriterium — keine neue Funktionalitaet, nur Struktur. + +### 4. Captive-Dependency-Check +Scoped -> Singleton wuerde DI-Fehler werfen. Ich habe per grep verifiziert, dass kein Singleton eine `I*PageService` konsumiert. Wer das nochmal manuell pruefen moechte: +```bash +grep -rn "PageService" TrafagSalesExporter/Services/ | grep -v "PageService.cs" +``` +Sollte nur Registrierungen in Program.cs und UI-Komponenten zeigen. + +### 5. Erweiterbarkeit testen +Um ein viertes Quellsystem hinzuzufuegen, reicht jetzt: +1. Konstante in `Models/SourceSystemDefinition.cs::SourceSystemConnectionKinds` +2. Neuer `IDataSourceAdapter` in `Services/DataSources/` +3. `builder.Services.AddSingleton();` in `Program.cs` + +Kein Eingriff in `SiteExportService` noetig. + +## Offene Themen fuer Follow-up-PRs + +1. **SQL-Injection (kritisch)** — `HanaQueryService.cs:191,204`: `schema`, `tsc`, `dateFilter` via String-Interpolation. Auf `HanaCommand`-Parameter umstellen (Beispiel: `GetAvailableSchemas()` nutzt das bereits korrekt). +2. **Blocking async** — `HanaQueryService` hat 8x `.GetAwaiter().GetResult()`. In Blazor Server Deadlock-Risiko — auf echtes `async/await` migrieren. +3. **Tests fuer Adapter** — Unit-Tests fuer die drei neuen Adapter mit Fakes der Connector-Services waeren sinnvoll. `DataSourceAdapterResolver`-Test (Dictionary-Lookup, Fehler bei unbekanntem Kind) einfach zu schreiben. +4. **Retry-Layer** — HTTP-Requests zu SharePoint/SAP Gateway ohne Polly. Bei Netzflackern bricht Export ab. + +## Dateien-Cheatsheet + +``` +TrafagSalesExporter/ +├── Program.cs [MOD: Lifetimes + Adapter-Registrierung] +├── Services/ +│ ├── SiteExportService.cs [MOD: 338 -> 187 Zeilen, pure Pipeline] +│ └── DataSources/ [NEU] +│ ├── IDataSourceAdapter.cs +│ ├── IDataSourceAdapterResolver.cs +│ ├── DataSourceAdapterResolver.cs +│ ├── DataSourceFetchContext.cs +│ ├── DataSourceFetchResult.cs +│ ├── DataSourceCredentials.cs +│ ├── HanaDataSourceAdapter.cs +│ ├── SapGatewayDataSourceAdapter.cs +│ └── ManualExcelDataSourceAdapter.cs +```