Files
zkxw/docs/sql/migrations/2026-11-13-uc-msc-production-task-backfill.sql
T
zlwuandCursor e4b62d6406 chore(sql): 增加 UC 入库编码生产任务一次性回补脚本
与种子 SQL 分开,按空任务入库工单补派五步任务;并在种子/Python 回补说明中交叉引用。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-13 11:12:07 +08:00

410 lines
12 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 【一次性回补】UC 开头实验室入库编码 → 补派「脐带MSC原代培养」5 步生产任务
-- 与种子脚本分开:先执行 2026-11-13-uc-msc-builtin-task-set.sql(或确保模版已存在),再执行本文件。
-- 等价于 backend/scripts/backfill_uc_msc_production_tasks.py --apply 的候选范围。
--
-- 候选条件(须全部满足):
-- 1) 样本接收 accept_conclusion=js、del_flag=0
-- 2) lab_storage_code 以 UC/uc 开头(非空)
-- 3) 关联入库生产工单 work_order_type=inbound、状态 dpz/jxz、del_flag=0
-- 4) 该工单当前无任何有效生产任务(已有任务如 UC2026010 跳过)
--
-- 动作:
-- - 每工单插入 1 条 biz_production_task(状态 dpz,任务名 {入库编码}样本处理)
-- - 从 UC 内置路线复制 5 个步骤到 biz_production_task_step(及试剂/耗材/产出/采集子表)
-- - 工单状态 dpz → jxz(已是 jxz/ywc 的不改 ywc;本脚本候选不含 ywc)
--
-- 幂等:已有有效任务的工单不会进入候选;重复执行影响行数应为 0。
-- 前置:biz_process_route.route_code='MSC原代-UC-BUILTIN'(或固定 id UCMSCROUTE…)及 5 步须已存在。
-- MySQL 5.7 / utf8mb4。未在生产库执行;执行前请先跑下方「预览」SELECT。
SET NAMES utf8mb4;
-- ---------------------------------------------------------------------------
-- 0. 解析 UC 内置工艺路线
-- ---------------------------------------------------------------------------
SET @uc_route_id := (
SELECT r.id
FROM biz_process_route r
WHERE r.del_flag = 0
AND (
r.id = 'UCMSCROUTEA5CC11F194118AC54085447A'
OR r.route_code = 'MSC原代-UC-BUILTIN'
OR (r.route_name = '脐带MSC原代培养(内置模版)' AND r.is_builtin = '1')
)
ORDER BY
CASE
WHEN r.id = 'UCMSCROUTEA5CC11F194118AC54085447A' THEN 0
WHEN r.route_code = 'MSC原代-UC-BUILTIN' THEN 1
ELSE 2
END
LIMIT 1
);
SET @uc_step_count := (
SELECT COUNT(*)
FROM biz_process_route_step s
WHERE s.route_id = @uc_route_id
AND s.del_flag = 0
);
-- 预览:模版是否就绪(应 route 非空且 step_count=5)
SELECT @uc_route_id AS uc_route_id, @uc_step_count AS uc_step_count;
-- 若模版未就绪则主动失败(避免插入无步骤任务)
SET @uc_ready := IF(@uc_route_id IS NOT NULL AND @uc_step_count = 5, 1, 0);
-- 下面用 @uc_ready 约束所有写操作;为 0 时 INSERT 选不出行
-- ---------------------------------------------------------------------------
-- 1. 候选工单临时表
-- ---------------------------------------------------------------------------
DROP TEMPORARY TABLE IF EXISTS tmp_uc_wo_backfill;
CREATE TEMPORARY TABLE tmp_uc_wo_backfill (
seq INT NOT NULL AUTO_INCREMENT,
work_order_id VARCHAR(64) NOT NULL,
reception_id VARCHAR(64) NOT NULL,
lab_storage_code VARCHAR(32) NOT NULL,
tenant_no VARCHAR(64) NOT NULL,
sample_code VARCHAR(32) NULL,
task_id VARCHAR(64) NULL,
task_no VARCHAR(32) NULL,
route_id VARCHAR(64) NULL,
PRIMARY KEY (seq),
UNIQUE KEY uk_wo (work_order_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO tmp_uc_wo_backfill (
work_order_id, reception_id, lab_storage_code, tenant_no, sample_code, route_id
)
SELECT
wo.id,
rec.id,
TRIM(rec.lab_storage_code),
wo.tenant_no,
wo.sample_code,
@uc_route_id
FROM biz_production_work_order wo
INNER JOIN biz_sample_reception rec
ON rec.id = wo.reception_id
AND rec.tenant_no = wo.tenant_no
AND rec.del_flag = 0
WHERE @uc_ready = 1
AND wo.del_flag = 0
AND wo.work_order_type = 'inbound'
AND wo.work_order_status IN ('dpz', 'jxz')
AND rec.accept_conclusion = 'js'
AND rec.lab_storage_code IS NOT NULL
AND TRIM(rec.lab_storage_code) <> ''
AND (
rec.lab_storage_code LIKE 'UC%'
OR rec.lab_storage_code LIKE 'uc%'
)
AND NOT EXISTS (
SELECT 1
FROM biz_production_task t
WHERE t.work_order_id = wo.id
AND t.tenant_no = wo.tenant_no
AND t.del_flag = 0
)
ORDER BY rec.reception_time ASC, wo.create_time ASC;
-- 预览候选(执行写库前请核对)
SELECT
seq,
work_order_id,
lab_storage_code,
sample_code,
tenant_no,
reception_id
FROM tmp_uc_wo_backfill
ORDER BY seq;
SELECT COUNT(*) AS candidate_count FROM tmp_uc_wo_backfill;
-- 分配 task_id / task_no(RW + yyyymmdd + 4 位序号,接当日已有最大序号)
SET @task_day := DATE_FORMAT(NOW(), '%Y%m%d');
SET @task_no_base := (
SELECT IFNULL(MAX(CAST(SUBSTRING(t.task_no, 11) AS UNSIGNED)), 0)
FROM biz_production_task t
WHERE t.task_no LIKE CONCAT('RW', @task_day, '%')
);
UPDATE tmp_uc_wo_backfill
SET
task_id = UPPER(REPLACE(UUID(), '-', '')),
task_no = CONCAT('RW', @task_day, LPAD(@task_no_base + seq, 4, '0'));
-- ---------------------------------------------------------------------------
-- 2. 插入生产任务
-- ---------------------------------------------------------------------------
INSERT INTO biz_production_task (
id, task_no, work_order_id, order_source, task_type, task_name, description,
route_id, task_status, current_assignee_user_id, started_time, completed_time,
conclusion, remark, attachments, equipment_ids, equipment_name,
tenant_no, order_num, create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
c.task_id,
c.task_no,
c.work_order_id,
'inbound',
'cell_storage',
CONCAT(c.lab_storage_code, '样本处理'),
'脐带MSC原代培养(内置模版)',
c.route_id,
'dpz',
NULL,
NULL,
NULL,
NULL,
'一次性SQL回补:UC入库编码自动派发',
NULL,
r.equipment_ids,
r.equipment_name,
c.tenant_no,
0,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_wo_backfill c
INNER JOIN biz_process_route r
ON r.id = c.route_id
AND r.del_flag = 0
WHERE @uc_ready = 1
AND c.task_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM biz_production_task t
WHERE t.work_order_id = c.work_order_id
AND t.tenant_no = c.tenant_no
AND t.del_flag = 0
);
-- ---------------------------------------------------------------------------
-- 3. 步骤映射:路线步骤 → 新任务步骤 ID
-- ---------------------------------------------------------------------------
DROP TEMPORARY TABLE IF EXISTS tmp_uc_step_map;
CREATE TEMPORARY TABLE tmp_uc_step_map (
task_id VARCHAR(64) NOT NULL,
work_order_id VARCHAR(64) NOT NULL,
tenant_no VARCHAR(64) NOT NULL,
route_step_id VARCHAR(64) NOT NULL,
task_step_id VARCHAR(64) NOT NULL,
step_order INT NOT NULL,
PRIMARY KEY (task_id, route_step_id),
KEY ix_route_step (route_step_id),
KEY ix_task_step (task_step_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO tmp_uc_step_map (
task_id, work_order_id, tenant_no, route_step_id, task_step_id, step_order
)
SELECT
c.task_id,
c.work_order_id,
c.tenant_no,
rs.id,
UPPER(REPLACE(UUID(), '-', '')),
rs.step_order
FROM tmp_uc_wo_backfill c
INNER JOIN biz_process_route_step rs
ON rs.route_id = c.route_id
AND rs.del_flag = 0
WHERE @uc_ready = 1
AND EXISTS (
SELECT 1 FROM biz_production_task t
WHERE t.id = c.task_id AND t.del_flag = 0
);
-- ---------------------------------------------------------------------------
-- 4. 插入任务步骤
-- ---------------------------------------------------------------------------
INSERT INTO biz_production_task_step (
id, task_id, step_order, process_code, category_id, process_name, description,
equipment_ids, equipment_name, estimated_duration, actual_duration,
sop_ids, sop_content, step_status, planned_start_time, started_time,
completed_time, completed_by, tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
m.task_step_id,
m.task_id,
rs.step_order,
rs.process_code,
rs.category_id,
rs.process_name,
rs.description,
rs.equipment_ids,
rs.equipment_name,
rs.estimated_duration,
NULL,
rs.sop_ids,
rs.sop_content,
'dzx',
NULL,
NULL,
NULL,
NULL,
m.tenant_no,
IFNULL(rs.order_num, rs.step_order),
NULL,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_step_map m
INNER JOIN biz_process_route_step rs
ON rs.id = m.route_step_id
AND rs.del_flag = 0
WHERE NOT EXISTS (
SELECT 1 FROM biz_production_task_step x
WHERE x.id = m.task_step_id
);
-- ---------------------------------------------------------------------------
-- 5. 复制路线步骤子表 → 任务步骤子表
-- ---------------------------------------------------------------------------
INSERT INTO biz_production_task_step_reagent (
id, step_id, reagent_code, reagent_name, spec, standard_usage, unit,
is_key_material, tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(REPLACE(UUID(), '-', '')),
m.task_step_id,
src.reagent_code,
src.reagent_name,
src.spec,
src.standard_usage,
src.unit,
src.is_key_material,
m.tenant_no,
src.order_num,
src.remark,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_step_map m
INNER JOIN biz_process_route_step_reagent src
ON src.step_id = m.route_step_id
AND src.del_flag = 0;
INSERT INTO biz_production_task_step_consumable (
id, step_id, consumable_code, consumable_name, spec_model, standard_usage,
unit, is_required, remark, tenant_no, order_num,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(REPLACE(UUID(), '-', '')),
m.task_step_id,
src.consumable_code,
src.consumable_name,
src.spec_model,
src.standard_usage,
src.unit,
src.is_required,
src.remark,
m.tenant_no,
src.order_num,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_step_map m
INNER JOIN biz_process_route_step_consumable src
ON src.step_id = m.route_step_id
AND src.del_flag = 0;
INSERT INTO biz_production_task_step_output (
id, step_id, output_type_id, output_name, output_barcode,
tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(REPLACE(UUID(), '-', '')),
m.task_step_id,
src.output_type_id,
src.output_name,
src.output_barcode,
m.tenant_no,
src.order_num,
src.remark,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_step_map m
INNER JOIN biz_process_route_step_output src
ON src.step_id = m.route_step_id
AND src.del_flag = 0;
INSERT INTO biz_production_task_step_data_collection (
id, step_id, collection_name, unit, tenant_no, order_num, remark,
create_by, create_dept_id, create_time, update_by, update_time, del_flag
)
SELECT
UPPER(REPLACE(UUID(), '-', '')),
m.task_step_id,
src.collection_name,
src.unit,
m.tenant_no,
src.order_num,
src.remark,
NULL,
'',
NOW(),
NULL,
NOW(),
0
FROM tmp_uc_step_map m
INNER JOIN biz_process_route_step_data_collection src
ON src.step_id = m.route_step_id
AND src.del_flag = 0;
-- ---------------------------------------------------------------------------
-- 6. 回写工单状态:有任务则 jxz(不改 ywc)
-- ---------------------------------------------------------------------------
UPDATE biz_production_work_order wo
INNER JOIN tmp_uc_wo_backfill c ON c.work_order_id = wo.id
SET
wo.work_order_status = 'jxz',
wo.update_time = NOW()
WHERE wo.del_flag = 0
AND wo.work_order_status = 'dpz'
AND EXISTS (
SELECT 1 FROM biz_production_task t
WHERE t.work_order_id = wo.id
AND t.tenant_no = wo.tenant_no
AND t.del_flag = 0
);
-- ---------------------------------------------------------------------------
-- 7. 结果核对
-- ---------------------------------------------------------------------------
SELECT
c.lab_storage_code,
c.work_order_id,
wo.work_order_no,
wo.work_order_status,
t.id AS task_id,
t.task_no,
t.task_name,
(SELECT COUNT(*) FROM biz_production_task_step s WHERE s.task_id = t.id AND s.del_flag = 0) AS step_count
FROM tmp_uc_wo_backfill c
LEFT JOIN biz_production_work_order wo ON wo.id = c.work_order_id
LEFT JOIN biz_production_task t ON t.id = c.task_id AND t.del_flag = 0
ORDER BY c.seq;
DROP TEMPORARY TABLE IF EXISTS tmp_uc_step_map;
DROP TEMPORARY TABLE IF EXISTS tmp_uc_wo_backfill;