namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting; /// /// IQC 来料检验结果 → WMS 入库路由的纯逻辑映射(C1 · 路线 B 服务化重写)。 /// /// 契约来源:dopdemorq 旧 LIVE 链真定义(**非死码 check 版**): /// 入口 dbo.qms_WMS_SaveIQCResult(5 个 (pd,clfs) 分支,逐分支转换 QCStatus/MRBStatus/QtyAcc/QtyReject) /// → dbo.pr_WMS_SaveIQCResult(据 @Barcodes=''/@Shelf='' 固定入参推导 PartRctFlag 与收货/过账门 L299)。 /// /// 本组件**只做纯逻辑**:输入 (pd, clfs, dhsl, bhgsl) → 输出判定/数量/路由。 /// 不触库、无副作用、可单测。运行期数据门(@IsRctTemp>0、#missedPrints 待过账明细是否存在) /// 不在此判定,交由 Service 层按真实数据校验;此处只给 (pd,clfs) 可纯判定的过账前置资格。 /// public static class IqcResultMapping { /// 合格判定值(qms_qcp_inspbill.pd = 0)。 public const int PdPass = 0; /// 不合格判定值(qms_qcp_inspbill.pd = 1)。 public const int PdFail = 1; /// /// 把 IQC 检验结果映射为 WMS 入库路由决策。旧入口 qms_WMS_SaveIQCResult 的 5 个平行分支: /// ① pd=0,clfs='' 合格·无处理 → YES/0 /// ② pd=0,clfs='3' 合格·挑选 → NO/1 /// ③ pd=1,clfs='0' 不良·退货 → NO/2 /// ④ pd=1,clfs='2' 不良·让步接收 → NO/3 /// ⑤ pd=1,clfs='3' 不良·挑选 → NO/1 /// 其余 (pd,clfs) 组合旧入口不动作 → Unmatched。 /// public static IqcResultMappingResult Map(IqcResultMappingInput input) { if (input == null) throw new ArgumentNullException(nameof(input)); var clfs = input.Clfs; var clfsEmpty = string.IsNullOrEmpty(clfs); var dhsl = input.Dhsl; var bhgsl = input.Bhgsl; // ① pd=0, clfs 为空 —— 来料合格·处理方式为空 if (input.Pd == PdPass && clfsEmpty) return Build(1, "合格·无处理", "YES", 0, dhsl, 0m); // ② pd=0, clfs='3' —— 合格·挑选使用 if (input.Pd == PdPass && clfs == "3") return Build(2, "合格·挑选使用", "NO", 1, dhsl, bhgsl); // ③ pd=1, clfs='0' —— 不良·退货 if (input.Pd == PdFail && clfs == "0") return Build(3, "不良·退货", "NO", 2, 0m, dhsl + bhgsl); // ④ pd=1, clfs='2' —— 不良·让步接收 if (input.Pd == PdFail && clfs == "2") return Build(4, "不良·让步接收", "NO", 3, dhsl + bhgsl, 0m); // ⑤ pd=1, clfs='3' —— 不良·挑选 if (input.Pd == PdFail && clfs == "3") return Build(5, "不良·挑选", "NO", 1, dhsl, bhgsl); // 其余组合:旧入口无匹配分支,不动作 return new IqcResultMappingResult { Matched = false, BranchNo = 0, BranchSemantics = "无匹配分支(旧入口不动作)", QcStatus = null, MrbStatus = 0, QtyAcc = 0m, QtyReject = 0m, PartRctFlag = 0, RoutingKind = IqcRoutingKind.Unmatched, EntersReceiptOrchestration = false, EntersInventoryPosting = false, }; } private static IqcResultMappingResult Build( int branchNo, string semantics, string qcStatus, int mrbStatus, decimal qtyAcc, decimal qtyReject) { // PartRctFlag 推导(pr_WMS_SaveIQCResult L49-71,固定 @Barcodes=''): // QCStatus='NO' 且 MRBStatus=1 → PartRctFlag=1(Barcodes 非空才会是 2,本入口路径恒非 2) // 其余 → PartRctFlag=0 var partRctFlag = (qcStatus == "NO" && mrbStatus == 1) ? 1 : 0; // 收货编排/库存过账门(pr_WMS_SaveIQCResult L299:@IsRctTemp>0 && @QtyAcc>0 && @RctDetails<>'') // 可纯逻辑判定部分 = PartRctFlag==0 && QtyAcc>0;运行期数据门(IsRctTemp/RctDetails)由 Service 层校验。 var entersPosting = partRctFlag == 0 && qtyAcc > 0m; IqcRoutingKind routing; if (partRctFlag == 1) routing = IqcRoutingKind.MrbChooseMobileTask; // 分支 ②⑤:挑选 → PurOrdRctByMRBChoose 移动任务,不过账 else if (entersPosting) routing = IqcRoutingKind.FullReceiptPosting; // 分支 ①④:收货编排 + 库存过账 else routing = IqcRoutingKind.ReturnOnly; // 分支 ③:退货标记,不过账 return new IqcResultMappingResult { Matched = true, BranchNo = branchNo, BranchSemantics = semantics, QcStatus = qcStatus, MrbStatus = mrbStatus, QtyAcc = qtyAcc, QtyReject = qtyReject, PartRctFlag = partRctFlag, RoutingKind = routing, EntersReceiptOrchestration = entersPosting, EntersInventoryPosting = entersPosting, }; } }