|
|
@@ -270,6 +270,10 @@ public class IqcTaskEntryService : IDynamicApiController, ITransient
|
|
|
// 真正的系统错误(DB 不可用 / SQL 异常)仍按异常向上抛,不吞。
|
|
|
var spec = await _specResolver.ResolveAsync(tenantId, entry.MaterialCode, now);
|
|
|
|
|
|
+ // B2:本单冻结的检规明细条数。闭包内赋值,事务回滚时该返回值不会被使用(324 行直接抛)。
|
|
|
+ // 与 SpecStatus 是两个正交事实:SpecStatus=MATCHED 且 ItemCount=0 是合法状态(检规未维护明细)。
|
|
|
+ var itemCount = 0;
|
|
|
+
|
|
|
var tran = await _db.Ado.UseTranAsync(async () =>
|
|
|
{
|
|
|
await _db.Ado.ExecuteCommandAsync(
|
|
|
@@ -320,6 +324,43 @@ public class IqcTaskEntryService : IDynamicApiController, ITransient
|
|
|
new SugarParameter("@Jygfid", spec.IsMatched && spec.SpecId.HasValue
|
|
|
? spec.SpecId.Value.ToString()
|
|
|
: (object)DBNull.Value));
|
|
|
+
|
|
|
+ // ── B2 检规明细快照(与 Header 同一事务)────────────────────────────────
|
|
|
+ // 把"生成时点"的检规明细只读冻结进 ado_s5_iqc_insp_bill_item,此后详情/审核
|
|
|
+ // 一律读该快照,绝不回查 qms_jygfzb(否则 S0 改检规会篡改历史检验单)。
|
|
|
+ //
|
|
|
+ // 【租户边界】源侧 z.tenant_id=@TenantId 过滤;写入的 tenant_id 取调用方解析值,
|
|
|
+ // **绝不透传 z.tenant_id**,杜绝跨租户检规被快照进本租户单据。
|
|
|
+ // 【只读边界】qms_jygfzb 仅 SELECT,本方法不对任何 qms_* 做写入。
|
|
|
+ // 【0 行合法】无快照对象时写 0 行且不抛错,Header 照常提交:
|
|
|
+ // · IsMatched=false(NO_SPEC / NO_EFFECTIVE_SPEC / AMBIGUOUS)→ 不执行本 INSERT
|
|
|
+ // · IsMatched=true 但该检规 0 明细 → INSERT…SELECT 命中 0 行
|
|
|
+ // 刻意不照抄 S6 的 "lineCount<=0 → throw"(S6ProcessInspectionService.cs:157-158):
|
|
|
+ // S5 的报检分录是 165 贴源既成事实,Ai-DOP 无权因检规配置不全拒绝建检验单
|
|
|
+ // (依据 S5IqcSpecResolver.cs:76-79 的刻意差异)。
|
|
|
+ // 【result_type 不推导】Result 组 8 列一律不写、保持 NULL;录入类型由 N1 首次
|
|
|
+ // 录入时选定(qms_jygfzb 无 lrlx 列,不存在可冻结的来源)。
|
|
|
+ if (spec.IsMatched && spec.SpecId.HasValue)
|
|
|
+ {
|
|
|
+ itemCount = await _db.Ado.ExecuteCommandAsync(
|
|
|
+ """
|
|
|
+ INSERT INTO ado_s5_iqc_insp_bill_item (
|
|
|
+ tenant_id, inspection_bill_id, seq, source_spec_id, source_spec_item_id,
|
|
|
+ inspection_item, inspection_standard, method_tool, image_category,
|
|
|
+ sampling_scheme, spec_remark, upper_limit, lower_limit
|
|
|
+ )
|
|
|
+ SELECT
|
|
|
+ @TenantId, @BillId, z.xh, @SpecId, z.id,
|
|
|
+ z.jyxm, z.jybz, z.jygjjyff, z.txfl,
|
|
|
+ z.cyfa, z.zs, z.sx, z.xx
|
|
|
+ FROM qms_jygfzb z
|
|
|
+ WHERE z.tenant_id = @TenantId AND z.glid = @SpecId
|
|
|
+ ORDER BY z.xh, z.id
|
|
|
+ """,
|
|
|
+ new SugarParameter("@TenantId", tenantId),
|
|
|
+ new SugarParameter("@BillId", billId),
|
|
|
+ new SugarParameter("@SpecId", spec.SpecId.Value));
|
|
|
+ }
|
|
|
});
|
|
|
if (!tran.IsSuccess) throw tran.ErrorException ?? Oops.Oh("生成检验单失败");
|
|
|
|
|
|
@@ -331,6 +372,7 @@ public class IqcTaskEntryService : IDynamicApiController, ITransient
|
|
|
SpecNo = spec.IsMatched ? spec.SpecNo : null,
|
|
|
SpecWarning = spec.Warning,
|
|
|
SpecCandidateCount = spec.CandidateCount,
|
|
|
+ ItemCount = itemCount,
|
|
|
};
|
|
|
}
|
|
|
|