Ensure ZSCHWEIZ OData mapping seed
This commit is contained in:
@@ -2,6 +2,57 @@
|
|||||||
|
|
||||||
Stand: 2026-05-05
|
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
|
## Nachtrag 2026-05-05 Aktueller Handoff FinanceProbe / Laenderabgleich
|
||||||
|
|
||||||
Der aktuelle Arbeitsstand fuer den naechsten Einstieg ist der lokale FinanceProbe:
|
Der aktuelle Arbeitsstand fuer den naechsten Einstieg ist der lokale FinanceProbe:
|
||||||
|
|||||||
@@ -17,6 +17,48 @@ Lokaler FinanceProbe:
|
|||||||
http://localhost:55417/finance
|
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:
|
Aktuelle FinanceProbe-Funktionen:
|
||||||
|
|
||||||
- `Meeting Ampel 2025` fuer alle Laender aus `check.xlsx`
|
- `Meeting Ampel 2025` fuer alle Laender aus `check.xlsx`
|
||||||
|
|||||||
@@ -2,6 +2,43 @@
|
|||||||
|
|
||||||
Stand: 2026-05-05
|
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
|
## Nachtrag 2026-05-05 Abschlussstand FinanceProbe / Spanien / Deutschland
|
||||||
|
|
||||||
Aktueller lokaler Testpunkt:
|
Aktueller lokaler Testpunkt:
|
||||||
|
|||||||
@@ -341,36 +341,51 @@ public class DatabaseSeedService : IDatabaseSeedService
|
|||||||
|
|
||||||
private static void EnsureSapODataDachMapping(AppDbContext db, int siteId)
|
private static void EnsureSapODataDachMapping(AppDbContext db, int siteId)
|
||||||
{
|
{
|
||||||
var existingSources = db.SapSourceDefinitions.Where(x => x.SiteId == siteId).ToList();
|
var changed = false;
|
||||||
var existingMappings = db.SapFieldMappings.Where(x => x.SiteId == siteId).ToList();
|
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;
|
db.SapSourceDefinitions.Add(new SapSourceDefinition
|
||||||
foreach (var source in existingSources.Where(x =>
|
{
|
||||||
string.Equals(x.Alias, "Z", StringComparison.OrdinalIgnoreCase) &&
|
SiteId = siteId,
|
||||||
string.Equals(x.EntitySet, "ZSCHWEIZ", StringComparison.OrdinalIgnoreCase)))
|
Alias = "Z",
|
||||||
|
EntitySet = "ZSCHWEIZSet",
|
||||||
|
IsPrimary = true,
|
||||||
|
IsActive = true,
|
||||||
|
SortOrder = 0
|
||||||
|
});
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (source.EntitySet != "ZSCHWEIZSet")
|
||||||
{
|
{
|
||||||
source.EntitySet = "ZSCHWEIZSet";
|
source.EntitySet = "ZSCHWEIZSet";
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (!source.IsPrimary)
|
||||||
db.SaveChanges();
|
{
|
||||||
|
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)[]
|
var mappings = new (string Target, string Source, bool Required)[]
|
||||||
{
|
{
|
||||||
(nameof(SalesRecord.Tsc), "Z.TSC", true),
|
(nameof(SalesRecord.Tsc), "Z.TSC", true),
|
||||||
@@ -402,17 +417,51 @@ public class DatabaseSeedService : IDatabaseSeedService
|
|||||||
|
|
||||||
for (var i = 0; i < mappings.Length; i++)
|
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,
|
db.SapFieldMappings.Add(new SapFieldMapping
|
||||||
TargetField = mappings[i].Target,
|
{
|
||||||
SourceExpression = mappings[i].Source,
|
SiteId = siteId,
|
||||||
IsRequired = mappings[i].Required,
|
TargetField = mappings[i].Target,
|
||||||
IsActive = true,
|
SourceExpression = mappings[i].Source,
|
||||||
SortOrder = i
|
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
|
# 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
|
## Finance-Abgrenzung: Antworten Andreas 2026-05-07
|
||||||
|
|
||||||
Fachliche Vorgabe nach Rueckmeldung:
|
Fachliche Vorgabe nach Rueckmeldung:
|
||||||
|
|||||||
Reference in New Issue
Block a user