@page "/settings"
@using TrafagSalesExporter.Models
@using TrafagSalesExporter.Services
@inject ISettingsPageService SettingsPageActions
@inject IJSRuntime JS
@inject ISnackbar Snackbar
Settings
Settings
Konfiguration Import/Export
Wenn deaktiviert, bleiben Passwörter und Secrets beim Export leer. Beim Import ohne Secrets werden bestehende Secrets auf dem Zielsystem beibehalten.
@(_exportingConfig ? "Exportiere..." : "Konfiguration exportieren")
@(_importingConfig ? "Importiere..." : "Konfiguration importieren")
@* SharePoint Config *@
SharePoint Konfiguration
Speichern
@if (_testingSp)
{
@("Teste...")
}
else
{
@("SharePoint Verbindung testen")
}
@if (!string.IsNullOrWhiteSpace(_sharePointTestPreview))
{
Test Preview
@_sharePointTestPreview
}
Quellsysteme
Diese Zugangsdaten werden pro Quellsystem als Standard verwendet. Ein Standort kann sie bei Bedarf mit eigenen Overrides überschreiben.
Quellsystem hinzufuegen
Code
Name
Anschlussart
Zentrale URL
User
Aktiv
Test
@context.Code
@context.DisplayName
@GetConnectionKindLabel(context.ConnectionKind)
@GetServiceUrlSummary(context)
@GetUsernameSummary(context)
@if (context.IsActive)
{
}
else
{
}
@if (!UsesManualImport(context))
{
@(_testingSystems.Contains(context.Code) ? "Teste..." : "Testen")
}
Quellsysteme speichern
@(_editingSourceSystem.Id == 0 ? "Quellsystem hinzufuegen" : "Quellsystem bearbeiten")
@foreach (var kind in SourceSystemConnectionKinds.All)
{
@GetConnectionKindLabel(kind)
}
@if (UsesSapGateway(_editingSourceSystem))
{
}
Abbrechen
Uebernehmen
Wechselkurse
Diese Kurstabelle wird von der Transformation ConvertCurrency verwendet. Gleiche Waehrung rechnet automatisch mit Faktor 1.
Kurs hinzufuegen
@(_refreshingExchangeRates ? "Aktualisiere ECB-Kurse..." : "Refresh Kurse")
Kurse speichern
Von
Nach
Kurs
Gueltig ab
Gueltig bis
Notiz
Aktiv
@* Export Settings *@
Export Einstellungen
Schreibt zusätzliche technische Fortschrittsmeldungen für HANA- und SAP-Lesevorgänge ins Dashboard und in die Logs.
Speichern
@* Filename Preview *@
Dateiname Vorschau
Sales_{"{TSC}"}_{DateTime.Now:yyyy-MM-dd}.xlsx
Beispiel: Sales_TRFR_@(DateTime.Now.ToString("yyyy-MM-dd")).xlsx
@code {
private SharePointConfig _spConfig = new();
private ExportSettings _exportSettings = new();
private List _sourceSystems = [];
private SourceSystemDefinition _editingSourceSystem = new();
private bool _testingSp;
private bool _includeSecretsInExport;
private bool _exportingConfig;
private bool _importingConfig;
private bool _refreshingExchangeRates;
private string _sharePointTestPreview = string.Empty;
private List _exchangeRates = [];
private readonly HashSet _testingSystems = [];
private bool _sourceSystemDialogVisible;
private readonly DialogOptions _sourceSystemDialogOptions = new() { MaxWidth = MaxWidth.Small, FullWidth = true };
protected override async Task OnInitializedAsync()
{
var state = await SettingsPageActions.LoadAsync();
_spConfig = state.SharePointConfig;
_exportSettings = state.ExportSettings;
_sourceSystems = state.SourceSystems;
_exchangeRates = state.ExchangeRates;
}
private async Task SaveSharePoint()
{
await SettingsPageActions.SaveSharePointAsync(_spConfig);
Snackbar.Add("SharePoint Konfiguration gespeichert", Severity.Success);
}
private async Task TestSharePoint()
{
_testingSp = true;
try
{
_sharePointTestPreview = await SettingsPageActions.BuildSharePointTestPreviewAsync(_spConfig);
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()
{
await SettingsPageActions.SaveExportSettingsAsync(_exportSettings);
Snackbar.Add("Export Einstellungen gespeichert", Severity.Success);
}
private void AddSourceSystem()
{
_editingSourceSystem = new SourceSystemDefinition
{
Code = string.Empty,
DisplayName = string.Empty,
ConnectionKind = SourceSystemConnectionKinds.Hana,
IsActive = true
};
_sourceSystemDialogVisible = true;
}
private void EditSourceSystem(SourceSystemDefinition definition)
{
_editingSourceSystem = new SourceSystemDefinition
{
Id = definition.Id,
Code = definition.Code,
DisplayName = definition.DisplayName,
ConnectionKind = definition.ConnectionKind,
IsActive = definition.IsActive,
CentralServiceUrl = definition.CentralServiceUrl,
CentralUsername = definition.CentralUsername,
CentralPassword = definition.CentralPassword
};
_sourceSystemDialogVisible = true;
}
private void SaveSourceSystemEdit()
{
_editingSourceSystem.Code = NormalizeSourceSystemCode(_editingSourceSystem.Code);
_editingSourceSystem.DisplayName = NormalizeConfigValue(_editingSourceSystem.DisplayName);
_editingSourceSystem.ConnectionKind = NormalizeConnectionKind(_editingSourceSystem.ConnectionKind);
_editingSourceSystem.CentralServiceUrl = NormalizeConfigValue(_editingSourceSystem.CentralServiceUrl);
_editingSourceSystem.CentralUsername = NormalizeConfigValue(_editingSourceSystem.CentralUsername);
_editingSourceSystem.CentralPassword = _editingSourceSystem.CentralPassword ?? string.Empty;
if (string.IsNullOrWhiteSpace(_editingSourceSystem.Code) || string.IsNullOrWhiteSpace(_editingSourceSystem.DisplayName))
{
Snackbar.Add("Code und Name fuer das Quellsystem sind Pflicht.", Severity.Warning);
return;
}
if (_sourceSystems.Any(x => x.Id != _editingSourceSystem.Id && x.Code == _editingSourceSystem.Code))
{
Snackbar.Add($"Quellsystem-Code doppelt vorhanden: {_editingSourceSystem.Code}", Severity.Warning);
return;
}
if (_editingSourceSystem.Id == 0)
{
_sourceSystems.Add(_editingSourceSystem);
}
else
{
var existing = _sourceSystems.FirstOrDefault(x => x.Id == _editingSourceSystem.Id);
if (existing is not null)
{
existing.Code = _editingSourceSystem.Code;
existing.DisplayName = _editingSourceSystem.DisplayName;
existing.ConnectionKind = _editingSourceSystem.ConnectionKind;
existing.IsActive = _editingSourceSystem.IsActive;
existing.CentralServiceUrl = _editingSourceSystem.CentralServiceUrl;
existing.CentralUsername = _editingSourceSystem.CentralUsername;
existing.CentralPassword = _editingSourceSystem.CentralPassword;
}
}
_sourceSystems = _sourceSystems.OrderBy(x => x.Code).ToList();
_sourceSystemDialogVisible = false;
}
private void CloseSourceSystemDialog()
{
_sourceSystemDialogVisible = false;
}
private void RemoveSourceSystem(SourceSystemDefinition definition)
{
_sourceSystems.Remove(definition);
}
private async Task SaveSourceSystems()
{
try
{
_sourceSystems = await SettingsPageActions.SaveSourceSystemsAsync(_sourceSystems);
Snackbar.Add("Quellsysteme gespeichert", Severity.Success);
}
catch (Exception ex)
{
Snackbar.Add(ex.Message, Severity.Warning);
}
}
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()
{
_exchangeRates = await SettingsPageActions.SaveExchangeRatesAsync(_exchangeRates);
Snackbar.Add("Wechselkurse gespeichert", Severity.Success);
}
private async Task RefreshEcbRates()
{
if (_refreshingExchangeRates)
return;
_refreshingExchangeRates = true;
try
{
var result = await SettingsPageActions.RefreshEcbRatesAsync();
_exchangeRates = result.ExchangeRates;
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 SettingsPageActions.ExportConfigurationAsync(_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();
var state = await SettingsPageActions.ImportConfigurationAsync(json);
_spConfig = state.SharePointConfig;
_exportSettings = state.ExportSettings;
_sourceSystems = state.SourceSystems;
_exchangeRates = state.ExchangeRates;
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)
{
var definition = _sourceSystems.FirstOrDefault(x => string.Equals(x.Code, sourceSystem, StringComparison.OrdinalIgnoreCase));
if (definition is null)
{
Snackbar.Add($"Quellsystem '{sourceSystem}' nicht gefunden.", Severity.Warning);
return;
}
if (!_testingSystems.Add(sourceSystem))
return;
try
{
var result = await SettingsPageActions.TestCentralCredentialsAsync(definition);
Snackbar.Add(result.Message, result.Success ? Severity.Success : result.Warning ? Severity.Warning : Severity.Error);
}
finally
{
_testingSystems.Remove(sourceSystem);
}
}
private static string NormalizeSourceSystemCode(string? code) => Services.SettingsPageService.NormalizeSourceSystemCode(code);
private static string NormalizeConnectionKind(string? connectionKind) => Services.SettingsPageService.NormalizeConnectionKind(connectionKind);
private static string GetConnectionKindLabel(string connectionKind) => connectionKind switch
{
SourceSystemConnectionKinds.Hana => "HANA",
SourceSystemConnectionKinds.SapGateway => "SAP Gateway",
SourceSystemConnectionKinds.ManualExcel => "Manual Excel",
_ => connectionKind
};
private static bool UsesManualImport(SourceSystemDefinition definition)
=> string.Equals(definition.ConnectionKind, SourceSystemConnectionKinds.ManualExcel, StringComparison.OrdinalIgnoreCase);
private static bool UsesSapGateway(SourceSystemDefinition definition)
=> string.Equals(definition.ConnectionKind, SourceSystemConnectionKinds.SapGateway, StringComparison.OrdinalIgnoreCase);
private static string GetServiceUrlSummary(SourceSystemDefinition definition)
=> string.IsNullOrWhiteSpace(definition.CentralServiceUrl) ? "-" : definition.CentralServiceUrl;
private static string GetUsernameSummary(SourceSystemDefinition definition)
=> string.IsNullOrWhiteSpace(definition.CentralUsername) ? "-" : definition.CentralUsername;
private static string NormalizeConfigValue(string? value) => Services.SettingsPageService.NormalizeConfigValue(value);
}