IqcInspectionDto.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. namespace Admin.NET.Plugin.AiDOP.MaterialWarehouse.Dto;
  2. // ════════════════════════════════════════════════════════════════════════════
  3. // S5 IQC 项目级结果(Batch 3)读写契约
  4. //
  5. // 读:GET /api/S5IqcInspBill/detail 的 lines[] / lineSummary / canEdit(纯加法)
  6. // 写:POST /api/S5IqcInspection/save-detail
  7. //
  8. // 后端派生 / 审计字段(前端一律不得 author,传了也被忽略):
  9. // sampleNumeric · sample.judgement · itemJudgement · judgementSource
  10. // inspectorId · inspectionTime · lastResultBy · lastResultAt · tenantId
  11. // ════════════════════════════════════════════════════════════════════════════
  12. /// <summary>
  13. /// 检验单项目实例(检规快照 + 项目级结果)——Detail lines[] 的行。
  14. /// 快照字段组生成后不可变;结果字段组仅 N1 可编辑态可写。
  15. /// </summary>
  16. public class IqcInspBillItemLineRow
  17. {
  18. /// <summary>项目实例主键(save-detail 回传用)</summary>
  19. public long Id { get; set; }
  20. /// <summary>展示序号(快照自 qms_jygfzb.xh,可空可重复,不作键)</summary>
  21. public int? Seq { get; set; }
  22. // ── 来源追溯(仅 lineage,允许悬挂,前端不展示)──
  23. public long SourceSpecId { get; set; }
  24. public long SourceSpecItemId { get; set; }
  25. // ── 检规快照(只读,永不回查 S0)──
  26. public string? InspectionItem { get; set; }
  27. public string? InspectionStandard { get; set; }
  28. public string? MethodTool { get; set; }
  29. public string? ImageCategory { get; set; }
  30. public string? SamplingScheme { get; set; }
  31. public string? SpecRemark { get; set; }
  32. public string? UpperLimit { get; set; }
  33. public string? LowerLimit { get; set; }
  34. // ── 项目级结果 ──
  35. /// <summary>NUMERIC / NON_NUMERIC;NULL = 未定(合法初态,由 N1 首次录入时选定)</summary>
  36. public string? ResultType { get; set; }
  37. /// <summary>PASS / FAIL / INVALID;NULL = 未录。后端唯一写入方</summary>
  38. public string? ItemJudgement { get; set; }
  39. /// <summary>AUTO / MANUAL;测量事实变更即强制复位为 AUTO</summary>
  40. public string? JudgementSource { get; set; }
  41. /// <summary>NON_NUMERIC 的测量真源之一;NUMERIC 恒为 NULL</summary>
  42. public decimal? QualifiedQty { get; set; }
  43. /// <summary>NON_NUMERIC 的测量真源之一;NUMERIC 恒为 NULL</summary>
  44. public decimal? UnqualifiedQty { get; set; }
  45. public string? ResultRemark { get; set; }
  46. public long? LastResultBy { get; set; }
  47. public DateTime? LastResultAt { get; set; }
  48. /// <summary>NUMERIC 的测量真源;NON_NUMERIC 恒为空数组</summary>
  49. public List<IqcInspBillItemSampleRow> Samples { get; set; } = [];
  50. }
  51. /// <summary>逐样本实测值(仅 NUMERIC 使用)。</summary>
  52. public class IqcInspBillItemSampleRow
  53. {
  54. public long Id { get; set; }
  55. public int SampleIndex { get; set; }
  56. /// <summary>检验员录入原文(原样保留,供 INVALID 复盘)</summary>
  57. public string? SampleValueRaw { get; set; }
  58. /// <summary>后端解析值;不可解析 = NULL(不丢原文)</summary>
  59. public decimal? SampleNumeric { get; set; }
  60. /// <summary>PASS / FAIL / INVALID;后端唯一写入方</summary>
  61. public string? Judgement { get; set; }
  62. public string? Remark { get; set; }
  63. public long? InspectorId { get; set; }
  64. public DateTime? InspectionTime { get; set; }
  65. }
  66. /// <summary>
  67. /// 项目级结果汇总(后端实时聚合,不落表)。
  68. /// itemCount = 0 时全部为 0(LEGACY MODE:历史单 / NO_SPEC 新单 / MATCHED+0 明细新单同一语义)。
  69. /// </summary>
  70. public class IqcInspBillLineSummary
  71. {
  72. /// <summary>项目实例总数;0 ⇒ LEGACY MODE</summary>
  73. public int ItemCount { get; set; }
  74. /// <summary>已给出 PASS/FAIL 的项目数(可提交口径)</summary>
  75. public int JudgedCount { get; set; }
  76. public int PassCount { get; set; }
  77. public int FailCount { get; set; }
  78. public int InvalidCount { get; set; }
  79. /// <summary>itemJudgement 为 NULL 的项目数</summary>
  80. public int UnjudgedCount { get; set; }
  81. }
  82. // ────────────────────────────── save-detail 入参 ──────────────────────────────
  83. /// <summary>
  84. /// 保存项目级检验结果(草稿,**不推进流程**)。
  85. /// item 级增量:未出现在 items 中的项目完全不动。
  86. /// item 内样本全量替换:携带的 samples 即该项目的完整新集合。
  87. /// </summary>
  88. public class IqcSaveDetailInput
  89. {
  90. /// <summary>检验单 id(qms_qcp_inspbill.id)</summary>
  91. public long BillId { get; set; }
  92. public List<IqcSaveDetailItemInput> Items { get; set; } = [];
  93. }
  94. /// <summary>单个项目的结果入参。</summary>
  95. public class IqcSaveDetailItemInput
  96. {
  97. /// <summary>项目实例 id;必须属当前租户 + 当前 bill,否则整单 400</summary>
  98. public long ItemId { get; set; }
  99. /// <summary>
  100. /// 录入类型 NUMERIC / NON_NUMERIC。
  101. /// 与库中现值不同(含 NULL→非 NULL)视为类型切换,会清空该项目的全部旧测量事实。
  102. /// 不传(null)表示沿用库中现值。
  103. /// </summary>
  104. public string? ResultType { get; set; }
  105. /// <summary>NON_NUMERIC 测量真源;NUMERIC 传值 → 400(禁双真源)</summary>
  106. public decimal? QualifiedQty { get; set; }
  107. /// <summary>NON_NUMERIC 测量真源;NUMERIC 传值 → 400(禁双真源)</summary>
  108. public decimal? UnqualifiedQty { get; set; }
  109. public string? ResultRemark { get; set; }
  110. /// <summary>
  111. /// 人工判定,仅允许 PASS / FAIL(不得人工设 INVALID)。
  112. /// 传值 ⇒ judgementSource=MANUAL;不传 ⇒ 按测量真源 AUTO 重算。
  113. /// </summary>
  114. public string? ManualJudgement { get; set; }
  115. /// <summary>
  116. /// NUMERIC 测量真源,**该项目的完整新集合**(未出现的旧样本会被删除)。
  117. /// NON_NUMERIC 携带 → 400。
  118. /// </summary>
  119. public List<IqcSaveDetailSampleInput>? Samples { get; set; }
  120. }
  121. /// <summary>单个样本入参。</summary>
  122. public class IqcSaveDetailSampleInput
  123. {
  124. /// <summary>样本序号,必须 &gt;= 1 且在同一项目内不重复</summary>
  125. public int SampleIndex { get; set; }
  126. /// <summary>录入原文,非空(空值语义 = 该样本不存在 ⇒ 请从数组中移除,而不是传空串)</summary>
  127. public string? SampleValueRaw { get; set; }
  128. public string? Remark { get; set; }
  129. }
  130. // ────────────────────────────── save-detail 出参 ──────────────────────────────
  131. /// <summary>保存结果。回传受影响项目的最终判定与实时汇总,供前端免二次拉取。</summary>
  132. public class IqcSaveDetailOutput
  133. {
  134. public bool Ok { get; set; } = true;
  135. /// <summary>本次实际更新的项目数</summary>
  136. public int SavedItems { get; set; }
  137. /// <summary>本次写入的样本行数</summary>
  138. public int SavedSamples { get; set; }
  139. /// <summary>本次删除的样本行数(含类型切换清理与全量替换剪枝)</summary>
  140. public int DeletedSamples { get; set; }
  141. /// <summary>因类型切换而清空过测量事实的项目 id</summary>
  142. public List<long> ClearedByTypeChange { get; set; } = [];
  143. /// <summary>因测量事实变更而被作废的旧 MANUAL 判定所属项目 id</summary>
  144. public List<long> ManualInvalidated { get; set; } = [];
  145. public IqcInspBillLineSummary LineSummary { get; set; } = new();
  146. /// <summary>本次涉及项目的最终结果(含重算后的 judgement / source)</summary>
  147. public List<IqcInspBillItemLineRow> Items { get; set; } = [];
  148. }