Files
Ai/TrafagSalesExporter/Services/DataSources/SapGatewayDataSourceAdapter.cs
Claude 82ac7df0ec DataSourceAdapter-Pattern + SiteExportService schlanker + Page-Services Scoped
- IDataSourceAdapter mit 3 Implementierungen (HANA, SAP_GATEWAY, MANUAL_EXCEL)
  und DataSourceAdapterResolver ersetzen das if/else auf ConnectionKind.
- SiteExportService von 338 auf 187 Zeilen reduziert: Pipeline
  Resolve -> Fetch -> Transform -> Excel -> Central -> SharePoint.
- Page-Services auf Scoped (per Blazor-Circuit); Orchestrator bleibt Singleton
  fuer geteilten Export-Status.
2026-04-17 12:11:35 +00:00

82 lines
3.5 KiB
C#

using Microsoft.EntityFrameworkCore;
using TrafagSalesExporter.Data;
using TrafagSalesExporter.Models;
namespace TrafagSalesExporter.Services.DataSources;
public sealed class SapGatewayDataSourceAdapter : IDataSourceAdapter
{
private readonly IDbContextFactory<AppDbContext> _dbFactory;
private readonly ISapCompositionService _sapCompositionService;
private readonly IAppEventLogService _appEventLogService;
public SapGatewayDataSourceAdapter(
IDbContextFactory<AppDbContext> dbFactory,
ISapCompositionService sapCompositionService,
IAppEventLogService appEventLogService)
{
_dbFactory = dbFactory;
_sapCompositionService = sapCompositionService;
_appEventLogService = appEventLogService;
}
public string ConnectionKind => SourceSystemConnectionKinds.SapGateway;
public async Task<DataSourceFetchResult> FetchAsync(DataSourceFetchContext context)
{
var site = context.Site;
var sourceDefinition = context.SourceDefinition;
var credentials = DataSourceCredentials.Resolve(site, sourceDefinition);
var sapServiceUrl = DataSourceCredentials.ResolveSapServiceUrl(site, sourceDefinition);
if (string.IsNullOrWhiteSpace(sapServiceUrl))
throw new InvalidOperationException($"Standort '{site.Land}' hat keine SAP Service URL.");
using var db = await _dbFactory.CreateDbContextAsync();
var sapSources = await db.SapSourceDefinitions.Where(s => s.SiteId == site.Id).ToListAsync();
var sapJoins = await db.SapJoinDefinitions.Where(j => j.SiteId == site.Id).ToListAsync();
var sapMappings = await db.SapFieldMappings.Where(m => m.SiteId == site.Id).ToListAsync();
if (sapSources.Count == 0)
throw new InvalidOperationException($"Standort '{site.Land}' hat keine SAP-Quellen konfiguriert.");
if (sapMappings.Count == 0)
throw new InvalidOperationException($"Standort '{site.Land}' hat keine SAP-Feldmappings.");
context.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}");
var effectiveSite = CloneSiteWithSapServiceUrl(site, sapServiceUrl);
var records = await _sapCompositionService.BuildSalesRecordsAsync(
effectiveSite, sapSources, sapJoins, sapMappings,
credentials.Username, credentials.Password);
return new DataSourceFetchResult { Records = records };
}
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
};
}
}