Zentrales PW
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
@page "/settings"
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using TrafagSalesExporter.Data
|
||||
@using TrafagSalesExporter.Models
|
||||
@using TrafagSalesExporter.Services
|
||||
@inject IDbContextFactory<AppDbContext> DbFactory
|
||||
@inject ISharePointUploadService SpService
|
||||
@inject TimerBackgroundService TimerService
|
||||
@inject IHanaQueryService HanaService
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<PageTitle>Settings</PageTitle>
|
||||
@@ -53,6 +55,74 @@
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
<MudText Typo="Typo.h5" Class="mb-2">Zentrale Quellsystem-Zugangsdaten</MudText>
|
||||
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined">
|
||||
Diese Zugangsdaten werden pro Quellsystem als Standard verwendet. Ein Standort kann sie bei Bedarf mit eigenen Overrides überschreiben.
|
||||
</MudAlert>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudText Typo="Typo.h6" Class="mb-2">SAP</MudText>
|
||||
<MudTextField @bind-Value="_exportSettings.SapUsername" Label="SAP Username" />
|
||||
<MudTextField @bind-Value="_exportSettings.SapPassword" Label="SAP Password" InputType="InputType.Password" />
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick='@(() => TestCentralCredentials("SAP"))'
|
||||
StartIcon="@Icons.Material.Filled.NetworkCheck" Disabled='@_testingSystems.Contains("SAP")' Class="mt-2">
|
||||
@if (_testingSystems.Contains("SAP"))
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate Class="mr-2" />
|
||||
@("Teste...")
|
||||
}
|
||||
else
|
||||
{
|
||||
@("SAP testen")
|
||||
}
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudText Typo="Typo.h6" Class="mb-2">BI1</MudText>
|
||||
<MudTextField @bind-Value="_exportSettings.Bi1Username" Label="BI1 Username" />
|
||||
<MudTextField @bind-Value="_exportSettings.Bi1Password" Label="BI1 Password" InputType="InputType.Password" />
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick='@(() => TestCentralCredentials("BI1"))'
|
||||
StartIcon="@Icons.Material.Filled.NetworkCheck" Disabled='@_testingSystems.Contains("BI1")' Class="mt-2">
|
||||
@if (_testingSystems.Contains("BI1"))
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate Class="mr-2" />
|
||||
@("Teste...")
|
||||
}
|
||||
else
|
||||
{
|
||||
@("BI1 testen")
|
||||
}
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudText Typo="Typo.h6" Class="mb-2">SAGE</MudText>
|
||||
<MudTextField @bind-Value="_exportSettings.SageUsername" Label="SAGE Username" />
|
||||
<MudTextField @bind-Value="_exportSettings.SagePassword" Label="SAGE Password" InputType="InputType.Password" />
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick='@(() => TestCentralCredentials("SAGE"))'
|
||||
StartIcon="@Icons.Material.Filled.NetworkCheck" Disabled='@_testingSystems.Contains("SAGE")' Class="mt-2">
|
||||
@if (_testingSystems.Contains("SAGE"))
|
||||
{
|
||||
<MudProgressCircular Size="Size.Small" Indeterminate Class="mr-2" />
|
||||
@("Teste...")
|
||||
}
|
||||
else
|
||||
{
|
||||
@("SAGE testen")
|
||||
}
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
<MudItem xs="12">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="SaveExportSettings"
|
||||
StartIcon="@Icons.Material.Filled.Save">
|
||||
Speichern
|
||||
</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudPaper>
|
||||
|
||||
@* Export Settings *@
|
||||
<MudText Typo="Typo.h5" Class="mb-2">Export Einstellungen</MudText>
|
||||
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
||||
@@ -95,6 +165,7 @@
|
||||
private SharePointConfig _spConfig = new();
|
||||
private ExportSettings _exportSettings = new();
|
||||
private bool _testingSp;
|
||||
private readonly HashSet<string> _testingSystems = [];
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -156,9 +227,87 @@
|
||||
existing.TimerHour = _exportSettings.TimerHour;
|
||||
existing.TimerMinute = _exportSettings.TimerMinute;
|
||||
existing.TimerEnabled = _exportSettings.TimerEnabled;
|
||||
existing.SapUsername = _exportSettings.SapUsername;
|
||||
existing.SapPassword = _exportSettings.SapPassword;
|
||||
existing.Bi1Username = _exportSettings.Bi1Username;
|
||||
existing.Bi1Password = _exportSettings.Bi1Password;
|
||||
existing.SageUsername = _exportSettings.SageUsername;
|
||||
existing.SagePassword = _exportSettings.SagePassword;
|
||||
}
|
||||
await db.SaveChangesAsync();
|
||||
TimerService.Recalculate();
|
||||
Snackbar.Add("Export Einstellungen gespeichert", Severity.Success);
|
||||
}
|
||||
|
||||
private async Task TestCentralCredentials(string sourceSystem)
|
||||
{
|
||||
if (!_testingSystems.Add(sourceSystem))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
var username = GetCentralUsername(sourceSystem);
|
||||
var password = GetCentralPassword(sourceSystem);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
|
||||
{
|
||||
Snackbar.Add($"Für {sourceSystem} sind keine zentralen Zugangsdaten gepflegt.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
using var db = await DbFactory.CreateDbContextAsync();
|
||||
var site = await db.Sites
|
||||
.Include(s => s.HanaServer)
|
||||
.Where(s => (string.IsNullOrWhiteSpace(s.SourceSystem) ? "SAP" : s.SourceSystem) == sourceSystem)
|
||||
.OrderBy(s => s.Land)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (site?.HanaServer is null)
|
||||
{
|
||||
Snackbar.Add($"Kein Standort mit Quellsystem {sourceSystem} und HANA-Verbindung gefunden.", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var testServer = new HanaServer
|
||||
{
|
||||
Name = $"{sourceSystem} Central Test",
|
||||
Host = site.HanaServer.Host,
|
||||
Port = site.HanaServer.Port,
|
||||
Username = username.Trim(),
|
||||
Password = password.Trim(),
|
||||
DatabaseName = site.HanaServer.DatabaseName,
|
||||
UseSsl = site.HanaServer.UseSsl,
|
||||
ValidateCertificate = site.HanaServer.ValidateCertificate,
|
||||
AdditionalParams = site.HanaServer.AdditionalParams
|
||||
};
|
||||
|
||||
var result = await Task.Run(() => HanaService.TestConnectionDetailed(testServer));
|
||||
if (result.Success)
|
||||
{
|
||||
Snackbar.Add($"{sourceSystem}: Verbindung erfolgreich über Standort '{site.Land}'.", Severity.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add($"{sourceSystem}: {result.ExceptionType} - {result.ErrorMessage}", Severity.Error);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_testingSystems.Remove(sourceSystem);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetCentralUsername(string sourceSystem) => sourceSystem switch
|
||||
{
|
||||
"BI1" => _exportSettings.Bi1Username,
|
||||
"SAGE" => _exportSettings.SageUsername,
|
||||
_ => _exportSettings.SapUsername
|
||||
};
|
||||
|
||||
private string GetCentralPassword(string sourceSystem) => sourceSystem switch
|
||||
{
|
||||
"BI1" => _exportSettings.Bi1Password,
|
||||
"SAGE" => _exportSettings.SagePassword,
|
||||
_ => _exportSettings.SapPassword
|
||||
};
|
||||
}
|
||||
|
||||
@@ -141,11 +141,18 @@
|
||||
<MudSelectItem Value="system">@system</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudTextField @bind-Value="_editingSite.UsernameOverride" Label="Username Override"
|
||||
HelperText="Optional. Wenn leer, wird der zentrale Username des Quellsystems verwendet." />
|
||||
<MudTextField @bind-Value="_editingSite.PasswordOverride" Label="Password Override" InputType="InputType.Password"
|
||||
HelperText="Optional. Wenn leer, wird das zentrale Passwort des Quellsystems verwendet." />
|
||||
<MudCheckBox @bind-Value="_editingSite.IsActive" Label="Aktiv" />
|
||||
|
||||
<MudDivider Class="my-4" />
|
||||
|
||||
<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.
|
||||
</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
|
||||
@@ -301,6 +308,8 @@
|
||||
TSC = site.TSC,
|
||||
Land = site.Land,
|
||||
SourceSystem = string.IsNullOrWhiteSpace(site.SourceSystem) ? "SAP" : site.SourceSystem,
|
||||
UsernameOverride = site.UsernameOverride,
|
||||
PasswordOverride = site.PasswordOverride,
|
||||
IsActive = site.IsActive
|
||||
};
|
||||
_editingSiteServer = site.HanaServer is null
|
||||
@@ -329,6 +338,8 @@
|
||||
existing.TSC = _editingSite.TSC;
|
||||
existing.Land = _editingSite.Land;
|
||||
existing.SourceSystem = _editingSite.SourceSystem;
|
||||
existing.UsernameOverride = _editingSite.UsernameOverride;
|
||||
existing.PasswordOverride = _editingSite.PasswordOverride;
|
||||
existing.IsActive = _editingSite.IsActive;
|
||||
}
|
||||
}
|
||||
@@ -403,6 +414,8 @@
|
||||
_editingSiteServer.Name = string.IsNullOrWhiteSpace(_editingSiteServer.Name)
|
||||
? $"{_editingSite.Land} HANA".Trim()
|
||||
: _editingSiteServer.Name.Trim();
|
||||
_editingSite.UsernameOverride = _editingSite.UsernameOverride.Trim();
|
||||
_editingSite.PasswordOverride = _editingSite.PasswordOverride.Trim();
|
||||
_editingSiteServer.Host = _editingSiteServer.Host.Trim();
|
||||
_editingSiteServer.Username = _editingSiteServer.Username.Trim();
|
||||
_editingSiteServer.DatabaseName = _editingSiteServer.DatabaseName.Trim();
|
||||
|
||||
@@ -7,4 +7,10 @@ public class ExportSettings
|
||||
public int TimerHour { get; set; } = 3;
|
||||
public int TimerMinute { get; set; }
|
||||
public bool TimerEnabled { get; set; } = true;
|
||||
public string SapUsername { get; set; } = string.Empty;
|
||||
public string SapPassword { get; set; } = string.Empty;
|
||||
public string Bi1Username { get; set; } = string.Empty;
|
||||
public string Bi1Password { get; set; } = string.Empty;
|
||||
public string SageUsername { get; set; } = string.Empty;
|
||||
public string SagePassword { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,10 @@ public class HanaServer
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return string.Empty;
|
||||
|
||||
if (Uri.TryCreate(value, UriKind.Absolute, out var uri))
|
||||
// Treat plain "host:port" values as HANA ServerNode, not as a URI scheme.
|
||||
// Only parse as URI when an explicit scheme is present.
|
||||
if (value.Contains("://", StringComparison.Ordinal) &&
|
||||
Uri.TryCreate(value, UriKind.Absolute, out var uri))
|
||||
{
|
||||
return uri.IsDefaultPort ? uri.Host : $"{uri.Host}:{uri.Port}";
|
||||
}
|
||||
|
||||
@@ -24,5 +24,9 @@ public class Site
|
||||
[Required]
|
||||
public string SourceSystem { get; set; } = "SAP";
|
||||
|
||||
public string UsernameOverride { get; set; } = string.Empty;
|
||||
|
||||
public string PasswordOverride { get; set; } = string.Empty;
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,14 @@ public class DatabaseInitializationService : IDatabaseInitializationService
|
||||
AddColumnIfMissing(db, "HanaServers", "ValidateCertificate", "INTEGER NOT NULL DEFAULT 0");
|
||||
AddColumnIfMissing(db, "HanaServers", "AdditionalParams", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "Sites", "SourceSystem", "TEXT NOT NULL DEFAULT 'SAP'");
|
||||
AddColumnIfMissing(db, "Sites", "UsernameOverride", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "Sites", "PasswordOverride", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "SapUsername", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "SapPassword", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "Bi1Username", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "Bi1Password", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "SageUsername", "TEXT NOT NULL DEFAULT ''");
|
||||
AddColumnIfMissing(db, "ExportSettings", "SagePassword", "TEXT NOT NULL DEFAULT ''");
|
||||
EnsureTransformationTable(db);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,10 +49,11 @@ public class SiteExportService : ISiteExportService
|
||||
using var db = await _dbFactory.CreateDbContextAsync();
|
||||
var settings = await db.ExportSettings.FirstOrDefaultAsync() ?? new ExportSettings();
|
||||
var spConfig = await db.SharePointConfigs.FirstOrDefaultAsync();
|
||||
var exportServer = BuildEffectiveServer(site, settings);
|
||||
|
||||
updateStatus?.Invoke("HANA Abfrage...");
|
||||
var records = await Task.Run(() => _hanaService.GetSalesRecords(
|
||||
site.HanaServer, site.Schema, site.TSC, site.Land, settings.DateFilter));
|
||||
exportServer, site.Schema, site.TSC, site.Land, settings.DateFilter));
|
||||
|
||||
updateStatus?.Invoke("Transformationen anwenden...");
|
||||
var rules = await db.FieldTransformationRules
|
||||
@@ -111,4 +112,53 @@ public class SiteExportService : ISiteExportService
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static HanaServer BuildEffectiveServer(Site site, ExportSettings settings)
|
||||
{
|
||||
if (site.HanaServer is null)
|
||||
throw new InvalidOperationException($"Standort '{site.Land}' hat keinen HANA-Server.");
|
||||
|
||||
var sourceSystem = string.IsNullOrWhiteSpace(site.SourceSystem) ? "SAP" : site.SourceSystem.Trim().ToUpperInvariant();
|
||||
var inheritedUsername = GetCentralUsername(sourceSystem, settings);
|
||||
var inheritedPassword = GetCentralPassword(sourceSystem, settings);
|
||||
|
||||
return new HanaServer
|
||||
{
|
||||
Id = site.HanaServer.Id,
|
||||
Name = site.HanaServer.Name,
|
||||
Host = site.HanaServer.Host,
|
||||
Port = site.HanaServer.Port,
|
||||
Username = FirstNonEmpty(site.UsernameOverride, inheritedUsername, site.HanaServer.Username),
|
||||
Password = FirstNonEmpty(site.PasswordOverride, inheritedPassword, site.HanaServer.Password),
|
||||
DatabaseName = site.HanaServer.DatabaseName,
|
||||
UseSsl = site.HanaServer.UseSsl,
|
||||
ValidateCertificate = site.HanaServer.ValidateCertificate,
|
||||
AdditionalParams = site.HanaServer.AdditionalParams
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetCentralUsername(string sourceSystem, ExportSettings settings) => sourceSystem switch
|
||||
{
|
||||
"BI1" => settings.Bi1Username,
|
||||
"SAGE" => settings.SageUsername,
|
||||
_ => settings.SapUsername
|
||||
};
|
||||
|
||||
private static string GetCentralPassword(string sourceSystem, ExportSettings settings) => sourceSystem switch
|
||||
{
|
||||
"BI1" => settings.Bi1Password,
|
||||
"SAGE" => settings.SagePassword,
|
||||
_ => settings.SapPassword
|
||||
};
|
||||
|
||||
private static string FirstNonEmpty(params string[] values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
return value.Trim();
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user