Files
Ai/TrafagSalesExporter/Services/PurchasingDataSourcePageService.cs
T

241 lines
12 KiB
C#

using Microsoft.EntityFrameworkCore;
using TrafagSalesExporter.Data;
using TrafagSalesExporter.Models;
namespace TrafagSalesExporter.Services;
public sealed class PurchasingDataSourcePageService : IPurchasingDataSourcePageService
{
public const string PurchasingTsc = "PURCHASING_SAP";
private readonly IDbContextFactory<AppDbContext> _dbFactory;
private readonly ISapGatewayService _sapGatewayService;
public PurchasingDataSourcePageService(IDbContextFactory<AppDbContext> dbFactory, ISapGatewayService sapGatewayService)
{
_dbFactory = dbFactory;
_sapGatewayService = sapGatewayService;
}
public async Task<PurchasingDataSourceState> LoadAsync()
{
await using var db = await _dbFactory.CreateDbContextAsync();
await EnsureDefaultsAsync(db);
return await LoadStateAsync(db);
}
public async Task<PurchasingDataSourceState> SaveAsync(PurchasingDataSourceState state)
{
await using var db = await _dbFactory.CreateDbContextAsync();
var site = await GetOrCreateSiteAsync(db);
site.SapServiceUrl = state.Site.SapServiceUrl.Trim();
site.UsernameOverride = state.Site.UsernameOverride.Trim();
site.PasswordOverride = state.Site.PasswordOverride;
site.IsActive = state.Site.IsActive;
Replace(db, db.SapSourceDefinitions.Where(x => x.SiteId == site.Id), state.Sources.Select((x, i) => new SapSourceDefinition
{
SiteId = site.Id,
Alias = x.Alias.Trim(),
EntitySet = x.EntitySet.Trim(),
IsPrimary = x.IsPrimary,
IsActive = x.IsActive,
SortOrder = x.SortOrder == 0 ? i * 10 : x.SortOrder
}));
Replace(db, db.SapJoinDefinitions.Where(x => x.SiteId == site.Id), state.Joins.Select((x, i) => new SapJoinDefinition
{
SiteId = site.Id,
LeftAlias = x.LeftAlias.Trim(),
RightAlias = x.RightAlias.Trim(),
LeftKeys = x.LeftKeys.Trim(),
RightKeys = x.RightKeys.Trim(),
JoinType = string.IsNullOrWhiteSpace(x.JoinType) ? "Left" : x.JoinType.Trim(),
IsActive = x.IsActive,
SortOrder = x.SortOrder == 0 ? i * 10 : x.SortOrder
}));
Replace(db, db.SapFieldMappings.Where(x => x.SiteId == site.Id), state.Mappings.Select((x, i) => new SapFieldMapping
{
SiteId = site.Id,
TargetField = x.TargetField.Trim(),
SourceExpression = x.SourceExpression.Trim(),
IsRequired = x.IsRequired,
IsActive = x.IsActive,
SortOrder = x.SortOrder == 0 ? i * 10 : x.SortOrder
}));
await db.SaveChangesAsync();
return await LoadStateAsync(db);
}
public async Task<PurchasingDataSourceState> ResetDefaultsAsync()
{
await using var db = await _dbFactory.CreateDbContextAsync();
var site = await GetOrCreateSiteAsync(db);
db.SapSourceDefinitions.RemoveRange(db.SapSourceDefinitions.Where(x => x.SiteId == site.Id));
db.SapJoinDefinitions.RemoveRange(db.SapJoinDefinitions.Where(x => x.SiteId == site.Id));
db.SapFieldMappings.RemoveRange(db.SapFieldMappings.Where(x => x.SiteId == site.Id));
await db.SaveChangesAsync();
AddDefaultSources(db, site.Id);
AddDefaultJoins(db, site.Id);
AddDefaultMappings(db, site.Id);
await db.SaveChangesAsync();
return await LoadStateAsync(db);
}
public async Task<PageActionResult> TestConnectionAsync(PurchasingDataSourceState state)
{
await using var db = await _dbFactory.CreateDbContextAsync();
var sourceSystem = await db.SourceSystemDefinitions
.AsNoTracking()
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(x => x.Code == "SAP");
var serviceUrl = string.IsNullOrWhiteSpace(state.Site.SapServiceUrl)
? sourceSystem?.CentralServiceUrl ?? string.Empty
: state.Site.SapServiceUrl;
var username = string.IsNullOrWhiteSpace(state.Site.UsernameOverride)
? sourceSystem?.CentralUsername ?? string.Empty
: state.Site.UsernameOverride;
var password = string.IsNullOrWhiteSpace(state.Site.PasswordOverride)
? sourceSystem?.CentralPassword ?? string.Empty
: state.Site.PasswordOverride;
if (string.IsNullOrWhiteSpace(serviceUrl))
return PageActionResult.WarningResult("Keine SAP Service URL gepflegt.");
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
return PageActionResult.WarningResult("Keine SAP Gateway Zugangsdaten gepflegt.");
try
{
await _sapGatewayService.TestConnectionAsync(serviceUrl.Trim(), username.Trim(), password);
return PageActionResult.SuccessResult("SAP OData Verbindung erfolgreich.");
}
catch (Exception ex)
{
return PageActionResult.ErrorResult($"SAP OData Verbindung fehlgeschlagen: {ex.Message}");
}
}
private async Task<PurchasingDataSourceState> LoadStateAsync(AppDbContext db)
{
var site = await GetOrCreateSiteAsync(db);
var sourceSystem = await db.SourceSystemDefinitions
.AsNoTracking()
.OrderBy(x => x.Id)
.FirstOrDefaultAsync(x => x.Code == "SAP");
return new PurchasingDataSourceState
{
Site = Clone(site),
SourceSystem = sourceSystem,
Sources = await db.SapSourceDefinitions.AsNoTracking().Where(x => x.SiteId == site.Id).OrderBy(x => x.SortOrder).ThenBy(x => x.Id).ToListAsync(),
Joins = await db.SapJoinDefinitions.AsNoTracking().Where(x => x.SiteId == site.Id).OrderBy(x => x.SortOrder).ThenBy(x => x.Id).ToListAsync(),
Mappings = await db.SapFieldMappings.AsNoTracking().Where(x => x.SiteId == site.Id).OrderBy(x => x.SortOrder).ThenBy(x => x.Id).ToListAsync()
};
}
private static async Task EnsureDefaultsAsync(AppDbContext db)
{
var site = await GetOrCreateSiteAsync(db);
var hasSources = await db.SapSourceDefinitions.AnyAsync(x => x.SiteId == site.Id);
if (hasSources)
return;
AddDefaultSources(db, site.Id);
AddDefaultJoins(db, site.Id);
AddDefaultMappings(db, site.Id);
await db.SaveChangesAsync();
}
private static async Task<Site> GetOrCreateSiteAsync(AppDbContext db)
{
var site = await db.Sites.OrderBy(x => x.Id).FirstOrDefaultAsync(x => x.TSC == PurchasingTsc);
if (site is not null)
return site;
site = new Site
{
Schema = string.Empty,
TSC = PurchasingTsc,
Land = "Einkauf SAP",
SourceSystem = "SAP",
IsActive = false
};
db.Sites.Add(site);
await db.SaveChangesAsync();
return site;
}
private static void AddDefaultSources(AppDbContext db, int siteId)
{
db.SapSourceDefinitions.AddRange(
new SapSourceDefinition { SiteId = siteId, Alias = "EKKO", EntitySet = "EKKOSet", IsPrimary = true, IsActive = true, SortOrder = 10 },
new SapSourceDefinition { SiteId = siteId, Alias = "EKPO", EntitySet = "EKPOSet", IsPrimary = false, IsActive = true, SortOrder = 20 },
new SapSourceDefinition { SiteId = siteId, Alias = "EKET", EntitySet = "eketSet", IsPrimary = false, IsActive = true, SortOrder = 30 },
new SapSourceDefinition { SiteId = siteId, Alias = "LIEF", EntitySet = "Data", IsPrimary = false, IsActive = true, SortOrder = 40 },
new SapSourceDefinition { SiteId = siteId, Alias = "WG", EntitySet = "Data2", IsPrimary = false, IsActive = true, SortOrder = 50 });
}
private static void AddDefaultJoins(AppDbContext db, int siteId)
{
db.SapJoinDefinitions.AddRange(
new SapJoinDefinition { SiteId = siteId, LeftAlias = "EKKO", RightAlias = "EKPO", LeftKeys = "Ebeln", RightKeys = "Ebeln", JoinType = "Left", IsActive = true, SortOrder = 10 },
new SapJoinDefinition { SiteId = siteId, LeftAlias = "EKPO", RightAlias = "EKET", LeftKeys = "Ebeln,Ebelp", RightKeys = "Ebeln,Ebelp", JoinType = "Left", IsActive = true, SortOrder = 20 },
new SapJoinDefinition { SiteId = siteId, LeftAlias = "EKKO", RightAlias = "LIEF", LeftKeys = "Lifnr", RightKeys = "Lifnr", JoinType = "Left", IsActive = true, SortOrder = 30 },
new SapJoinDefinition { SiteId = siteId, LeftAlias = "EKPO", RightAlias = "WG", LeftKeys = "Matkl", RightKeys = "Matkl", JoinType = "Left", IsActive = true, SortOrder = 40 });
}
private static void AddDefaultMappings(AppDbContext db, int siteId)
{
db.SapFieldMappings.AddRange(
new SapFieldMapping { SiteId = siteId, TargetField = "PurchaseOrder", SourceExpression = "EKKO.Ebeln", IsRequired = true, IsActive = true, SortOrder = 10 },
new SapFieldMapping { SiteId = siteId, TargetField = "PurchaseOrderDate", SourceExpression = "EKKO.Bedat", IsRequired = true, IsActive = true, SortOrder = 20 },
new SapFieldMapping { SiteId = siteId, TargetField = "SupplierNumber", SourceExpression = "EKKO.Lifnr", IsRequired = false, IsActive = true, SortOrder = 30 },
new SapFieldMapping { SiteId = siteId, TargetField = "SupplierName", SourceExpression = "LIEF.Name", IsRequired = false, IsActive = true, SortOrder = 40 },
new SapFieldMapping { SiteId = siteId, TargetField = "Position", SourceExpression = "EKPO.Ebelp", IsRequired = true, IsActive = true, SortOrder = 50 },
new SapFieldMapping { SiteId = siteId, TargetField = "Material", SourceExpression = "EKPO.Matnr", IsRequired = false, IsActive = true, SortOrder = 60 },
new SapFieldMapping { SiteId = siteId, TargetField = "MaterialText", SourceExpression = "EKPO.Txz01", IsRequired = false, IsActive = true, SortOrder = 70 },
new SapFieldMapping { SiteId = siteId, TargetField = "MaterialGroup", SourceExpression = "EKPO.Matkl", IsRequired = false, IsActive = true, SortOrder = 80 },
new SapFieldMapping { SiteId = siteId, TargetField = "MaterialGroupText", SourceExpression = "WG.WgKomplett", IsRequired = false, IsActive = true, SortOrder = 90 },
new SapFieldMapping { SiteId = siteId, TargetField = "NetValueChf", SourceExpression = "EKPO.NetwrChf", IsRequired = false, IsActive = true, SortOrder = 100 },
new SapFieldMapping { SiteId = siteId, TargetField = "NetValueChfPerPiece", SourceExpression = "EKPO.NetwrChfStk", IsRequired = false, IsActive = true, SortOrder = 110 },
new SapFieldMapping { SiteId = siteId, TargetField = "OrderQuantity", SourceExpression = "EKPO.Menge", IsRequired = false, IsActive = true, SortOrder = 120 },
new SapFieldMapping { SiteId = siteId, TargetField = "ScheduleDate", SourceExpression = "EKET.Eindt", IsRequired = false, IsActive = true, SortOrder = 130 },
new SapFieldMapping { SiteId = siteId, TargetField = "ScheduleQuantity", SourceExpression = "EKET.Menge", IsRequired = false, IsActive = true, SortOrder = 140 });
}
private static void Replace<TEntity>(AppDbContext db, IQueryable<TEntity> oldRows, IEnumerable<TEntity> newRows)
where TEntity : class
{
var set = db.Set<TEntity>();
set.RemoveRange(oldRows);
set.AddRange(newRows);
}
private static Site Clone(Site site) => new()
{
Id = site.Id,
HanaServerId = site.HanaServerId,
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 = site.SapServiceUrl,
SapEntitySet = site.SapEntitySet,
SapEntitySetsCache = site.SapEntitySetsCache,
SapEntitySetsRefreshedAtUtc = site.SapEntitySetsRefreshedAtUtc,
IsActive = site.IsActive
};
}