refactoring
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@page "/standorte"
|
||||
@page "/standorte"
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using System.Text.Json
|
||||
@@ -17,27 +17,30 @@
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Standorte</MudText>
|
||||
|
||||
<MudText Typo="Typo.h5" Class="mb-2">HANA Server</MudText>
|
||||
<MudText Typo="Typo.h5" Class="mb-2">Zentrale HANA-Technik</MudText>
|
||||
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add"
|
||||
OnClick="AddServer" Class="mb-3">
|
||||
Server hinzufügen
|
||||
</MudButton>
|
||||
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Class="mb-3">
|
||||
Hier erscheinen nur Quellsysteme mit Anschlussart HANA. SAP wird zentral unter Settings -> Quellsysteme gepflegt.
|
||||
Standorte mit `BI1` oder `SAGE` verwenden diese technischen HANA-Werte automatisch. Im Standort selbst bleiben nur Schema, TSC, Land und optionale Username-/Password-Overrides.
|
||||
</MudAlert>
|
||||
<MudText Typo="Typo.body2" Class="mb-3">
|
||||
Neue HANA-Zeilen entstehen aus den zentral gepflegten Quellsystemen. Falls hier etwas fehlt, lege das Quellsystem in Settings -> Quellsysteme mit Anschlussart `HANA` an.
|
||||
</MudText>
|
||||
|
||||
<MudTable Items="_servers" Dense Hover Striped>
|
||||
<HeaderContent>
|
||||
<MudTh>Quellsystem</MudTh>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Host</MudTh>
|
||||
<MudTh>Port</MudTh>
|
||||
<MudTh>Username</MudTh>
|
||||
<MudTh>Verbindungsstatus</MudTh>
|
||||
<MudTh>Aktionen</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.SourceSystem</MudTd>
|
||||
<MudTd>@context.Name</MudTd>
|
||||
<MudTd>@context.Host</MudTd>
|
||||
<MudTd>@context.Port</MudTd>
|
||||
<MudTd>@context.Username</MudTd>
|
||||
<MudTd>
|
||||
@if (_connectionStatus.TryGetValue(context.Id, out var status))
|
||||
{
|
||||
@@ -68,7 +71,7 @@
|
||||
<MudPaper Class="pa-4" Elevation="1">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add"
|
||||
OnClick="AddSite" Class="mb-3">
|
||||
Neuen Standort hinzufügen
|
||||
Neuen Standort hinzufügen
|
||||
</MudButton>
|
||||
|
||||
<MudTable Items="_sites" Dense Hover Striped>
|
||||
@@ -109,22 +112,21 @@
|
||||
|
||||
<MudDialog @bind-Visible="_serverDialogVisible" Options="_dialogOptions">
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">@(_editingServer.Id == 0 ? "Server hinzufügen" : "Server bearbeiten")</MudText>
|
||||
<MudText Typo="Typo.h6">Zentrale HANA-Technik bearbeiten</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudTextField Value="_editingServer.SourceSystem" Label="Quellsystem" ReadOnly />
|
||||
<MudTextField @bind-Value="_editingServer.Name" Label="Name" Required />
|
||||
<MudTextField @bind-Value="_editingServer.Host" Label="Host" Required
|
||||
HelperText="IP oder Hostname (ohne Protokoll)" />
|
||||
<MudNumericField @bind-Value="_editingServer.Port" Label="Port"
|
||||
HelperText="Typisch 30015 (Tenant), 30013 (SystemDB), 3xx15 für Instanz xx" />
|
||||
<MudTextField @bind-Value="_editingServer.Username" Label="Username" />
|
||||
<MudTextField @bind-Value="_editingServer.Password" Label="Password" InputType="InputType.Password" />
|
||||
HelperText="Typisch 30015 (Tenant), 30013 (SystemDB), 3xx15 für Instanz xx" />
|
||||
<MudTextField @bind-Value="_editingServer.DatabaseName" Label="Database Name (MDC)"
|
||||
HelperText="Nur bei Multi-Tenant Setup angeben, sonst leer lassen" />
|
||||
<MudSwitch @bind-Value="_editingServer.UseSsl" Label="SSL/TLS verwenden (encrypt=true)" Color="Color.Primary" />
|
||||
<MudSwitch @bind-Value="_editingServer.ValidateCertificate" Label="SSL-Zertifikat validieren" Color="Color.Primary"
|
||||
Disabled="!_editingServer.UseSsl" />
|
||||
<MudTextField @bind-Value="_editingServer.AdditionalParams" Label="Zusätzliche Parameter"
|
||||
<MudTextField @bind-Value="_editingServer.AdditionalParams" Label="Zusätzliche Parameter"
|
||||
HelperText="Optional, z.B. sslCryptoProvider=openssl;communicationTimeout=0" />
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@@ -135,16 +137,16 @@
|
||||
|
||||
<MudDialog @bind-Visible="_siteDialogVisible" Options="_dialogOptions">
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">@(_editingSite.Id == 0 ? "Standort hinzufügen" : "Standort bearbeiten")</MudText>
|
||||
<MudText Typo="Typo.h6">@(_editingSite.Id == 0 ? "Standort hinzufügen" : "Standort bearbeiten")</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudTextField @bind-Value="_editingSite.Schema" Label="Schema" Required />
|
||||
<MudTextField @bind-Value="_editingSite.TSC" Label="TSC" Required />
|
||||
<MudTextField @bind-Value="_editingSite.Land" Label="Land" Required />
|
||||
<MudSelect @bind-Value="_editingSite.SourceSystem" Label="Quellsystem" Required>
|
||||
@foreach (var system in _sourceSystems)
|
||||
@foreach (var system in GetAvailableSourceSystems())
|
||||
{
|
||||
<MudSelectItem Value="@system">@system</MudSelectItem>
|
||||
<MudSelectItem Value="@system.Code">@GetSourceSystemLabel(system)</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudTextField @bind-Value="_editingSite.UsernameOverride" Label="Username Override"
|
||||
@@ -152,7 +154,7 @@
|
||||
<MudTextField @bind-Value="_editingSite.PasswordOverride" Label="Password Override" InputType="InputType.Password"
|
||||
HelperText="Optional. Wenn leer, wird das zentrale Passwort des Quellsystems verwendet." />
|
||||
<MudTextField @bind-Value="_editingSite.LocalExportFolderOverride" Label="Lokaler Exportpfad Override"
|
||||
HelperText="Optional. Wenn leer, wird der zentrale Standardpfad für Standort-Dateien verwendet." />
|
||||
HelperText="Optional. Wenn leer, wird der zentrale Standardpfad für Standort-Dateien verwendet." />
|
||||
<MudCheckBox @bind-Value="_editingSite.IsActive" Label="Aktiv" />
|
||||
|
||||
<MudDivider Class="my-4" />
|
||||
@@ -161,10 +163,11 @@
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mb-2">SAP Gateway</MudText>
|
||||
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Class="mb-3">
|
||||
Die Service-URL zeigt auf den OData-Service. Die verfügbaren Entity Sets werden nur per Knopfdruck aktualisiert und lokal zwischengespeichert.
|
||||
Die Service-URL zeigt auf den OData-Service. Die verfügbaren Entity Sets werden nur per Knopfdruck aktualisiert und lokal zwischengespeichert.
|
||||
</MudAlert>
|
||||
<MudTextField @bind-Value="_editingSite.SapServiceUrl" Label="SAP Service URL" Required
|
||||
HelperText="z.B. http://server:8000/sap/opu/odata/sap/ZPOWERBI_EINKAUF_SRV/" />
|
||||
<MudText Typo="Typo.body2">Zentrale SAP Service URL: @GetCentralSapServiceUrlSummary(_editingSite.SourceSystem)</MudText>
|
||||
<MudTextField @bind-Value="_editingSite.SapServiceUrl" Label="SAP Service URL Override"
|
||||
HelperText="Optional. Wenn leer, wird die zentrale SAP Service URL des Quellsystems verwendet." />
|
||||
<MudStack Row Spacing="2" Class="mb-3">
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick="RefreshSapEntitySets"
|
||||
StartIcon="@Icons.Material.Filled.Refresh" Disabled="_refreshingSapEntitySets">
|
||||
@@ -188,16 +191,16 @@
|
||||
<MudDivider Class="my-4" />
|
||||
<MudStack Row Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center" Class="mb-2">
|
||||
<MudText Typo="Typo.h6">SAP Quellen</MudText>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapSource">Quelle hinzufügen</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapSource">Quelle hinzufügen</MudButton>
|
||||
</MudStack>
|
||||
<MudText Typo="Typo.caption" Class="mb-2">
|
||||
Pro Quelle Alias und Entity Set definieren. Joins verwenden links/rechts kommagetrennte Schlüsselfelder wie `VBELN,POSNR`. Feldmappings erwarten `Alias.Feldname` oder Konstanten wie `=SAP`.
|
||||
Pro Quelle Alias und Entity Set definieren. Joins verwenden links/rechts kommagetrennte Schlüsselfelder wie `VBELN,POSNR`. Feldmappings erwarten `Alias.Feldname` oder Konstanten wie `=SAP`.
|
||||
</MudText>
|
||||
<MudTable Items="_sapSources" Dense Hover Striped>
|
||||
<HeaderContent>
|
||||
<MudTh>Alias</MudTh>
|
||||
<MudTh>Entity Set</MudTh>
|
||||
<MudTh>Primär</MudTh>
|
||||
<MudTh>Primär</MudTh>
|
||||
<MudTh>Aktiv</MudTh>
|
||||
<MudTh>Aktionen</MudTh>
|
||||
</HeaderContent>
|
||||
@@ -225,7 +228,7 @@
|
||||
OnClick="AutoMatchSapJoins">
|
||||
Auto-Match
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapJoin">Join hinzufügen</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapJoin">Join hinzufügen</MudButton>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
<MudTable Items="_sapJoins" Dense Hover Striped>
|
||||
@@ -305,11 +308,11 @@
|
||||
@("Felder aus Quellen laden")
|
||||
}
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapMapping">Mapping hinzufügen</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Add" OnClick="AddSapMapping">Mapping hinzufügen</MudButton>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
<MudText Typo="Typo.caption" Class="mb-2">
|
||||
Source Expressions werden aus den hinzugefügten SAP-Quellen als `Alias.Feldname` gelesen. Vorhandene manuelle Werte bleiben auswählbar.
|
||||
Source Expressions werden aus den hinzugefügten SAP-Quellen als `Alias.Feldname` gelesen. Vorhandene manuelle Werte bleiben auswählbar.
|
||||
</MudText>
|
||||
<MudTable Items="_sapMappings" Dense Hover Striped>
|
||||
<HeaderContent>
|
||||
@@ -346,7 +349,7 @@
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mb-2">Manueller Excel-Import</MudText>
|
||||
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Class="mb-3">
|
||||
Für diesen Standort wird keine SAP- oder HANA-Verbindung verwendet. Es wird die hier hinterlegte Excel-Datei gelesen und in `CentralSalesRecords` übernommen.
|
||||
Für diesen Standort wird keine SAP- oder HANA-Verbindung verwendet. Es wird die hier hinterlegte Excel-Datei gelesen und in `CentralSalesRecords` übernommen.
|
||||
</MudAlert>
|
||||
<InputFile OnChange="UploadManualImportFileAsync" accept=".xlsx" />
|
||||
@if (_uploadingManualImport)
|
||||
@@ -371,23 +374,12 @@
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mb-2">HANA-Verbindung</MudText>
|
||||
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Class="mb-3">
|
||||
Host, Port und technische HANA-Parameter kommen von dieser Verbindung. Username und Password hier dienen nur noch als Fallback für bestehende Einträge.
|
||||
Die technische HANA-Verbindung kommt aus der zentralen HANA-Konfiguration des Quellsystems. Im Standort selbst pflegst du nur fachliche Standortdaten und optionale Username-/Password-Overrides.
|
||||
</MudAlert>
|
||||
<MudTextField @bind-Value="_editingSiteServer.Name" Label="Verbindungsname" Required
|
||||
HelperText="Interner Anzeigename für diesen Standort" />
|
||||
<MudTextField @bind-Value="_editingSiteServer.Host" Label="Host oder ServerNode" Required
|
||||
HelperText="z.B. hana01 oder hana01:30015 oder derselbe HanaServer-Wert wie in Power BI" />
|
||||
<MudNumericField @bind-Value="_editingSiteServer.Port" Label="Port"
|
||||
HelperText="Wird ignoriert, wenn im Host bereits ein Port enthalten ist" />
|
||||
<MudTextField @bind-Value="_editingSiteServer.Username" Label="Username" />
|
||||
<MudTextField @bind-Value="_editingSiteServer.Password" Label="Password" InputType="InputType.Password" />
|
||||
<MudTextField @bind-Value="_editingSiteServer.DatabaseName" Label="Database Name (MDC)"
|
||||
HelperText="Nur bei Multi-Tenant Setup angeben, sonst leer lassen" />
|
||||
<MudSwitch @bind-Value="_editingSiteServer.UseSsl" Label="SSL/TLS verwenden (encrypt=true)" Color="Color.Primary" />
|
||||
<MudSwitch @bind-Value="_editingSiteServer.ValidateCertificate" Label="SSL-Zertifikat validieren" Color="Color.Primary"
|
||||
Disabled="!_editingSiteServer.UseSsl" />
|
||||
<MudTextField @bind-Value="_editingSiteServer.AdditionalParams" Label="Zusätzliche Parameter"
|
||||
HelperText="Optional, z.B. sslCryptoProvider=openssl;communicationTimeout=0" />
|
||||
<MudText Typo="Typo.body2">Aktive Zentralverbindung: @GetCentralHanaSummary(_editingSite.SourceSystem)</MudText>
|
||||
<MudText Typo="Typo.caption" Class="mt-2">
|
||||
Host, Port, SSL und technische Parameter bearbeitest du oben in der zentralen HANA-Konfiguration.
|
||||
</MudText>
|
||||
}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
@@ -397,10 +389,10 @@
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
private readonly string[] _sourceSystems = ["SAP", "BI1", "SAGE", "MANUAL_EXCEL"];
|
||||
private readonly Dictionary<int, ConnectionTestResult> _connectionStatus = new();
|
||||
private List<HanaServer> _servers = new();
|
||||
private List<Site> _sites = new();
|
||||
private List<SourceSystemDefinition> _sourceSystemDefinitions = new();
|
||||
private List<string> _sapEntitySetsCache = [];
|
||||
private List<string> _sapAvailableSourceExpressions = [];
|
||||
private Dictionary<string, List<string>> _sapSourceFieldMap = new(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -413,7 +405,6 @@
|
||||
.ToArray();
|
||||
private HanaServer _editingServer = new();
|
||||
private Site _editingSite = new();
|
||||
private HanaServer _editingSiteServer = new();
|
||||
private bool _serverDialogVisible;
|
||||
private bool _siteDialogVisible;
|
||||
private bool _refreshingSapEntitySets;
|
||||
@@ -431,16 +422,17 @@
|
||||
private async Task LoadDataAsync()
|
||||
{
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
_servers = await db.HanaServers.OrderBy(s => s.Name).ToListAsync();
|
||||
_sourceSystemDefinitions = await db.SourceSystemDefinitions
|
||||
.OrderBy(x => x.Code)
|
||||
.ToListAsync();
|
||||
_servers = await db.HanaServers
|
||||
.Where(s => GetHanaSourceSystemCodes().Contains(s.SourceSystem))
|
||||
.OrderBy(s => s.SourceSystem)
|
||||
.ThenBy(s => s.Name)
|
||||
.ToListAsync();
|
||||
_sites = await db.Sites.Include(s => s.HanaServer).OrderBy(s => s.Land).ToListAsync();
|
||||
}
|
||||
|
||||
private void AddServer()
|
||||
{
|
||||
_editingServer = new HanaServer { Port = 30015 };
|
||||
_serverDialogVisible = true;
|
||||
}
|
||||
|
||||
private void EditServer(HanaServer server)
|
||||
{
|
||||
_editingServer = CloneServer(server);
|
||||
@@ -455,21 +447,50 @@
|
||||
_savingServer = true;
|
||||
try
|
||||
{
|
||||
_editingServer.SourceSystem = string.IsNullOrWhiteSpace(_editingServer.SourceSystem)
|
||||
? GetHanaSourceSystemCodes().FirstOrDefault() ?? string.Empty
|
||||
: _editingServer.SourceSystem.Trim().ToUpperInvariant();
|
||||
_editingServer.Name = string.IsNullOrWhiteSpace(_editingServer.Name) ? _editingServer.SourceSystem : _editingServer.Name.Trim();
|
||||
_editingServer.Host = _editingServer.Host.Trim();
|
||||
_editingServer.DatabaseName = _editingServer.DatabaseName.Trim();
|
||||
_editingServer.AdditionalParams = _editingServer.AdditionalParams.Trim();
|
||||
_editingServer.Username = string.Empty;
|
||||
_editingServer.Password = string.Empty;
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
if (_editingServer.Id == 0)
|
||||
{
|
||||
db.HanaServers.Add(_editingServer);
|
||||
var existingForSourceSystem = await db.HanaServers
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefaultAsync(x => x.SourceSystem == _editingServer.SourceSystem);
|
||||
|
||||
if (existingForSourceSystem is null)
|
||||
{
|
||||
db.HanaServers.Add(_editingServer);
|
||||
}
|
||||
else
|
||||
{
|
||||
existingForSourceSystem.Name = _editingServer.Name;
|
||||
existingForSourceSystem.Host = _editingServer.Host;
|
||||
existingForSourceSystem.Port = _editingServer.Port;
|
||||
existingForSourceSystem.Username = string.Empty;
|
||||
existingForSourceSystem.Password = string.Empty;
|
||||
existingForSourceSystem.DatabaseName = _editingServer.DatabaseName;
|
||||
existingForSourceSystem.UseSsl = _editingServer.UseSsl;
|
||||
existingForSourceSystem.ValidateCertificate = _editingServer.ValidateCertificate;
|
||||
existingForSourceSystem.AdditionalParams = _editingServer.AdditionalParams;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var existing = await db.HanaServers.FindAsync(_editingServer.Id);
|
||||
if (existing is not null)
|
||||
{
|
||||
existing.SourceSystem = _editingServer.SourceSystem;
|
||||
existing.Name = _editingServer.Name;
|
||||
existing.Host = _editingServer.Host;
|
||||
existing.Port = _editingServer.Port;
|
||||
existing.Username = _editingServer.Username;
|
||||
existing.Password = _editingServer.Password;
|
||||
existing.Username = string.Empty;
|
||||
existing.Password = string.Empty;
|
||||
existing.DatabaseName = _editingServer.DatabaseName;
|
||||
existing.UseSsl = _editingServer.UseSsl;
|
||||
existing.ValidateCertificate = _editingServer.ValidateCertificate;
|
||||
@@ -490,10 +511,16 @@
|
||||
|
||||
private async Task DeleteServer(HanaServer server)
|
||||
{
|
||||
if (IsHanaSourceSystem(server.SourceSystem))
|
||||
{
|
||||
Snackbar.Add($"Die zentrale HANA-Konfiguration fuer {server.SourceSystem} kann nicht geloescht werden.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var result = await DialogService.ShowMessageBox(
|
||||
"Server löschen",
|
||||
$"Server '{server.Name}' wirklich löschen?",
|
||||
yesText: "Löschen", cancelText: "Abbrechen");
|
||||
"Server löschen",
|
||||
$"Server '{server.Name}' wirklich löschen?",
|
||||
yesText: "Löschen", cancelText: "Abbrechen");
|
||||
|
||||
if (result != true) return;
|
||||
|
||||
@@ -509,7 +536,7 @@
|
||||
if (linkedSites.Count > 0)
|
||||
{
|
||||
Snackbar.Add(
|
||||
$"Server kann nicht gelöscht werden. Noch verknüpfte Standorte: {string.Join(", ", linkedSites)}",
|
||||
$"Server kann nicht gelöscht werden. Noch verknüpfte Standorte: {string.Join(", ", linkedSites)}",
|
||||
Severity.Warning);
|
||||
return;
|
||||
}
|
||||
@@ -523,19 +550,51 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Server konnte nicht gelöscht werden: {ex.Message}", Severity.Error);
|
||||
Snackbar.Add($"Server konnte nicht gelöscht werden: {ex.Message}", Severity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
await LoadDataAsync();
|
||||
Snackbar.Add("Server gelöscht", Severity.Info);
|
||||
Snackbar.Add("Server gelöscht", Severity.Info);
|
||||
}
|
||||
|
||||
private async Task TestServerConnection(HanaServer server)
|
||||
{
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
var sourceDefinition = await db.SourceSystemDefinitions
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefaultAsync(x => x.Code == server.SourceSystem);
|
||||
|
||||
if (sourceDefinition is null)
|
||||
{
|
||||
Snackbar.Add($"Quellsystem '{server.SourceSystem}' nicht gefunden.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(sourceDefinition.CentralUsername) || string.IsNullOrWhiteSpace(sourceDefinition.CentralPassword))
|
||||
{
|
||||
Snackbar.Add($"Fuer {server.SourceSystem} sind keine zentralen Zugangsdaten im Quellsystem gepflegt.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var testServer = new HanaServer
|
||||
{
|
||||
Id = server.Id,
|
||||
SourceSystem = server.SourceSystem,
|
||||
Name = server.Name,
|
||||
Host = server.Host,
|
||||
Port = server.Port,
|
||||
Username = sourceDefinition.CentralUsername.Trim(),
|
||||
Password = sourceDefinition.CentralPassword,
|
||||
DatabaseName = server.DatabaseName,
|
||||
UseSsl = server.UseSsl,
|
||||
ValidateCertificate = server.ValidateCertificate,
|
||||
AdditionalParams = server.AdditionalParams
|
||||
};
|
||||
|
||||
await AppEventLogService.WriteAsync("HANA", "Server-Test aus UI gestartet",
|
||||
details: server.GetConnectionStringPreview());
|
||||
var result = await Task.Run(() => HanaService.TestConnectionDetailed(server));
|
||||
details: testServer.GetConnectionStringPreview());
|
||||
var result = await Task.Run(() => HanaService.TestConnectionDetailed(testServer));
|
||||
_connectionStatus[server.Id] = result;
|
||||
|
||||
if (result.Success)
|
||||
@@ -562,7 +621,7 @@
|
||||
_editingSite = new Site
|
||||
{
|
||||
IsActive = true,
|
||||
SourceSystem = "SAP",
|
||||
SourceSystem = GetAvailableSourceSystems().FirstOrDefault()?.Code ?? "SAP",
|
||||
HanaServerId = null,
|
||||
ManualImportFilePath = string.Empty
|
||||
};
|
||||
@@ -572,7 +631,6 @@
|
||||
_sapSources = [];
|
||||
_sapJoins = [];
|
||||
_sapMappings = [];
|
||||
_editingSiteServer = CreateDefaultSiteServer();
|
||||
_siteDialogVisible = true;
|
||||
}
|
||||
|
||||
@@ -585,7 +643,9 @@
|
||||
Schema = site.Schema,
|
||||
TSC = site.TSC,
|
||||
Land = site.Land,
|
||||
SourceSystem = string.IsNullOrWhiteSpace(site.SourceSystem) ? "SAP" : site.SourceSystem,
|
||||
SourceSystem = string.IsNullOrWhiteSpace(site.SourceSystem)
|
||||
? GetAvailableSourceSystems().FirstOrDefault()?.Code ?? "SAP"
|
||||
: site.SourceSystem,
|
||||
UsernameOverride = site.UsernameOverride,
|
||||
PasswordOverride = site.PasswordOverride,
|
||||
LocalExportFolderOverride = site.LocalExportFolderOverride,
|
||||
@@ -604,9 +664,6 @@
|
||||
_sapMappings = db.SapFieldMappings.Where(m => m.SiteId == site.Id).OrderBy(m => m.SortOrder).ThenBy(m => m.Id).ToList();
|
||||
_sapAvailableSourceExpressions = BuildSourceExpressionsFromMappings();
|
||||
_sapSourceFieldMap = BuildSourceFieldMapFromJoins();
|
||||
_editingSiteServer = site.HanaServer is null
|
||||
? CreateDefaultSiteServer(site)
|
||||
: CloneServer(site.HanaServer);
|
||||
_siteDialogVisible = true;
|
||||
}
|
||||
|
||||
@@ -619,7 +676,7 @@
|
||||
try
|
||||
{
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
var serverId = UsesHanaConnection() ? await SaveOrCreateSiteServerAsync(db) : (int?)null;
|
||||
var serverId = UsesHanaConnection() ? await ResolveCentralHanaServerIdAsync(db, _editingSite.SourceSystem) : (int?)null;
|
||||
_editingSite.HanaServerId = serverId;
|
||||
_editingSite.SapEntitySetsCache = SerializeSapEntitySets(_sapEntitySetsCache);
|
||||
|
||||
@@ -669,9 +726,9 @@
|
||||
private async Task DeleteSite(Site site)
|
||||
{
|
||||
var result = await DialogService.ShowMessageBox(
|
||||
"Standort löschen",
|
||||
$"Standort '{site.Land}' wirklich löschen?",
|
||||
yesText: "Löschen", cancelText: "Abbrechen");
|
||||
"Standort löschen",
|
||||
$"Standort '{site.Land}' wirklich löschen?",
|
||||
yesText: "Löschen", cancelText: "Abbrechen");
|
||||
|
||||
if (result != true) return;
|
||||
|
||||
@@ -692,7 +749,7 @@
|
||||
}
|
||||
|
||||
await LoadDataAsync();
|
||||
Snackbar.Add("Standort gelöscht", Severity.Info);
|
||||
Snackbar.Add("Standort gelöscht", Severity.Info);
|
||||
}
|
||||
|
||||
private static string GetServerNode(HanaServer? server)
|
||||
@@ -703,40 +760,17 @@
|
||||
return server.Host.Contains(':', StringComparison.Ordinal) ? server.Host : $"{server.Host}:{server.Port}";
|
||||
}
|
||||
|
||||
private static string GetConnectionTarget(Site site)
|
||||
{
|
||||
var sourceSystem = string.IsNullOrWhiteSpace(site.SourceSystem) ? "SAP" : site.SourceSystem;
|
||||
if (string.Equals(sourceSystem, "SAP", StringComparison.OrdinalIgnoreCase))
|
||||
return string.IsNullOrWhiteSpace(site.SapServiceUrl) ? "-" : site.SapServiceUrl;
|
||||
if (string.Equals(sourceSystem, "MANUAL_EXCEL", StringComparison.OrdinalIgnoreCase))
|
||||
return string.IsNullOrWhiteSpace(site.ManualImportFilePath) ? "-" : Path.GetFileName(site.ManualImportFilePath);
|
||||
|
||||
return GetServerNode(site.HanaServer);
|
||||
}
|
||||
|
||||
private HanaServer CreateDefaultSiteServer(Site? site = null)
|
||||
{
|
||||
var label = !string.IsNullOrWhiteSpace(site?.Land) ? site!.Land : site?.TSC;
|
||||
if (string.IsNullOrWhiteSpace(label))
|
||||
label = "Neuer Standort";
|
||||
|
||||
return new HanaServer
|
||||
{
|
||||
Name = $"{label} HANA",
|
||||
Port = 30015
|
||||
};
|
||||
}
|
||||
|
||||
private static HanaServer CloneServer(HanaServer server)
|
||||
{
|
||||
return new HanaServer
|
||||
{
|
||||
Id = server.Id,
|
||||
SourceSystem = server.SourceSystem,
|
||||
Name = server.Name,
|
||||
Host = server.Host,
|
||||
Port = server.Port,
|
||||
Username = server.Username,
|
||||
Password = server.Password,
|
||||
Username = string.Empty,
|
||||
Password = string.Empty,
|
||||
DatabaseName = server.DatabaseName,
|
||||
UseSsl = server.UseSsl,
|
||||
ValidateCertificate = server.ValidateCertificate,
|
||||
@@ -744,66 +778,98 @@
|
||||
};
|
||||
}
|
||||
|
||||
private async Task<int> SaveOrCreateSiteServerAsync(AppDbContext db)
|
||||
private async Task<int> ResolveCentralHanaServerIdAsync(AppDbContext db, string sourceSystem)
|
||||
{
|
||||
_editingSiteServer.Name = string.IsNullOrWhiteSpace(_editingSiteServer.Name)
|
||||
? $"{_editingSite.Land} HANA".Trim()
|
||||
: _editingSiteServer.Name.Trim();
|
||||
_editingSite.UsernameOverride = _editingSite.UsernameOverride.Trim();
|
||||
_editingSite.PasswordOverride = _editingSite.PasswordOverride.Trim();
|
||||
_editingSite.LocalExportFolderOverride = _editingSite.LocalExportFolderOverride.Trim();
|
||||
_editingSite.ManualImportFilePath = _editingSite.ManualImportFilePath.Trim();
|
||||
_editingSite.SapServiceUrl = _editingSite.SapServiceUrl.Trim();
|
||||
_editingSite.SapEntitySet = _editingSite.SapEntitySet.Trim();
|
||||
_editingSiteServer.Host = _editingSiteServer.Host.Trim();
|
||||
_editingSiteServer.Username = _editingSiteServer.Username.Trim();
|
||||
_editingSiteServer.DatabaseName = _editingSiteServer.DatabaseName.Trim();
|
||||
_editingSiteServer.AdditionalParams = _editingSiteServer.AdditionalParams.Trim();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_editingSiteServer.Host))
|
||||
throw new InvalidOperationException("Host oder ServerNode muss gesetzt sein.");
|
||||
var normalizedSourceSystem = string.IsNullOrWhiteSpace(sourceSystem) ? string.Empty : sourceSystem.Trim().ToUpperInvariant();
|
||||
var centralServer = await db.HanaServers
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefaultAsync(x => x.SourceSystem == normalizedSourceSystem);
|
||||
|
||||
if (_editingSite.HanaServerId == 0)
|
||||
{
|
||||
db.HanaServers.Add(_editingSiteServer);
|
||||
await db.SaveChangesAsync();
|
||||
return _editingSiteServer.Id;
|
||||
}
|
||||
if (centralServer is null || string.IsNullOrWhiteSpace(centralServer.Host))
|
||||
throw new InvalidOperationException($"Fuer Quellsystem '{normalizedSourceSystem}' ist keine gueltige zentrale HANA-Konfiguration vorhanden.");
|
||||
|
||||
var sharedUseCount = await db.Sites.CountAsync(s => s.HanaServerId == _editingSite.HanaServerId && s.Id != _editingSite.Id);
|
||||
if (sharedUseCount > 0)
|
||||
{
|
||||
var dedicatedServer = CloneServer(_editingSiteServer);
|
||||
dedicatedServer.Id = 0;
|
||||
db.HanaServers.Add(dedicatedServer);
|
||||
await db.SaveChangesAsync();
|
||||
return dedicatedServer.Id;
|
||||
}
|
||||
|
||||
var existingServer = await db.HanaServers.FindAsync(_editingSite.HanaServerId);
|
||||
if (existingServer is null)
|
||||
{
|
||||
db.HanaServers.Add(_editingSiteServer);
|
||||
await db.SaveChangesAsync();
|
||||
return _editingSiteServer.Id;
|
||||
}
|
||||
|
||||
existingServer.Name = _editingSiteServer.Name;
|
||||
existingServer.Host = _editingSiteServer.Host;
|
||||
existingServer.Port = _editingSiteServer.Port;
|
||||
existingServer.Username = _editingSiteServer.Username;
|
||||
existingServer.Password = _editingSiteServer.Password;
|
||||
existingServer.DatabaseName = _editingSiteServer.DatabaseName;
|
||||
existingServer.UseSsl = _editingSiteServer.UseSsl;
|
||||
existingServer.ValidateCertificate = _editingSiteServer.ValidateCertificate;
|
||||
existingServer.AdditionalParams = _editingSiteServer.AdditionalParams;
|
||||
await db.SaveChangesAsync();
|
||||
return existingServer.Id;
|
||||
return centralServer.Id;
|
||||
}
|
||||
|
||||
private bool IsSapSite() => string.Equals(_editingSite.SourceSystem, "SAP", StringComparison.OrdinalIgnoreCase);
|
||||
private bool IsManualExcelSite() => string.Equals(_editingSite.SourceSystem, "MANUAL_EXCEL", StringComparison.OrdinalIgnoreCase);
|
||||
private bool UsesHanaConnection() => !IsSapSite() && !IsManualExcelSite();
|
||||
private IEnumerable<SourceSystemDefinition> GetAvailableSourceSystems()
|
||||
=> _sourceSystemDefinitions
|
||||
.Where(x => x.IsActive || string.Equals(x.Code, _editingSite.SourceSystem, StringComparison.OrdinalIgnoreCase))
|
||||
.OrderBy(x => x.DisplayName)
|
||||
.ThenBy(x => x.Code);
|
||||
|
||||
private List<string> GetHanaSourceSystemCodes()
|
||||
=> _sourceSystemDefinitions
|
||||
.Where(x => string.Equals(x.ConnectionKind, SourceSystemConnectionKinds.Hana, StringComparison.OrdinalIgnoreCase))
|
||||
.Select(x => x.Code)
|
||||
.OrderBy(x => x)
|
||||
.ToList();
|
||||
|
||||
private string GetSourceSystemConnectionKind(string? sourceSystem)
|
||||
=> _sourceSystemDefinitions
|
||||
.FirstOrDefault(x => string.Equals(x.Code, sourceSystem, StringComparison.OrdinalIgnoreCase))
|
||||
?.ConnectionKind
|
||||
?? SourceSystemConnectionKinds.SapGateway;
|
||||
|
||||
private bool IsHanaSourceSystem(string? sourceSystem)
|
||||
=> string.Equals(GetSourceSystemConnectionKind(sourceSystem), SourceSystemConnectionKinds.Hana, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private bool IsSapSite()
|
||||
=> string.Equals(GetSourceSystemConnectionKind(_editingSite.SourceSystem), SourceSystemConnectionKinds.SapGateway, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private bool IsManualExcelSite()
|
||||
=> string.Equals(GetSourceSystemConnectionKind(_editingSite.SourceSystem), SourceSystemConnectionKinds.ManualExcel, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private bool UsesHanaConnection() => IsHanaSourceSystem(_editingSite.SourceSystem);
|
||||
|
||||
private string GetSourceSystemLabel(SourceSystemDefinition definition)
|
||||
=> string.IsNullOrWhiteSpace(definition.DisplayName) ? definition.Code : $"{definition.DisplayName} ({definition.Code})";
|
||||
|
||||
private string GetConnectionTarget(Site site)
|
||||
{
|
||||
var connectionKind = GetSourceSystemConnectionKind(site.SourceSystem);
|
||||
if (string.Equals(connectionKind, SourceSystemConnectionKinds.SapGateway, StringComparison.OrdinalIgnoreCase))
|
||||
return GetEffectiveSapServiceUrl(site);
|
||||
if (string.Equals(connectionKind, SourceSystemConnectionKinds.ManualExcel, StringComparison.OrdinalIgnoreCase))
|
||||
return string.IsNullOrWhiteSpace(site.ManualImportFilePath) ? "-" : Path.GetFileName(site.ManualImportFilePath);
|
||||
|
||||
return GetServerNode(site.HanaServer);
|
||||
}
|
||||
|
||||
private string GetEffectiveSapServiceUrl(Site site)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(site.SapServiceUrl))
|
||||
return site.SapServiceUrl;
|
||||
|
||||
var sourceDefinition = _sourceSystemDefinitions
|
||||
.FirstOrDefault(x => string.Equals(x.Code, site.SourceSystem, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return string.IsNullOrWhiteSpace(sourceDefinition?.CentralServiceUrl) ? "-" : sourceDefinition.CentralServiceUrl;
|
||||
}
|
||||
|
||||
private string GetCentralSapServiceUrlSummary(string sourceSystem)
|
||||
{
|
||||
var sourceDefinition = _sourceSystemDefinitions
|
||||
.FirstOrDefault(x => string.Equals(x.Code, sourceSystem, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return string.IsNullOrWhiteSpace(sourceDefinition?.CentralServiceUrl) ? "-" : sourceDefinition.CentralServiceUrl;
|
||||
}
|
||||
|
||||
private string GetCentralHanaSummary(string sourceSystem)
|
||||
{
|
||||
var normalizedSourceSystem = string.IsNullOrWhiteSpace(sourceSystem) ? string.Empty : sourceSystem.Trim().ToUpperInvariant();
|
||||
var centralServer = _servers.FirstOrDefault(x => x.SourceSystem == normalizedSourceSystem);
|
||||
if (centralServer is null || string.IsNullOrWhiteSpace(centralServer.Host))
|
||||
return $"keine zentrale HANA-Konfiguration fuer {normalizedSourceSystem}";
|
||||
|
||||
return $"{centralServer.Name} | {GetServerNode(centralServer)}";
|
||||
}
|
||||
|
||||
private async Task RefreshSapEntitySets()
|
||||
{
|
||||
@@ -813,20 +879,28 @@
|
||||
_refreshingSapEntitySets = true;
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_editingSite.SapServiceUrl))
|
||||
throw new InvalidOperationException("SAP Service URL muss gesetzt sein.");
|
||||
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
var settings = await db.ExportSettings.FirstOrDefaultAsync() ?? new();
|
||||
var username = string.IsNullOrWhiteSpace(_editingSite.UsernameOverride) ? settings.SapUsername : _editingSite.UsernameOverride;
|
||||
var password = string.IsNullOrWhiteSpace(_editingSite.PasswordOverride) ? settings.SapPassword : _editingSite.PasswordOverride;
|
||||
var sourceDefinition = await db.SourceSystemDefinitions
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefaultAsync(x => x.Code == _editingSite.SourceSystem);
|
||||
var serviceUrl = string.IsNullOrWhiteSpace(_editingSite.SapServiceUrl)
|
||||
? sourceDefinition?.CentralServiceUrl ?? string.Empty
|
||||
: _editingSite.SapServiceUrl;
|
||||
if (string.IsNullOrWhiteSpace(serviceUrl))
|
||||
throw new InvalidOperationException("Es ist weder eine zentrale SAP Service URL noch ein Standort-Override gesetzt.");
|
||||
var username = string.IsNullOrWhiteSpace(_editingSite.UsernameOverride)
|
||||
? sourceDefinition?.CentralUsername ?? string.Empty
|
||||
: _editingSite.UsernameOverride;
|
||||
var password = string.IsNullOrWhiteSpace(_editingSite.PasswordOverride)
|
||||
? sourceDefinition?.CentralPassword ?? string.Empty
|
||||
: _editingSite.PasswordOverride;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
throw new InvalidOperationException("Für SAP sind weder zentrale Zugangsdaten noch Standort-Overrides gesetzt.");
|
||||
throw new InvalidOperationException("Für SAP sind weder zentrale Zugangsdaten noch Standort-Overrides gesetzt.");
|
||||
|
||||
await AppEventLogService.WriteAsync("SAP", "Refresh aus UI gestartet", siteId: _editingSite.Id, land: _editingSite.Land,
|
||||
details: _editingSite.SapServiceUrl);
|
||||
var entitySets = await SapGatewayService.GetEntitySetsAsync(_editingSite.SapServiceUrl, username.Trim(), password.Trim());
|
||||
details: serviceUrl);
|
||||
var entitySets = await SapGatewayService.GetEntitySetsAsync(serviceUrl, username.Trim(), password.Trim());
|
||||
_sapEntitySetsCache = entitySets;
|
||||
_editingSite.SapEntitySetsCache = SerializeSapEntitySets(entitySets);
|
||||
_editingSite.SapEntitySetsRefreshedAtUtc = DateTime.UtcNow;
|
||||
@@ -884,7 +958,7 @@
|
||||
var extension = Path.GetExtension(file.Name);
|
||||
if (!string.Equals(extension, ".xlsx", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
throw new InvalidOperationException("Bitte eine Excel-Datei mit Endung .xlsx auswählen.");
|
||||
throw new InvalidOperationException("Bitte eine Excel-Datei mit Endung .xlsx auswählen.");
|
||||
}
|
||||
|
||||
var uploadDirectory = Path.Combine(AppContext.BaseDirectory, "manual-imports");
|
||||
@@ -974,13 +1048,13 @@
|
||||
|
||||
if (activeSources.Count < 2)
|
||||
{
|
||||
Snackbar.Add("Für Auto-Match werden mindestens zwei aktive SAP-Quellen benötigt.", Severity.Warning);
|
||||
Snackbar.Add("Für Auto-Match werden mindestens zwei aktive SAP-Quellen benötigt.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sapSourceFieldMap.Count == 0)
|
||||
{
|
||||
Snackbar.Add("Bitte zuerst 'Felder aus Quellen laden' ausführen.", Severity.Warning);
|
||||
Snackbar.Add("Bitte zuerst 'Felder aus Quellen laden' ausführen.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1038,7 +1112,7 @@
|
||||
}
|
||||
|
||||
NormalizeSapConfigCollections();
|
||||
Snackbar.Add($"{createdOrUpdated} Join-Vorschläge gesetzt.", Severity.Success);
|
||||
Snackbar.Add($"{createdOrUpdated} Join-Vorschläge gesetzt.", Severity.Success);
|
||||
}
|
||||
|
||||
private void RemoveSapJoin(SapJoinDefinition join)
|
||||
@@ -1116,9 +1190,6 @@
|
||||
_refreshingSapSourceFields = true;
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_editingSite.SapServiceUrl))
|
||||
throw new InvalidOperationException("SAP Service URL muss gesetzt sein.");
|
||||
|
||||
var activeSources = _sapSources
|
||||
.Where(s => s.IsActive && !string.IsNullOrWhiteSpace(s.Alias) && !string.IsNullOrWhiteSpace(s.EntitySet))
|
||||
.OrderBy(s => s.SortOrder)
|
||||
@@ -1129,18 +1200,29 @@
|
||||
throw new InvalidOperationException("Es gibt keine aktiven SAP-Quellen mit Alias und Entity Set.");
|
||||
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
var settings = await db.ExportSettings.FirstOrDefaultAsync() ?? new();
|
||||
var username = string.IsNullOrWhiteSpace(_editingSite.UsernameOverride) ? settings.SapUsername : _editingSite.UsernameOverride;
|
||||
var password = string.IsNullOrWhiteSpace(_editingSite.PasswordOverride) ? settings.SapPassword : _editingSite.PasswordOverride;
|
||||
var sourceDefinition = await db.SourceSystemDefinitions
|
||||
.OrderBy(x => x.Id)
|
||||
.FirstOrDefaultAsync(x => x.Code == _editingSite.SourceSystem);
|
||||
var serviceUrl = string.IsNullOrWhiteSpace(_editingSite.SapServiceUrl)
|
||||
? sourceDefinition?.CentralServiceUrl ?? string.Empty
|
||||
: _editingSite.SapServiceUrl;
|
||||
if (string.IsNullOrWhiteSpace(serviceUrl))
|
||||
throw new InvalidOperationException("Es ist weder eine zentrale SAP Service URL noch ein Standort-Override gesetzt.");
|
||||
var username = string.IsNullOrWhiteSpace(_editingSite.UsernameOverride)
|
||||
? sourceDefinition?.CentralUsername ?? string.Empty
|
||||
: _editingSite.UsernameOverride;
|
||||
var password = string.IsNullOrWhiteSpace(_editingSite.PasswordOverride)
|
||||
? sourceDefinition?.CentralPassword ?? string.Empty
|
||||
: _editingSite.PasswordOverride;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
throw new InvalidOperationException("Für SAP sind weder zentrale Zugangsdaten noch Standort-Overrides gesetzt.");
|
||||
throw new InvalidOperationException("Für SAP sind weder zentrale Zugangsdaten noch Standort-Overrides gesetzt.");
|
||||
|
||||
var expressions = new List<string> { "=SAP" };
|
||||
var sourceFieldMap = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var source in activeSources)
|
||||
{
|
||||
var fieldNames = await SapGatewayService.GetEntityFieldNamesAsync(_editingSite.SapServiceUrl, source.EntitySet, username.Trim(), password.Trim());
|
||||
var fieldNames = await SapGatewayService.GetEntityFieldNamesAsync(serviceUrl, source.EntitySet, username.Trim(), password.Trim());
|
||||
sourceFieldMap[source.Alias] = fieldNames;
|
||||
expressions.AddRange(fieldNames.Select(field => $"{source.Alias}.{field}"));
|
||||
}
|
||||
@@ -1250,4 +1332,6 @@
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.ToHashSet(StringComparer.OrdinalIgnoreCase)
|
||||
?? [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user