221 lines
14 KiB
SQL
221 lines
14 KiB
SQL
SET NAMES utf8mb4;
|
|
USE baiyue_firstleg;
|
|
|
|
DROP PROCEDURE IF EXISTS migrate_phase3_channel_containers;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE migrate_phase3_channel_containers()
|
|
BEGIN
|
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
|
BEGIN
|
|
GET DIAGNOSTICS CONDITION 1
|
|
@phase3_channel_sqlstate = RETURNED_SQLSTATE,
|
|
@phase3_channel_errno = MYSQL_ERRNO,
|
|
@phase3_channel_message = MESSAGE_TEXT;
|
|
END;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking' AND column_name='channel_code') THEN
|
|
ALTER TABLE fl_ocean_booking ADD COLUMN channel_code VARCHAR(64) NULL COMMENT '订舱渠道编码快照' AFTER customer_name;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking' AND column_name='channel_name') THEN
|
|
ALTER TABLE fl_ocean_booking ADD COLUMN channel_name VARCHAR(128) NULL COMMENT '订舱渠道名称快照' AFTER channel_code;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking' AND column_name='warehouse_id') THEN
|
|
ALTER TABLE fl_ocean_booking ADD COLUMN warehouse_id BIGINT UNSIGNED NULL COMMENT '国内中转仓ID快照' AFTER channel_name;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking' AND column_name='warehouse_name') THEN
|
|
ALTER TABLE fl_ocean_booking ADD COLUMN warehouse_name VARCHAR(128) NULL COMMENT '国内中转仓名称快照' AFTER warehouse_id;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking_container_requirement' AND column_name='capacity_cbm') THEN
|
|
ALTER TABLE fl_ocean_booking_container_requirement ADD COLUMN capacity_cbm DECIMAL(18,4) NULL COMMENT '柜型容量快照m3' AFTER container_kind;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_ocean_booking_container_requirement' AND column_name='max_weight_kg') THEN
|
|
ALTER TABLE fl_ocean_booking_container_requirement ADD COLUMN max_weight_kg DECIMAL(18,3) NULL COMMENT '柜型最大承重快照kg' AFTER capacity_cbm;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_container_booking' AND column_name='channel_code') THEN
|
|
ALTER TABLE fl_container_booking ADD COLUMN channel_code VARCHAR(64) NULL COMMENT '订舱渠道编码快照' AFTER cabinet_no;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_container_booking' AND column_name='channel_group_code') THEN
|
|
ALTER TABLE fl_container_booking ADD COLUMN channel_group_code VARCHAR(64) NULL COMMENT '模拟柜计划渠道分组;关联真实订舱后继续保留' AFTER merged_into_container_booking_id;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_container_booking' AND column_name='channel_name') THEN
|
|
ALTER TABLE fl_container_booking ADD COLUMN channel_name VARCHAR(128) NULL COMMENT '订舱渠道名称快照' AFTER channel_code;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_container_booking' AND column_name='ocean_booking_id') THEN
|
|
ALTER TABLE fl_container_booking ADD COLUMN ocean_booking_id BIGINT UNSIGNED NULL COMMENT '来源订舱ID' AFTER channel_name;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_container_booking' AND column_name='ocean_booking_requirement_id') THEN
|
|
ALTER TABLE fl_container_booking ADD COLUMN ocean_booking_requirement_id BIGINT UNSIGNED NULL COMMENT '来源订舱箱型需求ID' AFTER ocean_booking_id;
|
|
END IF;
|
|
|
|
UPDATE fl_container_booking c
|
|
JOIN fl_ocean_booking_container_allocation a ON a.container_booking_id=c.id
|
|
JOIN fl_ocean_booking b ON b.id=a.ocean_booking_id
|
|
SET c.ocean_booking_id=b.id,c.ocean_booking_requirement_id=a.requirement_id,
|
|
c.channel_code=COALESCE(c.channel_code,b.channel_code),c.channel_name=COALESCE(c.channel_name,b.channel_name)
|
|
WHERE c.ocean_booking_id IS NULL OR c.ocean_booking_requirement_id IS NULL
|
|
OR c.channel_code IS NULL OR c.channel_name IS NULL;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_loading_pick_task' AND column_name='container_booking_id') THEN
|
|
ALTER TABLE fl_loading_pick_task ADD COLUMN container_booking_id BIGINT UNSIGNED NULL COMMENT '稳定柜次ID' AFTER loading_plan_id;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='fl_loading_pick_task' AND column_name='cabinet_no') THEN
|
|
ALTER TABLE fl_loading_pick_task ADD COLUMN cabinet_no VARCHAR(64) NULL COMMENT '稳定内部柜次号快照' AFTER container_booking_id;
|
|
END IF;
|
|
ALTER TABLE fl_loading_pick_task MODIFY COLUMN container_no VARCHAR(64) NULL COMMENT '废弃兼容字段;不得作为任务身份';
|
|
UPDATE fl_loading_pick_task t JOIN fl_loading_plan p ON p.id=t.loading_plan_id
|
|
JOIN fl_container_booking c ON c.id=p.container_booking_id
|
|
SET t.container_booking_id=c.id,t.cabinet_no=c.cabinet_no
|
|
WHERE t.container_booking_id IS NULL OR t.cabinet_no IS NULL;
|
|
IF EXISTS (SELECT 1 FROM fl_loading_pick_task WHERE container_booking_id IS NULL OR cabinet_no IS NULL) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='渠道柜迁移失败:PDA任务无法回填稳定柜次归属';
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='fl_loading_pick_task' AND index_name='uk_loading_pick_task_booking') THEN
|
|
ALTER TABLE fl_loading_pick_task ADD UNIQUE KEY uk_loading_pick_task_booking (container_booking_id);
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
SET @phase3_channel_sqlstate = NULL;
|
|
SET @phase3_channel_errno = NULL;
|
|
SET @phase3_channel_message = NULL;
|
|
DROP TRIGGER IF EXISTS trg_container_booking_before_update;
|
|
DROP TRIGGER IF EXISTS trg_loading_pick_task_before_update;
|
|
CALL migrate_phase3_channel_containers();
|
|
DROP PROCEDURE IF EXISTS migrate_phase3_channel_containers;
|
|
|
|
-- Rebuild the production guard unconditionally before surfacing a migration failure.
|
|
DROP TRIGGER IF EXISTS trg_container_booking_before_update;
|
|
DELIMITER $$
|
|
CREATE TRIGGER trg_container_booking_before_update
|
|
BEFORE UPDATE ON fl_container_booking
|
|
FOR EACH ROW
|
|
BEGIN
|
|
DECLARE current_plan_status VARCHAR(24);
|
|
SELECT MAX(plan_status) INTO current_plan_status
|
|
FROM fl_loading_plan WHERE container_booking_id = OLD.id;
|
|
IF current_plan_status IN ('LOADING', 'COMPLETED') AND (
|
|
NOT (OLD.id <=> NEW.id)
|
|
OR NOT (OLD.cabinet_no <=> NEW.cabinet_no)
|
|
OR NOT (OLD.channel_group_code <=> NEW.channel_group_code)
|
|
OR NOT (OLD.channel_code <=> NEW.channel_code) OR NOT (OLD.channel_name <=> NEW.channel_name)
|
|
OR NOT (OLD.ocean_booking_id <=> NEW.ocean_booking_id)
|
|
OR NOT (OLD.ocean_booking_requirement_id <=> NEW.ocean_booking_requirement_id)
|
|
OR NOT (OLD.warehouse_id <=> NEW.warehouse_id) OR NOT (OLD.warehouse_name <=> NEW.warehouse_name)
|
|
OR NOT (OLD.container_type <=> NEW.container_type)
|
|
OR NOT (OLD.shipping_company_id <=> NEW.shipping_company_id) OR NOT (OLD.shipping_company_name <=> NEW.shipping_company_name)
|
|
OR NOT (OLD.departure_port_code <=> NEW.departure_port_code) OR NOT (OLD.departure_port_name <=> NEW.departure_port_name)
|
|
OR NOT (OLD.destination_port_code <=> NEW.destination_port_code) OR NOT (OLD.destination_port_name <=> NEW.destination_port_name)
|
|
OR NOT (OLD.destination_warehouse_code <=> NEW.destination_warehouse_code) OR NOT (OLD.destination_warehouse_name <=> NEW.destination_warehouse_name)
|
|
OR NOT (OLD.capacity_cbm <=> NEW.capacity_cbm) OR NOT (OLD.max_weight_kg <=> NEW.max_weight_kg)
|
|
OR NOT (OLD.terminal_trucking_company_id <=> NEW.terminal_trucking_company_id)
|
|
OR NOT (OLD.terminal_trucking_company <=> NEW.terminal_trucking_company) OR NOT (OLD.loading_at <=> NEW.loading_at)
|
|
OR NOT (OLD.actual_sailing_at <=> NEW.actual_sailing_at)
|
|
OR NOT (OLD.estimated_port_arrival_at <=> NEW.estimated_port_arrival_at) OR NOT (OLD.actual_port_arrival_at <=> NEW.actual_port_arrival_at)
|
|
OR NOT (OLD.estimated_warehouse_arrival_at <=> NEW.estimated_warehouse_arrival_at) OR NOT (OLD.actual_warehouse_arrival_at <=> NEW.actual_warehouse_arrival_at)
|
|
OR NOT (OLD.created_by <=> NEW.created_by) OR NOT (OLD.created_by_name <=> NEW.created_by_name)
|
|
OR NOT (OLD.created_at <=> NEW.created_at)
|
|
) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '装柜作业开始后仅允许修改集装箱号与放舱运输数据';
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
DROP TRIGGER IF EXISTS trg_loading_pick_task_before_update;
|
|
DELIMITER $$
|
|
CREATE TRIGGER trg_loading_pick_task_before_update
|
|
BEFORE UPDATE ON fl_loading_pick_task
|
|
FOR EACH ROW
|
|
BEGIN
|
|
IF OLD.task_status = 'COMPLETED' THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '已完成PDA拣货任务不可修改';
|
|
END IF;
|
|
IF NEW.loading_plan_id <> OLD.loading_plan_id
|
|
OR NOT (NEW.container_booking_id <=> OLD.container_booking_id)
|
|
OR NOT (NEW.cabinet_no <=> OLD.cabinet_no) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务稳定归属不可修改';
|
|
END IF;
|
|
-- 与装柜主基线一致,允许持久化完成命令的处理中、失败重试及最终完成。
|
|
IF NOT ((OLD.task_status = 'LOADING' AND NEW.task_status IN ('LOADING','COMPLETING'))
|
|
OR (OLD.task_status = 'COMPLETING' AND NEW.task_status IN ('COMPLETING','COMPLETION_FAILED','COMPLETED'))
|
|
OR (OLD.task_status = 'COMPLETION_FAILED' AND NEW.task_status = 'COMPLETING')) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务状态流转非法';
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
|
|
DROP PROCEDURE IF EXISTS assert_phase3_channel_container_migration;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE assert_phase3_channel_container_migration()
|
|
BEGIN
|
|
DECLARE diagnostic_message VARCHAR(128);
|
|
IF @phase3_channel_sqlstate IS NOT NULL THEN
|
|
SET diagnostic_message = LEFT(CONCAT('渠道柜迁移失败 [', @phase3_channel_sqlstate, '/',
|
|
@phase3_channel_errno, ']: ', @phase3_channel_message), 128);
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = diagnostic_message;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.triggers WHERE trigger_schema=DATABASE()
|
|
AND trigger_name='trg_container_booking_before_update') THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='渠道柜迁移失败:货柜只读触发器未恢复';
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.triggers WHERE trigger_schema=DATABASE()
|
|
AND trigger_name='trg_loading_pick_task_before_update') THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='渠道柜迁移失败:PDA任务只读触发器未恢复';
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
CALL assert_phase3_channel_container_migration();
|
|
DROP PROCEDURE IF EXISTS assert_phase3_channel_container_migration;
|
|
|
|
CREATE TABLE IF NOT EXISTS fl_container_transport_history (
|
|
id BIGINT UNSIGNED NOT NULL COMMENT '运输字段变更历史ID',
|
|
container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '稳定柜次ID',
|
|
before_container_no VARCHAR(64) NULL COMMENT '变更前真实集装箱号',
|
|
after_container_no VARCHAR(64) NULL COMMENT '变更后真实集装箱号',
|
|
before_voyage_no VARCHAR(64) NULL COMMENT '变更前航次号',
|
|
after_voyage_no VARCHAR(64) NULL COMMENT '变更后航次号',
|
|
operation_id VARCHAR(64) NOT NULL COMMENT '运输字段操作幂等ID',
|
|
request_hash CHAR(64) NOT NULL COMMENT '运输字段请求哈希',
|
|
reason VARCHAR(500) NULL COMMENT '运输字段变更原因',
|
|
operator_id BIGINT UNSIGNED NOT NULL COMMENT '变更操作人ID',
|
|
operator_name VARCHAR(64) NULL COMMENT '变更操作人名称快照',
|
|
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '变更记录创建时间', PRIMARY KEY(id),
|
|
UNIQUE KEY uk_container_transport_history_operation (container_booking_id,operator_id,operation_id),
|
|
KEY idx_container_transport_history (container_booking_id,created_at,id)
|
|
) ENGINE=InnoDB COMMENT='柜次真实运输字段不可变变更审计';
|
|
|
|
DROP PROCEDURE IF EXISTS ensure_container_transport_history_schema;
|
|
DELIMITER $$
|
|
CREATE PROCEDURE ensure_container_transport_history_schema()
|
|
BEGIN
|
|
IF (NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND column_name='operation_id')
|
|
OR NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND column_name='request_hash'))
|
|
AND EXISTS (SELECT 1 FROM fl_container_transport_history LIMIT 1) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='运输历史升级失败:旧表已有数据且缺少幂等字段';
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND column_name='operation_id') THEN
|
|
ALTER TABLE fl_container_transport_history
|
|
ADD COLUMN operation_id VARCHAR(64) NOT NULL COMMENT '运输字段操作幂等ID' AFTER after_voyage_no;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND column_name='request_hash') THEN
|
|
ALTER TABLE fl_container_transport_history
|
|
ADD COLUMN request_hash CHAR(64) NOT NULL COMMENT '运输字段请求哈希' AFTER operation_id;
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND index_name='uk_container_transport_history_operation') THEN
|
|
ALTER TABLE fl_container_transport_history
|
|
ADD UNIQUE KEY uk_container_transport_history_operation (container_booking_id,operator_id,operation_id);
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE()
|
|
AND table_name='fl_container_transport_history' AND index_name='idx_container_transport_history') THEN
|
|
ALTER TABLE fl_container_transport_history
|
|
ADD KEY idx_container_transport_history (container_booking_id,created_at,id);
|
|
END IF;
|
|
END$$
|
|
DELIMITER ;
|
|
CALL ensure_container_transport_history_schema();
|
|
DROP PROCEDURE ensure_container_transport_history_schema;
|