4. 工序流转卡数据模型设计
为什么流转卡需要独立的数据模型
流转卡不是一张静态表单,而是贯穿多道工序的过程记录载体。它要回答两类问题:正查——某件产品经过了哪些工序、每道工序谁做的、用了什么设备、结果是否合格;反查——某台设备/某个操作员/某个批次在某个时间段内处理过哪些产品。若把每道工序的数据平铺在一张宽表里,字段会随工序数量膨胀,且不同工序的投入产出结构不一致,正查与反查都会变得困难。
因此采用「流转卡主表 + 工序流转明细表」的两级模型:主表承载产品身份与整体状态,明细表按工序逐条记录投入、产出、设备、人员、时间和质量状态。每道工序一条记录,工序序号作为排序与追溯链的锚点。
字段设计
| 层级 | 字段 | 类型 | 说明 |
|---|---|---|---|
| 主表 card | card_id | 字符串 | 流转卡唯一标识 |
| 主表 card | sn | 字符串 | 产品序列号,正查入口 |
| 主表 card | work_order | 字符串 | 工单号 |
| 主表 card | product_model | 字符串 | 产品型号 |
| 主表 card | current_op | 整数 | 当前工序序号 |
| 主表 card | card_status | 枚举 | 在制/完工/报废/返修 |
| 明细 op_log | card_id | 字符串 | 外键,关联主表 |
| 明细 op_log | op_seq | 整数 | 工序序号,1..N |
| 明细 op_log | op_name | 字符串 | 工序名称 |
| 明细 op_log | input_batch | 字符串 | 投入批次/物料码 |
| 明细 op_log | input_qty | 数值 | 投入数量 |
| 明细 op_log | output_sn | 字符串 | 产出序列号(可为空表示未赋码) |
| 明细 op_log | output_qty | 数值 | 产出数量 |
| 明细 op_log | equipment_id | 字符串 | 设备编号,反查入口 |
| 明细 op_log | operator_id | 字符串 | 操作员编号,反查入口 |
| 明细 op_log | start_time | 时间戳 | 工序开始时间 |
| 明细 op_log | end_time | 时间戳 | 工序结束时间 |
| 明细 op_log | qc_status | 枚举 | 合格/不合格/待检 |
| 明细 op_log | defect_code | 字符串 | 不良代码,qc_status=不合格时必填 |
模型结构与正反查路径
建表与验证
以下 SQL 可直接在 SQLite 中执行,用于验证模型能否同时支撑正查与反查。示例数据为教学构造,非真实产线数据。
CREATE TABLE card (
card_id TEXT PRIMARY KEY,
sn TEXT NOT NULL UNIQUE,
work_order TEXT NOT NULL,
product_model TEXT NOT NULL,
current_op INTEGER DEFAULT 0,
card_status TEXT DEFAULT '在制'
);
CREATE TABLE op_log (
card_id TEXT NOT NULL,
op_seq INTEGER NOT NULL,
op_name TEXT NOT NULL,
input_batch TEXT,
input_qty REAL,
output_sn TEXT,
output_qty REAL,
equipment_id TEXT,
operator_id TEXT,
start_time TEXT,
end_time TEXT,
qc_status TEXT DEFAULT '待检',
defect_code TEXT,
PRIMARY KEY (card_id, op_seq),
FOREIGN KEY (card_id) REFERENCES card(card_id)
);
-- 教学示例数据
INSERT INTO card VALUES ('C001','SN20240001','WO-8801','M-100',3,'在制');
INSERT INTO op_log VALUES
('C001',1,'下料','B-A01',10,'SN20240001',10,'EQ-01','U01','2024-06-01 08:00','2024-06-01 08:20','合格',NULL),
('C001',2,'加工','B-A01',10,'SN20240001',10,'EQ-02','U02','2024-06-01 08:25','2024-06-01 09:10','合格',NULL),
('C001',3,'装配','B-B07',10,'SN20240001',10,'EQ-03','U01','2024-06-01 09:15','2024-06-01 10:00','不合格','D-12');
-- 正查:由 sn 查全部工序履历
SELECT op_seq, op_name, equipment_id, operator_id, qc_status, defect_code
FROM op_log
WHERE card_id = (SELECT card_id FROM card WHERE sn = 'SN20240001')
ORDER BY op_seq;
-- 反查:由设备查该设备在时间段内处理过的产品
SELECT DISTINCT c.sn, o.op_seq, o.op_name, o.start_time
FROM op_log o JOIN card c ON o.card_id = c.card_id
WHERE o.equipment_id = 'EQ-03'
AND o.start_time BETWEEN '2024-06-01 00:00' AND '2024-06-01 23:59';
验证要点:正查结果应按 op_seq 返回 1→2→3 三条记录,且第 3 条 qc_status 为「不合格」、defect_code 为「D-12」;反查 EQ-03 应返回 SN20240001 的 OP3 记录。若正查缺行或反查为空,说明 card_id 外键关联或 equipment_id 写入有误。
关键约束与边界处理
- 工序序号唯一性:主键 (card_id, op_seq) 防止同一张卡同一工序重复写入,返修时用新 op_seq 追加而非覆盖。
- 投入产出平衡:同一工序 input_qty 与 output_qty 的差值应等于该工序的报废/损耗数量,可在应用层校验。
- 质量状态联动:qc_status 为「不合格」时 defect_code 必填;主表 card_status 在末道工序合格后置为「完工」。
- 时间顺序:op_seq 递增时 start_time 不应早于上一工序的 end_time,用于发现补录或时钟异常。