2026-07-07-qc-material-batch-qty-edit-design.md 8.6 KB

质检物料库 · 编辑弹窗数量修正设计

日期: 2026-07-07
状态: 已实现
父模块: 质量检测 → 质检物料库(/#/quality-group/quality-base/qc-material)
关联文档: 2026-06-11-qc-material-batch-inbound-design.md

1. 背景与目标

问题

编辑入库批次弹窗中,入库数量(in_qty)与剩余数量(remaining_qty)为只读,入库时若填错数量无法事后修正,导致批次余额与物资汇总库存(stock_qty)不准确。

目标(用户确认:场景 C — 两种都要支持)

场景 说明 典型操作
A. 入库录入错误 初始入库量填错,出库/废弃/任务扣减记录本身正确 修正 in_qty,剩余按公式联动
B. 账实不符 入库量无误,实物盘点或发现剩余与账面不一致 直接修正 remaining_qty,写库存调整流水

非目标

  • 修改历史出库 / 废弃 / 任务扣减流水(审计记录不可篡改)
  • 回溯修改已完成盘点单中的快照行
  • 同步改造生产物料库、细胞存储物料库(本 spec 仅覆盖质检物料库;后续可复用模式)

2. 数据不变量

2.1 批次级

已出库总量(out_total) = Σ |change_qty|
  WHERE batch_id = 当前批次
    AND del_flag = 0
    AND change_type IN ('use', 'discard')

理论剩余(theoretical_remaining) = in_qty − out_total

恒等式(正常状态下):

  • 0 ≤ remaining_qty ≤ in_qty
  • remaining_qty = theoretical_remaining(无独立调整时)

2.2 物资汇总

material.stock_qty = Σ batch.remaining_qty(同 material_id、del_flag=0)

2.3 流水职责

类型 change_type source_type 是否随编辑修改
入库 in manual_in 是 — 同步 change_qty、amount 快照
出库 use manual_out 等 否
废弃 discard manual_discard 否
库存调整(新增) adjust batch_qty_edit 新增 — 仅当剩余与理论值不一致时

3. 业务规则

3.1 编辑弹窗字段

字段 可编辑 说明
入库数量 inQty ✅ el-input-number,min > 0,精度与入库一致(4 位小数)
剩余数量 remainingQty ✅ 同上;可与理论值不同(场景 B)
已出库总量 只读展示 打开弹窗时由后端返回或前端根据查看数据展示
理论剩余 只读展示 inQty − outTotal;用户改 inQty 时前端实时重算

UI 提示(有出库时):

该批次已出库/废弃共 {outTotal} {unit}。修改入库数量后,若剩余数量未手工改动,将自动调整为 {theoreticalRemaining}。

UI 提示(剩余与理论值不一致时):

剩余数量与「入库数量 − 已出库」不一致,保存后将写入一条库存调整记录。

3.2 前端联动逻辑

  1. 打开编辑弹窗:请求批次详情(含 outTotal),或列表行扩展字段 outTotal。
  2. 用户修改 inQty:
    • 若用户未手工改过 remainingQty(remainingQtyTouched = false)→ remainingQty = inQty − outTotal
    • 若 remainingQtyTouched = true → 不自动覆盖剩余(支持场景 B)
  3. 用户修改 remainingQty → 设 remainingQtyTouched = true
  4. 改 inQty 且未锁定金额时 → 重算 amount = unitPrice × inQty(与入库弹窗一致)
  5. 提交前校验:
    • inQty > 0
    • remainingQty ≥ 0
    • remainingQty ≤ inQty
    • inQty ≥ outTotal(入库量不能小于已出库总量)

3.3 后端 update_batch 扩展(已实现:保留原入库 + adjust 流水)

  • 原入库流水(change_type=in):不修改 change_qty、amount,仅同步编号/批号等元数据快照。
  • 入库数量变化:写入 adjust 流水,change_qty = 新入库量 − 旧入库量,备注 编辑修正入库数量(旧 → 新)。
  • 剩余数量在入库修正之外另有差异:再写入一条 adjust,change_qty = 新剩余 − (旧剩余 + 入库量差),备注 编辑修正剩余数量。
  • 出库/废弃/任务流水:仍不修改。

3.4 出库流水 — 明确不改

以下记录 只读、不 UPDATE:

  • change_type = use(含 manual_out、task_complete、outbound_handover)
  • change_type = discard

理由:反映真实领用/废弃/任务消耗,修正入库错误不应篡改历史操作。

3.5 边界情况

情况 处理
无出库记录(out_total = 0) 改 in_qty 时默认 remaining = in_qty;两字段可联动
有出库,in_qty 从 100 改为 1000,剩余未手工改 remaining 自动 970(已出 30)
有出库,仅改 remaining(in_qty 不变) 写 adjust 流水,差值进 material.stock_qty
in_qty 改小到小于 out_total 拒绝,400:「入库数量不能小于已出库量 {out_total}」
remaining 改负或大于 in_qty 拒绝,400
批次已删除 / 物资已停用 沿用现网校验

4. API 变更

4.1 批次详情(可选,推荐)

GET /api/admin/web/admin/qc-material-batches/{batchId}
Response 在现有字段上增加:
  outTotal: number      // 已出库+废弃总量
  outCount: number      // 出库/废弃流水条数(用于 UI 提示)

若暂不增详情接口,可在 list_batches 每行附带 outTotal(编辑时从列表行读取);有性能顾虑时优先详情接口。

4.2 更新批次

PUT /api/admin/web/admin/qc-material-batches/{batchId}
Body 新增可选字段:
  inQty: number
  remainingQty: number

QcMaterialBatchUpdateBody 增加上述两字段。

4.3 变动记录列表

  • change_type=adjust 纳入筛选(变动类型下拉新增「库存调整」,value=adjust)
  • _row_to_dict / 前端展示:adjust → Tag warning,文案「库存调整」;source_type=batch_qty_edit → 「批次数量修正」

5. 前端改造

5.1 文件

文件 改动
web-admin/src/views/quality-inspection/qc-material/index.vue 编辑弹窗:inQty/remainingQty 可编辑;只读展示已出库/理论剩余;联动与校验;提交 payload
web-admin/src/api/qc-material.ts 类型与 update 入参增加字段;可选 fetchBatchDetail
web-admin/src/views/quality-inspection/qc-material/QcMaterialUsageTab.vue 变动类型筛选项 + 展示文案

5.2 编辑弹窗布局(在现有 form-grid-3 内)

入库数量 [input-number]     剩余数量 [input-number]     已出库总量 [只读]
理论剩余 [只读,inQty−outTotal]   (有差异时 el-alert 提示将写调整流水)
  • 数量控件样式与入库弹窗 input-number 一致
  • form-label-tip:「已出库总量含手动出库、废弃及任务扣减(若启用)」

5.3 查看弹窗

  • 批次基础信息仍展示修正后的 inQty / remainingQty
  • 出库明细列表不变;若存在 adjust 流水,可在「变动记录」Tab 中查看

6. 后端改造

文件 改动
backend/app/crud/qc_material_stock_batch.py update_batch 数量修正逻辑;_sum_batch_out_total() helper
backend/app/api/qc.py QcMaterialBatchUpdateBody 增字段;可选 GET batch detail
backend/app/crud/qc_material_usage.py list_usages 支持 change_type=adjust 筛选;_row_to_dict 展示

无需新增数据库表;change_type / source_type 为 varchar,新枚举值直接写入。


7. 测试要点

  1. 场景 A:入库 100,无出库 → 改 in 为 1000 → remaining=1000,stock_qty +900,入库流水 change_qty=1000,无 adjust 流水
  2. 场景 A+出库:入库 100,出库 30 → 改 in 为 1000 → remaining=970,stock_qty +900,出库 3 条不变
  3. 场景 B:in 保持 100,出库 30,remaining 从 70 改为 65 → stock_qty −5,新增 adjust 流水 change_qty=−5
  4. 校验:in 改为 20(已出 30)→ 失败
  5. 校验:remaining 改为 101(in=100)→ 失败
  6. 仅改厂家/批号:数量不变,无 adjust、无 stock_qty 变化
  7. 变动记录 Tab:adjust 类型可筛选、Tag 展示正确

8. 与盘点的关系

  • 库存盘点 Tab 仍用于周期性盘点、登记未用完物料;本能力用于单批次事后纠错,二者互补。
  • 已完成盘点单中的 remaining_qty 快照不回溯修改。

9. 后续扩展(本 spec 不做)

  • 生产物料库 / 细胞存储物料库复用同一模式
  • 数量修正权限细分(如仅库管可改剩余量)