using Admin.NET.Plugin.ApprovalFlow;
using Admin.NET.Plugin.ApprovalFlow.Service;
namespace Admin.NET.Plugin.AiDOP.Manufacturing;
///
/// S6 Phase 1C 过程检验单审批流回调处理器(BizType=S6_PROCESS_INSPECTION)。
///
/// Handler 回调全部 no-op:不改写 Phase 1C 检验事实(ado_s6_process_inspection_result 仍是质量真源),
/// 不写 qms_gcjyd、不写库存/生产/仓储。审批状态由 ApprovalFlowInstance 承载。
/// GetBizData 返回 GW_RESULT 网关判据 disposition_required —— 直接由 Phase 1C overall_result 决定
/// (FAIL→1 进 N3 质量处置 / PASS→0 结束),**只读、不改写**质量结果(§20 质量结果与处置分离硬门)。
///
public class S6ProcessInspectionFlowBizHandler : IFlowBizHandler, ITransient
{
public string BizType => S6ProcessInspectionFlowConst.BizType;
private readonly ISqlSugarClient _db;
private readonly UserManager _userManager;
public S6ProcessInspectionFlowBizHandler(ISqlSugarClient db, UserManager userManager)
{
_db = db;
_userManager = userManager;
}
public Task OnFlowStarted(long bizId, long instanceId) => Task.CompletedTask;
public Task OnNodeCompleted(long bizId, long instanceId, string nodeId, string nodeName, long? approverUserId) => Task.CompletedTask;
public Task OnFlowCompleted(long bizId, long instanceId, FlowInstanceStatusEnum finalStatus, long? lastApproverId) => Task.CompletedTask;
/// 返回单据基础信息 + 网关判据 disposition_required(GW_RESULT 分流:FAIL==1→N3,PASS→end)。
public async Task> GetBizData(long bizId)
{
// 强制租户隔离:GetBizData 在流程审批 HTTP 请求上下文内被调用,裸 SQL 显式按当前登录租户过滤。
var tid = _userManager.TenantId;
var rows = await _db.Ado.SqlQueryAsync(
"""
SELECT b.work_order_no AS WorkOrderNo, b.item_code AS ItemCode, b.item_name AS ItemName,
r.overall_result AS OverallResult, r.status AS ResultStatus
FROM ado_s6_process_inspection_bill b
LEFT JOIN ado_s6_process_inspection_result r ON r.bill_id=b.id AND r.tenant_id=b.tenant_id
WHERE b.id=@id AND b.tenant_id=@tid LIMIT 1
""",
new List { new("@id", bizId), new("@tid", tid) });
var r = rows.FirstOrDefault();
// 网关判据:overall_result=FAIL → 需质量处置(1);否则(PASS/其它) → 0 直接结束。只读,不回写。
var dispositionRequired = string.Equals(r?.OverallResult, S6ProcessInspectionFlowConst.ResultFail, StringComparison.OrdinalIgnoreCase) ? 1 : 0;
if (r == null)
return new Dictionary { ["disposition_required"] = dispositionRequired };
return new Dictionary
{
["workOrderNo"] = r.WorkOrderNo ?? "",
["itemCode"] = r.ItemCode ?? "",
["itemName"] = r.ItemName ?? "",
["overallResult"] = r.OverallResult ?? "",
["disposition_required"] = dispositionRequired,
};
}
private class S6PiFlowBizData
{
public string? WorkOrderNo { get; set; }
public string? ItemCode { get; set; }
public string? ItemName { get; set; }
public string? OverallResult { get; set; }
public string? ResultStatus { get; set; }
}
}