- 将文档从代码审计任务转换为端到端业务回归测试链路 - 重新组织文档结构为链路总览、示例数据基线和详细步骤 - 添加完整的业务场景清单涵盖WMS/MES/工位终端三大系统 - 定义统一的测试数据包括产品型号、物料清单、工位派工等 - 提供详细的步骤断言和数量等式验证方法 - 建立贯穿全链路的数据流向和状态变更追踪体系
822 lines
47 KiB
Markdown
822 lines
47 KiB
Markdown
# 电表箱成品装配 · 端到端业务回归测试链路
|
||
|
||
> 本文档是**一条从头走到尾、环环相扣、不许断、禁止分支**的完整回归测试链路。
|
||
> 以「装配 1 台成品电表箱」为主线,从物料还没进公司门开始,一路走到成品入库、多余料退回库房、成品可追溯。
|
||
> 每一步的**前置数据都由它前面的步骤产出**;每一步都给出**具体数值的断言**(表名·字段·期望值·数量等式)。
|
||
> 全链路只有一条路径,没有"如果…就…"、没有"否则"、没有"另一种情况"。
|
||
>
|
||
> 涉及三个系统:库房系统(WMS,端口 8890,接口前缀 `/api`)、产线系统(MES,端口 8888,接口前缀 `/api/v1`)、工位终端(端口 8892,接口前缀 `/api`)。
|
||
> 系统之间内部互调用 `X-API-TOKEN` 头保护(值 `Hardman_2026`)。
|
||
> 登录态用 JWT:库房/工位终端登录后带 `Authorization: Bearer <token>`;产线系统同理。
|
||
|
||
---
|
||
|
||
## 一、链路总览(一条主线)
|
||
|
||
```
|
||
【主数据准备】
|
||
建产品型号(电表箱) → 建物料档案(铁架子/门子/电气件/螺丝/成品) → 建库区(A区)
|
||
→ 建产品物料清单BOM(4种料, 各归属装配工序) → 建工艺流程(3个流程绑工位2/5·6/8)
|
||
→ 工位派工(工位2=工序1, 工位5=工序2, 工位6=工序2, 工位8=工序3)
|
||
|
||
【物料进厂:入库 → 检验】
|
||
结构件按批次入库(铁架子/门子/螺丝, 质量状态=未检)
|
||
→ 电气件按序列号SN入库(4颗, 质量状态=未检)
|
||
→ 来料检验(逐批/逐SN判合格 → 库存质量状态改「合格」)
|
||
|
||
【工单与排产】
|
||
建工单(电表箱, 数量1, 状态=已创建) → 日排产(生产日D, 计划1台, 状态=待执行)
|
||
→ 工单下发(已创建→已下发) → 工单开工(已下发→执行中, 联动排产 待执行→执行中)
|
||
|
||
【备料与出库(生产日D早上)】
|
||
生成备料单(按排产+派工算料, 同步工单物料台账, 立即自动出库只领「合格」品)
|
||
→ 库存扣减(铁架子-1/门子-1/电气件SN×2/螺丝-3), 台账累计出库达标置「领料完结」
|
||
→ 接料确认(4张备料单 已接料=已发出, 状态置「已完结」)
|
||
|
||
【上线装配:3道工序顺序流转】
|
||
工件上线(SN=WP-DX-0001, 状态=已上线, 当前工序=0)
|
||
→ 报工工序1(工位2, 绑铁架子批次+门子批次 → 当前工序=1)
|
||
→ 报工工序2(工位5, 绑2颗电气件SN → 当前工序=2) 〔工位6是同工序并行位〕
|
||
→ 拧紧上报(工位8, 拧2颗螺丝, 写2条拧紧记录+扭矩判定)
|
||
→ 报工工序3(工位8, 绑螺丝批次 → 当前工序=3)
|
||
|
||
【完工与成品入库】
|
||
完工(兜底校验3工序物料齐套 → 工件状态=已完工, 建关联追溯,
|
||
工单已完工数+1, 排产已完成数+1置「已完成」,
|
||
成品回流库房库存(成品SN=工件SN, 品类=成品, 数量1, 合格, 在库),
|
||
反冲核销台账已消耗量〔只核销台账, 不再动库存, 库存已在出库时扣过〕)
|
||
→ 工单完工流转(执行中→已完成)
|
||
|
||
【多余料回仓库 + 追溯】
|
||
工位退料(工位8, 螺丝用剩1颗 → 库房预建待确认退库单)
|
||
→ 库管确认收货(退库单置「已收货」, 螺丝加回 1 颗置「未检」, 在库总量 97→98)
|
||
→ 成品追溯(按成品SN回查: 工序时间线/操作人/物料批次SN/拧紧数据 全链路可追)
|
||
```
|
||
|
||
**贯穿全链路的 1 台成品**:成品序列号 `WP-DX-0001`,工单 `WO-20260922-001`,产品 `DX-100 电表箱`。
|
||
|
||
---
|
||
|
||
## 二、示例数据基线(全链路统一口径)
|
||
|
||
### 2.1 产品与物料
|
||
|
||
| 编码 | 名称 | 品类 | 管理方式 | 说明 |
|
||
|---|---|---|---|---|
|
||
| DX-100 | 电表箱 | 成品 | 序列号(2) | 本链路装配的成品 |
|
||
| TLJ-01 | 铁架子 | 原材料 | 结构件·批次(1) | 工序1装配,单台用量1 |
|
||
| MEN-01 | 门子 | 原材料 | 结构件·批次(1) | 工序1装配,单台用量1 |
|
||
| DQJ-01 | 电气件 | 原材料 | 电气件·序列号(2) | 工序2装配,单台用量2 |
|
||
| LS-01 | 螺丝 | 原材料 | 结构件·批次(1) | 工序3装配,单台用量2,损耗率50% |
|
||
|
||
### 2.2 产品物料清单(BOM,产品 DX-100,清单名「默认」)
|
||
|
||
| 物料 | 管理方式 | 单台用量 | 损耗率 | 装配工序 |
|
||
|---|---|---|---|---|
|
||
| TLJ-01 铁架子 | 结构件(1) | 1 | 0% | 工序1 |
|
||
| MEN-01 门子 | 结构件(1) | 1 | 0% | 工序1 |
|
||
| DQJ-01 电气件 | 电气件(2) | 2 | 0% | 工序2 |
|
||
| LS-01 螺丝 | 结构件(1) | 2 | 50% | 工序3 |
|
||
|
||
> 螺丝损耗率 50% 的含义:按「试拧/滑牙预留」,单台标准备料 = 2 ×(1+50%) = 3 颗;实际装配拧 2 颗,剩 1 颗完工后退回库房。这是"多余的料回仓库"的数据来源。
|
||
|
||
### 2.3 工位派工(生产日 D,班次=单班)
|
||
|
||
| 工位号 | 工序编号 | 承担装配 |
|
||
|---|---|---|
|
||
| 2 | 工序1 | 装铁架子 + 门子 |
|
||
| 5 | 工序2 | 装电气件(本工件走此工位) |
|
||
| 6 | 工序2 | 装电气件(同工序并行位,本工件不经过) |
|
||
| 8 | 工序3 | 拧螺丝 |
|
||
|
||
> 连续性校验:按工位号升序,工序编号为 `1,2,2,3`,单调不降、不穿插,合法。
|
||
|
||
### 2.4 工艺流程(每个工位绑定一个启用流程)
|
||
|
||
| 流程名 | 绑定工位 | 工序步骤 |
|
||
|---|---|---|
|
||
| 装铁架子门子 | 工位2 | 步骤「装铁架子」、步骤「装门子」 |
|
||
| 装电气件 | 工位5、工位6 | 步骤「装电气件」 |
|
||
| 拧螺丝 | 工位8 | 步骤「拧螺丝1」(扭矩采集,标准:扭矩 RANGE 8~12)、步骤「拧螺丝2」(扭矩采集,标准:扭矩 RANGE 8~12) |
|
||
|
||
> 工位8 的流程含 **2 个扭矩采集步骤**,所以拧紧汇总里「应拧颗数=2」;实拧 2 颗即满足。
|
||
|
||
### 2.5 工单 / 排产 / 批次 / 序列号
|
||
|
||
- 工单号 `WO-20260922-001`,产品 DX-100,数量 **1** 台。
|
||
- 生产日 **D = 2026-09-22**(`生成备料单` 取"系统当天"作为派工生效日,因此**派工生效日 = 排产日 = 备料日 = D = 执行回归测试的当天**;入库/建单可在 D-1=2026-09-21 完成)。
|
||
- 入库批次 / 序列号:
|
||
- 铁架子批次 `PC-TLJ-001`,入库 **5** 个
|
||
- 门子批次 `PC-MEN-001`,入库 **5** 个
|
||
- 螺丝批次 `PC-LS-001`,入库 **100** 颗
|
||
- 电气件序列号 `SN-DQ-001`、`SN-DQ-002`、`SN-DQ-003`、`SN-DQ-004`,各 1 颗(共 **4** 颗)
|
||
- 成品序列号(=工件序列号):`WP-DX-0001`
|
||
|
||
### 2.6 数量主线(最终必须闭合的等式,逐步在下方断言)
|
||
|
||
| 物料 | 入库 | 出库到工位 | 退回库房 | 期末在库 | 装进成品 |
|
||
|---|---|---|---|---|---|
|
||
| 铁架子 TLJ-01 | 5 | 1 | 0 | 4 | 1 |
|
||
| 门子 MEN-01 | 5 | 1 | 0 | 4 | 1 |
|
||
| 电气件 DQJ-01 | 4(SN) | 2(SN001,002) | 0 | 2(SN003,004) | 2 |
|
||
| 螺丝 LS-01 | 100 | 3 | 1 | 98 | 2 |
|
||
| 成品 DX-100 | — | — | — | 1(WP-DX-0001) | — |
|
||
|
||
---
|
||
|
||
## 三、端到端步骤
|
||
|
||
> 每一步统一格式:
|
||
> - **前置**:本步开始前必须已存在的数据(且都来自前面步骤)。
|
||
> - **操作**:角色 + 系统 + 菜单 + 接口 + 请求体关键字段。
|
||
> - **系统反应**:业务语言描述系统做了什么。
|
||
> - **数据变化**:哪张表、哪个字段、变成什么值。
|
||
> - **断言**:具体数值 / 状态 / 条数 / 等式。
|
||
|
||
### 阶段一 · 主数据准备
|
||
|
||
---
|
||
|
||
## Step 1:建产品型号(电表箱)
|
||
|
||
**前置**:无(链路起点)。产线系统已登录(账号具备"产品型号"维护权限)。
|
||
|
||
**操作**:工艺员在【产线系统 → 基础数据 → 产品型号】点"新增",填:名称=电表箱、编码=DX-100、规格型号=DX-100 户用单相、单位=台、类别=成品、启用=是。
|
||
- 接口:`POST /api/v1/product-types`
|
||
- 请求体:`{"name":"电表箱","code":"DX-100","spec":"DX-100 户用单相","unit":"台","category":"成品","isActive":true}`
|
||
|
||
**系统反应**:新增一条产品型号并启用。
|
||
|
||
**数据变化**:产品型号表新增一行:编码=DX-100、名称=电表箱、规格=DX-100 户用单相、单位=台、类别=成品、启用=是。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/product-types?code=DX-100` 返回 1 条,名称=电表箱、启用=是。
|
||
- 记下返回的产品型号主键 id(记作 `${productTypeId}`),Step 10 建工单要用。
|
||
|
||
---
|
||
|
||
## Step 2:建物料档案(5 个物料)
|
||
|
||
**前置**:Step 1 完成(成品 DX-100 也在此建档,供成品入库带出名称)。库房系统已登录(账号具备"物料档案:新增"权限)。
|
||
|
||
**操作**:仓管在【库房系统 → 基础数据 → 物料档案】逐个"新增"。
|
||
- 接口:`POST /api/material/create`
|
||
- 5 次请求体(除说明外全部必填:图号/名称/规格/单位/品类/类型):
|
||
|
||
| # | 请求体 |
|
||
|---|---|
|
||
| 铁架子 | `{"code":"TLJ-01","name":"铁架子","spec":"TLJ-01","unit":"个","itemType":1,"manageMode":1,"safetyStock":10}` |
|
||
| 门子 | `{"code":"MEN-01","name":"门子","spec":"MEN-01","unit":"个","itemType":1,"manageMode":1,"safetyStock":10}` |
|
||
| 电气件 | `{"code":"DQJ-01","name":"电气件","spec":"DQJ-01","unit":"个","itemType":1,"manageMode":2,"safetyStock":10}` |
|
||
| 螺丝 | `{"code":"LS-01","name":"螺丝","spec":"M4×10","unit":"颗","itemType":1,"manageMode":1,"safetyStock":50}` |
|
||
| 成品 | `{"code":"DX-100","name":"电表箱","spec":"DX-100 户用单相","unit":"台","itemType":3,"manageMode":2,"safetyStock":0}` |
|
||
|
||
**系统反应**:新增 5 条物料档案;结构件按批次管理、电气件按序列号管理自动置位;图号唯一校验通过。
|
||
|
||
**数据变化**:物料表新增 5 行。以铁架子为例:图号=TLJ-01、名称=铁架子、管理方式=1、按批次管理=是、按序列号管理=否、品类=1(原材料)、安全库存=10。电气件 DQJ-01:管理方式=2、按序列号管理=是。成品 DX-100:品类=3(成品)、管理方式=2。
|
||
|
||
**断言**:
|
||
- `GET /api/material/query?code=TLJ-01` 等逐个返回 1 条,管理方式与上表一致。
|
||
- 铁架子/门子/螺丝 管理方式=1;电气件/成品 管理方式=2。
|
||
- 重复提交同一图号返回冲突提示"图号已存在"。
|
||
|
||
---
|
||
|
||
## Step 3:建仓库区域(A 区)
|
||
|
||
**前置**:Step 2 完成。库房系统已登录(账号具备"区域:新增"权限)。
|
||
|
||
**操作**:仓管在【库房系统 → 库位管理 → 区域】新增一级区域。
|
||
- 接口:`POST /api/zone/node/create`
|
||
- 请求体:`{"level":1,"code":"A","name":"合格品存储区"}`
|
||
|
||
**系统反应**:新增一级区域,区域编码自动转大写为 A。
|
||
|
||
**数据变化**:区域表新增一行:层级=1、编码=A、区域编码=A、名称=合格品存储区。
|
||
|
||
**断言**:
|
||
- `GET /api/zone/list` 含层级=1、区域编码=A 的记录。
|
||
- Step 7/8 入库时 `zoneCode=A` 必须能命中此区域。
|
||
|
||
---
|
||
|
||
## Step 4:建产品物料清单(BOM)
|
||
|
||
**前置**:Step 1(产品 DX-100)、Step 2(4 种零部件物料档案已存在)。产线系统已登录。
|
||
|
||
**操作**:工艺员在【产线系统 → 基础数据 → 产品物料清单】为 DX-100 维护清单(清单名「默认」),录入 4 行物料并指定各自装配工序。
|
||
- 接口:`PUT /api/v1/bom`
|
||
- 请求体(关键:每行的 `manageMode` 管理方式、`unitQty` 单台用量、`lossRate` 损耗率、`processCode` 装配工序):
|
||
```json
|
||
{
|
||
"productCode": "DX-100",
|
||
"bomName": "默认",
|
||
"items": [
|
||
{"materialCode":"TLJ-01","materialName":"铁架子","unit":"个","manageMode":"1","unitQty":1,"lossRate":0,"processCode":1},
|
||
{"materialCode":"MEN-01","materialName":"门子","unit":"个","manageMode":"1","unitQty":1,"lossRate":0,"processCode":1},
|
||
{"materialCode":"DQJ-01","materialName":"电气件","unit":"个","manageMode":"2","unitQty":2,"lossRate":0,"processCode":2},
|
||
{"materialCode":"LS-01","materialName":"螺丝","unit":"颗","manageMode":"1","unitQty":2,"lossRate":50,"processCode":3}
|
||
]
|
||
}
|
||
```
|
||
|
||
**系统反应**:按「产品编码+清单名+物料编码」覆盖式保存 4 行物料清单。
|
||
|
||
**数据变化**:物料清单表新增 4 行,产品编码=DX-100、清单名=默认。铁架子行:装配工序=1、单台用量=1、损耗率=0。电气件行:装配工序=2、单台用量=2、管理方式=2。螺丝行:装配工序=3、单台用量=2、损耗率=50。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/bom?productCode=DX-100&bomName=默认` 返回 **4** 行。
|
||
- 各行的 装配工序 / 单台用量 / 损耗率 / 管理方式 与请求体一致。
|
||
- 工序分布:工序1 有 2 种料(铁架子、门子)、工序2 有 1 种料(电气件)、工序3 有 1 种料(螺丝)。
|
||
|
||
---
|
||
|
||
## Step 5:建工艺流程(3 个流程,绑定工位 2/5·6/8)
|
||
|
||
**前置**:工位 2、5、6、8 为系统内置工位(种子数据已存在)。产线系统已登录。
|
||
|
||
**操作**:工艺员在【产线系统 → 工艺管理 → 工艺流程】新建 3 个启用流程,并绑定工位、维护工序步骤。
|
||
- 接口:`POST /api/v1/process-flows`
|
||
- 流程1(装铁架子门子,绑工位2):
|
||
```json
|
||
{"name":"装铁架子门子","status":"ACTIVE","stations":[2],
|
||
"steps":[{"seq":1,"name":"装铁架子","collectType":"手动"},{"seq":2,"name":"装门子","collectType":"手动"}]}
|
||
```
|
||
- 流程2(装电气件,绑工位5、6):
|
||
```json
|
||
{"name":"装电气件","status":"ACTIVE","stations":[5,6],
|
||
"steps":[{"seq":1,"name":"装电气件","collectType":"扫码"}]}
|
||
```
|
||
- 流程3(拧螺丝,绑工位8,2 个扭矩步骤 + 扭矩 RANGE 标准):
|
||
```json
|
||
{"name":"拧螺丝","status":"ACTIVE","stations":[8],
|
||
"steps":[
|
||
{"seq":1,"name":"拧螺丝1","collectType":"扭矩","isTorque":true,
|
||
"criteria":[{"name":"扭矩","unit":"N·m","logic":"RANGE","min":8,"max":12}]},
|
||
{"seq":2,"name":"拧螺丝2","collectType":"扭矩","isTorque":true,
|
||
"criteria":[{"name":"扭矩","unit":"N·m","logic":"RANGE","min":8,"max":12}]}
|
||
]}
|
||
```
|
||
|
||
**系统反应**:新建 3 个流程;把工位2→流程1、工位5和6→流程2、工位8→流程3 绑定;覆盖式重建各流程的工序步骤与考核标准。
|
||
|
||
**数据变化**:
|
||
- 工艺流程表新增 3 行,状态=启用(ACTIVE)。
|
||
- 工位表:工位2 的流程id=流程1;工位5、工位6 的流程id=流程2;工位8 的流程id=流程3。
|
||
- 工序步骤表:流程1 有 2 步;流程2 有 1 步;流程3 有 2 步且"是否扭矩"=是。
|
||
- 考核标准表:流程3 的两步各挂 1 条"扭矩 / RANGE / 8~12"标准。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/stations` 中工位2/5/6/8 的流程绑定与上表一致。
|
||
- `GET /api/v1/process-flows?stationNo=8` 返回流程3,含 2 个扭矩步骤 → 决定 Step 19 拧紧"应拧颗数=2"。
|
||
|
||
---
|
||
|
||
## Step 6:工位派工(工位↔工序,生产日 D)
|
||
|
||
**前置**:Step 5 完成(工位2/5/6/8 已绑流程)。产线系统已登录。生产日 D = 执行当天。
|
||
|
||
**操作**:生产主管在【产线系统 → 生产管理 → 工位派工】为生产日 D 逐工位派工。
|
||
- 接口:`POST /api/v1/station-process/save`(逐条保存,同工位同天同班次唯一)
|
||
- 4 次请求体:
|
||
```json
|
||
{"stationNo":2,"processCode":1,"effectDate":"2026-09-22","shift":"","operator":"主管01"}
|
||
{"stationNo":5,"processCode":2,"effectDate":"2026-09-22","shift":"","operator":"主管01"}
|
||
{"stationNo":6,"processCode":2,"effectDate":"2026-09-22","shift":"","operator":"主管01"}
|
||
{"stationNo":8,"processCode":3,"effectDate":"2026-09-22","shift":"","operator":"主管01"}
|
||
```
|
||
|
||
**系统反应**:覆盖式保存 4 条派工;保存前做连续性校验(工序号沿工位号 1,2,2,3 单调不降,通过)。
|
||
|
||
**数据变化**:工位派工表新增 4 行,生效日=2026-09-22、班次=空:(工位2,工序1)、(工位5,工序2)、(工位6,工序2)、(工位8,工序3)。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/station-process?effectDate=2026-09-22` 返回 **4** 行,工位→工序映射与上表一致。
|
||
- `GET /api/v1/station-process/route?effectDate=2026-09-22` 派生路线:工位串 `2,5,6,8`、工序集合 `1,2,3`。
|
||
- 反例(可选验证):把工位4 派为工序1(夹在工位2工序1与工位5工序2之间但破坏单调)时保存被拒,提示"工序编号必须沿工位号单调不降、不可穿插"。
|
||
|
||
---
|
||
|
||
### 阶段二 · 物料进厂:入库 → 检验
|
||
|
||
---
|
||
|
||
## Step 7:结构件入库(铁架子 / 门子 / 螺丝,按批次)
|
||
|
||
**前置**:Step 2(物料档案)、Step 3(A 区)。库房系统已登录。3 种结构件随货带供应商质检报告单号(外部单号,非本系统检验记录)。
|
||
|
||
**操作**:仓管在【库房系统 → 入库管理 → 结构件入库】按批次录入。
|
||
- 接口:`POST /api/inbound/create`
|
||
- 3 次请求体(`inspectionNo` 检测单号必填、`zoneCode` 区域必填、`quantity`>0):
|
||
```json
|
||
{"inboundType":"purchase","materialCode":"TLJ-01","batchNo":"PC-TLJ-001","quantity":5,"zoneCode":"A","inspectionNo":"QC-TLJ-20260921","operator":"库管01"}
|
||
{"inboundType":"purchase","materialCode":"MEN-01","batchNo":"PC-MEN-001","quantity":5,"zoneCode":"A","inspectionNo":"QC-MEN-20260921","operator":"库管01"}
|
||
{"inboundType":"purchase","materialCode":"LS-01","batchNo":"PC-LS-001","quantity":100,"zoneCode":"A","inspectionNo":"QC-LS-20260921","operator":"库管01"}
|
||
```
|
||
|
||
**系统反应**:每笔在事务内建"入库单 + 库存行 + 入库明细"。结构件走批次管理,不允许携带 SN 清单。库存行质量状态先置「未检」(等 Step 9 检验判定)。
|
||
|
||
**数据变化**:
|
||
- 入库单表新增 3 行,入库单号形如 `IB<12位>`,数量分别 5/5/100,检测单号回填。
|
||
- 库存表新增 3 行(管理方式=1):铁架子批次 PC-TLJ-001 数量=5、门子批次 PC-MEN-001 数量=5、螺丝批次 PC-LS-001 数量=100;质量状态=未检、状态=在库、区域=A、锁定量=0。
|
||
- 入库明细表新增 3 行(按批次号 + 数量)。
|
||
|
||
**断言**:
|
||
- `GET /api/stock/query?materialCode=TLJ-01` 返回批次 PC-TLJ-001,数量=5、质量状态=未检、状态=在库。
|
||
- 门子数量=5、螺丝数量=100,同样质量状态=未检。
|
||
- 3 笔入库单数量合计 = 5+5+100 = 110。
|
||
|
||
---
|
||
|
||
## Step 8:电气件入库(4 颗 SN)
|
||
|
||
**前置**:Step 2(电气件档案 DQJ-01 管理方式=2)、Step 3(A 区)。库房系统已登录。
|
||
|
||
**操作**:仓管在【库房系统 → 入库管理 → 电气件入库】逐个扫 SN 录入。
|
||
- 接口:`POST /api/inbound/create`
|
||
- 请求体(电气件用 `snList`,不带 quantity):
|
||
```json
|
||
{"inboundType":"purchase","materialCode":"DQJ-01","snList":["SN-DQ-001","SN-DQ-002","SN-DQ-003","SN-DQ-004"],"zoneCode":"A","inspectionNo":"QC-DQJ-20260921","operator":"库管01"}
|
||
```
|
||
|
||
**系统反应**:对每个 SN 建一条库存行(管理方式=2,数量=1),SN 全局唯一防重;质量状态置「未检」。
|
||
|
||
**数据变化**:
|
||
- 入库单表新增 1 行,数量=4(=SN 个数)。
|
||
- 库存表新增 4 行(管理方式=2):SN-DQ-001/002/003/004,各数量=1、质量状态=未检、状态=在库、区域=A。
|
||
- 入库明细表新增 4 行(每 SN 一行,数量=1)。
|
||
|
||
**断言**:
|
||
- `GET /api/stock/query?materialCode=DQJ-01` 返回 4 条 SN 行,各数量=1、质量状态=未检。
|
||
- 重复入库同一 SN 返回冲突提示"SN 已存在"。
|
||
|
||
---
|
||
|
||
## Step 9:来料检验(逐批 / 逐 SN 判合格)
|
||
|
||
**前置**:Step 7、Step 8 完成——库存里已有 3 个批次行 + 4 个 SN 行(质量状态=未检)。库房系统已登录。
|
||
|
||
**操作**:质检员在【库房系统 → 质量管理 → 来料检验】按批次号/SN 逐条判合格。
|
||
- 接口:`POST /api/inspection/create`(`targetId` 传批次号或 SN,系统自动识别类型并定位到那条库存行;`status` 只能"合格/不合格")
|
||
- 7 次请求体(全部判合格):
|
||
```json
|
||
{"targetId":"PC-TLJ-001","status":"合格","inspectionType":"来料检","inspectQty":5,"passQty":5,"inspector":"质检01"}
|
||
{"targetId":"PC-MEN-001","status":"合格","inspectionType":"来料检","inspectQty":5,"passQty":5,"inspector":"质检01"}
|
||
{"targetId":"PC-LS-001","status":"合格","inspectionType":"来料检","inspectQty":100,"passQty":100,"inspector":"质检01"}
|
||
{"targetId":"SN-DQ-001","status":"合格","inspectionType":"来料检","inspectQty":1,"passQty":1,"inspector":"质检01"}
|
||
{"targetId":"SN-DQ-002","status":"合格","inspectionType":"来料检","inspectQty":1,"passQty":1,"inspector":"质检01"}
|
||
{"targetId":"SN-DQ-003","status":"合格","inspectionType":"来料检","inspectQty":1,"passQty":1,"inspector":"质检01"}
|
||
{"targetId":"SN-DQ-004","status":"合格","inspectionType":"来料检","inspectQty":1,"passQty":1,"inspector":"质检01"}
|
||
```
|
||
|
||
**系统反应**:每条检验在事务内建检验记录,并把定位到的那条库存行质量状态由「未检」改为「合格」。这一步是 Step 14 自动出库能领到货的前提(出库只领"合格"品)。
|
||
|
||
**数据变化**:
|
||
- 检验记录表新增 7 行:目标类型(批次/SN 自动判定)、目标id、物料编码(由库存行回填)、状态=合格、检验数量、合格数量。
|
||
- 库存表:3 个批次行 + 4 个 SN 行的质量状态 全部由「未检」→「合格」。
|
||
|
||
**断言**:
|
||
- `GET /api/inspection/query?materialCode=LS-01` 返回状态=合格 的记录。
|
||
- `GET /api/stock/query?materialCode=TLJ-01`:批次 PC-TLJ-001 质量状态=**合格**。
|
||
- 7 个目标(3 批次 + 4 SN)质量状态全部=合格;未检数量=0。
|
||
- 反例(可选):把某批判"不合格"后,该批在 Step 14 自动出库时被跳过(仅合格品可领料上线)。
|
||
|
||
---
|
||
|
||
### 阶段三 · 工单与排产
|
||
|
||
---
|
||
|
||
## Step 10:建工单(电表箱,数量 1)
|
||
|
||
**前置**:Step 1(产品型号 DX-100,主键 `${productTypeId}`)。产线系统已登录。**产线上当前没有其他「执行中/已暂停」工单**(单工单互斥,否则 Step 12 下发会被拦)。
|
||
|
||
**操作**:计划员在【产线系统 → 生产管理 → 工单管理】点"新建工单",选产品型号=电表箱、数量=1、完成日期=2026-09-22。
|
||
- 接口:`POST /api/v1/work-orders`
|
||
- 请求体:
|
||
```json
|
||
{"productTypeId":${productTypeId},"productCode":"DX-100","productName":"电表箱","quantity":1,"dueDate":"2026-09-22"}
|
||
```
|
||
|
||
**系统反应**:创建工单,工单号未指定时按规则自动生成 `WO-<当天>-001`;状态恒为「已创建」(不允许直接建到后续状态)。
|
||
|
||
**数据变化**:工单表新增一行:工单号=`WO-20260922-001`(记作 `${orderNo}`)、产品编码=DX-100、产品名称=电表箱、数量=1、状态=**已创建(CREATED)**、已完工数=0。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/work-orders?orderNo=WO-20260922-001` 返回 1 条,数量=1、状态=已创建、已完工数=0。
|
||
- 记下工单主键 id(记作 `${orderId}`),Step 12/13 状态流转要用。
|
||
|
||
---
|
||
|
||
## Step 11:日排产(生产日 D,计划 1 台)
|
||
|
||
**前置**:Step 10(工单 `${orderNo}` 状态=已创建,非终态可排产)。
|
||
|
||
**操作**:计划员在【产线系统 → 生产管理 → 日排产】为该工单排产到生产日 D。
|
||
- 接口:`POST /api/v1/daily-plans`
|
||
- 请求体:`{"orderNo":"WO-20260922-001","planDate":"2026-09-22","planQty":1}`
|
||
|
||
**系统反应**:校验该工单所有日排产累计不超过未开工数量(=数量1−已完工0−在产0=1),本次排 1 台,通过。新建排产,状态默认「待执行」。
|
||
|
||
**数据变化**:日排产表新增一行:工单号=WO-20260922-001、排产日=2026-09-22、计划数量=1、已完成数量=0、状态=**待执行(PENDING)**。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/daily-plans?orderNo=WO-20260922-001` 返回 1 条,计划数量=1、状态=待执行。
|
||
- 反例(可选):再排 planQty=1(累计2 > 未开工1)被拒,提示"排产合计数量超过未开工数量"。
|
||
|
||
---
|
||
|
||
## Step 12:工单下发(已创建 → 已下发)
|
||
|
||
**前置**:Step 10(工单状态=已创建)、Step 11(已排产)。产线无其他在产工单。
|
||
|
||
**操作**:计划员在【工单管理】对该工单点"下发"。
|
||
- 接口:`POST /api/v1/work-orders/status`
|
||
- 请求体:`{"id":${orderId},"status":"RELEASED","reason":"排产完成,下发生产"}`
|
||
|
||
**系统反应**:校验流转合法(已创建可下发)+ 单工单互斥(产线无其他执行中/暂停工单),状态改为「已下发」。
|
||
|
||
**数据变化**:工单表该行状态 由 已创建(CREATED) → **已下发(RELEASED)**;写状态变更日志(原状态/新状态/原因)。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/work-orders/:id`(`${orderId}`)状态=已下发。
|
||
- 非法流转(如已创建直接→执行中跳过下发,或→已完成)被拒,提示"不允许从「已创建」变更为「X」"。
|
||
|
||
---
|
||
|
||
## Step 13:工单开工(已下发 → 执行中,联动排产)
|
||
|
||
**前置**:Step 12(工单状态=已下发)、Step 11(排产状态=待执行)。
|
||
|
||
**操作**:生产主管在【工单管理】对该工单点"开工"。
|
||
- 接口:`POST /api/v1/work-orders/status`
|
||
- 请求体:`{"id":${orderId},"status":"IN_PROGRESS","reason":"产线开工"}`
|
||
|
||
**系统反应**:状态改为「执行中」;联动把该工单「待执行」的日排产置为「执行中」。
|
||
|
||
**数据变化**:
|
||
- 工单表:状态 已下发(RELEASED) → **执行中(IN_PROGRESS)**。
|
||
- 日排产表:WO-20260922-001 / 2026-09-22 那行状态 待执行(PENDING) → **执行中(PROCESSING)**。
|
||
|
||
**断言**:
|
||
- 工单状态=执行中。
|
||
- `GET /api/v1/daily-plans?orderNo=WO-20260922-001` 排产状态=执行中。
|
||
|
||
---
|
||
|
||
### 阶段四 · 备料与出库(生产日 D 早上)
|
||
|
||
---
|
||
|
||
## Step 14:生成备料单(按排产+派工算料,同步台账,自动出库领合格品)
|
||
|
||
**前置**:Step 4(BOM)、Step 6(生产日 D 的工位派工)、Step 9(库存全部合格)、Step 11(排产日 D 计划 1 台)、Step 13(工单执行中)。**执行当天 = D = 2026-09-22**(生成备料单用"系统当天"匹配派工生效日)。
|
||
|
||
**操作**:仓管/计划员在【产线系统 → 生产管理 → 备料管理】点"生成备料单",选排产日=2026-09-22。
|
||
- 接口:`POST /api/v1/material-requests/generate`
|
||
- 请求体:`{"planDate":"2026-09-22"}`
|
||
|
||
**系统反应**(一次触发三件事,顺序执行):
|
||
1. **算料**:按 BOM 物料的装配工序,拆到当天该工序派工的工位,生成工位级备料单。数量 = 工位分配产量 × 单台用量 ×(1+损耗率)。工序2 派到工位5、6,产量 1 台按工位号拆分给到工位5(工位6 分得 0,不生成)。
|
||
2. **同步台账**:把工单级需求总量下发库房「工单物料台账」(按物料聚合,需求量 = 工单数量 × 单台用量 ×(1+损耗率),向上取整)。
|
||
3. **自动出库**:对每张备料单按 FIFO 从"合格"库存领料——结构件按批次逐批扣、电气件按 SN 逐颗扣;出库量达标后回写备料单已发出量并置「已锁定」,台账累计出库达标置「领料完结」。
|
||
|
||
**数据变化**:
|
||
- **备料单表**新增 4 行(工单 WO-20260922-001,排产日 2026-09-22):
|
||
|
||
| 备料单 | 物料 | 工位 | 工序 | 需求量 | 已发出 | 状态 |
|
||
|---|---|---|---|---|---|---|
|
||
| MR…001 | 铁架子 TLJ-01 | 2 | 1 | 1 | 1 | 已锁定(LOCKED) |
|
||
| MR…002 | 门子 MEN-01 | 2 | 1 | 1 | 1 | 已锁定 |
|
||
| MR…003 | 电气件 DQJ-01 | 5 | 2 | 2 | 2 | 已锁定 |
|
||
| MR…004 | 螺丝 LS-01 | 8 | 3 | 3 | 3 | 已锁定 |
|
||
|
||
- **工单物料台账表**新增 4 行:铁架子 总量1/出库1、门子 总量1/出库1、电气件 总量2/出库2、螺丝 总量3/出库3;4 行状态均=**领料完结**。
|
||
- **库存表扣减**:铁架子批次 PC-TLJ-001 数量 5→**4**;门子批次 PC-MEN-001 5→**4**;螺丝批次 PC-LS-001 100→**97**;电气件 SN-DQ-001、SN-DQ-002 状态 在库→**出库**(SN-DQ-003/004 仍在库)。
|
||
- **出库单表**新增 5 笔(出库即扣库存,状态=已出库):铁架子 1 笔(数量1,批次PC-TLJ-001)、门子 1 笔(数量1)、螺丝 1 笔(数量3,批次PC-LS-001)、电气件 2 笔(每 SN 一笔,各数量1)。
|
||
- **出库明细表**:结构件按批次记、电气件按 SN 记。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/material-requests?orderNo=WO-20260922-001` 返回 **4** 张备料单,需求量分别 1/1/2/3、已发出=需求量、状态=已锁定。
|
||
- 台账:`GET /api/ledger/query?orderNo=WO-20260922-001`(库房侧)返回 4 行,出库量=总量、状态=领料完结。
|
||
- 库存:铁架子=4、门子=4、螺丝=97;电气件在库 SN 数=2(SN-DQ-003、SN-DQ-004),出库 SN 数=2(SN-DQ-001、SN-DQ-002)。
|
||
- **数量等式(出库阶段)**:铁架子 5=4+1;门子 5=4+1;螺丝 100=97+3;电气件 4=2(在库)+2(出库)。
|
||
|
||
---
|
||
|
||
## Step 15:接料确认(工位收到料)
|
||
|
||
**前置**:Step 14 生成 4 张备料单且已自动出库(已发出量>0)。工位终端已登录(Step 16 前的工位账号)或产线备料页人工确认。
|
||
|
||
**操作**:工位/仓管对 4 张备料单逐张确认接料(一键确认本批全部剩余)。
|
||
- 接口:`POST /api/v1/material-requests/receive`
|
||
- 4 次请求体(`qty` 传 0 表示"确认本批全部剩余"):
|
||
```json
|
||
{"requestNo":"MR…001","qty":0}
|
||
{"requestNo":"MR…002","qty":0}
|
||
{"requestNo":"MR…003","qty":0}
|
||
{"requestNo":"MR…004","qty":0}
|
||
```
|
||
|
||
**系统反应**:把已接料量累加到"已发出量"上限(不超接);当已发出≥需求量且已接料≥已发出时,备料单状态置「已完结」(送达与接料双完结)。
|
||
|
||
**数据变化**:4 张备料单:已接料量=已发出量(1/1/2/3),状态 已锁定(LOCKED) → **已完结(DONE)**;回填接料时间、接料人。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/material-requests?orderNo=WO-20260922-001` 4 张单 已接料量=已发出量、状态=已完结。
|
||
- 配送进度:在途量(已发出−已接料)= 0。
|
||
|
||
---
|
||
|
||
### 阶段五 · 上线装配(3 道工序顺序流转,禁止跳站)
|
||
|
||
---
|
||
|
||
## Step 16:工件上线(进线登记)
|
||
|
||
**前置**:Step 13(工单执行中)、Step 15(4 张备料单已完结,料已到工位)。工位终端已登录(工位2 账号)。
|
||
|
||
**操作**:操作工在【工位终端 → 上线】扫工件序列号,选工单。
|
||
- 接口:`POST /api/v1/workpiece/online`
|
||
- 请求体:`{"sn":"WP-DX-0001","orderNo":"WO-20260922-001","workOrderId":${orderId}}`
|
||
|
||
**系统反应**:登记一台在制工件进线;路线不冗余存储,由当天工位派工实时派生(工位串 2,5,6,8)。当前工序置 0(尚未报任何工序)。
|
||
|
||
**数据变化**:工件表新增一行:序列号=WP-DX-0001、工单号=WO-20260922-001、状态=**已上线(ONLINE)**、当前工序=**0**。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/workpieces/in-process?orderNo=WO-20260922-001` 含 WP-DX-0001,状态=已上线、当前工序=0。
|
||
- 重复上线同一序列号被拒(工件已存在)。
|
||
|
||
---
|
||
|
||
## Step 17:报工工序 1(工位 2 · 装铁架子 + 门子)
|
||
|
||
**前置**:Step 16(工件已上线、当前工序=0)、Step 5(工位2 绑「装铁架子门子」流程)、Step 15(铁架子批次 PC-TLJ-001、门子批次 PC-MEN-001 已到工位2)。工位终端已登录(工位2)。
|
||
|
||
**操作**:操作工在工位2 扫工件号 → 装铁架子、装门子 → 扫两个结构件批次号绑定 → 点"报工"。
|
||
- 接口:`POST /api/v1/workpiece/process/report`
|
||
- 请求体(`binds` 结构件的 `bindValue` 传批次号):
|
||
```json
|
||
{"sn":"WP-DX-0001","processCode":1,"stationNo":2,
|
||
"binds":[{"materialCode":"TLJ-01","bindValue":"PC-TLJ-001"},
|
||
{"materialCode":"MEN-01","bindValue":"PC-MEN-001"}]}
|
||
```
|
||
|
||
**系统反应**:顺序校验(请求工序1 = 当前工序0+1,通过)→ 落装机绑定 → 齐套校验(工序1 的铁架子、门子各至少绑 1 个批次,通过)→ 在同一事务内写报工实绩、推进工件状态。任一步失败整体回滚。
|
||
|
||
**数据变化**:
|
||
- 工件装配绑定表新增 2 行:WP-DX-0001 绑 铁架子批次 PC-TLJ-001、门子批次 PC-MEN-001(工序1、工位2)。
|
||
- 工件工序实绩表新增 1 行:工序=1、工位=2、状态=已完成、结果=**合格(OK)**、操作人、作业时长。
|
||
- 工件表:当前工序 0→**1**、状态 已上线(ONLINE)→**在制(PROCESSING)**。
|
||
|
||
**断言**:
|
||
- 工件当前工序=1、状态=在制。
|
||
- `GET /api/v1/workpiece/process/records?sn=WP-DX-0001` 有工序1 记录,工位=2、结果=合格。
|
||
- 反例:若只绑铁架子不绑门子,报工被拒并返回缺料清单(门子未绑齐)。
|
||
|
||
---
|
||
|
||
## Step 18:报工工序 2(工位 5 · 装 2 颗电气件)
|
||
|
||
**前置**:Step 17(当前工序=1)、Step 5(工位5 绑「装电气件」流程)、Step 15(电气件 SN-DQ-001、SN-DQ-002 已到工位5)。工位终端已登录(工位5)。
|
||
|
||
**操作**:操作工在工位5 扫工件号 → 逐颗扫 2 个电气件序列号绑定 → 点"报工"。
|
||
- 接口:`POST /api/v1/workpiece/process/report`
|
||
- 请求体(电气件的 `bindValue` 传序列号,必须绑满单台用量 2 颗):
|
||
```json
|
||
{"sn":"WP-DX-0001","processCode":2,"stationNo":5,
|
||
"binds":[{"materialCode":"DQJ-01","bindValue":"SN-DQ-001"},
|
||
{"materialCode":"DQJ-01","bindValue":"SN-DQ-002"}]}
|
||
```
|
||
|
||
**系统反应**:顺序校验(工序2 = 当前工序1+1,通过)→ 落绑定 → 齐套校验(电气件按单台用量逐颗序列号,必须绑满 2 颗,通过)→ 写实绩、推进工件状态。
|
||
|
||
> 说明:工位6 与工位5 同为工序2(并行位),本工件走工位5 完成工序2;工位6 在本链路不产生该工件的报工记录。
|
||
|
||
**数据变化**:
|
||
- 工件装配绑定表新增 2 行:WP-DX-0001 绑 电气件 SN-DQ-001、SN-DQ-002(工序2、工位5)。
|
||
- 工件工序实绩表新增 1 行:工序=2、工位=5、状态=已完成、结果=合格(OK)。
|
||
- 工件表:当前工序 1→**2**、状态=在制(PROCESSING)。
|
||
|
||
**断言**:
|
||
- 工件当前工序=2。
|
||
- `GET /api/v1/workpiece/process/records?sn=WP-DX-0001` 有工序2 记录,工位=5、结果=合格。
|
||
- 反例:只绑 1 颗电气件(少于单台用量2)报工被拒,提示电气件未绑齐。
|
||
|
||
---
|
||
|
||
## Step 19:拧紧上报(工位 8 · 拧 2 颗螺丝,扭矩判定)
|
||
|
||
**前置**:Step 5(工位8 绑「拧螺丝」流程,含 2 个扭矩步骤,扭矩标准 RANGE 8~12)、Step 15(螺丝批次 PC-LS-001 已到工位8)。工件当前工序=2(拧紧属工序3 工位,先采拧紧数据再报工序3)。工位终端已登录(工位8)。
|
||
|
||
**操作**:拧紧工具/操作工在工位8 对 2 颗螺丝分别上报扭矩。
|
||
- 接口:`POST /api/v1/torque/report`(工位终端经 `POST /api/internal/torque/report` 转发)
|
||
- 2 次请求体(`strain`=扭矩值 N·m,落在 8~12 内):
|
||
```json
|
||
{"sn":"WP-DX-0001","workOrderNo":"WO-20260922-001","stationNo":"8","screwNo":"1","strain":10,"angle":95,"operator":"操作工08"}
|
||
{"sn":"WP-DX-0001","workOrderNo":"WO-20260922-001","stationNo":"8","screwNo":"2","strain":11,"angle":92,"operator":"操作工08"}
|
||
```
|
||
|
||
**系统反应**:每颗写一条拧紧记录;并按「扭矩 / RANGE 8~12」标准自动判定,各写一条步骤考核数据(10、11 均在区间内 → 合格)。
|
||
|
||
**数据变化**:
|
||
- 拧紧记录表新增 2 行:WP-DX-0001 / 工位8 / 螺丝序号1(扭矩10)、序号2(扭矩11),结果=合格(OK)。
|
||
- 步骤考核数据表新增 2 行:考核标准=扭矩、判定逻辑=区间(RANGE)、值=10 与 11、是否合格=是。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/torque/records?sn=WP-DX-0001&stationNo=8` 返回 2 条,扭矩=10、11,结果=合格。
|
||
- 拧紧汇总「应拧颗数=2、实拧颗数=2、合格=2、不合格=0」,满足判定=是。
|
||
- 反例:上报扭矩=13(超上限12)时该条判定=不合格(NG),并触发一条「拧紧扭矩不合格」预警。
|
||
|
||
---
|
||
|
||
## Step 20:报工工序 3(工位 8 · 装螺丝批次)
|
||
|
||
**前置**:Step 18(当前工序=2)、Step 19(2 颗螺丝已拧紧合格)、Step 5(工位8 绑「拧螺丝」流程)。工位终端已登录(工位8)。
|
||
|
||
**操作**:操作工在工位8 扫工件号 → 扫螺丝批次号绑定 → 点"报工"。
|
||
- 接口:`POST /api/v1/workpiece/process/report`
|
||
- 请求体(结构件螺丝 `bindValue` 传批次号,至少绑 1 个批次):
|
||
```json
|
||
{"sn":"WP-DX-0001","processCode":3,"stationNo":8,
|
||
"binds":[{"materialCode":"LS-01","bindValue":"PC-LS-001"}]}
|
||
```
|
||
|
||
**系统反应**:顺序校验(工序3 = 当前工序2+1,通过)→ 落绑定 → 齐套校验(螺丝至少绑 1 个批次,通过)→ 写实绩、推进工件状态。工件走完全部 3 道工序。
|
||
|
||
**数据变化**:
|
||
- 工件装配绑定表新增 1 行:WP-DX-0001 绑 螺丝批次 PC-LS-001(工序3、工位8)。
|
||
- 工件工序实绩表新增 1 行:工序=3、工位=8、状态=已完成、结果=合格(OK)。
|
||
- 工件表:当前工序 2→**3**、状态=在制(PROCESSING)。
|
||
|
||
**断言**:
|
||
- 工件当前工序=3(= 路线工序总数)。
|
||
- `GET /api/v1/workpiece/process/records?sn=WP-DX-0001` 有工序1/2/3 三条实绩,结果均=合格。
|
||
- 反例:在工序2 未完成时直接报工序3(跳站),被拒提示"工序顺序不符,应在工位2 报工"。
|
||
|
||
---
|
||
|
||
### 阶段六 · 完工与成品入库
|
||
|
||
---
|
||
|
||
## Step 21:完工(兜底齐套校验 + 成品回流 + 反冲核销)
|
||
|
||
**前置**:Step 20(工件当前工序=3,三道工序物料均已绑齐)。工位终端已登录(下线工位)。
|
||
|
||
**操作**:操作工在【工位终端 → 下线完工】扫工件号,确认结构件批次与电气件序列号清单,点"完工"。
|
||
- 接口:`POST /api/v1/workpiece/done`
|
||
- 请求体(`batchItems` 结构件批次号、`serialItems` 电气件序列号):
|
||
```json
|
||
{"sn":"WP-DX-0001",
|
||
"batchItems":["PC-TLJ-001","PC-MEN-001","PC-LS-001"],
|
||
"serialItems":["SN-DQ-001","SN-DQ-002"]}
|
||
```
|
||
|
||
**系统反应**(一个事务内顺序完成 5 件事):
|
||
1. **兜底齐套校验**:复核工艺路线中每道工序的装配物料是否都绑齐(工序1 铁架子+门子、工序2 电气件×2、工序3 螺丝),通过。
|
||
2. **工件置完工**:工件状态改「已完工」,记完工时间。
|
||
3. **建关联追溯**:以成品序列号为主键,记录工单号、经过的工位串(`2,5,6,8`)、结构件批次清单、电气件序列号清单,形成"这台成品用了哪些料"的正向追溯。
|
||
4. **进度回写**:工单已完工数 +1(状态回「执行中」,不自动置已完成);日排产已完成数 +1,达计划量 1 → 排产置「已完成」。
|
||
5. **成品回流库房 + 反冲核销**:把成品作为一条新库存回流到库房(成品序列号=工件序列号);反冲按 BOM 单台用量核销工单台账的"已消耗量"(**只核销台账,不再动库存——库存已在 Step 14 出库时扣过**)。
|
||
|
||
**数据变化**:
|
||
- 工件表:WP-DX-0001 状态 在制(PROCESSING)→**已完工(DONE)**,完工时间回填。
|
||
- 关联追溯表新增 1 行:成品序列号=WP-DX-0001、工单号=WO-20260922-001、工位串=2,5,6,8、批次清单=[PC-TLJ-001,PC-MEN-001,PC-LS-001]、序列号清单=[SN-DQ-001,SN-DQ-002]。
|
||
- 工单表:已完工数 0→**1**、状态=执行中(IN_PROGRESS)。
|
||
- 日排产表:已完成数 0→**1**,状态 执行中(PROCESSING)→**已完成(DONE)**。
|
||
- 库房库存表新增 1 行(成品回流):管理方式=2、品类=**成品(3)**、物料编码=DX-100、序列号=WP-DX-0001、数量=1、质量状态=合格、状态=在库、入库单号=`MES:WO-20260922-001`。
|
||
- 工单物料台账表:铁架子已消耗 0→1、门子 0→1、电气件 0→2、螺丝 0→3(消耗量=单台用量×(1+损耗率) 取整:螺丝=2×1.5=3)。
|
||
|
||
**断言**:
|
||
- 工件状态=已完工。
|
||
- `GET /api/v1/work-orders?orderNo=WO-20260922-001` 已完工数=1。
|
||
- `GET /api/v1/daily-plans?orderNo=WO-20260922-001` 已完成数=1、状态=已完成。
|
||
- 库房侧 `GET /api/stock/query?materialCode=DX-100` 返回 1 条成品库存,序列号=WP-DX-0001、品类=成品、数量=1、质量状态=合格、状态=在库。
|
||
- 台账已消耗量:铁架子1、门子1、电气件2、螺丝3;核销不产生新出库单、不再改动库存数量(螺丝库存仍=97)。
|
||
|
||
---
|
||
|
||
## Step 22:工单完工流转(执行中 → 已完成)
|
||
|
||
**前置**:Step 21(工单已完工数=1 = 工单数量1,状态=执行中)。
|
||
|
||
**操作**:计划员在【产线系统 → 工单管理】对该工单点"完工"。
|
||
- 接口:`POST /api/v1/work-orders/status`
|
||
- 请求体:`{"id":${orderId},"status":"DONE","reason":"1 台已全部完工"}`
|
||
|
||
**系统反应**:校验流转合法(执行中可置已完成),状态改「已完成」。这是工单终态。
|
||
|
||
**数据变化**:工单表:状态 执行中(IN_PROGRESS)→**已完成(DONE)**;写状态变更日志。
|
||
|
||
**断言**:
|
||
- `GET /api/v1/work-orders/:id` 状态=已完成、已完工数=1、数量=1。
|
||
- 已完工数=数量,工单闭合。
|
||
|
||
---
|
||
|
||
### 阶段七 · 多余料回仓库 + 成品追溯
|
||
|
||
---
|
||
|
||
## Step 23:工位退料(工位 8 · 螺丝用剩 1 颗)
|
||
|
||
**前置**:Step 21 完工。螺丝单台标准备料 3 颗(含 50% 损耗预留),实装拧 2 颗,剩 1 颗需退回库房。工位终端已登录(工位8)。
|
||
|
||
**操作**:操作工在【工位终端 → 退料】选工单、物料=螺丝、数量=1、原因="装配用剩退库",提交。
|
||
- 接口:`POST /api/return-material`(工位终端 → 产线内部接口 → 库房预建退库单)
|
||
- 请求体:
|
||
```json
|
||
{"orderNo":"WO-20260922-001","stationNo":8,"sn":"WP-DX-0001",
|
||
"materialCode":"LS-01","materialName":"螺丝","spec":"M4×10","unit":"颗",
|
||
"qty":1,"reason":"装配用剩退库"}
|
||
```
|
||
|
||
**系统反应**:产线系统落一条退料事件日志,转调库房预建一张「待确认收货」退库单(来源=工位)。库存在库管确认收货后才加回。
|
||
|
||
**数据变化**:库房退库单表新增 1 行:退库单号=`RT<...>`、来源类型=工位(station)、工单号=WO-20260922-001、工位=8、物料=LS-01 螺丝、数量=1、原因=装配用剩退库、状态=**待确认(PENDING)**。
|
||
|
||
**断言**:
|
||
- 库房侧退库单列表存在该单,状态=待确认、数量=1。
|
||
- 此刻螺丝库存仍=97(尚未加回,等 Step 24 确认)。
|
||
|
||
---
|
||
|
||
## Step 24:库管确认收货(退库单 → 已收货,库存加回)
|
||
|
||
**前置**:Step 23(退库单待确认)。库房系统已登录(库管账号)。
|
||
|
||
**操作**:库管在【库房系统 → 退库管理】对该退库单点"确认收货",退库类型选"剩余物料",指定回退库位 A 区、批次 PC-LS-001。
|
||
- 接口:`POST /api/return-order/confirm`
|
||
- 请求体:`{"returnNo":"RT<上一步单号>","returnType":"surplus","zoneCode":"A","batchNo":"PC-LS-001"}`
|
||
|
||
**系统反应**:在一个事务内把退库单置「已收货」并把库存加回。剩余物料(surplus)按口径置质量状态「**未检**」——用剩的料不直接判合格,需复检后方可再上线,因此不并入原「合格」批次行,而是独立成一条未检库存行(同批次号 PC-LS-001、数量 1、质量状态未检)。
|
||
|
||
**数据变化**:
|
||
- 退库单表:状态 待确认(PENDING)→**已收货(RECEIVED)**,回填收货人、收货时间。
|
||
- 库房库存表新增 1 行(螺丝退库):管理方式=1、物料=LS-01、批次=PC-LS-001、数量=1、质量状态=**未检**、状态=在库、区域=A、入库单号=`RET:RT<单号>`。
|
||
- 工单物料台账表(螺丝行):已退回量 0→**1**;净领用(已出库 3 − 已退回 1 = 2)< 需求量 3,状态由「领料完结」**回退为「进行中」**(退料回补缺口,允许后续再补料)。
|
||
|
||
**断言**:
|
||
- 退库单状态=已收货。
|
||
- `GET /api/stock/query?materialCode=LS-01`:合格批次 PC-LS-001 数量=97(未变),另有一条未检 PC-LS-001 数量=1;螺丝在库总量=97+1=**98**。
|
||
- 台账螺丝行:已出库=3、已退回=1、净领用=2、已消耗=3、状态=进行中。
|
||
- **数量等式(螺丝全链路闭合)**:入库 100 = 出库 3 + 期末在库 97;出库 3 = 装进成品 2 + 退回 1;退回 1 → 未检库存 1。总库存 98 = 97(合格) + 1(未检退回)。
|
||
|
||
---
|
||
|
||
## Step 25:成品追溯(按成品序列号回查全链路)
|
||
|
||
**前置**:Step 21(关联追溯已建)、Step 19(拧紧记录)、Step 17~20(三道工序实绩)。产线系统或工位终端已登录。
|
||
|
||
**操作**:质量员在【产线系统 → 追溯查询】扫成品序列号 WP-DX-0001。
|
||
- 接口:`GET /api/v1/trace?sn=WP-DX-0001`(工位终端经 `GET /api/trace?sn=` 代理)
|
||
|
||
**系统反应**:以成品序列号汇总回查:工件状态、工单、经过的工位串、每道工序的报工时间与操作人、装机的结构件批次与电气件序列号、拧紧扭矩数据。
|
||
|
||
**数据变化**:只读查询,不改数据。
|
||
|
||
**断言**:
|
||
- 追溯返回:成品序列号=WP-DX-0001、工单=WO-20260922-001、工件状态=已完工、工位串=2,5,6,8。
|
||
- 工序时间线含工序1(工位2)、工序2(工位5)、工序3(工位8) 三条实绩,结果均合格。
|
||
- 物料清单:铁架子批次 PC-TLJ-001、门子批次 PC-MEN-001、螺丝批次 PC-LS-001、电气件序列号 SN-DQ-001 与 SN-DQ-002。
|
||
- 拧紧数据:2 颗,扭矩 10 与 11,均合格。
|
||
|
||
---
|
||
|
||
## 四、全链路数量等式总断言(跑完必须全部闭合)
|
||
|
||
| 物料 | 入库(Step7/8) | 出库到工位(Step14) | 装进成品(Step17~21) | 退回库房(Step23/24) | 期末在库 |
|
||
|---|---|---|---|---|---|
|
||
| 铁架子 TLJ-01 | 5 | 1 | 1 | 0 | 4 |
|
||
| 门子 MEN-01 | 5 | 1 | 1 | 0 | 4 |
|
||
| 电气件 DQJ-01 | 4(SN) | 2(SN001/002) | 2 | 0 | 2(SN003/004 在库) |
|
||
| 螺丝 LS-01 | 100 | 3 | 2 | 1 | 98(97合格+1未检) |
|
||
| 成品 DX-100 | — | — | 下线 1(WP-DX-0001) | — | 1(合格·在库) |
|
||
|
||
**闭合校验(逐条必须成立)**:
|
||
- 铁架子:5 = 4(在库) + 1(装进成品)。
|
||
- 门子:5 = 4(在库) + 1(装进成品)。
|
||
- 电气件:4 = 2(SN003/004 在库) + 2(SN001/002 装进成品)。
|
||
- 螺丝:100 = 97(合格在库) + 3(出库);出库 3 = 2(装进成品) + 1(退回未检);期末在库 98 = 97 + 1。
|
||
- 工单:数量 1 = 已完工 1;工单状态=已完成。
|
||
- 日排产:计划 1 = 已完成 1;排产状态=已完成。
|
||
- 台账(Step21 反冲后、Step24 退库后最终态):铁架子 已出库=已消耗=总量=1、状态领料完结;门子 已出库=已消耗=总量=1、状态领料完结;电气件 已出库=已消耗=总量=2、状态领料完结;螺丝 已出库=总量=3、已消耗=3(按 BOM 单台标准量 2×1.5 计)、已退回=1、净领用=2、状态因退料回退为进行中。
|
||
- 关联追溯:成品 WP-DX-0001 的批次清单 3 项 + 序列号清单 2 项,与装进成品列完全一致。
|
||
|
||
---
|
||
|
||
## 五、回归后数据复位(供重复执行)
|
||
|
||
> 本链路会写入成品序列号 WP-DX-0001(全局唯一)、批次 PC-* 与序列号 SN-DQ-*(全局唯一)。重复执行前需清理,否则上线/入库会撞唯一约束。
|
||
|
||
复位顺序(与建数据相反):
|
||
1. 删除关联追溯、工件工序实绩、工件装配绑定、拧紧记录、步骤考核数据(按 sn=WP-DX-0001)。
|
||
2. 删除工件(WP-DX-0001)、日排产、工单(WO-20260922-001)及其状态日志。
|
||
3. 删除备料单、工单物料台账(按 orderNo)。
|
||
4. 删除库房退库单、出库单及明细、入库单及明细、检验记录、库存行(成品 DX-100 与 4 种零部件的批次/SN 行)。
|
||
5. 删除工位派工(生产日 D)、工艺流程与工序步骤/考核标准、产品物料清单、物料档案、产品型号、区域 A(如与其他用例共用则保留)。
|
||
|
||
> 若只需快速重跑,可保留主数据(Step1~6),仅清理 Step7 起的库存/单据/工件数据,并从 Step7 重新入库。
|