IqcResultMapping.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.InventoryPosting;
  2. /// <summary>
  3. /// IQC 来料检验结果 → WMS 入库路由的纯逻辑映射(C1 · 路线 B 服务化重写)。
  4. ///
  5. /// 契约来源:dopdemorq 旧 LIVE 链真定义(**非死码 check 版**):
  6. /// 入口 dbo.qms_WMS_SaveIQCResult(5 个 (pd,clfs) 分支,逐分支转换 QCStatus/MRBStatus/QtyAcc/QtyReject)
  7. /// → dbo.pr_WMS_SaveIQCResult(据 @Barcodes=''/@Shelf='' 固定入参推导 PartRctFlag 与收货/过账门 L299)。
  8. ///
  9. /// 本组件**只做纯逻辑**:输入 (pd, clfs, dhsl, bhgsl) → 输出判定/数量/路由。
  10. /// 不触库、无副作用、可单测。运行期数据门(@IsRctTemp>0、#missedPrints 待过账明细是否存在)
  11. /// 不在此判定,交由 Service 层按真实数据校验;此处只给 (pd,clfs) 可纯判定的过账前置资格。
  12. /// </summary>
  13. public static class IqcResultMapping
  14. {
  15. /// <summary>合格判定值(qms_qcp_inspbill.pd = 0)。</summary>
  16. public const int PdPass = 0;
  17. /// <summary>不合格判定值(qms_qcp_inspbill.pd = 1)。</summary>
  18. public const int PdFail = 1;
  19. /// <summary>
  20. /// 把 IQC 检验结果映射为 WMS 入库路由决策。旧入口 qms_WMS_SaveIQCResult 的 5 个平行分支:
  21. /// ① pd=0,clfs='' 合格·无处理 → YES/0
  22. /// ② pd=0,clfs='3' 合格·挑选 → NO/1
  23. /// ③ pd=1,clfs='0' 不良·退货 → NO/2
  24. /// ④ pd=1,clfs='2' 不良·让步接收 → NO/3
  25. /// ⑤ pd=1,clfs='3' 不良·挑选 → NO/1
  26. /// 其余 (pd,clfs) 组合旧入口不动作 → Unmatched。
  27. /// </summary>
  28. public static IqcResultMappingResult Map(IqcResultMappingInput input)
  29. {
  30. if (input == null) throw new ArgumentNullException(nameof(input));
  31. var clfs = input.Clfs;
  32. var clfsEmpty = string.IsNullOrEmpty(clfs);
  33. var dhsl = input.Dhsl;
  34. var bhgsl = input.Bhgsl;
  35. // ① pd=0, clfs 为空 —— 来料合格·处理方式为空
  36. if (input.Pd == PdPass && clfsEmpty)
  37. return Build(1, "合格·无处理", "YES", 0, dhsl, 0m);
  38. // ② pd=0, clfs='3' —— 合格·挑选使用
  39. if (input.Pd == PdPass && clfs == "3")
  40. return Build(2, "合格·挑选使用", "NO", 1, dhsl, bhgsl);
  41. // ③ pd=1, clfs='0' —— 不良·退货
  42. if (input.Pd == PdFail && clfs == "0")
  43. return Build(3, "不良·退货", "NO", 2, 0m, dhsl + bhgsl);
  44. // ④ pd=1, clfs='2' —— 不良·让步接收
  45. if (input.Pd == PdFail && clfs == "2")
  46. return Build(4, "不良·让步接收", "NO", 3, dhsl + bhgsl, 0m);
  47. // ⑤ pd=1, clfs='3' —— 不良·挑选
  48. if (input.Pd == PdFail && clfs == "3")
  49. return Build(5, "不良·挑选", "NO", 1, dhsl, bhgsl);
  50. // 其余组合:旧入口无匹配分支,不动作
  51. return new IqcResultMappingResult
  52. {
  53. Matched = false,
  54. BranchNo = 0,
  55. BranchSemantics = "无匹配分支(旧入口不动作)",
  56. QcStatus = null,
  57. MrbStatus = 0,
  58. QtyAcc = 0m,
  59. QtyReject = 0m,
  60. PartRctFlag = 0,
  61. RoutingKind = IqcRoutingKind.Unmatched,
  62. EntersReceiptOrchestration = false,
  63. EntersInventoryPosting = false,
  64. };
  65. }
  66. private static IqcResultMappingResult Build(
  67. int branchNo, string semantics, string qcStatus, int mrbStatus, decimal qtyAcc, decimal qtyReject)
  68. {
  69. // PartRctFlag 推导(pr_WMS_SaveIQCResult L49-71,固定 @Barcodes=''):
  70. // QCStatus='NO' 且 MRBStatus=1 → PartRctFlag=1(Barcodes 非空才会是 2,本入口路径恒非 2)
  71. // 其余 → PartRctFlag=0
  72. var partRctFlag = (qcStatus == "NO" && mrbStatus == 1) ? 1 : 0;
  73. // 收货编排/库存过账门(pr_WMS_SaveIQCResult L299:@IsRctTemp>0 && @QtyAcc>0 && @RctDetails<>'')
  74. // 可纯逻辑判定部分 = PartRctFlag==0 && QtyAcc>0;运行期数据门(IsRctTemp/RctDetails)由 Service 层校验。
  75. var entersPosting = partRctFlag == 0 && qtyAcc > 0m;
  76. IqcRoutingKind routing;
  77. if (partRctFlag == 1)
  78. routing = IqcRoutingKind.MrbChooseMobileTask; // 分支 ②⑤:挑选 → PurOrdRctByMRBChoose 移动任务,不过账
  79. else if (entersPosting)
  80. routing = IqcRoutingKind.FullReceiptPosting; // 分支 ①④:收货编排 + 库存过账
  81. else
  82. routing = IqcRoutingKind.ReturnOnly; // 分支 ③:退货标记,不过账
  83. return new IqcResultMappingResult
  84. {
  85. Matched = true,
  86. BranchNo = branchNo,
  87. BranchSemantics = semantics,
  88. QcStatus = qcStatus,
  89. MrbStatus = mrbStatus,
  90. QtyAcc = qtyAcc,
  91. QtyReject = qtyReject,
  92. PartRctFlag = partRctFlag,
  93. RoutingKind = routing,
  94. EntersReceiptOrchestration = entersPosting,
  95. EntersInventoryPosting = entersPosting,
  96. };
  97. }
  98. }