DaoSales 培训手册

QC

面向品控:验货、不良品、退货

今天要做什么

按节拍守住入库闸门:每天抽检新到批次并清掉昨日异常单,每周跑批次一致性和拒收清单,每月出拒收率给采购做供应商评分。

每日(开工 ~30 分钟)

  1. 打开收货单列表,筛顶部黄色「待质检放行」横幅的单据——这些是新到货、批次已被系统「隔离中」等你验收。
  2. 进每张收货单详情,对照实物抽检数量 / 外观 / 颜色 / 批次号,录一张到货检验单(整批通过 / 部分通过 / 全拒)。
  3. 处理昨日遗留的「已提交」异常单:到异常单工作台逐张复核。
  4. 板材 / 皮革类定制家具:扫 QR 批次号确认与项目已开料批次色差一致,不一致直接拒收整批。
日常入口:/dashboard/purchasing/goods-receipts/dashboard/inventory/exceptions

每周

  • 批次一致性抽样:同一采购订单相邻批次的 ΔE 色差、板材厚度、漆面对比复核。
  • 拒收清单对账:把「未通过」和「部分通过」的批次同步给采购跟进退货 / 让步。
  • 外协回库抽检:批次号以 OS-<委外单号>- 开头的单独过一遍。

每月

  • 拒收率汇总 = 拒收批次数 / 总批次数,按供应商出 Top10,交采购做供应商评分输入。
  • 按异常类型聚合:「运输损坏」/「质量不合格」/「退供应商」前三大产品与供应商。
  • 月末最后一天不要推进异常单到「已完成」——完成会落库存调整流水,跨月需加备注给财务。
qc/nav-overview.jpg

权限红线(先看这 5 条)

  • 异常单状态严格单向前进——「草稿 → 已提交 → 已审批 → 已完成」不能回退;判错了只能在草稿阶段取消,完成后想冲销只能另开一张反向异常单。
  • 免检放行(仅 admin 有权)——QC 本人点按钮会被服务端权限拦截;确需免检的场景须请管理员代执行。
  • 外协批次必须以 OS-<委外单号>- 开头——前缀错了系统无法从委外单反查批次,放行后排产追溯断链。
  • 没通过验收不能付款——财务付款前会校验本 PO 的验收结论,「未通过」或未验收的付款按钮直接禁用,不要绕路人工预付。
  • 不能跨组织 / 跨账套调批次——批次绑定租户(organization_id)和账套(book_id),跨租户操作 RLS 直接拦截,别手工改 DB。

Quickstart — 日常核心任务

2.1 到货抽检(整批通过 / 部分通过 / 全拒)

采购确认到货后收货单自动生成,对应批次被系统「隔离中」。QC 按抽检规则查数量 / 外观 / 颜色,给出整批通过、部分通过或全拒的判定。

  1. 打开收货单列表,按搜索框查批次号或采购单号定位当日到货。(见图 ①、②)
  2. 点列表第一列的收货单号进入详情。
  3. 核对送货明细:产品、数量、批次号与实物一致——数量差异先跟采购电话核实是否补发。
  4. 对照送货单抽检:整批通过选「通过」、部分通过选「部分通过」并填实际合格数、全拒选「未通过」并写拒收原因。
  5. 上传外观 / 色差 / 检测报告照片作为证据,保存验收单。
  6. 保存后系统自动推进批次:通过 / 部分通过的批次放行进可用库存;未通过的批次保持「隔离中」。
qc/gr-list.jpg
何时不该做:实物未到现场不要提前录入验收单——预判录入会让批次提前放行,后续实物差异无法追溯验收时间线。数量差异先核实是否补发,不要直接走「未通过」,否则采购会多建一张退货单;补发场景留「隔离中」状态等下一车到齐再验。
观测信号:
  1. 收货单详情顶部黄色「待质检放行」横幅消失(批次已从「隔离中」放行)。
  2. 库存总览里对应 SKU 的可用数量按接收数上涨。
  3. 通过 / 部分通过的批次在批次列表出现放行时间戳。
技术追溯:inbound_inspections.overall_resultaccepted | rejected | partialstock_batches.status='active'released_at / released_by / inspection_id 三字段同写;stock_movements 新增一行 reference_type='qc_release'
系统动作:createInboundInspectionreleaseBatchesAfterInspectionadjustStocktype='receipt'referenceType='qc_release'

2.2 部分通过的 FIFO 分配

同一收货单多批次且只合格一部分,系统按「先进先出(FIFO)」顺序给早到的批次优先放行,剩余超出部分截断不放行。

  1. 验收单选「部分通过」。
  2. 填本次实际合格数量(总数不超过到货数)。
  3. 保存——系统自动遍历「隔离中」批次按入库时间 FIFO 分配:第一批先拿够合格数,后续批次超出部分截断。
  4. 未放行批次仅写入验收单关联,状态仍为「隔离中」,等下一轮补检或退货决定。
  5. 复核批次列表:已放行批次变「可用」;未放行批次仍在「隔离中」列。
何时不该做:不要手改合格数绕过 FIFO 顺序——强行指定后到批次先放行会造成账面批次号与实物出库顺序错乱,板材色差追溯断链。全批质量一致但数量不够就填真实合格数,缺量部分走补发,别把不合格凑进去。
观测信号:
  1. 批次列表里部分批次状态变「可用」,部分仍「隔离中」。
  2. 可用库存只涨本次合格数,不是到货全量。
  3. 未放行批次在批次详情显示关联验收单 ID。
技术追溯:stock_batches.available_quantity 按 FIFO 截断后写入;未放行批次 status='held'inspection_id 指向同一张验收单。
系统动作:releaseBatchesAfterInspection

2.3 拒收整批的隔离

整批质量不合格或颜色批次与项目已开料批次不一致,直接拒收不放行,等采购决定退货或让步。

  1. 验收单选「未通过」,在「拒收原因」写明不合格项(色差、厚度、甲醛超标等)。
  2. 上传照片作为证据。
  3. 保存——批次保持「隔离中」,不触发任何库存变动流水。
  4. 企微通知采购跟进退供应商或申请让步,同时挂在「本周拒收清单」里。
  5. 若决定退货:接着走任务 2.4 建「退供应商」异常单。
何时不该做:拒收不要走免检放行——批次已判不合格再放行会把瑕疵板材混入主库,下游工厂拿到会造成成品返工。照片证据不全不要保存验收单,后续供应商扯皮无材料对证。
观测信号:
  1. 收货单详情顶部黄色「待质检放行」横幅仍在(批次仍「隔离中」)。
  2. 可用库存数量没有变化。
  3. 「本周拒收清单」出现这条记录,供采购周会复盘。
技术追溯:inbound_inspections.overall_result='rejected'stock_batches.status='held' 不变、仅 inspection_id 回填;stock_movements 无新增行。
系统动作:createInboundInspection

2.4 建异常单(退货 / 质量不合格 / 损坏)

拒收后决定退供应商,或在库内发现质量问题 / 运输损坏,必须起一张异常单走审批链。

  1. 进异常单列表页,右上角点「新建异常」。(见图 ①)
  2. 弹窗里选仓库。(见图 ②)
  3. 选异常类型——「退供应商」/「质量不合格」/「运输损坏」。(见图 ②)
  4. 填备注写明异常原因、涉及批次号、责任方。(见图 ②)
  5. 点「创建」——系统按当月号段生成单号(格式 YC-YYMM-XXX),落草稿;草稿行可在列表操作下拉里直接「取消」或「删除」。(见图 ③)
qc/exceptions-list.jpg
qc/exception-create-dialog.jpg
qc/exception-row-actions.jpg
何时不该做:损坏但供应商未书面承认前不要建「退供应商」——这个类型会在完成时从账面扣库存,供应商扯皮则账实对不齐。样品出库 / 赠品用「样品」/「赠品」类型,别用「质量不合格」,否则月度质量统计失真。
观测信号:
  1. 异常单列表顶部出现新行,单号 YC-YYMM- 前缀,状态「草稿」。
  2. 汇总卡片「草稿」计数 +1。
  3. 详情页显示方向:「发现入库」/「客退入库」显示「入库 ↑」,其余显示「出库 ↓」。
技术追溯:stock_exceptions.exception_numbergenerateDocumentNumber('stock_exception') 自增;status='draft'directionexception_type 自动推断(found / customer_returnin,其余 → out)。
系统动作:createExceptionAction

2.5 添加明细并提交审批

草稿异常单需要逐行加产品 / 数量 / 单位成本,再提交给管理员审批。

  1. 异常单详情点「添加明细」。
  2. 弹窗里选产品(下拉自动拉当前仓库实际库存)、填数量、单位成本(可选)。
  3. 继续点「添加明细」加下一行;错录行点「移除」撤掉(仅「草稿」阶段可改)。
  4. 明细齐了点「提交审批」——状态从「草稿」推进到「已提交」。
  5. 等管理员审批:通过则转「已审批」;驳回则转「已驳回」(终态)。(见图 ①)
qc/exceptions-submitted-queue.jpg
何时不该做:明细没加完就提交——「已提交」状态不能加 / 改 / 删明细;要补录只能取消当前单新建一张。数量填超过仓库实际可用库存会在审批时被拦截(出库类异常),别临时把账面调高再回调。
观测信号:
  1. 单据顶部状态徽标从「草稿」变「已提交」。
  2. 汇总卡片「草稿」计数 -1,「已审批」不变(等管理员)。
  3. 列表筛选「已提交」出现该单。
技术追溯:stock_exception_items 每行对应一条;stock_exceptions.status='submitted';尚无 approved_by / approved_at
系统动作:addExceptionItemActionremoveExceptionItemActionsubmitExceptionAction

2.6 审批通过并完成(管理员)

管理员在「已提交」异常单上审批通过,QC 或管理员再推进到「已完成」——完成会实际落库存调整流水。

  1. 管理员进异常单详情,点「审批通过」——状态推进到「已审批」,系统自动记录审批人和审批时间。
  2. QC 或管理员点「完成」——弹窗显示「完成将执行库存调整,此操作不可逆」。
  3. 确认后系统按方向走库存调整:出库类扣减、入库类增加;批次追踪产品同步扣减对应批次的可用数量。
  4. 完成后状态变「已完成」(终态);库存流水里出现一行异常单执行记录。
何时不该做:完成后发现数量 / 产品判错——不能回退!状态机严格单向,没有「重开异常单」按钮;只能另开一张反向异常单(错扣库存起「发现入库」,错加库存起「质量不合格」出库)冲销。非 admin 点「完成」按钮会因权限不足被禁用——不要反复点击,找管理员代执行。
观测信号:
  1. 状态徽标先变「已审批」,完成后变「已完成」。
  2. 产品库存变化:出库类型数量下降,入库类型数量上升。
  3. 库存流水模块新增一行,「来源类型」列为「异常单」,「来源 ID」指向该异常单。
技术追溯:stock_exceptions.status='approved'approved_byapproved_at;完成后 status='completed'stock_movements 新增行 reference_type='stock_exception',批次表 available_quantity 同步变化。
系统动作:approveExceptionActionrejectExceptionActioncompleteExceptionActionadjustStockreferenceType='stock_exception'

2.7 批次隔离与免检放行(仅 admin 有权)

收货单顶部「待质检放行」横幅可直接跳转质检;确因特殊情况免检放行的,只有管理员(owner / admin)能点「免检放行」按钮。

  1. QC 日常:进收货单详情看黄色横幅,点「执行质检」跳去走 2.1 正常流程。
  2. 特殊场景(例如紧急项目 + 信任供应商)由管理员点「免检放行」。
  3. 弹窗二次确认「此操作将跳过质检流程,直接将批次放行为可用库存。此操作不可撤销」,确认后批次直接从「隔离中」变「可用」。
  4. 系统在批次备注追加 [Force release] <备注> 留痕——没有独立审计日志,备注就是唯一痕迹。
  5. QC 无权限时按钮点击会被服务端权限校验(要求 role ∈ {owner, admin})拦截,提示权限不足——找管理员处理。
何时不该做:QC 本人点「免检放行」会被权限拦截——不要反复尝试;紧急场景由管理员操作并在备注写清原因。免检放行不可撤销——批次变「可用」后无 UI 回滚入口,发现问题只能走「质量不合格」异常单反向扣减。
观测信号:
  1. 放行成功 toast「批次已放行」出现。
  2. 收货单详情黄色横幅消失。
  3. 批次详情备注列出现 [Force release] ... 字样。
技术追溯:stock_batches.statusheldactivebatches.notes 追加 [Force release] <notes>;流水无新增行。
系统动作:forceReleaseBatchAction(内部调 forceReleaseBatch,强制 role in {owner, admin}

上下游交接契约

QC 是入库闸门:上游采购 / 委外送来,下游仓库收账、采购拿拒收结论找供应商、财务拿验收结果决定付款。任何字段缺失都会打断链路。

采购 / 委外 → QC:到货验收

上游做什么:采购确认采购单到货生成收货单,系统按仓库 QC Hold 开关判定是否把批次落「隔离中」;委外回库则批次号按 OS-<委外单号>- 前缀命名。

我看到什么:收货单列表顶部出现黄色「待质检放行」横幅;批次列表新批次标「隔离中」、关联对应采购单或委外单。

缺失会回来找上游:批次号空或前缀错(委外非 OS- 开头)→ 无法反查委外单 → 退回采购重录。收货数量为 0 或缺送货单照片 → 验收无据可依。

技术字段(给 IT/采购交叉核对)

上游动作:采购的 createGoodsReceipt;QC 收端查询 getGoodsReceiptDatalistGoodsReceiptsForPage

必要字段:goods_receipts.receipt_number, items[].productId, items[].quantity, items[].batchId, stock_batches.status='held', stock_batches.batch_number(委外:LIKE 'OS-%'

QC → 仓库:合格批次入可用库存

我做什么:验收单给出「通过」或「部分通过」结果,系统自动把对应批次从「隔离中」放行为「可用」,并落一条收货类型的库存流水。

仓库看到什么:库存总览 SKU 可用数量上涨;批次列表批次状态变「可用」,系统同步记录放行时间、放行人、关联验收单三字段;流水页新增一行「QC 放行」来源。

缺失会回来找我:验收单未保存 → 仓库看不到放行 → PMC 催货。验收单关联 ID 未回写批次 → 批次追溯页断链。

技术字段(给 IT/仓库交叉核对)

触发动作:createInboundInspectionreleaseBatchesAfterInspectionadjustStock(type='receipt', referenceType='qc_release')

必传字段:warehouse_id, reference_type, reference_id, items[].productId, items[].quantity, overall_result, accepted_qty(partial 必填)、rejection_reason(rejected 必填)、photos[]

QC → 仓库:拒收批次隔离保持

我做什么:验收结果「未通过」,批次保持「隔离中」不放行,等后续退货或让步决定;仅在批次上关联验收单。

仓库看到什么:批次列表该批次仍「隔离中」不出现在可用库存;流水页无新增行。

缺失会回来找我:拒收原因空 → 仓库和采购不知怎么处置 → 隔离区货品无限期堆积。

技术字段(给 IT/仓库交叉核对)

触发动作:createInboundInspection(不触发 adjustStock

必传字段:overall_result='rejected', rejection_reason, photos[]

QC → 采购:退货 / 质量扣款依据

我做什么:拒收后起一张「退供应商」/「质量不合格」异常单,加明细、提交、审批通过、完成,落出库流水。

采购看到什么:异常单列表新条目(YC-YYMM- 前缀);完成后库存流水出一行来源为「异常单」的记录;采购据此发 debit note 或扣供应商货款。

缺失会回来找我:备注 / 照片 / 批次号缺失 → 采购找供应商扯皮无材料。异常类型选错(「运输损坏」当「质量不合格」)→ 月度质量分析口径乱。

技术字段(给 IT/采购交叉核对)

触发动作:createExceptionActionaddExceptionItemActionsubmitExceptionActionapproveExceptionActioncompleteExceptionAction

必传字段:warehouseId, exceptionType, items[].productId, items[].quantity, items[].unitCost?, notes

QC → 财务:付款放行门槛

我做什么:对每张采购单对应的收货单出一张验收单——结果必须是「通过」或「部分通过」,财务付款时才会放行。

财务看到什么:在采购单付款页,服务层跑 requiresInspectionBeforeStock() 校验是否通过;未通过时付款按钮被禁用,提示「请先完成到货验收」。

缺失会回来找我:验收单漏录或结果「未通过」→ 财务无法付款 → 供应商催款反过来找 QC。特别注意:就算采购想要「先付款后验收」,这道闸门也不会放水——设计上把验收做成了硬门槛,绕不过去。

技术字段(给 IT/财务交叉核对)

触发动作:requiresInspectionBeforeStock(referenceType, referenceId)(财务付款前调用)

依赖字段:inbound_inspections.reference_type, reference_id, overall_result ∈ {accepted, partial}

异常回滚

QC 最重要的认知:异常单状态严格单向前进——「草稿 → 已提交 → 已审批 → 已完成」各状态只能往前走,没有「重开」/「撤销审批」按钮。错了只能在草稿阶段撤回,或事后开反向异常单冲销。不要直接改 DB。

症状 做什么 前置条件 / 后果
草稿异常单填错类型 / 仓库 列表行「取消」或详情「取消」;或直接「删除」 仅「草稿」可删;「已提交」以后只能「取消」不能「删除」
草稿异常单明细行录错 详情表格行末「移除」 仅「草稿」可改;「已提交」后明细冻结
已提交异常单发现判错 详情点「取消」——状态转「已取消」(终态),再新建一张正确的 「已提交」/「已审批」均可取消;「已取消」后不能恢复,只能重建
管理员误审批通过 详情点「取消」转「已取消」;不要推进「完成」 完成后无法回滚,库存已动——只能开反向异常单
已「完成」异常单发现数量 / 产品错 不能回退——另建反向异常单(错扣库存走「发现入库」,错加库存走「质量不合格」)冲销原影响 原单「已完成」保留不动;反向单走完整审批链,库存最终对齐
批次误「通过」放行了 建「质量不合格」异常单扣减,并让 DBA 手工改批次状态回「隔离中」 放行无 UI 回滚;库存流水已落账,只能反向调整
免检放行后发现不合格 建「质量不合格」异常单从可用库存扣减,备注写明来源批次 免检放行不可撤销;反向扣减后批次仍为「可用」,DBA 手工改回「隔离中」
验收单「部分通过」数量填错 当张验收单已保存不能改;起一张补充异常单(「发现入库」补入或「质量不合格」扣减) 避免手工改验收单明细,审计痕迹断链
对应系统动作(IT 追溯)
  • cancelExceptionAction — 把 draft / submitted / approved 推到 cancelled(终态)
  • deleteExceptionAction — 仅 status='draft' 可删;其余状态拒绝
  • removeExceptionItemAction — 仅 draft 阶段删明细行
  • rejectExceptionAction — 管理员驳回 submitted(转终态 rejected,不能再动)
  • createExceptionActioncompleted 后的反向冲销靠起新单(found 入库、quality_reject 出库)
  • forceReleaseBatchAction — 仅 owner / admin;无撤销入口,留痕在 batches.notes[Force release] 前缀字符串
  • 状态机常量:VALID_STATUS_TRANSITIONS @ src/services/stock-exceptions.ts——严格单向,没有 reopen / revokeApproval

进阶功能

外协回库批次识别(OS- 前缀)

委外订单回库生成的批次号固定格式 OS-<委外单号>-<序号>。验收路径与采购单相同,但查询走委外单反查;前缀错误会导致无法反查委外单、工厂成品追溯断链。

入口:/dashboard/purchasing/goods-receipts/[id];SQL 查询 stock_batches WHERE batch_number LIKE 'OS-%'

月度拒收率统计

按异常类型 + 供应商聚合异常单,输出 Top 供应商拒收率给采购做供应商评分输入。月末复盘必跑。

系统动作:getExceptionStatistics(按 byType / bySupplier 分组)。

批次追溯:从验收单反查收货单

批次列表里每条「可用」批次都记了来源验收单 ID;点进去能反查原验收单和对应收货单 / 采购订单。生产追责用。

字段:stock_batches.inspection_idinbound_inspections.reference_idgoods_receipts / outsource_orders

QC Hold 全局开关

组织级开关——关闭时收货直接变「可用」、不冻结批次,QC 不再是强制闸门。仅在临时停 QC 验收场景使用,由管理员切换。

检查函数:isQcHoldEnabled() @ src/services/inventory.ts;配置位于 organization_settings.settings->>qc_hold_enabled

照片证据与附件管理

验收单照片字段存图片 URL 数组,走 Supabase Storage;建议按批次号 / 日期分文件夹命名,方便事后翻阅。图片缺失是供应商扯皮时最常见的证据盲区。

相关业务场景

QC 参与 6 大场景中的 2 条核心链路(定制项目板材到货、采购付款门槛),其余场景不参与或仅读。

  1. 标准成单流(询盘 → 报价 → 订单 → 发货 → 开票): QC 不参与客户端侧——销售主导。仅在客户反向退货时由 QC 验收入库,走「客退入库」异常单。 → 场景(仅客户退货环节)
  2. 定制家具项目流: QC 核心参与——板材到货抽检,颜色 / 厚度 / 甲醛报告与项目开料批次比对;部分通过的 FIFO 分配确保同批次板材给同工期工位。 → 场景详解
  3. 回款流:QC 不参与。 → 场景(了解即可)
  4. 采购付款流: QC 是付款闸门——财务在付款前校验本 PO 的验收结论,「通过」/「部分通过」才放行。未验收或「未通过」则付款按钮禁用。 → 场景详解
  5. 月结流: QC 月末前清完「已提交」/「已审批」异常单,避免库存调整跨月;月度拒收率统计交采购做供应商评分。不参与会计结账。 → 场景(部分参与)
  6. 报销审批流:QC 作为申请人(实验室耗材 / 检测费报销)走 /dashboard/expenses——非核心动作,不在 Quickstart。 → 场景(作为申请人)

外部协作入口

权限与范围

看得到什么(RLS 边界)

  • 当前组织(organization_id)下的所有收货单 / 批次 / 异常单 / 验收单——跨组织数据看不到,别试。
  • 当前账套(book_id)下的库存流水——多账套隔离,切账套后批次可能消失(不是丢,是账本不同)。
  • 采购模块只读:采购单 / 询价 / 供应商评分可见但不能写。

核心概念

  • 租户隔离organization_id)——批次、验收单、异常单都带此字段,跨租户 RLS 拦截。
  • 账套隔离book_id)——库存流水受账套隔离;切账套在右上角账套切换器。
  • 状态机严格单向——异常单的状态流转(VALID_STATUS_TRANSITIONS 常量写在 src/services/stock-exceptions.ts)只能前进:「草稿 → 已提交 → 已审批 → 已完成」,不允许回退,没有「重开」/「撤销审批」入口。判错只能取消重建或反向冲销。加新的状态流转必须改代码,不能用通用工作流引擎配置。
  • 批次追踪产品——开启了批次追踪的产品,入库必生成批次记录;未开启则只累加总量库存。
  • 跨模块付款门槛——财务付款前会调 QC 的 requiresInspectionBeforeStock() 校验,这是 QC 对财务唯一的硬约束:没通过验收的 PO,付款按钮物理禁用,不能手工绕过。

术语表

收货单
到货登记单(goods_receipts.receipt_number,采购确认到货生成)
到货检验单 / 验收单
QC 抽检结论(inbound_inspectionsitems 为 JSONB 数组,不走独立明细表)
异常单
库存异常处理单(stock_exceptions.exception_number,单号格式 YC-YYMM-NNN
异常明细
异常单的产品行(stock_exception_items:产品 + 数量 + 单位成本)
库存批次
批次记录(stock_batches),每批带状态、可用数量、来源单据引用
批次状态:隔离中
stock_batches.status='held'(待质检,不能出库)
批次状态:可用
stock_batches.status='active'(已放行,可以出库)
批次放行三字段
stock_batches.released_at / released_by / inspection_id(放行时同写,用于追溯)
验收结果
通过 / 未通过 / 部分通过(inbound_inspections.overall_result ∈ accepted | rejected | partial
异常类型(12 种)
运输损坏 damage、偷盗 theft、发现入库 found、样品 sample、退供应商 return_to_supplier、客退入库 customer_return、生产报废 production_scrap、质量不合格 quality_reject、赠品 gift、内部领用 internal_use、过期 expired、其他 other
异常方向
入库 infound / customer_return)/ 出库 out(其余)——由异常类型自动推断
异常单状态机
草稿 → 已提交 → 已审批 → 已完成(draft → submitted → approved → completed,严格单向);分支终态:已驳回 rejected、已取消 cancelled
QC 放行流水
stock_movements.reference_type='qc_release'(从流水反查放行来源)
异常执行流水
stock_movements.reference_type='stock_exception'(异常单完成后落账)
外协批次前缀
batch_number LIKE 'OS-<委外单号>-%'
QC Hold 全局开关
组织级开关 organization_settings.settings->>qc_hold_enabledisQcHoldEnabled()
付款放行门槛
requiresInspectionBeforeStock().passed(要求 acceptedpartial
抽检比例
无独立字段;按 inbound_inspections.items[].quantity 人工填入(sampling_rate 未建模)
免检放行核心动作
forceReleaseBatch(仅 role in {owner, admin}
验收核心动作
createInboundInspectionreleaseBatchesAfterInspectionadjustStock
异常单核心动作
createExceptionActionsubmitExceptionActionapproveExceptionActioncompleteExceptionAction

常见问题

异常单状态机真的不能回退吗?

真的。代码里的 VALID_STATUS_TRANSITIONS 常量写死了「草稿 → 已提交 → 已审批 → 已完成」只能单向前进,没有配置入口、不走通用工作流引擎——想加回退必须改源码并发版。设计上就是防止审批后被人「再打开改一下」破坏审计链。判错的正确姿势是:「已审批」之前用「取消」转终态再重建;「已完成」之后只能另开一张反向异常单冲销。

「已完成」之后发现判错怎么办?

不能回退。「已完成」是终态——只能起一张反向异常单冲销:原单多扣了库存就起「发现入库」(found)补回来,少扣了起「质量不合格」(quality_reject)再扣一次。两张单的审计链完整,比改 DB 干净。反向单同样要走「草稿 → 已提交 → 已审批 → 已完成」完整流程。

为什么我点不了免检放行?

因为服务端校验 role in {owner, admin}——普通 QC 角色不在白名单,服务端直接返回权限错误。UI 按钮能点但会被 server-side 拦截。遇到确需免检的紧急场景(例如客户催货 + 信任供应商),请找管理员代执行,并让其在备注里写清楚原因(这是唯一的审计痕迹)。

批次状态到底是 held 还是 hold

DB 真值是 held(过去分词)。部分老文档、旧测试文件里写成 hold(动词原形)是历史遗留——代码里 stock_batches.status='held' 是当前实际查询条件,以代码为准。若看到 hold 字样请把它当成文档笔误,在 SQL 查询时一律写 held。若要提给 IT 修 bug,附上报错截图说明是老字符串。

部分通过后,剩余未放行的批次怎么处理?

三条路径:(a)若供应商同意补发合格货,等新批次到货再做一次验收;(b)若判定不合格要退,起一张「退供应商」异常单,完成后批次从库存扣减;(c)请采购谈「让步接收」——若客户项目能容忍小瑕疵,起「质量不合格」异常单扣价后由管理员免检放行(批次留「隔离中」不能直接走通道)。

为什么财务说「付款按钮禁用」要我补验收?

财务付款前会查 requiresInspectionBeforeStock()——要求对应采购单有「通过」或「部分通过」的验收记录,「未通过」或未验收就返回 passed=false,按钮物理禁用。这是 QC 对财务的硬门槛,无法手工绕过(即便管理员也不能)。找到对应收货单补验收即可;若是整批拒收,走退货 / 扣款流程,付款本来就不该发生。

外协批次能和采购单批次一起验收吗?

不要混——外协批次号 OS-<委外单号>- 前缀、来源类型是委外单;采购单批次来源类型是采购单。验收单按来源单据归属,混录会导致反查链错位。同一车到货含两种来源,分开建两张验收单。