using Admin.NET.Plugin.AiDOP.DataPlatform.MdpRebuild;
using Microsoft.Extensions.Logging;
namespace Admin.NET.Plugin.AiDOP.DataPlatform.Inbound;
///
/// 入站成功后按实体触发模块重建。映射为显式静态表;未登记实体记 Warning 不阻断接收。
///
public sealed class MdpInboundModuleTrigger : ITransient
{
// 方案 §7.7:MDM 不属任何单一模块,推送成功后触发所有依赖模块
private static readonly IReadOnlyDictionary EntityModuleMap =
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
["MDM_ITEM"] = ["S1", "S2", "S3", "S5", "S6"],
["MDM_CUSTOMER"] = ["S1"],
["MDM_SUPPLIER"] = ["S3", "S4", "S5"],
["MDM_SOURCE_LIST"] = ["S3"],
["MDM_LOCATION"] = ["S5", "S7"],
["MDM_EMPLOYEE_HEADCOUNT"] = ["S9"]
};
private readonly ModuleRebuildService _rebuild;
private readonly ILogger _logger;
public MdpInboundModuleTrigger(ModuleRebuildService rebuild, ILogger logger)
{
_rebuild = rebuild;
_logger = logger;
}
///
/// 任一模块 202 入队或 409 去抖视为已加急。异常不抛给接收方。
/// factoryId:Rebuild 要求 >0 且 ≠ tenantId,任务书字面 0 无法入队;grant 绑工厂优先生效,否则回落 1(与看板刷新一致)。
///
public async Task EnqueueForEntityAsync(
string entityCode, long tenantId, long? grantFactoryId, CancellationToken ct)
{
var modules = ResolveModules(entityCode);
if (modules.Count == 0)
return false;
var factoryId = ResolveFactoryId(tenantId, grantFactoryId);
var enqueued = false;
foreach (var module in modules)
{
if (string.Equals(module, "S9", StringComparison.OrdinalIgnoreCase))
{
_logger.LogInformation("inbound trigger skip S9 (no rebuild handler) entity={Entity}", entityCode);
continue;
}
if (!MdpRebuildScope.RebuildModules.Contains(module))
{
_logger.LogWarning("inbound trigger skip unregistered module {Module} entity={Entity}", module, entityCode);
continue;
}
try
{
var (status, body) = await _rebuild.EnqueueAsync(
module, tenantId, factoryId, requestedBy: null, triggerType: "INBOUND", ct);
if (status == 202)
{
enqueued = true;
_logger.LogInformation(
"inbound trigger queued module={Module} entity={Entity} job={Job} tenant={Tenant} factory={Factory}",
module, entityCode, body.JobId, tenantId, factoryId);
}
else if (status == 409)
{
enqueued = true;
_logger.LogInformation(
"inbound trigger debounce module={Module} entity={Entity} status=409 {Message}",
module, entityCode, body.Message);
}
else
{
_logger.LogWarning(
"inbound trigger not accepted module={Module} entity={Entity} status={Status} {Message}",
module, entityCode, status, body.Message);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "inbound trigger failed module={Module} entity={Entity}", module, entityCode);
}
}
return enqueued;
}
private List ResolveModules(string entityCode)
{
if (string.IsNullOrWhiteSpace(entityCode))
return [];
if (EntityModuleMap.TryGetValue(entityCode, out var mapped))
return mapped.ToList();
var prefix = entityCode.Trim();
var us = prefix.IndexOf('_');
if (us > 0)
prefix = prefix[..us];
prefix = prefix.ToUpperInvariant();
if (MdpRebuildScope.RebuildModules.Contains(prefix))
return [prefix];
_logger.LogWarning("inbound trigger: entity {Entity} not in map and prefix {Prefix} is not a rebuild module",
entityCode, prefix);
return [];
}
private static long ResolveFactoryId(long tenantId, long? grantFactoryId)
{
if (grantFactoryId is > 0 && grantFactoryId.Value != tenantId)
return grantFactoryId.Value;
return 1;
}
}