Ensure ZSCHWEIZ OData mapping seed
This commit is contained in:
@@ -2,6 +2,57 @@
|
||||
|
||||
Stand: 2026-05-05
|
||||
|
||||
## 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 `50/50` erfolgreich.
|
||||
|
||||
## Nachtrag 2026-05-05 Aktueller Handoff FinanceProbe / Laenderabgleich
|
||||
|
||||
Der aktuelle Arbeitsstand fuer den naechsten Einstieg ist der lokale FinanceProbe:
|
||||
|
||||
@@ -17,6 +17,48 @@ Lokaler FinanceProbe:
|
||||
http://localhost:55417/finance
|
||||
```
|
||||
|
||||
## Aktueller Zusatzstand 2026-05-07 SAP OData / ZSCHWEIZ
|
||||
|
||||
Schweiz/Oesterreich werden ueber eine neue SAP-Tabelle `ZSCHWEIZ` bereitgestellt.
|
||||
|
||||
Wichtige Punkte:
|
||||
|
||||
- ABAP-Report: `report.abap`
|
||||
- SAP-Tabelle: `ZSCHWEIZ`
|
||||
- OData EntitySet: `ZSCHWEIZSet`
|
||||
- App-Standort: `ZSCHWEIZ` / `Schweiz/Oesterreich`
|
||||
- Geplanter App-Pfad: `SAP` = `SAP OData`, nicht direkter HANA-Spezialcode
|
||||
|
||||
Quellsystem-Codes:
|
||||
|
||||
- `SAP`: SAP OData/Gateway, DisplayName `SAP OData`
|
||||
- `SAP_HANA`: direkte HANA-Tabellen/Views, DisplayName `SAP HANA Tables/Views`
|
||||
- `BI1`: HANA
|
||||
- `SAGE`: HANA
|
||||
- `MANUAL_EXCEL`: Excel/CSV
|
||||
|
||||
Mapper:
|
||||
|
||||
- SAP OData nutzt `SapSourceDefinition`, `SapJoinDefinition`, `SapFieldMapping`.
|
||||
- Direkte HANA-Tabellen/Views koennen dieselben Mapping-Tabellen ebenfalls nutzen.
|
||||
- Bei HANA mit gepflegten Quellen/Mappings nutzt `HanaDataSourceAdapter` den generischen Mapping-Pfad.
|
||||
- Ohne HANA-Mapping bleibt der alte B1-HANA-Standardpfad fuer `OINV/INV1/ORIN/RIN1` aktiv.
|
||||
|
||||
ZSCHWEIZ-Seed:
|
||||
|
||||
- Quelle Alias `Z`
|
||||
- EntitySet `ZSCHWEIZSet`
|
||||
- Mapping auf `SalesRecord` ist vorbefuellt und grafisch editierbar.
|
||||
- Beim App-Start wird die ZSCHWEIZ-Quelle samt Feldmapping per Upsert angelegt oder repariert.
|
||||
- Wenn Gateway `$metadata` liefert, koennen Felder in der UI per `Felder aus Quellen laden` gelesen werden.
|
||||
|
||||
ABAP-Fachlogik:
|
||||
|
||||
- `BUKRS 1100` = Schweiz, `TSC TRCH`, `LAND1 CH`
|
||||
- `BUKRS 1200` = Oesterreich, `TSC TRAT`, `LAND1 AT`
|
||||
- `CUSTOMER_LAND` = Kundenland aus `KNA1-LAND1`
|
||||
- Netto-/Steuerwerte werden in Belegwaehrung und Hauswaehrung geschrieben.
|
||||
|
||||
Aktuelle FinanceProbe-Funktionen:
|
||||
|
||||
- `Meeting Ampel 2025` fuer alle Laender aus `check.xlsx`
|
||||
|
||||
@@ -2,6 +2,43 @@
|
||||
|
||||
Stand: 2026-05-05
|
||||
|
||||
## Nachtrag 2026-05-07 ZSCHWEIZ ueber SAP OData
|
||||
|
||||
Finaler Stand fuer Schweiz/Oesterreich:
|
||||
|
||||
- ABAP-Report `report.abap` fuellt SAP-Tabelle `ZSCHWEIZ`.
|
||||
- Buchungskreis `1100` = Schweiz, `1200` = Oesterreich.
|
||||
- `LAND1` in `ZSCHWEIZ` ist Reporting-Land aus Buchungskreis.
|
||||
- `CUSTOMER_LAND` ist Kundenland aus `KNA1-LAND1`.
|
||||
- Die App liest `ZSCHWEIZ` ueber SAP OData, nicht ueber direkten HANA-Spezialcode.
|
||||
|
||||
In der App:
|
||||
|
||||
- Quellsystem-Code `SAP` bleibt bestehen, DisplayName jetzt `SAP OData`.
|
||||
- `SAP_HANA` ist nur fuer direkte HANA-Tabellen/Views und heisst `SAP HANA Tables/Views`.
|
||||
- Der grafische Mapper funktioniert fuer SAP OData und fuer HANA-Tabellen/Views.
|
||||
- Vorkonfigurierter Standort:
|
||||
- `TSC = ZSCHWEIZ`
|
||||
- `Land = Schweiz/Oesterreich`
|
||||
- `SourceSystem = SAP`
|
||||
- Quelle `Z`
|
||||
- EntitySet `ZSCHWEIZSet`
|
||||
- Quelle und Feldmapping werden beim App-Start per Seed-/Repair-Logik nachgezogen, auch wenn der Standort bereits existiert.
|
||||
|
||||
Naechste Schritte:
|
||||
|
||||
1. App neu starten, damit die Seed-/Repair-Logik laeuft.
|
||||
2. In `Settings -> Quellsysteme` pruefen, ob `SAP` als `SAP OData` angezeigt wird.
|
||||
3. In `Standorte` den Standort `ZSCHWEIZ` oeffnen.
|
||||
4. Falls die zentrale SAP-Service-URL noch auf `ZPOWERBI_EINKAUF_SRV` zeigt, beim Standort `SAP Service URL Override` auf den finalen OData-Service fuer `ZSCHWEIZ` setzen.
|
||||
5. `Entity Sets refreshen`.
|
||||
6. Quelle `Z` auf `ZSCHWEIZSet` kontrollieren.
|
||||
7. `Felder aus Quellen laden`.
|
||||
8. Grafisches Mapping kontrollieren; manuell mappen musst du nur, wenn Gateway-Feldnamen vom erwarteten `ZSCHWEIZ`-Layout abweichen.
|
||||
9. Standort aktivieren und Export testen.
|
||||
|
||||
Keine manuelle Feldliste ist noetig, wenn der Gateway-Service `$metadata` korrekt liefert.
|
||||
|
||||
## Nachtrag 2026-05-05 Abschlussstand FinanceProbe / Spanien / Deutschland
|
||||
|
||||
Aktueller lokaler Testpunkt:
|
||||
|
||||
@@ -341,36 +341,51 @@ public class DatabaseSeedService : IDatabaseSeedService
|
||||
|
||||
private static void EnsureSapODataDachMapping(AppDbContext db, int siteId)
|
||||
{
|
||||
var existingSources = db.SapSourceDefinitions.Where(x => x.SiteId == siteId).ToList();
|
||||
var existingMappings = db.SapFieldMappings.Where(x => x.SiteId == siteId).ToList();
|
||||
var changed = false;
|
||||
var source = db.SapSourceDefinitions
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefault(x => x.SiteId == siteId && x.Alias == "Z");
|
||||
|
||||
if (existingSources.Count > 0 || existingMappings.Count > 0)
|
||||
if (source is null)
|
||||
{
|
||||
var changed = false;
|
||||
foreach (var source in existingSources.Where(x =>
|
||||
string.Equals(x.Alias, "Z", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(x.EntitySet, "ZSCHWEIZ", StringComparison.OrdinalIgnoreCase)))
|
||||
db.SapSourceDefinitions.Add(new SapSourceDefinition
|
||||
{
|
||||
SiteId = siteId,
|
||||
Alias = "Z",
|
||||
EntitySet = "ZSCHWEIZSet",
|
||||
IsPrimary = true,
|
||||
IsActive = true,
|
||||
SortOrder = 0
|
||||
});
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (source.EntitySet != "ZSCHWEIZSet")
|
||||
{
|
||||
source.EntitySet = "ZSCHWEIZSet";
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
db.SaveChanges();
|
||||
if (!source.IsPrimary)
|
||||
{
|
||||
source.IsPrimary = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return;
|
||||
if (!source.IsActive)
|
||||
{
|
||||
source.IsActive = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (source.SortOrder != 0)
|
||||
{
|
||||
source.SortOrder = 0;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
db.SapSourceDefinitions.Add(new SapSourceDefinition
|
||||
{
|
||||
SiteId = siteId,
|
||||
Alias = "Z",
|
||||
EntitySet = "ZSCHWEIZSet",
|
||||
IsPrimary = true,
|
||||
IsActive = true,
|
||||
SortOrder = 0
|
||||
});
|
||||
|
||||
var mappings = new (string Target, string Source, bool Required)[]
|
||||
{
|
||||
(nameof(SalesRecord.Tsc), "Z.TSC", true),
|
||||
@@ -402,17 +417,51 @@ public class DatabaseSeedService : IDatabaseSeedService
|
||||
|
||||
for (var i = 0; i < mappings.Length; i++)
|
||||
{
|
||||
db.SapFieldMappings.Add(new SapFieldMapping
|
||||
var mapping = db.SapFieldMappings
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefault(x => x.SiteId == siteId && x.TargetField == mappings[i].Target);
|
||||
|
||||
if (mapping is null)
|
||||
{
|
||||
SiteId = siteId,
|
||||
TargetField = mappings[i].Target,
|
||||
SourceExpression = mappings[i].Source,
|
||||
IsRequired = mappings[i].Required,
|
||||
IsActive = true,
|
||||
SortOrder = i
|
||||
});
|
||||
db.SapFieldMappings.Add(new SapFieldMapping
|
||||
{
|
||||
SiteId = siteId,
|
||||
TargetField = mappings[i].Target,
|
||||
SourceExpression = mappings[i].Source,
|
||||
IsRequired = mappings[i].Required,
|
||||
IsActive = true,
|
||||
SortOrder = i
|
||||
});
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mapping.SourceExpression != mappings[i].Source)
|
||||
{
|
||||
mapping.SourceExpression = mappings[i].Source;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mapping.IsRequired != mappings[i].Required)
|
||||
{
|
||||
mapping.IsRequired = mappings[i].Required;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!mapping.IsActive)
|
||||
{
|
||||
mapping.IsActive = true;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mapping.SortOrder != i)
|
||||
{
|
||||
mapping.SortOrder = i;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
db.SaveChanges();
|
||||
if (changed)
|
||||
db.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,60 @@
|
||||
# Last Change 2026-05-04
|
||||
|
||||
## SAP OData / ZSCHWEIZ / HANA Mapping 2026-05-07
|
||||
|
||||
Aktueller Entscheid:
|
||||
|
||||
- `ZSCHWEIZ` wird nicht direkt als SAP-HANA-Spezialfall gelesen.
|
||||
- `ZSCHWEIZ` wird ueber den bestehenden SAP-OData/Gateway-Pfad gelesen.
|
||||
- Der grafische Quellen- und Feldmapper bleibt dafuer aktiv.
|
||||
- Feldinfos muessen nicht hart codiert werden, solange der Gateway-Service `$metadata` fuer das EntitySet liefert.
|
||||
|
||||
Quellsystem-Namen wurden zur Entwirrung geschaerft:
|
||||
|
||||
- Code `SAP` bleibt technisch bestehen, DisplayName ist jetzt `SAP OData`.
|
||||
- Code `SAP_HANA` bleibt fuer direkte HANA-Tabellen/Views bestehen, DisplayName ist jetzt `SAP HANA Tables/Views`.
|
||||
- Bestehende Konfigurationen bleiben dadurch kompatibel.
|
||||
|
||||
Seed / Vorkonfiguration:
|
||||
|
||||
- Standort `ZSCHWEIZ` / Land `Schweiz/Oesterreich` wird als inaktiver Standort angelegt bzw. repariert.
|
||||
- `SourceSystem = SAP`.
|
||||
- Quelle: Alias `Z`, EntitySet `ZSCHWEIZSet`.
|
||||
- Mapping ist grafisch editierbar und wird auf die Felder der Tabelle `ZSCHWEIZ` gesetzt.
|
||||
- Die Seed-/Repair-Logik zieht Quelle und Mapping auch bei bereits vorhandener ZSCHWEIZ-Konfiguration nach; manuelles Mapping ist nur noetig, wenn die Gateway-Feldnamen vom erwarteten `ZSCHWEIZ`-Layout abweichen.
|
||||
|
||||
Wichtig fuer die UI:
|
||||
|
||||
1. App neu starten, damit Seed/Repair laeuft.
|
||||
2. `Settings -> Quellsysteme`: `SAP` sollte als `SAP OData` erscheinen.
|
||||
3. `Standorte -> ZSCHWEIZ`:
|
||||
- Quellsystem `SAP OData (SAP)`
|
||||
- SAP Service URL Override auf den finalen OData-Service fuer `ZSCHWEIZ` setzen, falls die zentrale SAP-URL noch auf `ZPOWERBI_EINKAUF_SRV` zeigt.
|
||||
- `Entity Sets refreshen`.
|
||||
- Quelle `Z` soll auf `ZSCHWEIZSet` zeigen.
|
||||
- `Felder aus Quellen laden`.
|
||||
- Mapping kontrollieren.
|
||||
|
||||
ABAP / SAP:
|
||||
|
||||
- ABAP-Report liegt in `report.abap`.
|
||||
- Report fuellt Tabelle `ZSCHWEIZ` aus Buchungskreis `1100` = Schweiz und `1200` = Oesterreich.
|
||||
- `LAND1` ist Reporting-Land aus Buchungskreis.
|
||||
- `CUSTOMER_LAND` ist Kundenland aus `KNA1-LAND1`.
|
||||
- Upsert erfolgt per `MODIFY zschweiz FROM TABLE`.
|
||||
|
||||
Letzte technische Verifikation:
|
||||
|
||||
```text
|
||||
dotnet build .\TrafagSalesExporter.csproj --no-restore -p:UseAppHost=false --verbosity minimal
|
||||
dotnet test .\TrafagSalesExporter.Tests\TrafagSalesExporter.Tests.csproj --no-restore --verbosity minimal
|
||||
```
|
||||
|
||||
Ergebnis:
|
||||
|
||||
- Build erfolgreich
|
||||
- Tests erfolgreich, `50/50`
|
||||
|
||||
## Finance-Abgrenzung: Antworten Andreas 2026-05-07
|
||||
|
||||
Fachliche Vorgabe nach Rueckmeldung:
|
||||
|
||||
Reference in New Issue
Block a user