using Admin.NET.Plugin.AiDOP.Entity.DataPlatform;
namespace Admin.NET.Plugin.AiDOP.DataPlatform;
///
/// 方式甲贴源完成后,复用标准 API 已有的通用贴源到中立层投影。
/// 未在 登记的实体为 no-op,
/// 仍由 S1-S7 原有模块转换处理。
///
public sealed class MdpDbSyncNeutralProjection : ITransient
{
private readonly ISqlSugarClient _db;
private readonly InboundNeutralProjectionService _projection;
public MdpDbSyncNeutralProjection(
ISqlSugarClient db,
InboundNeutralProjectionService projection)
{
_db = db;
_projection = projection;
}
public async Task ProjectAsync(
IEnumerable entities,
long tenantId,
CancellationToken cancellationToken = default)
{
if (tenantId <= 0)
throw new InvalidOperationException("方式甲中立层投影要求 tenantId 大于 0");
var list = entities
.GroupBy(x => x.EntityCode, StringComparer.OrdinalIgnoreCase)
.Select(x => x.OrderByDescending(e => e.TenantId).First())
.ToList();
var sourceIds = list.Select(x => x.SourceId).Distinct().ToList();
var sources = await _db.Queryable()
.Where(x => sourceIds.Contains(x.Id))
.ToListAsync(cancellationToken);
var sourceById = sources.ToDictionary(x => x.Id);
foreach (var entity in list)
{
cancellationToken.ThrowIfCancellationRequested();
if (!sourceById.TryGetValue(entity.SourceId, out var source))
throw new InvalidOperationException($"实体 {entity.EntityCode} 的数据源不存在");
var neutral = MdpSourceIdentity.NeutralCode(source.SystemCode, source.SourceCode);
var routes = new[] { entity.EntityCode, entity.TransformSourceTable }
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x!.Trim())
.Distinct(StringComparer.OrdinalIgnoreCase);
foreach (var route in routes)
{
await _projection.ProjectAsync(
route,
tenantId,
neutral,
MdpSourceIdentity.DbSync,
cancellationToken);
}
}
}
}