141 lines
4.7 KiB
SQL
141 lines
4.7 KiB
SQL
-- 迁移前只读核查必须在一个一致性快照中同时生成:
|
||
-- 1. 未完成报废单数量;2. 缺失根资产/资产树异常数量;3. 供人工核对及计算指纹的完整资产树。
|
||
-- deploy.sh 会展示并哈希同一批 REVIEW_ROW,禁止把展示与指纹拆成两次查询。
|
||
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
|
||
START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY;
|
||
|
||
WITH RECURSIVE `active_disposals` AS (
|
||
SELECT
|
||
disposal.`id`,
|
||
disposal.`status`,
|
||
disposal.`equipment_id`,
|
||
disposal.`equipment_code`,
|
||
disposal.`applied_at`,
|
||
disposal.`applied_by`,
|
||
disposal.`created_at`,
|
||
disposal.`updated_at`
|
||
FROM `disposal_record` disposal
|
||
WHERE disposal.`status` IN ('pending', 'approved')
|
||
), `active_disposal_tree` AS (
|
||
SELECT
|
||
disposal.`id` AS `disposal_id`,
|
||
equipment.`id` AS `equipment_id`,
|
||
equipment.`equipment_code`,
|
||
equipment.`equipment_name`,
|
||
equipment.`equipment_model`,
|
||
equipment.`equipment_type`,
|
||
equipment.`parent_id`,
|
||
parent.`equipment_code` AS `parent_equipment_code`,
|
||
equipment.`status` AS `current_status`,
|
||
equipment.`department_id`,
|
||
equipment.`storage_location_id`,
|
||
equipment.`mount_status`,
|
||
equipment.`updated_at` AS `equipment_updated_at`,
|
||
0 AS `depth`,
|
||
CAST(CONCAT('/', equipment.`id`, '/') AS CHAR(4096)) AS `visited_path`,
|
||
0 AS `cycle_detected`
|
||
FROM `active_disposals` disposal
|
||
INNER JOIN `equipment` equipment ON equipment.`id` = disposal.`equipment_id`
|
||
LEFT JOIN `equipment` parent ON parent.`id` = equipment.`parent_id`
|
||
|
||
UNION ALL
|
||
|
||
SELECT
|
||
tree.`disposal_id`,
|
||
child.`id`,
|
||
child.`equipment_code`,
|
||
child.`equipment_name`,
|
||
child.`equipment_model`,
|
||
child.`equipment_type`,
|
||
child.`parent_id`,
|
||
tree.`equipment_code`,
|
||
child.`status`,
|
||
child.`department_id`,
|
||
child.`storage_location_id`,
|
||
child.`mount_status`,
|
||
child.`updated_at`,
|
||
tree.`depth` + 1,
|
||
CONCAT(tree.`visited_path`, child.`id`, '/'),
|
||
LOCATE(CONCAT('/', child.`id`, '/'), tree.`visited_path`) > 0
|
||
FROM `active_disposal_tree` tree
|
||
INNER JOIN `equipment` child ON child.`parent_id` = tree.`equipment_id`
|
||
WHERE tree.`depth` < 100
|
||
AND tree.`cycle_detected` = 0
|
||
), `review_rows` AS (
|
||
SELECT
|
||
1 AS `sort_group`,
|
||
CONCAT('D:', LPAD(disposal.`id`, 20, '0')) AS `sort_key`,
|
||
CAST(JSON_OBJECT(
|
||
'record_type', 'disposal',
|
||
'disposal_id', disposal.`id`,
|
||
'status', disposal.`status`,
|
||
'root_equipment_id', disposal.`equipment_id`,
|
||
'root_equipment_code', disposal.`equipment_code`,
|
||
'applied_at', DATE_FORMAT(disposal.`applied_at`, '%Y-%m-%dT%H:%i:%s.%f'),
|
||
'applied_by', disposal.`applied_by`,
|
||
'created_at', DATE_FORMAT(disposal.`created_at`, '%Y-%m-%dT%H:%i:%s.%f'),
|
||
'updated_at', DATE_FORMAT(disposal.`updated_at`, '%Y-%m-%dT%H:%i:%s.%f')
|
||
) AS CHAR) AS `payload`
|
||
FROM `active_disposals` disposal
|
||
|
||
UNION ALL
|
||
|
||
SELECT
|
||
2 AS `sort_group`,
|
||
CONCAT(
|
||
'T:', LPAD(tree.`disposal_id`, 20, '0'), ':',
|
||
LPAD(tree.`depth`, 3, '0'), ':', LPAD(tree.`equipment_id`, 20, '0')
|
||
) AS `sort_key`,
|
||
CAST(JSON_OBJECT(
|
||
'record_type', 'asset_tree',
|
||
'disposal_id', tree.`disposal_id`,
|
||
'equipment_id', tree.`equipment_id`,
|
||
'equipment_code', tree.`equipment_code`,
|
||
'equipment_name', tree.`equipment_name`,
|
||
'equipment_model', tree.`equipment_model`,
|
||
'equipment_type', tree.`equipment_type`,
|
||
'parent_id', tree.`parent_id`,
|
||
'parent_equipment_code', tree.`parent_equipment_code`,
|
||
'current_status', tree.`current_status`,
|
||
'department_id', tree.`department_id`,
|
||
'storage_location_id', tree.`storage_location_id`,
|
||
'mount_status', tree.`mount_status`,
|
||
'equipment_updated_at', DATE_FORMAT(tree.`equipment_updated_at`, '%Y-%m-%dT%H:%i:%s.%f'),
|
||
'depth', tree.`depth`,
|
||
'cycle_detected', tree.`cycle_detected`
|
||
) AS CHAR) AS `payload`
|
||
FROM `active_disposal_tree` tree
|
||
), `precheck_output` AS (
|
||
SELECT 0 AS `sort_group`, '1' AS `sort_key`, 'MISSING_ROOT_COUNT' AS `record_type`,
|
||
CAST(COUNT(*) AS CHAR) AS `payload`
|
||
FROM `active_disposals` disposal
|
||
LEFT JOIN `equipment` equipment ON equipment.`id` = disposal.`equipment_id`
|
||
WHERE equipment.`id` IS NULL
|
||
|
||
UNION ALL
|
||
|
||
SELECT 0, '2', 'TREE_ANOMALY_COUNT', CAST(COUNT(*) AS CHAR)
|
||
FROM `active_disposal_tree`
|
||
WHERE `cycle_detected` = 1 OR `depth` >= 100
|
||
|
||
UNION ALL
|
||
|
||
SELECT 0, '3', 'ACTIVE_DISPOSAL_COUNT', CAST(COUNT(*) AS CHAR)
|
||
FROM `active_disposals`
|
||
|
||
UNION ALL
|
||
|
||
SELECT 0, '4', 'REVIEW_ROW_COUNT', CAST(COUNT(*) AS CHAR)
|
||
FROM `review_rows`
|
||
|
||
UNION ALL
|
||
|
||
SELECT `sort_group`, `sort_key`, 'REVIEW_ROW', `payload`
|
||
FROM `review_rows`
|
||
)
|
||
SELECT `record_type`, `payload`
|
||
FROM `precheck_output`
|
||
ORDER BY `sort_group`, `sort_key`;
|
||
|
||
COMMIT;
|