feat: complete tail order controls and terminal drayage
This commit is contained in:
@@ -18019,6 +18019,65 @@ DELIMITER ;
|
||||
CALL assert_wallet_event_schema();
|
||||
DROP PROCEDURE IF EXISTS assert_wallet_event_schema;
|
||||
|
||||
-- 目的港码头拖车、提柜与还空闭环(模块来源:phase3-terminal-drayage-schema.sql)
|
||||
USE baiyue_firstleg;
|
||||
CREATE TABLE IF NOT EXISTS fl_terminal_drayage (
|
||||
id BIGINT UNSIGNED NOT NULL, container_booking_id BIGINT UNSIGNED NOT NULL,
|
||||
fleet_supplier_id BIGINT UNSIGNED NOT NULL, fleet_supplier_name VARCHAR(128) NOT NULL,
|
||||
pickup_appointment_at DATETIME(3) NULL, actual_pickup_at DATETIME(3) NULL,
|
||||
estimated_empty_return_at DATETIME(3) NULL, actual_empty_return_at DATETIME(3) NULL,
|
||||
version INT UNSIGNED NOT NULL DEFAULT 1, created_by BIGINT UNSIGNED NOT NULL,
|
||||
created_by_name VARCHAR(64) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_by BIGINT UNSIGNED NOT NULL, updated_by_name VARCHAR(64) NULL,
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_terminal_drayage_container(container_booking_id),
|
||||
KEY idx_terminal_drayage_warning(actual_empty_return_at,estimated_empty_return_at),
|
||||
CONSTRAINT fk_terminal_drayage_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id),
|
||||
CONSTRAINT chk_terminal_drayage_times CHECK((actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL)
|
||||
AND (actual_empty_return_at IS NULL OR actual_pickup_at IS NOT NULL)
|
||||
AND (actual_empty_return_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
|
||||
) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实';
|
||||
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history (
|
||||
id BIGINT UNSIGNED NOT NULL, drayage_id BIGINT UNSIGNED NOT NULL,
|
||||
container_booking_id BIGINT UNSIGNED NOT NULL, action VARCHAR(32) NOT NULL,
|
||||
from_status VARCHAR(32) NOT NULL, to_status VARCHAR(32) NOT NULL,
|
||||
from_version INT UNSIGNED NOT NULL, to_version INT UNSIGNED NOT NULL,
|
||||
reason VARCHAR(500) NULL, operator_id BIGINT UNSIGNED NOT NULL, operator_name VARCHAR(64) NULL,
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id),
|
||||
KEY idx_terminal_drayage_history(container_booking_id,created_at,id),
|
||||
CONSTRAINT fk_terminal_drayage_history FOREIGN KEY(drayage_id) REFERENCES fl_terminal_drayage(id),
|
||||
CONSTRAINT chk_terminal_drayage_history_action CHECK(action IN
|
||||
('SELECT_FLEET','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN'))
|
||||
) ENGINE=InnoDB COMMENT='目的港码头拖车不可变操作历史';
|
||||
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_operation (
|
||||
id BIGINT UNSIGNED NOT NULL, container_booking_id BIGINT UNSIGNED NOT NULL,
|
||||
operation VARCHAR(32) NOT NULL, idempotency_key VARCHAR(255) NOT NULL,
|
||||
request_hash CHAR(64) NOT NULL, result_version INT UNSIGNED NOT NULL,
|
||||
operator_id BIGINT UNSIGNED NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_terminal_drayage_operation(container_booking_id,idempotency_key),
|
||||
KEY idx_terminal_drayage_operation(container_booking_id,created_at),
|
||||
CONSTRAINT fk_terminal_drayage_operation_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id)
|
||||
) ENGINE=InnoDB COMMENT='目的港码头拖车成功幂等操作';
|
||||
|
||||
DROP PROCEDURE IF EXISTS assert_terminal_drayage_schema;
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE assert_terminal_drayage_schema()
|
||||
BEGIN
|
||||
IF (SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='baiyue_firstleg'
|
||||
AND TABLE_NAME IN ('fl_terminal_drayage','fl_terminal_drayage_history','fl_terminal_drayage_operation')) <> 3 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:目的港码头拖车表不完整';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA='baiyue_firstleg'
|
||||
AND TABLE_NAME='fl_terminal_drayage' AND INDEX_NAME='uk_terminal_drayage_container' AND NON_UNIQUE=0) <> 1
|
||||
OR (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA='baiyue_firstleg'
|
||||
AND TABLE_NAME='fl_terminal_drayage_operation' AND INDEX_NAME='uk_terminal_drayage_operation' AND NON_UNIQUE=0) <> 2 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:目的港码头拖车唯一约束不完整';
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
CALL assert_terminal_drayage_schema();
|
||||
DROP PROCEDURE IF EXISTS assert_terminal_drayage_schema;
|
||||
|
||||
CALL baiyue_firstleg.assert_unified_final_schema();
|
||||
DROP PROCEDURE IF EXISTS baiyue_firstleg.assert_unified_final_schema;
|
||||
SELECT 'PASS' AS migration_status,
|
||||
|
||||
@@ -219,6 +219,7 @@ SET @ddl = (SELECT IF(EXISTS (
|
||||
WHERE table_schema=DATABASE() AND table_name='ll_overseas_procurement_order' AND column_name='review_idempotency_key'
|
||||
), 'SELECT 1', 'ALTER TABLE ll_overseas_procurement_order ADD COLUMN review_idempotency_key VARCHAR(255) NULL COMMENT ''审核幂等键'' AFTER review_remark'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema=DATABASE() AND table_name='ll_overseas_procurement_order' AND column_name='review_request_hash'
|
||||
@@ -1860,3 +1861,93 @@ SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE tab
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
ALTER TABLE ll_inbound_stock_receipt
|
||||
MODIFY COLUMN pallet_no VARCHAR(64) NOT NULL COMMENT '海外仓实物托盘码';
|
||||
|
||||
-- 尾程单票人工计划、暂扣与人工展示节点。
|
||||
USE baiyue_lastleg;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='hold_chargeable'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN hold_chargeable TINYINT NOT NULL DEFAULT 0 COMMENT ''当前暂扣是否计费:0否1是'' AFTER detained'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='hold_reason'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN hold_reason VARCHAR(500) NULL COMMENT ''当前暂扣原因;解除后为空'' AFTER hold_chargeable'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='manual_node_override'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN manual_node_override TINYINT NOT NULL DEFAULT 0 COMMENT ''是否启用单票人工计划节点覆盖:0否1是'' AFTER hold_reason'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='version'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN version INT NOT NULL DEFAULT 0 COMMENT ''尾程订单命令乐观锁版本'' AFTER manual_node_override'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_order_command_record (
|
||||
id BIGINT NOT NULL COMMENT '尾程订单命令幂等记录ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键',
|
||||
order_id BIGINT NOT NULL COMMENT '尾程订单ID', action VARCHAR(32) NOT NULL COMMENT '命令动作', operator_id VARCHAR(128) NOT NULL COMMENT '平台操作人ID',
|
||||
idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键', request_hash VARCHAR(64) NOT NULL COMMENT '规范化请求SHA-256摘要',
|
||||
result_ref VARCHAR(128) NULL COMMENT '结果业务引用', result_json LONGTEXT NOT NULL COMMENT '首次成功响应JSON快照',
|
||||
result_version INT NOT NULL COMMENT '命令成功后的订单版本', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '首次成功时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_order_command_key(customer_id,order_id,action,operator_id,idempotency_key),
|
||||
KEY idx_ll_order_command_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='尾程订单写命令幂等与结果审计记录';
|
||||
CREATE TABLE IF NOT EXISTS ll_order_hold_history (
|
||||
id BIGINT NOT NULL COMMENT '尾程订单暂扣历史ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||||
held TINYINT NOT NULL COMMENT '操作后是否暂扣:0否1是', chargeable TINYINT NOT NULL COMMENT '本次暂扣是否计费:0否1是', reason VARCHAR(500) NOT NULL COMMENT '暂扣或解除原因',
|
||||
order_version INT NOT NULL COMMENT '操作成功后的订单版本', operator_id VARCHAR(128) NOT NULL COMMENT '操作人ID', operator_name VARCHAR(128) NOT NULL COMMENT '操作人名称',
|
||||
idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键', created_at DATETIME(3) NOT NULL COMMENT '操作时间', PRIMARY KEY(id),
|
||||
UNIQUE KEY uk_ll_order_hold_key(customer_id,order_id,operator_id,idempotency_key), KEY idx_ll_order_hold_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='尾程订单暂扣与解除不可变历史';
|
||||
CREATE TABLE IF NOT EXISTS ll_order_manual_node (
|
||||
id BIGINT NOT NULL COMMENT '尾程订单人工节点ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||||
node_code VARCHAR(32) NOT NULL COMMENT '八行人工展示节点稳定代码', node_at DATETIME(3) NULL COMMENT '人工填写节点时间,允许为空',
|
||||
source VARCHAR(16) NOT NULL DEFAULT 'MANUAL' COMMENT '节点来源,固定MANUAL', order_version INT NOT NULL COMMENT '最近编辑后的订单版本',
|
||||
updated_by VARCHAR(128) NOT NULL COMMENT '最近操作人ID', updated_at DATETIME(3) NOT NULL COMMENT '最近编辑时间', PRIMARY KEY(id),
|
||||
UNIQUE KEY uk_ll_order_manual_node(customer_id,order_id,node_code), KEY idx_ll_order_manual_node_order(customer_id,order_id,node_at)
|
||||
) ENGINE=InnoDB COMMENT='尾程订单当前人工节点覆盖事实';
|
||||
CREATE TABLE IF NOT EXISTS ll_order_manual_node_history (
|
||||
id BIGINT NOT NULL COMMENT '尾程订单人工节点历史ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||||
nodes_json LONGTEXT NOT NULL COMMENT '本次全量人工节点JSON快照', order_version INT NOT NULL COMMENT '操作成功后的订单版本', operator_id VARCHAR(128) NOT NULL COMMENT '操作人ID',
|
||||
operator_name VARCHAR(128) NOT NULL COMMENT '操作人名称', idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键', created_at DATETIME(3) NOT NULL COMMENT '操作时间',
|
||||
PRIMARY KEY(id), UNIQUE KEY uk_ll_order_manual_node_history_key(customer_id,order_id,operator_id,idempotency_key),
|
||||
KEY idx_ll_order_manual_node_history(customer_id,order_id,created_at)
|
||||
) ENGINE=InnoDB COMMENT='尾程订单人工节点覆盖不可变历史';
|
||||
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='planned_arrival_date'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN planned_arrival_date DATE NULL COMMENT ''人工计划预计到仓日期'' AFTER overseas_warehouse_id'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='pallet_type'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN pallet_type VARCHAR(32) NULL COMMENT ''人工计划托盘类型'' AFTER planned_arrival_date'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='assigned_flag'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN assigned_flag TINYINT NOT NULL DEFAULT 0 COMMENT ''人工计划是否已分配:0否1是'' AFTER pallet_type'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='merge_required'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN merge_required TINYINT NOT NULL DEFAULT 0 COMMENT ''人工计划是否要求合托:0否1是'' AFTER assigned_flag'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='urgent_flag'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN urgent_flag TINYINT NOT NULL DEFAULT 0 COMMENT ''人工计划是否加急:0否1是'' AFTER merge_required'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='creation_mode'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN creation_mode VARCHAR(16) NOT NULL DEFAULT ''AUTO'' COMMENT ''计划生成方式:AUTO柜级自动、MANUAL单票人工'' AFTER urgent_flag'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan' AND column_name='plan_remark'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan ADD COLUMN plan_remark VARCHAR(1000) NULL COMMENT ''入仓计划备注'' AFTER creation_mode'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan_pallet' AND column_name='pallet_type'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN pallet_type VARCHAR(32) NULL COMMENT ''人工计划托盘类型'' AFTER pallet_no'));
|
||||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
DROP PROCEDURE IF EXISTS assert_tail_order_commands_ready;
|
||||
DELIMITER $$
|
||||
CREATE PROCEDURE assert_tail_order_commands_ready()
|
||||
BEGIN
|
||||
IF (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='baiyue_lastleg'
|
||||
AND table_name='ll_order' AND column_name IN
|
||||
('hold_chargeable','hold_reason','manual_node_override','version')) <> 4 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='尾程订单人工计划、暂扣与人工节点字段未完整部署';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='baiyue_lastleg'
|
||||
AND table_name IN ('ll_order_command_record','ll_order_hold_history','ll_order_manual_node','ll_order_manual_node_history')) <> 4 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='尾程订单命令审计表未完整部署';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema='baiyue_lastleg'
|
||||
AND table_name='ll_inbound_plan' AND column_name IN
|
||||
('planned_arrival_date','pallet_type','assigned_flag','merge_required','urgent_flag','creation_mode','plan_remark')) <> 7 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='尾程人工计划字段未完整部署';
|
||||
END IF;
|
||||
IF (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema='baiyue_lastleg'
|
||||
AND table_name='ll_order_command_record' AND index_name='uk_ll_order_command_key' AND non_unique=0) <> 5
|
||||
OR (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema='baiyue_lastleg'
|
||||
AND table_name='ll_order_manual_node' AND index_name='uk_ll_order_manual_node' AND non_unique=0) <> 3 THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='尾程订单命令幂等或人工节点唯一约束未完整部署';
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
CALL assert_tail_order_commands_ready();
|
||||
DROP PROCEDURE IF EXISTS assert_tail_order_commands_ready;
|
||||
|
||||
SELECT 'PASS' AS migration_status, '海外尾程人工计划、暂扣与人工节点结构已就绪' AS message;
|
||||
|
||||
Reference in New Issue
Block a user