refactoring

This commit is contained in:
2026-04-17 10:29:41 +02:00
parent 83a400a90e
commit bec0410ef4
17 changed files with 1752 additions and 432 deletions
@@ -20,6 +20,7 @@ public class ConfigTransferService : IConfigTransferService
using var db = await _dbFactory.CreateDbContextAsync();
var sharePoint = await db.SharePointConfigs.FirstOrDefaultAsync();
var exportSettings = await db.ExportSettings.FirstOrDefaultAsync();
var sourceSystems = await db.SourceSystemDefinitions.OrderBy(x => x.Code).ToListAsync();
var exchangeRates = await db.CurrencyExchangeRates
.OrderBy(x => x.FromCurrency)
.ThenBy(x => x.ToCurrency)
@@ -55,14 +56,18 @@ public class ConfigTransferService : IConfigTransferService
TimerEnabled = exportSettings.TimerEnabled,
DebugLoggingEnabled = exportSettings.DebugLoggingEnabled,
LocalSiteExportFolder = exportSettings.LocalSiteExportFolder,
LocalConsolidatedExportFolder = exportSettings.LocalConsolidatedExportFolder,
SapUsername = includeSecrets ? exportSettings.SapUsername : null,
SapPassword = includeSecrets ? exportSettings.SapPassword : null,
Bi1Username = includeSecrets ? exportSettings.Bi1Username : null,
Bi1Password = includeSecrets ? exportSettings.Bi1Password : null,
SageUsername = includeSecrets ? exportSettings.SageUsername : null,
SagePassword = includeSecrets ? exportSettings.SagePassword : null
LocalConsolidatedExportFolder = exportSettings.LocalConsolidatedExportFolder
},
SourceSystemDefinitions = sourceSystems.Select(system => new ConfigTransferSourceSystemDefinition
{
Code = system.Code,
DisplayName = system.DisplayName,
ConnectionKind = system.ConnectionKind,
IsActive = system.IsActive,
CentralServiceUrl = system.CentralServiceUrl,
CentralUsername = includeSecrets ? system.CentralUsername : null,
CentralPassword = includeSecrets ? system.CentralPassword : null
}).ToList(),
CurrencyExchangeRates = exchangeRates.Select(rate => new ConfigTransferCurrencyExchangeRate
{
FromCurrency = rate.FromCurrency,
@@ -76,11 +81,10 @@ public class ConfigTransferService : IConfigTransferService
HanaServers = hanaServers.Select(server => new ConfigTransferHanaServer
{
Key = serverKeyMap[server.Id],
SourceSystem = server.SourceSystem,
Name = server.Name,
Host = server.Host,
Port = server.Port,
Username = includeSecrets ? server.Username : null,
Password = includeSecrets ? server.Password : null,
DatabaseName = server.DatabaseName,
UseSsl = server.UseSsl,
ValidateCertificate = server.ValidateCertificate,
@@ -158,6 +162,7 @@ public class ConfigTransferService : IConfigTransferService
using var db = await _dbFactory.CreateDbContextAsync();
var existingSharePoint = await db.SharePointConfigs.FirstOrDefaultAsync();
var existingSettings = await db.ExportSettings.FirstOrDefaultAsync();
var existingSourceSystems = await db.SourceSystemDefinitions.ToListAsync();
var existingServers = await db.HanaServers.ToListAsync();
var existingExchangeRates = await db.CurrencyExchangeRates.ToListAsync();
var existingSites = await db.Sites.ToListAsync();
@@ -168,20 +173,10 @@ public class ConfigTransferService : IConfigTransferService
var existingCentralRecords = await db.CentralSalesRecords.ToListAsync();
var preservedSharePointSecret = existingSharePoint?.ClientSecret ?? string.Empty;
var preservedSecrets = existingSettings is null
? new ConfigTransferExportSettings()
: new ConfigTransferExportSettings
{
SapUsername = existingSettings.SapUsername,
SapPassword = existingSettings.SapPassword,
Bi1Username = existingSettings.Bi1Username,
Bi1Password = existingSettings.Bi1Password,
SageUsername = existingSettings.SageUsername,
SagePassword = existingSettings.SagePassword
};
var preservedServerSecrets = existingServers.ToDictionary(
x => BuildServerSignature(x.Name, x.Host, x.Port, x.DatabaseName),
x => (x.Username, x.Password));
var preservedSourceSystemSecrets = existingSourceSystems.ToDictionary(
x => x.Code,
x => (CentralUsername: x.CentralUsername, CentralPassword: x.CentralPassword),
StringComparer.OrdinalIgnoreCase);
var preservedSiteSecrets = existingSites.ToDictionary(
x => BuildSiteSignature(x.Land, x.TSC, x.Schema, x.SourceSystem),
x => (x.UsernameOverride, x.PasswordOverride));
@@ -194,6 +189,7 @@ public class ConfigTransferService : IConfigTransferService
if (existingCentralRecords.Count > 0) db.CentralSalesRecords.RemoveRange(existingCentralRecords);
if (existingSites.Count > 0) db.Sites.RemoveRange(existingSites);
if (existingServers.Count > 0) db.HanaServers.RemoveRange(existingServers);
if (existingSourceSystems.Count > 0) db.SourceSystemDefinitions.RemoveRange(existingSourceSystems);
if (existingSharePoint is not null) db.SharePointConfigs.Remove(existingSharePoint);
if (existingSettings is not null) db.ExportSettings.Remove(existingSettings);
await db.SaveChangesAsync();
@@ -218,15 +214,28 @@ public class ConfigTransferService : IConfigTransferService
TimerEnabled = importedSettings.TimerEnabled,
DebugLoggingEnabled = importedSettings.DebugLoggingEnabled,
LocalSiteExportFolder = importedSettings.LocalSiteExportFolder,
LocalConsolidatedExportFolder = importedSettings.LocalConsolidatedExportFolder,
SapUsername = package.IncludesSecrets ? importedSettings.SapUsername ?? string.Empty : preservedSecrets.SapUsername ?? string.Empty,
SapPassword = package.IncludesSecrets ? importedSettings.SapPassword ?? string.Empty : preservedSecrets.SapPassword ?? string.Empty,
Bi1Username = package.IncludesSecrets ? importedSettings.Bi1Username ?? string.Empty : preservedSecrets.Bi1Username ?? string.Empty,
Bi1Password = package.IncludesSecrets ? importedSettings.Bi1Password ?? string.Empty : preservedSecrets.Bi1Password ?? string.Empty,
SageUsername = package.IncludesSecrets ? importedSettings.SageUsername ?? string.Empty : preservedSecrets.SageUsername ?? string.Empty,
SagePassword = package.IncludesSecrets ? importedSettings.SagePassword ?? string.Empty : preservedSecrets.SagePassword ?? string.Empty
LocalConsolidatedExportFolder = importedSettings.LocalConsolidatedExportFolder
});
var importedSourceSystems = package.SourceSystemDefinitions.Count > 0
? package.SourceSystemDefinitions
: BuildDefaultSourceSystems();
foreach (var sourceSystem in importedSourceSystems)
{
preservedSourceSystemSecrets.TryGetValue(sourceSystem.Code, out var preserved);
db.SourceSystemDefinitions.Add(new SourceSystemDefinition
{
Code = sourceSystem.Code,
DisplayName = sourceSystem.DisplayName,
ConnectionKind = sourceSystem.ConnectionKind,
IsActive = sourceSystem.IsActive,
CentralServiceUrl = sourceSystem.CentralServiceUrl,
CentralUsername = package.IncludesSecrets ? sourceSystem.CentralUsername ?? string.Empty : preserved.CentralUsername ?? string.Empty,
CentralPassword = package.IncludesSecrets ? sourceSystem.CentralPassword ?? string.Empty : preserved.CentralPassword ?? string.Empty
});
}
if (package.CurrencyExchangeRates.Count > 0)
{
db.CurrencyExchangeRates.AddRange(package.CurrencyExchangeRates.Select(rate => new CurrencyExchangeRate
@@ -244,14 +253,14 @@ public class ConfigTransferService : IConfigTransferService
var serverIdMap = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
foreach (var server in package.HanaServers)
{
preservedServerSecrets.TryGetValue(BuildServerSignature(server.Name, server.Host, server.Port, server.DatabaseName), out var preserved);
var entity = new HanaServer
{
SourceSystem = server.SourceSystem,
Name = server.Name,
Host = server.Host,
Port = server.Port,
Username = package.IncludesSecrets ? server.Username ?? string.Empty : preserved.Username ?? string.Empty,
Password = package.IncludesSecrets ? server.Password ?? string.Empty : preserved.Password ?? string.Empty,
Username = string.Empty,
Password = string.Empty,
DatabaseName = server.DatabaseName,
UseSsl = server.UseSsl,
ValidateCertificate = server.ValidateCertificate,
@@ -355,10 +364,42 @@ public class ConfigTransferService : IConfigTransferService
await db.SaveChangesAsync();
}
private static string BuildServerSignature(string name, string host, int port, string databaseName)
=> $"{name}|{host}|{port}|{databaseName}".ToUpperInvariant();
private static string BuildSiteSignature(string land, string tsc, string schema, string sourceSystem)
=> $"{land}|{tsc}|{schema}|{sourceSystem}".ToUpperInvariant();
private static List<ConfigTransferSourceSystemDefinition> BuildDefaultSourceSystems()
{
return
[
new ConfigTransferSourceSystemDefinition
{
Code = "SAP",
DisplayName = "SAP",
ConnectionKind = SourceSystemConnectionKinds.SapGateway,
IsActive = true,
CentralServiceUrl = string.Empty
},
new ConfigTransferSourceSystemDefinition
{
Code = "BI1",
DisplayName = "BI1",
ConnectionKind = SourceSystemConnectionKinds.Hana,
IsActive = true
},
new ConfigTransferSourceSystemDefinition
{
Code = "SAGE",
DisplayName = "SAGE",
ConnectionKind = SourceSystemConnectionKinds.Hana,
IsActive = true
},
new ConfigTransferSourceSystemDefinition
{
Code = "MANUAL_EXCEL",
DisplayName = "Manual Excel",
ConnectionKind = SourceSystemConnectionKinds.ManualExcel,
IsActive = true
}
];
}
}
@@ -46,7 +46,10 @@ public class DatabaseInitializationService : IDatabaseInitializationService
private static void EnsureSchema(AppDbContext db)
{
EnsureSitesTableSupportsOptionalHanaServer(db);
EnsureExportSettingsTableSupportsCurrentSchema(db);
EnsureHanaServersTableSupportsCurrentSchema(db);
RepairBrokenSiteForeignKeys(db);
AddColumnIfMissing(db, "HanaServers", "SourceSystem", "TEXT NOT NULL DEFAULT ''");
AddColumnIfMissing(db, "HanaServers", "DatabaseName", "TEXT NOT NULL DEFAULT ''");
AddColumnIfMissing(db, "HanaServers", "UseSsl", "INTEGER NOT NULL DEFAULT 0");
AddColumnIfMissing(db, "HanaServers", "ValidateCertificate", "INTEGER NOT NULL DEFAULT 0");
@@ -61,12 +64,6 @@ public class DatabaseInitializationService : IDatabaseInitializationService
AddColumnIfMissing(db, "Sites", "SapEntitySet", "TEXT NOT NULL DEFAULT ''");
AddColumnIfMissing(db, "Sites", "SapEntitySetsCache", "TEXT NOT NULL DEFAULT ''");
AddColumnIfMissing(db, "Sites", "SapEntitySetsRefreshedAtUtc", "TEXT NULL");
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 ''");
AddColumnIfMissing(db, "ExportSettings", "DebugLoggingEnabled", "INTEGER NOT NULL DEFAULT 0");
AddColumnIfMissing(db, "ExportSettings", "LocalSiteExportFolder", "TEXT NOT NULL DEFAULT ''");
AddColumnIfMissing(db, "ExportSettings", "LocalConsolidatedExportFolder", "TEXT NOT NULL DEFAULT ''");
@@ -75,11 +72,57 @@ public class DatabaseInitializationService : IDatabaseInitializationService
EnsureTransformationTable(db);
AddColumnIfMissing(db, "FieldTransformationRules", "RuleScope", "TEXT NOT NULL DEFAULT 'Value'");
EnsureCurrencyExchangeRateTable(db);
EnsureSourceSystemDefinitionTable(db);
AddColumnIfMissing(db, "SourceSystemDefinitions", "CentralServiceUrl", "TEXT NOT NULL DEFAULT ''");
EnsureSapSourceTable(db);
EnsureSapJoinTable(db);
EnsureSapFieldMappingTable(db);
EnsureCentralSalesRecordTable(db);
EnsureAppEventLogTable(db);
EnsureSourceSystemDefinitions(db);
EnsureCentralHanaServerRecords(db);
}
private static void EnsureExportSettingsTableSupportsCurrentSchema(AppDbContext db)
{
var conn = db.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
conn.Open();
var columns = GetTableColumns(conn, transaction: null, "ExportSettings");
if (columns.Count == 0)
return;
var legacyColumns = new[]
{
"SapUsername",
"SapPassword",
"Bi1Username",
"Bi1Password",
"SageUsername",
"SagePassword"
};
if (!legacyColumns.Any(columns.Contains))
return;
RebuildTable(conn, "ExportSettings", GetExportSettingsCreateSql());
}
private static void EnsureHanaServersTableSupportsCurrentSchema(AppDbContext db)
{
var conn = db.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
conn.Open();
var columns = GetTableColumns(conn, transaction: null, "HanaServers");
if (columns.Count == 0)
return;
if (!columns.Contains("Username") && !columns.Contains("Password"))
return;
RebuildTable(conn, "HanaServers", GetHanaServersCreateSql());
}
private static void EnsureSitesTableSupportsOptionalHanaServer(AppDbContext db)
@@ -272,7 +315,7 @@ FROM Sites_old;";
enableFk.ExecuteNonQuery();
}
private static List<string> GetSharedColumns(System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, string newTableName, string oldTableName)
private static List<string> GetSharedColumns(System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction? transaction, string newTableName, string oldTableName)
{
var newColumns = GetTableColumns(connection, transaction, newTableName);
var oldColumns = GetTableColumns(connection, transaction, oldTableName);
@@ -280,7 +323,7 @@ FROM Sites_old;";
return newColumns.Where(oldColumns.Contains).ToList();
}
private static HashSet<string> GetTableColumns(System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, string tableName)
private static HashSet<string> GetTableColumns(System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction? transaction, string tableName)
{
var columns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
@@ -315,6 +358,31 @@ CREATE TABLE ExportLogs (
FOREIGN KEY (SiteId) REFERENCES Sites (Id)
);";
private static string GetExportSettingsCreateSql() => @"
CREATE TABLE ExportSettings (
Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
DateFilter TEXT NOT NULL,
TimerHour INTEGER NOT NULL,
TimerMinute INTEGER NOT NULL,
TimerEnabled INTEGER NOT NULL,
DebugLoggingEnabled INTEGER NOT NULL DEFAULT 0,
LocalSiteExportFolder TEXT NOT NULL DEFAULT '',
LocalConsolidatedExportFolder TEXT NOT NULL DEFAULT ''
);";
private static string GetHanaServersCreateSql() => @"
CREATE TABLE HanaServers (
Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
SourceSystem TEXT NOT NULL,
Name TEXT NOT NULL,
Host TEXT NOT NULL,
Port INTEGER NOT NULL,
DatabaseName TEXT NOT NULL DEFAULT '',
UseSsl INTEGER NOT NULL DEFAULT 0,
ValidateCertificate INTEGER NOT NULL DEFAULT 0,
AdditionalParams TEXT NOT NULL DEFAULT ''
);";
private static string GetAppEventLogsCreateSql() => @"
CREATE TABLE AppEventLogs (
Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
@@ -604,21 +672,42 @@ CREATE TABLE IF NOT EXISTS AppEventLogs (
cmd.ExecuteNonQuery();
}
private static void EnsureSourceSystemDefinitionTable(AppDbContext db)
{
var conn = db.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
conn.Open();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS SourceSystemDefinitions (
Id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
Code TEXT NOT NULL,
DisplayName TEXT NOT NULL,
ConnectionKind TEXT NOT NULL,
IsActive INTEGER NOT NULL DEFAULT 1,
CentralServiceUrl TEXT NOT NULL DEFAULT '',
CentralUsername TEXT NOT NULL DEFAULT '',
CentralPassword TEXT NOT NULL DEFAULT ''
);";
cmd.ExecuteNonQuery();
}
private static void SeedIfEmpty(AppDbContext db)
{
if (db.HanaServers.Any())
if (db.Sites.Any() || db.HanaServers.Any() || db.SharePointConfigs.Any() || db.ExportSettings.Any())
return;
var serverInternal = new HanaServer { Name = "Internal", Host = "travtrp0", Port = 30015, Username = "", Password = "" };
var serverIndia = new HanaServer { Name = "India", Host = "20.197.20.60", Port = 30015, Username = "", Password = "" };
db.HanaServers.AddRange(serverInternal, serverIndia);
var serverBi1 = new HanaServer { SourceSystem = "BI1", Name = "BI1", Host = "travtrp0", Port = 30015, Username = "", Password = "" };
var serverSage = new HanaServer { SourceSystem = "SAGE", Name = "SAGE", Host = "20.197.20.60", Port = 30015, Username = "", Password = "" };
db.HanaServers.AddRange(serverBi1, serverSage);
db.SaveChanges();
db.Sites.AddRange(
new Site { HanaServerId = serverInternal.Id, Schema = "fr01_p", TSC = "TRFR", Land = "Frankreich", IsActive = true },
new Site { HanaServerId = serverInternal.Id, Schema = "it01_p", TSC = "TRIT", Land = "Italien", IsActive = true },
new Site { HanaServerId = serverInternal.Id, Schema = "us01_p", TSC = "TRUS", Land = "USA", IsActive = true },
new Site { HanaServerId = serverIndia.Id, Schema = "TRAFAG_LIVE", TSC = "TRIN", Land = "Indien", IsActive = true }
new Site { HanaServerId = serverBi1.Id, Schema = "fr01_p", TSC = "TRFR", Land = "Frankreich", SourceSystem = "BI1", IsActive = true },
new Site { HanaServerId = serverBi1.Id, Schema = "it01_p", TSC = "TRIT", Land = "Italien", SourceSystem = "BI1", IsActive = true },
new Site { HanaServerId = serverBi1.Id, Schema = "us01_p", TSC = "TRUS", Land = "USA", SourceSystem = "BI1", IsActive = true },
new Site { HanaServerId = serverSage.Id, Schema = "TRAFAG_LIVE", TSC = "TRIN", Land = "Indien", SourceSystem = "SAGE", IsActive = true }
);
db.SharePointConfigs.Add(new SharePointConfig
@@ -695,4 +784,121 @@ CREATE TABLE IF NOT EXISTS AppEventLogs (
if (hasChanges)
db.SaveChanges();
}
private static void EnsureCentralHanaServerRecords(AppDbContext db)
{
var centralSystems = db.SourceSystemDefinitions
.AsNoTracking()
.Where(x => x.ConnectionKind == SourceSystemConnectionKinds.Hana)
.OrderBy(x => x.Code)
.Select(x => x.Code)
.ToList();
var changed = false;
foreach (var sourceSystem in centralSystems)
{
var existingCentral = db.HanaServers
.OrderBy(x => x.Id)
.FirstOrDefault(x => x.SourceSystem == sourceSystem);
if (existingCentral is not null)
{
if (string.IsNullOrWhiteSpace(existingCentral.Name))
{
existingCentral.Name = sourceSystem;
changed = true;
}
continue;
}
var linkedServer = db.Sites
.Include(x => x.HanaServer)
.Where(x => x.SourceSystem == sourceSystem && x.HanaServerId != null && x.HanaServer != null)
.Select(x => x.HanaServer!)
.OrderBy(x => x.Id)
.FirstOrDefault();
if (linkedServer is not null)
{
linkedServer.SourceSystem = sourceSystem;
if (string.IsNullOrWhiteSpace(linkedServer.Name))
linkedServer.Name = sourceSystem;
changed = true;
continue;
}
db.HanaServers.Add(new HanaServer
{
SourceSystem = sourceSystem,
Name = sourceSystem,
Host = string.Empty,
Port = 30015,
Username = string.Empty,
Password = string.Empty,
DatabaseName = string.Empty,
AdditionalParams = string.Empty
});
changed = true;
}
if (changed)
db.SaveChanges();
}
private static void EnsureSourceSystemDefinitions(AppDbContext db)
{
var defaults = new[]
{
new SourceSystemDefinition { Code = "SAP", DisplayName = "SAP", ConnectionKind = SourceSystemConnectionKinds.SapGateway, IsActive = true },
new SourceSystemDefinition { Code = "BI1", DisplayName = "BI1", ConnectionKind = SourceSystemConnectionKinds.Hana, IsActive = true },
new SourceSystemDefinition { Code = "SAGE", DisplayName = "SAGE", ConnectionKind = SourceSystemConnectionKinds.Hana, IsActive = true },
new SourceSystemDefinition { Code = "MANUAL_EXCEL", DisplayName = "Manual Excel", ConnectionKind = SourceSystemConnectionKinds.ManualExcel, IsActive = true }
};
var existing = db.SourceSystemDefinitions.ToList();
var changed = false;
foreach (var item in defaults)
{
var current = existing.FirstOrDefault(x => x.Code == item.Code);
if (current is null)
{
db.SourceSystemDefinitions.Add(item);
existing.Add(item);
changed = true;
continue;
}
if (string.IsNullOrWhiteSpace(current.DisplayName))
{
current.DisplayName = item.DisplayName;
changed = true;
}
if (string.IsNullOrWhiteSpace(current.ConnectionKind))
{
current.ConnectionKind = item.ConnectionKind;
changed = true;
}
if (string.IsNullOrWhiteSpace(current.CentralServiceUrl) &&
string.Equals(current.ConnectionKind, SourceSystemConnectionKinds.SapGateway, StringComparison.OrdinalIgnoreCase))
{
var sapSite = db.Sites
.Where(x => x.SourceSystem == current.Code && !string.IsNullOrWhiteSpace(x.SapServiceUrl))
.OrderBy(x => x.Id)
.FirstOrDefault();
if (sapSite is not null)
{
current.CentralServiceUrl = sapSite.SapServiceUrl;
changed = true;
}
}
}
if (changed)
db.SaveChanges();
}
}
@@ -65,13 +65,19 @@ public class SiteExportService : ISiteExportService
var spConfig = await db.SharePointConfigs.FirstOrDefaultAsync();
var outputDir = ResolveSiteOutputDirectory(settings, site);
var sourceSystem = NormalizeSourceSystem(site.SourceSystem);
var sourceDefinition = await db.SourceSystemDefinitions
.AsNoTracking()
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(x => x.Code == sourceSystem)
?? throw new InvalidOperationException($"Quellsystem '{sourceSystem}' ist nicht konfiguriert.");
var records = new List<SalesRecord>();
string filePath;
if (sourceSystem == "SAP")
if (string.Equals(sourceDefinition.ConnectionKind, SourceSystemConnectionKinds.SapGateway, StringComparison.OrdinalIgnoreCase))
{
var credentials = ResolveCredentials(site, settings, sourceSystem);
if (string.IsNullOrWhiteSpace(site.SapServiceUrl))
var credentials = ResolveCredentials(site, sourceDefinition);
var sapServiceUrl = ResolveSapServiceUrl(site, sourceDefinition);
if (string.IsNullOrWhiteSpace(sapServiceUrl))
throw new InvalidOperationException($"Standort '{site.Land}' hat keine SAP Service URL.");
var sapSources = await db.SapSourceDefinitions.Where(s => s.SiteId == site.Id).ToListAsync();
var sapJoins = await db.SapJoinDefinitions.Where(j => j.SiteId == site.Id).ToListAsync();
@@ -84,7 +90,8 @@ public class SiteExportService : ISiteExportService
updateStatus?.Invoke("SAP Quellen laden...");
await _appEventLogService.WriteAsync("Export", "SAP Quellen laden", siteId: site.Id, land: site.Land,
details: $"Sources={sapSources.Count} | Mappings={sapMappings.Count}");
records = await _sapCompositionService.BuildSalesRecordsAsync(site, sapSources, sapJoins, sapMappings, credentials.Username, credentials.Password);
var effectiveSite = CloneSiteWithSapServiceUrl(site, sapServiceUrl);
records = await _sapCompositionService.BuildSalesRecordsAsync(effectiveSite, sapSources, sapJoins, sapMappings, credentials.Username, credentials.Password);
updateStatus?.Invoke("Transformationen anwenden...");
await _appEventLogService.WriteAsync("Export", "Transformationen anwenden", siteId: site.Id, land: site.Land,
details: $"Records vor Transformation={records.Count}");
@@ -99,7 +106,7 @@ public class SiteExportService : ISiteExportService
filePath = _excelService.CreateExcelFile(outputDir, site.TSC, DateTime.UtcNow.Date, records);
log.RowCount = records.Count;
}
else if (sourceSystem == "MANUAL_EXCEL")
else if (string.Equals(sourceDefinition.ConnectionKind, SourceSystemConnectionKinds.ManualExcel, StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrWhiteSpace(site.ManualImportFilePath))
throw new InvalidOperationException($"Standort '{site.Land}' hat keine manuelle Excel-Datei.");
@@ -125,7 +132,7 @@ public class SiteExportService : ISiteExportService
}
else
{
var exportServer = BuildEffectiveServer(site, settings, sourceSystem);
var exportServer = await BuildEffectiveServerAsync(db, site, sourceDefinition);
updateStatus?.Invoke("HANA Abfrage...");
await _appEventLogService.WriteAsync("Export", "HANA Abfrage gestartet", siteId: site.Id, land: site.Land,
details: exportServer.GetConnectionStringPreview());
@@ -208,45 +215,40 @@ public class SiteExportService : ISiteExportService
}
}
private static HanaServer BuildEffectiveServer(Site site, ExportSettings settings, string sourceSystem)
private static async Task<HanaServer> BuildEffectiveServerAsync(AppDbContext db, Site site, SourceSystemDefinition sourceDefinition)
{
if (site.HanaServer is null)
throw new InvalidOperationException($"Standort '{site.Land}' hat keinen HANA-Server.");
var centralServer = await db.HanaServers
.AsNoTracking()
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(x => x.SourceSystem == sourceDefinition.Code);
var credentials = ResolveCredentials(site, settings, sourceSystem);
if (centralServer is null)
throw new InvalidOperationException($"Fuer Quellsystem '{sourceDefinition.Code}' ist keine zentrale HANA-Konfiguration vorhanden.");
var credentials = ResolveCredentials(site, sourceDefinition);
return new HanaServer
{
Id = site.HanaServer.Id,
Name = site.HanaServer.Name,
Host = site.HanaServer.Host,
Port = site.HanaServer.Port,
Username = FirstNonEmpty(credentials.Username, site.HanaServer.Username),
Password = FirstNonEmpty(credentials.Password, site.HanaServer.Password),
DatabaseName = site.HanaServer.DatabaseName,
UseSsl = site.HanaServer.UseSsl,
ValidateCertificate = site.HanaServer.ValidateCertificate,
AdditionalParams = site.HanaServer.AdditionalParams
Id = centralServer.Id,
SourceSystem = centralServer.SourceSystem,
Name = centralServer.Name,
Host = centralServer.Host,
Port = centralServer.Port,
Username = credentials.Username,
Password = credentials.Password,
DatabaseName = centralServer.DatabaseName,
UseSsl = centralServer.UseSsl,
ValidateCertificate = centralServer.ValidateCertificate,
AdditionalParams = centralServer.AdditionalParams
};
}
private static (string Username, string Password) ResolveCredentials(Site site, ExportSettings settings, string sourceSystem)
=> (FirstNonEmpty(site.UsernameOverride, GetCentralUsername(sourceSystem, settings)),
FirstNonEmpty(site.PasswordOverride, GetCentralPassword(sourceSystem, settings)));
private static (string Username, string Password) ResolveCredentials(Site site, SourceSystemDefinition sourceDefinition)
=> (FirstNonEmpty(site.UsernameOverride, sourceDefinition.CentralUsername),
FirstNonEmpty(site.PasswordOverride, sourceDefinition.CentralPassword));
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 ResolveSapServiceUrl(Site site, SourceSystemDefinition sourceDefinition)
=> FirstNonEmpty(site.SapServiceUrl, sourceDefinition.CentralServiceUrl);
private static string NormalizeSourceSystem(string? sourceSystem)
=> string.IsNullOrWhiteSpace(sourceSystem) ? "SAP" : sourceSystem.Trim().ToUpperInvariant();
@@ -269,4 +271,28 @@ public class SiteExportService : ISiteExportService
? Path.Combine(AppContext.BaseDirectory, "output")
: configured;
}
private static Site CloneSiteWithSapServiceUrl(Site site, string sapServiceUrl)
{
return new Site
{
Id = site.Id,
HanaServerId = site.HanaServerId,
HanaServer = site.HanaServer,
Schema = site.Schema,
TSC = site.TSC,
Land = site.Land,
SourceSystem = site.SourceSystem,
UsernameOverride = site.UsernameOverride,
PasswordOverride = site.PasswordOverride,
LocalExportFolderOverride = site.LocalExportFolderOverride,
ManualImportFilePath = site.ManualImportFilePath,
ManualImportLastUploadedAtUtc = site.ManualImportLastUploadedAtUtc,
SapServiceUrl = sapServiceUrl,
SapEntitySet = site.SapEntitySet,
SapEntitySetsCache = site.SapEntitySetsCache,
SapEntitySetsRefreshedAtUtc = site.SapEntitySetsRefreshedAtUtc,
IsActive = site.IsActive
};
}
}