现象
----
报废申请单指向在管不良品时,待执行清单里明明能看到该 SKU,扫码却报
「不在该报废申请单的批准明细中,禁止报废」。
根因
----
在管不良品的 SKU 是从原库存行**复制**的(退回时 sku=getattr(stock_row,'sku','')),
因此同一个条码可能同时命中 stock_buy#M 与 trans_defective_goods#N —— 这是
**两个不同的实物**。
而 ScrapService.get_stock_by_barcode 原实现按固定顺序
(stock_product → stock_semi → stock_buy → trans_defective_goods)返回
**首个命中**。原库存行只要还在,就永远遮蔽在管不良品,扫码结果恒为
stock_buy。改造前双方都用 SKU 作为匹配键,遮蔽不暴露问题;上一轮给匹配键
加上来源表后,`sku:trans_defective_goods:X` ≠ `sku:stock_buy:X`,
问题才浮出水面。
实测复现(业务报障的 SKU 0000000590):
stock_buy#589 在库 6 件
trans_defective_goods#24 在管 1 件(同一 SKU)
批准明细期望 -> ('trans_defective_goods', 24)
扫码实际返回 -> stock_buy#589 → 键不匹配 → 报错
修复
----
条码本身无法区分这两个实物,**只有单据上下文能决定该扫到哪一个**,故把
单据上下文引入扫码解析:
- get_stock_by_barcode(barcode, prefer_pairs=None):改为**收集全部候选**,
再按 prefer_pairs(当前申请单批准明细的 (source_table, stock_id) 集合)
优先命中;无上下文时退回固定顺序,行为与改造前一致
- GET /scrap/scan 新增可选 request_id:据此加载该单的批准明细构造优先集。
优先集构造失败不阻断扫码,仅告警并回退默认选路
- 前端 scanBarcode(barcode, requestId) 与 create.vue 调用处带上当前申请单 id
验证(隔离数据端到端,非仅单元):
同一 SKU 建于 stock_buy#2202 与 trans_defective_goods#25
不带上下文扫码 -> stock_buy#2202 (命中批准明细? False ← 旧行为)
带上下文扫码 -> trans_defective_goods#25(命中批准明细? True)
执行后:在管 2→0、状态=已报废;**库存行 10/10 分毫未动**(未误扣错误实物)
Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 <script setup> SFCs, check out the script setup docs to learn more.
Learn more about the recommended Project Setup and IDE Support in the Vue Docs TypeScript Guide.