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; } } }