667 lines
27 KiB
Plaintext
667 lines
27 KiB
Plaintext
@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 ISapGatewayService SapGatewayService
|
|
@inject IConfigTransferService ConfigTransferService
|
|
@inject IExchangeRateImportService ExchangeRateImportService
|
|
@inject IJSRuntime JS
|
|
@inject ISnackbar Snackbar
|
|
|
|
<PageTitle>Settings</PageTitle>
|
|
|
|
<MudText Typo="Typo.h4" Class="mb-4">Settings</MudText>
|
|
|
|
<MudText Typo="Typo.h5" Class="mb-2">Konfiguration Import/Export</MudText>
|
|
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
|
<MudGrid>
|
|
<MudItem xs="12" md="6">
|
|
<MudCheckBox @bind-Value="_includeSecretsInExport" Label="Mit Secrets exportieren" />
|
|
<MudText Typo="Typo.caption">
|
|
Wenn deaktiviert, bleiben Passwörter und Secrets beim Export leer. Beim Import ohne Secrets werden bestehende Secrets auf dem Zielsystem beibehalten.
|
|
</MudText>
|
|
</MudItem>
|
|
<MudItem xs="12" md="6">
|
|
<MudStack Row Spacing="2">
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="ExportConfiguration"
|
|
StartIcon="@Icons.Material.Filled.Download" Disabled="_exportingConfig">
|
|
@(_exportingConfig ? "Exportiere..." : "Konfiguration exportieren")
|
|
</MudButton>
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Warning" HtmlTag="label"
|
|
StartIcon="@Icons.Material.Filled.UploadFile" Disabled="_importingConfig">
|
|
@(_importingConfig ? "Importiere..." : "Konfiguration importieren")
|
|
<InputFile OnChange="ImportConfiguration" accept=".json,application/json" style="display:none" />
|
|
</MudButton>
|
|
</MudStack>
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudPaper>
|
|
|
|
@* SharePoint Config *@
|
|
<MudText Typo="Typo.h5" Class="mb-2">SharePoint Konfiguration</MudText>
|
|
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
|
<MudGrid>
|
|
<MudItem xs="12" md="6">
|
|
<MudTextField @bind-Value="_spConfig.SiteUrl" Label="Site URL" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="6">
|
|
<MudTextField @bind-Value="_spConfig.ExportFolder" Label="Export Folder" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="6">
|
|
<MudTextField @bind-Value="_spConfig.CentralExportFolder"
|
|
Label="Central Export Folder"
|
|
HelperText="Optional. Wenn leer, wird weiterhin Export Folder/Alle verwendet." />
|
|
</MudItem>
|
|
<MudItem xs="12" md="4">
|
|
<MudTextField @bind-Value="_spConfig.TenantId" Label="Tenant ID" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="4">
|
|
<MudTextField @bind-Value="_spConfig.ClientId" Label="Client ID" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="4">
|
|
<MudTextField @bind-Value="_spConfig.ClientSecret" Label="Client Secret" InputType="InputType.Password" />
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudStack Row Spacing="2">
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="SaveSharePoint"
|
|
StartIcon="@Icons.Material.Filled.Save">
|
|
Speichern
|
|
</MudButton>
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick="TestSharePoint"
|
|
StartIcon="@Icons.Material.Filled.NetworkCheck" Disabled="_testingSp">
|
|
@if (_testingSp)
|
|
{
|
|
<MudProgressCircular Size="Size.Small" Indeterminate Class="mr-2" />
|
|
@("Teste...")
|
|
}
|
|
else
|
|
{
|
|
@("SharePoint Verbindung testen")
|
|
}
|
|
</MudButton>
|
|
</MudStack>
|
|
</MudItem>
|
|
@if (!string.IsNullOrWhiteSpace(_sharePointTestPreview))
|
|
{
|
|
<MudItem xs="12">
|
|
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Outlined" Class="mt-3">
|
|
<div><b>Test Preview</b></div>
|
|
<div style="white-space: pre-wrap">@_sharePointTestPreview</div>
|
|
</MudAlert>
|
|
</MudItem>
|
|
}
|
|
</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>
|
|
|
|
<MudText Typo="Typo.h5" Class="mb-2">Wechselkurse</MudText>
|
|
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
|
<MudText Typo="Typo.body2" Class="mb-3">
|
|
Diese Kurstabelle wird von der Transformation <b>ConvertCurrency</b> verwendet. Gleiche Waehrung rechnet automatisch mit Faktor 1.
|
|
</MudText>
|
|
<MudStack Row Spacing="2" Class="mb-3">
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Primary" OnClick="AddExchangeRate"
|
|
StartIcon="@Icons.Material.Filled.Add">
|
|
Kurs hinzufuegen
|
|
</MudButton>
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Info" OnClick="RefreshEcbRates"
|
|
StartIcon="@Icons.Material.Filled.Refresh" Disabled="_refreshingExchangeRates">
|
|
@(_refreshingExchangeRates ? "Aktualisiere ECB-Kurse..." : "Refresh Kurse")
|
|
</MudButton>
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="SaveExchangeRates"
|
|
StartIcon="@Icons.Material.Filled.Save">
|
|
Kurse speichern
|
|
</MudButton>
|
|
</MudStack>
|
|
<MudTable Items="_exchangeRates" Hover="true" Breakpoint="Breakpoint.Md">
|
|
<HeaderContent>
|
|
<MudTh>Von</MudTh>
|
|
<MudTh>Nach</MudTh>
|
|
<MudTh>Kurs</MudTh>
|
|
<MudTh>Gueltig ab</MudTh>
|
|
<MudTh>Gueltig bis</MudTh>
|
|
<MudTh>Notiz</MudTh>
|
|
<MudTh>Aktiv</MudTh>
|
|
<MudTh></MudTh>
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
<MudTd>
|
|
<MudTextField @bind-Value="context.FromCurrency" Immediate="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudTextField @bind-Value="context.ToCurrency" Immediate="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudNumericField T="decimal" @bind-Value="context.Rate" Immediate="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudDatePicker Date="context.ValidFrom"
|
|
DateChanged="@(value => context.ValidFrom = value ?? context.ValidFrom)"
|
|
Editable="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudDatePicker Date="context.ValidTo"
|
|
DateChanged="@(value => context.ValidTo = value)"
|
|
Editable="true"
|
|
Clearable="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudTextField @bind-Value="context.Notes" Immediate="true" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudCheckBox @bind-Value="context.IsActive" />
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@(() => RemoveExchangeRate(context))" />
|
|
</MudTd>
|
|
</RowTemplate>
|
|
</MudTable>
|
|
</MudPaper>
|
|
|
|
@* Export Settings *@
|
|
<MudText Typo="Typo.h5" Class="mb-2">Export Einstellungen</MudText>
|
|
<MudPaper Class="pa-4 mb-6" Elevation="1">
|
|
<MudGrid>
|
|
<MudItem xs="12" md="4">
|
|
<MudTextField @bind-Value="_exportSettings.DateFilter" Label="Datum-Filter (ab)"
|
|
HelperText="Format: yyyy-MM-dd" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="2">
|
|
<MudNumericField @bind-Value="_exportSettings.TimerHour" Label="Timer Stunde" Min="0" Max="23" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="2">
|
|
<MudNumericField @bind-Value="_exportSettings.TimerMinute" Label="Timer Minute" Min="0" Max="59" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="4">
|
|
<MudSwitch @bind-Value="_exportSettings.TimerEnabled" Label="Timer aktiviert" Color="Color.Primary" />
|
|
</MudItem>
|
|
<MudItem xs="12" md="4">
|
|
<MudSwitch @bind-Value="_exportSettings.DebugLoggingEnabled" Label="Debug Live-Logging" Color="Color.Warning" />
|
|
<MudText Typo="Typo.caption">
|
|
Schreibt zusätzliche technische Fortschrittsmeldungen für HANA- und SAP-Lesevorgänge ins Dashboard und in die Logs.
|
|
</MudText>
|
|
</MudItem>
|
|
<MudItem xs="12" md="6">
|
|
<MudTextField @bind-Value="_exportSettings.LocalSiteExportFolder" Label="Lokaler Standardpfad Standort-Dateien"
|
|
HelperText="Wenn leer, wird ./output unter dem Programmverzeichnis verwendet." />
|
|
</MudItem>
|
|
<MudItem xs="12" md="6">
|
|
<MudTextField @bind-Value="_exportSettings.LocalConsolidatedExportFolder" Label="Lokaler Pfad Zentrale Datei"
|
|
HelperText="Optional. Wenn leer, wird der Standardpfad der Standort-Dateien verwendet." />
|
|
</MudItem>
|
|
<MudItem xs="12">
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="SaveExportSettings"
|
|
StartIcon="@Icons.Material.Filled.Save">
|
|
Speichern
|
|
</MudButton>
|
|
</MudItem>
|
|
</MudGrid>
|
|
</MudPaper>
|
|
|
|
@* Filename Preview *@
|
|
<MudText Typo="Typo.h5" Class="mb-2">Dateiname Vorschau</MudText>
|
|
<MudPaper Class="pa-4" Elevation="1">
|
|
<MudText Typo="Typo.body1">
|
|
<MudIcon Icon="@Icons.Material.Filled.InsertDriveFile" Size="Size.Small" Class="mr-1" />
|
|
Sales_{"{TSC}"}_{DateTime.Now:yyyy-MM-dd}.xlsx
|
|
</MudText>
|
|
<MudText Typo="Typo.caption" Class="mt-1">
|
|
Beispiel: Sales_TRFR_@(DateTime.Now.ToString("yyyy-MM-dd")).xlsx
|
|
</MudText>
|
|
</MudPaper>
|
|
|
|
@code {
|
|
private SharePointConfig _spConfig = new();
|
|
private ExportSettings _exportSettings = new();
|
|
private bool _testingSp;
|
|
private bool _includeSecretsInExport;
|
|
private bool _exportingConfig;
|
|
private bool _importingConfig;
|
|
private bool _refreshingExchangeRates;
|
|
private string _sharePointTestPreview = string.Empty;
|
|
private List<CurrencyExchangeRate> _exchangeRates = [];
|
|
private readonly HashSet<string> _testingSystems = [];
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
_spConfig = await db.SharePointConfigs.FirstOrDefaultAsync() ?? new SharePointConfig();
|
|
_exportSettings = await db.ExportSettings.FirstOrDefaultAsync() ?? new ExportSettings();
|
|
_exchangeRates = await db.CurrencyExchangeRates
|
|
.OrderBy(x => x.FromCurrency)
|
|
.ThenBy(x => x.ToCurrency)
|
|
.ThenByDescending(x => x.ValidFrom)
|
|
.ToListAsync();
|
|
}
|
|
|
|
private async Task SaveSharePoint()
|
|
{
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
var existing = await db.SharePointConfigs.FirstOrDefaultAsync();
|
|
if (existing is null)
|
|
{
|
|
db.SharePointConfigs.Add(_spConfig);
|
|
}
|
|
else
|
|
{
|
|
existing.SiteUrl = _spConfig.SiteUrl;
|
|
existing.ExportFolder = _spConfig.ExportFolder;
|
|
existing.CentralExportFolder = _spConfig.CentralExportFolder;
|
|
existing.TenantId = _spConfig.TenantId;
|
|
existing.ClientId = _spConfig.ClientId;
|
|
existing.ClientSecret = _spConfig.ClientSecret;
|
|
}
|
|
await db.SaveChangesAsync();
|
|
Snackbar.Add("SharePoint Konfiguration gespeichert", Severity.Success);
|
|
}
|
|
|
|
private async Task TestSharePoint()
|
|
{
|
|
_testingSp = true;
|
|
try
|
|
{
|
|
var tenantId = NormalizeConfigValue(_spConfig.TenantId);
|
|
var clientId = NormalizeConfigValue(_spConfig.ClientId);
|
|
var clientSecret = NormalizeConfigValue(_spConfig.ClientSecret);
|
|
var siteUrl = NormalizeConfigValue(_spConfig.SiteUrl);
|
|
|
|
_sharePointTestPreview = BuildSharePointTestPreview(tenantId, clientId, clientSecret, siteUrl);
|
|
|
|
await SpService.TestConnectionAsync(
|
|
tenantId, clientId, clientSecret, siteUrl);
|
|
Snackbar.Add("SharePoint Verbindung erfolgreich!", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Verbindung fehlgeschlagen: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
_testingSp = false;
|
|
}
|
|
}
|
|
|
|
private async Task SaveExportSettings()
|
|
{
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
var existing = await db.ExportSettings.FirstOrDefaultAsync();
|
|
if (existing is null)
|
|
{
|
|
db.ExportSettings.Add(_exportSettings);
|
|
}
|
|
else
|
|
{
|
|
existing.DateFilter = _exportSettings.DateFilter;
|
|
existing.TimerHour = _exportSettings.TimerHour;
|
|
existing.TimerMinute = _exportSettings.TimerMinute;
|
|
existing.TimerEnabled = _exportSettings.TimerEnabled;
|
|
existing.DebugLoggingEnabled = _exportSettings.DebugLoggingEnabled;
|
|
existing.LocalSiteExportFolder = _exportSettings.LocalSiteExportFolder;
|
|
existing.LocalConsolidatedExportFolder = _exportSettings.LocalConsolidatedExportFolder;
|
|
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 void AddExchangeRate()
|
|
{
|
|
_exchangeRates.Add(new CurrencyExchangeRate
|
|
{
|
|
FromCurrency = "USD",
|
|
ToCurrency = "EUR",
|
|
Rate = 1m,
|
|
ValidFrom = DateTime.Today,
|
|
IsActive = true
|
|
});
|
|
}
|
|
|
|
private void RemoveExchangeRate(CurrencyExchangeRate rate)
|
|
{
|
|
_exchangeRates.Remove(rate);
|
|
}
|
|
|
|
private async Task SaveExchangeRates()
|
|
{
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
var existingRates = await db.CurrencyExchangeRates.ToListAsync();
|
|
if (existingRates.Count > 0)
|
|
db.CurrencyExchangeRates.RemoveRange(existingRates);
|
|
|
|
db.CurrencyExchangeRates.AddRange(_exchangeRates.Select(rate => new CurrencyExchangeRate
|
|
{
|
|
FromCurrency = NormalizeConfigValue(rate.FromCurrency).ToUpperInvariant(),
|
|
ToCurrency = NormalizeConfigValue(rate.ToCurrency).ToUpperInvariant(),
|
|
Rate = rate.Rate,
|
|
ValidFrom = rate.ValidFrom.Date,
|
|
ValidTo = rate.ValidTo?.Date,
|
|
Notes = NormalizeConfigValue(rate.Notes),
|
|
IsActive = rate.IsActive
|
|
}).Where(rate => !string.IsNullOrWhiteSpace(rate.FromCurrency)
|
|
&& !string.IsNullOrWhiteSpace(rate.ToCurrency)
|
|
&& rate.Rate > 0m));
|
|
|
|
await db.SaveChangesAsync();
|
|
|
|
_exchangeRates = await db.CurrencyExchangeRates
|
|
.OrderBy(x => x.FromCurrency)
|
|
.ThenBy(x => x.ToCurrency)
|
|
.ThenByDescending(x => x.ValidFrom)
|
|
.ToListAsync();
|
|
|
|
Snackbar.Add("Wechselkurse gespeichert", Severity.Success);
|
|
}
|
|
|
|
private async Task RefreshEcbRates()
|
|
{
|
|
if (_refreshingExchangeRates)
|
|
return;
|
|
|
|
_refreshingExchangeRates = true;
|
|
try
|
|
{
|
|
var result = await ExchangeRateImportService.RefreshEcbRatesAsync();
|
|
_exchangeRates = await LoadExchangeRatesAsync();
|
|
Snackbar.Add($"ECB-Kurse aktualisiert: {result.ImportedCount} Kurse vom {result.RateDate:yyyy-MM-dd}.", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"ECB-Kursimport fehlgeschlagen: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
_refreshingExchangeRates = false;
|
|
}
|
|
}
|
|
|
|
private async Task ExportConfiguration()
|
|
{
|
|
if (_exportingConfig)
|
|
return;
|
|
|
|
_exportingConfig = true;
|
|
try
|
|
{
|
|
var json = await ConfigTransferService.ExportJsonAsync(_includeSecretsInExport);
|
|
var suffix = _includeSecretsInExport ? "with-secrets" : "without-secrets";
|
|
var fileName = $"trafag-config-{DateTime.UtcNow:yyyyMMdd-HHmmss}-{suffix}.json";
|
|
await JS.InvokeVoidAsync("trafagDownload.saveTextFile", fileName, json, "application/json;charset=utf-8");
|
|
Snackbar.Add("Konfiguration exportiert", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Export fehlgeschlagen: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
_exportingConfig = false;
|
|
}
|
|
}
|
|
|
|
private async Task ImportConfiguration(InputFileChangeEventArgs args)
|
|
{
|
|
if (_importingConfig)
|
|
return;
|
|
|
|
_importingConfig = true;
|
|
try
|
|
{
|
|
var file = args.File;
|
|
await using var stream = file.OpenReadStream(5 * 1024 * 1024);
|
|
using var reader = new StreamReader(stream);
|
|
var json = await reader.ReadToEndAsync();
|
|
await ConfigTransferService.ImportJsonAsync(json);
|
|
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
_spConfig = await db.SharePointConfigs.FirstOrDefaultAsync() ?? new SharePointConfig();
|
|
_exportSettings = await db.ExportSettings.FirstOrDefaultAsync() ?? new ExportSettings();
|
|
_exchangeRates = await db.CurrencyExchangeRates
|
|
.OrderBy(x => x.FromCurrency)
|
|
.ThenBy(x => x.ToCurrency)
|
|
.ThenByDescending(x => x.ValidFrom)
|
|
.ToListAsync();
|
|
TimerService.Recalculate();
|
|
Snackbar.Add("Konfiguration importiert", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Import fehlgeschlagen: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
_importingConfig = false;
|
|
}
|
|
}
|
|
|
|
private async Task TestCentralCredentials(string sourceSystem)
|
|
{
|
|
if (sourceSystem == "SAP")
|
|
{
|
|
await TestCentralSapCredentials();
|
|
return;
|
|
}
|
|
|
|
await TestCentralHanaCredentials(sourceSystem);
|
|
}
|
|
|
|
private async Task TestCentralHanaCredentials(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 async Task TestCentralSapCredentials()
|
|
{
|
|
const string sourceSystem = "SAP";
|
|
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 SAP sind keine zentralen Gateway-Zugangsdaten gepflegt.", Severity.Warning);
|
|
return;
|
|
}
|
|
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
var site = await db.Sites
|
|
.Where(s => (string.IsNullOrWhiteSpace(s.SourceSystem) ? "SAP" : s.SourceSystem) == sourceSystem
|
|
&& !string.IsNullOrWhiteSpace(s.SapServiceUrl))
|
|
.OrderBy(s => s.Land)
|
|
.FirstOrDefaultAsync();
|
|
|
|
if (site is null)
|
|
{
|
|
Snackbar.Add("Kein SAP-Standort mit Service URL gefunden.", Severity.Warning);
|
|
return;
|
|
}
|
|
|
|
await SapGatewayService.TestConnectionAsync(site.SapServiceUrl, username.Trim(), password.Trim());
|
|
Snackbar.Add($"SAP: Gateway-Verbindung erfolgreich über Standort '{site.Land}'.", Severity.Success);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"SAP: {ex.Message}", 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
|
|
};
|
|
|
|
private static string NormalizeConfigValue(string? value) => value?.Trim() ?? string.Empty;
|
|
|
|
private static string BuildSharePointTestPreview(string tenantId, string clientId, string clientSecret, string siteUrl)
|
|
{
|
|
var maskedSecret = string.IsNullOrEmpty(clientSecret)
|
|
? "<leer>"
|
|
: $"{new string('*', Math.Min(clientSecret.Length, 8))} (len={clientSecret.Length})";
|
|
|
|
return string.Join(Environment.NewLine,
|
|
[
|
|
$"Tenant ID: {tenantId}",
|
|
$"Client ID: {clientId}",
|
|
$"Client Secret: {maskedSecret}",
|
|
$"Site URL: {siteUrl}"
|
|
]);
|
|
}
|
|
|
|
private async Task<List<CurrencyExchangeRate>> LoadExchangeRatesAsync()
|
|
{
|
|
using var db = await DbFactory.CreateDbContextAsync();
|
|
return await db.CurrencyExchangeRates
|
|
.OrderBy(x => x.FromCurrency)
|
|
.ThenBy(x => x.ToCurrency)
|
|
.ThenByDescending(x => x.ValidFrom)
|
|
.ToListAsync();
|
|
}
|
|
}
|