namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto; // ════════════════════════════════════════════════════════════════════════════ // S5 IQC 项目级结果(Batch 3)读写契约 // // 读:GET /api/S5IqcInspBill/detail 的 lines[] / lineSummary / canEdit(纯加法) // 写:POST /api/S5IqcInspection/save-detail // // 后端派生 / 审计字段(前端一律不得 author,传了也被忽略): // sampleNumeric · sample.judgement · itemJudgement · judgementSource // inspectorId · inspectionTime · lastResultBy · lastResultAt · tenantId // ════════════════════════════════════════════════════════════════════════════ /// /// 检验单项目实例(检规快照 + 项目级结果)——Detail lines[] 的行。 /// 快照字段组生成后不可变;结果字段组仅 N1 可编辑态可写。 /// public class IqcInspBillItemLineRow { /// 项目实例主键(save-detail 回传用) public long Id { get; set; } /// 展示序号(快照自 qms_jygfzb.xh,可空可重复,不作键) public int? Seq { get; set; } // ── 来源追溯(仅 lineage,允许悬挂,前端不展示)── public long SourceSpecId { get; set; } public long SourceSpecItemId { get; set; } // ── 检规快照(只读,永不回查 S0)── public string? InspectionItem { get; set; } public string? InspectionStandard { get; set; } public string? MethodTool { get; set; } public string? ImageCategory { get; set; } public string? SamplingScheme { get; set; } public string? SpecRemark { get; set; } public string? UpperLimit { get; set; } public string? LowerLimit { get; set; } // ── 项目级结果 ── /// NUMERIC / NON_NUMERIC;NULL = 未定(合法初态,由 N1 首次录入时选定) public string? ResultType { get; set; } /// PASS / FAIL / INVALID;NULL = 未录。后端唯一写入方 public string? ItemJudgement { get; set; } /// AUTO / MANUAL;测量事实变更即强制复位为 AUTO public string? JudgementSource { get; set; } /// NON_NUMERIC 的测量真源之一;NUMERIC 恒为 NULL public decimal? QualifiedQty { get; set; } /// NON_NUMERIC 的测量真源之一;NUMERIC 恒为 NULL public decimal? UnqualifiedQty { get; set; } public string? ResultRemark { get; set; } public long? LastResultBy { get; set; } public DateTime? LastResultAt { get; set; } /// NUMERIC 的测量真源;NON_NUMERIC 恒为空数组 public List Samples { get; set; } = []; } /// 逐样本实测值(仅 NUMERIC 使用)。 public class IqcInspBillItemSampleRow { public long Id { get; set; } public int SampleIndex { get; set; } /// 检验员录入原文(原样保留,供 INVALID 复盘) public string? SampleValueRaw { get; set; } /// 后端解析值;不可解析 = NULL(不丢原文) public decimal? SampleNumeric { get; set; } /// PASS / FAIL / INVALID;后端唯一写入方 public string? Judgement { get; set; } public string? Remark { get; set; } public long? InspectorId { get; set; } public DateTime? InspectionTime { get; set; } } /// /// 项目级结果汇总(后端实时聚合,不落表)。 /// itemCount = 0 时全部为 0(LEGACY MODE:历史单 / NO_SPEC 新单 / MATCHED+0 明细新单同一语义)。 /// public class IqcInspBillLineSummary { /// 项目实例总数;0 ⇒ LEGACY MODE public int ItemCount { get; set; } /// 已给出 PASS/FAIL 的项目数(可提交口径) public int JudgedCount { get; set; } public int PassCount { get; set; } public int FailCount { get; set; } public int InvalidCount { get; set; } /// itemJudgement 为 NULL 的项目数 public int UnjudgedCount { get; set; } } // ────────────────────────────── save-detail 入参 ────────────────────────────── /// /// 保存项目级检验结果(草稿,**不推进流程**)。 /// item 级增量:未出现在 items 中的项目完全不动。 /// item 内样本全量替换:携带的 samples 即该项目的完整新集合。 /// public class IqcSaveDetailInput { /// 检验单 id(qms_qcp_inspbill.id) public long BillId { get; set; } public List Items { get; set; } = []; } /// 单个项目的结果入参。 public class IqcSaveDetailItemInput { /// 项目实例 id;必须属当前租户 + 当前 bill,否则整单 400 public long ItemId { get; set; } /// /// 录入类型 NUMERIC / NON_NUMERIC。 /// 与库中现值不同(含 NULL→非 NULL)视为类型切换,会清空该项目的全部旧测量事实。 /// 不传(null)表示沿用库中现值。 /// public string? ResultType { get; set; } /// NON_NUMERIC 测量真源;NUMERIC 传值 → 400(禁双真源) public decimal? QualifiedQty { get; set; } /// NON_NUMERIC 测量真源;NUMERIC 传值 → 400(禁双真源) public decimal? UnqualifiedQty { get; set; } public string? ResultRemark { get; set; } /// /// 人工判定,仅允许 PASS / FAIL(不得人工设 INVALID)。 /// 传值 ⇒ judgementSource=MANUAL;不传 ⇒ 按测量真源 AUTO 重算。 /// public string? ManualJudgement { get; set; } /// /// NUMERIC 测量真源,**该项目的完整新集合**(未出现的旧样本会被删除)。 /// NON_NUMERIC 携带 → 400。 /// public List? Samples { get; set; } } /// 单个样本入参。 public class IqcSaveDetailSampleInput { /// 样本序号,必须 >= 1 且在同一项目内不重复 public int SampleIndex { get; set; } /// 录入原文,非空(空值语义 = 该样本不存在 ⇒ 请从数组中移除,而不是传空串) public string? SampleValueRaw { get; set; } public string? Remark { get; set; } } // ────────────────────────────── save-detail 出参 ────────────────────────────── /// 保存结果。回传受影响项目的最终判定与实时汇总,供前端免二次拉取。 public class IqcSaveDetailOutput { public bool Ok { get; set; } = true; /// 本次实际更新的项目数 public int SavedItems { get; set; } /// 本次写入的样本行数 public int SavedSamples { get; set; } /// 本次删除的样本行数(含类型切换清理与全量替换剪枝) public int DeletedSamples { get; set; } /// 因类型切换而清空过测量事实的项目 id public List ClearedByTypeChange { get; set; } = []; /// 因测量事实变更而被作废的旧 MANUAL 判定所属项目 id public List ManualInvalidated { get; set; } = []; public IqcInspBillLineSummary LineSummary { get; set; } = new(); /// 本次涉及项目的最终结果(含重算后的 judgement / source) public List Items { get; set; } = []; }