namespace Admin.NET.Plugin.AiDOP.Supply;
/// S4 采购闭环后读路径一致性检查(运行表 vs DWD)。
public class S4ReadPathConsistencyService : ITransient
{
private readonly ISqlSugarClient _db;
public S4ReadPathConsistencyService(ISqlSugarClient db)
{
_db = db;
}
public async Task CheckTenantAsync(long tenantId)
{
var runtimePr = await CountAsync(
"""
SELECT COUNT(*) FROM srm_pr_main
WHERE tenant_id = @TenantId AND IFNULL(IsDeleted, 0) = 0
""",
tenantId);
var runtimePo = await CountAsync(
"""
SELECT COUNT(*) FROM PurOrdMaster
WHERE tenant_id = @TenantId AND IFNULL(IsActive, 1) = 1
""",
tenantId);
var runtimeDelivery = await CountAsync(
"""
SELECT COUNT(*) FROM srm_polist_ds
WHERE tenant_id = @TenantId AND IFNULL(isactive, 1) = 1
""",
tenantId);
var dwdExecution = await SafeCountAsync(
"""
SELECT COUNT(*) FROM dwd_s4_purchase_execution
WHERE tenant_id = @TenantId
""",
tenantId);
var dwdPoTrans = await SafeCountAsync(
"""
SELECT COUNT(*) FROM dwd_po_trans
WHERE tenant_id = @TenantId
""",
tenantId);
var dwdDelivery = await SafeCountAsync(
"""
SELECT COUNT(*) FROM dwd_supplier_delivery
WHERE tenant_id = @TenantId
""",
tenantId);
var checks = new List
{
BuildCheck("runtime_pr", runtimePr, null, runtimePr >= 0),
BuildCheck("runtime_po", runtimePo, dwdPoTrans, dwdPoTrans is null || runtimePo <= dwdPoTrans + 50),
BuildCheck("runtime_delivery", runtimeDelivery, dwdDelivery, dwdDelivery is null || runtimeDelivery <= dwdDelivery + 50),
BuildCheck("dwd_purchase_execution", runtimePo, dwdExecution, dwdExecution is null || dwdExecution > 0 || runtimePo == 0)
};
return new S4ReadPathConsistencyResult
{
TenantId = tenantId,
Checks = checks,
Ok = checks.All(x => x.Ok)
};
}
private static S4ReadPathCheckItem BuildCheck(string name, int runtime, int? dwd, bool ok) =>
new()
{
Name = name,
RuntimeCount = runtime,
DwdCount = dwd,
Ok = ok
};
private async Task CountAsync(string sql, long tenantId) =>
await _db.Ado.GetIntAsync(sql, new SugarParameter("@TenantId", tenantId));
private async Task SafeCountAsync(string sql, long tenantId)
{
try
{
return await CountAsync(sql, tenantId);
}
catch
{
return null;
}
}
}
public sealed class S4ReadPathConsistencyResult
{
public long TenantId { get; set; }
public bool Ok { get; set; }
public List Checks { get; set; } = new();
}
public sealed class S4ReadPathCheckItem
{
public string Name { get; set; } = string.Empty;
public int RuntimeCount { get; set; }
public int? DwdCount { get; set; }
public bool Ok { get; set; }
}