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