2026-08-20 19:55:21 +08:00
-- 海外区域固定增量入口。空库先执行 lastleg-service/src/main/resources/db/lastleg.sql 基线;
2026-08-26 11:06:24 +08:00
-- 本入口同时初始化海外 Event Bridge 独立库,避免国内/海外实例误共用 Inbox。
2026-08-20 19:55:21 +08:00
-- 本文件只由人工审核执行,服务部署默认不自动执行 SQL。
SET NAMES utf8mb4 ;
2026-08-26 11:06:24 +08:00
CREATE DATABASE IF NOT EXISTS baiyue_event_bridge_overseas
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ;
USE baiyue_event_bridge_overseas ;
CREATE TABLE IF NOT EXISTS bridge_outbox (
event_id VARCHAR ( 128 ) NOT NULL COMMENT '事件全局标识' ,
idempotency_key VARCHAR ( 191 ) NOT NULL COMMENT '发送幂等键' ,
event_type VARCHAR ( 64 ) NOT NULL COMMENT '事件类型' ,
event_version INT NOT NULL COMMENT '事件契约版本' ,
source_region VARCHAR ( 32 ) NOT NULL COMMENT '来源区域' ,
target_region VARCHAR ( 32 ) NOT NULL COMMENT '目标区域' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户标识' ,
aggregate_type VARCHAR ( 64 ) NOT NULL COMMENT '聚合类型' ,
aggregate_id VARCHAR ( 128 ) NOT NULL COMMENT '聚合标识' ,
aggregate_version BIGINT NOT NULL COMMENT '聚合版本' ,
handover_version BIGINT NULL COMMENT '跨区交接版本' ,
trace_id VARCHAR ( 128 ) NOT NULL COMMENT '链路标识' ,
correlation_id VARCHAR ( 128 ) NOT NULL COMMENT '业务关联标识' ,
causation_id VARCHAR ( 128 ) NULL COMMENT '上游事件标识' ,
occurred_at DATETIME ( 3 ) NOT NULL COMMENT '业务事实发生时间' ,
payload_hash VARCHAR ( 71 ) NOT NULL COMMENT '规范化负载摘要' ,
payload_json JSON NOT NULL COMMENT '事件负载' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '投递状态' ,
retry_count INT NOT NULL DEFAULT 0 COMMENT '已重试次数' ,
next_retry_at DATETIME ( 3 ) NULL COMMENT '下次重试时间' ,
lease_owner VARCHAR ( 128 ) NULL COMMENT '租约持有者' ,
lease_until DATETIME ( 3 ) NULL COMMENT '租约截止时间' ,
last_error VARCHAR ( 1000 ) NULL COMMENT '最后错误' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
delivered_at DATETIME ( 3 ) NULL COMMENT '投递成功时间' ,
PRIMARY KEY ( event_id ),
UNIQUE KEY uk_bridge_outbox_idempotency ( idempotency_key ),
KEY idx_bridge_outbox_schedule ( target_region , status , next_retry_at , lease_until )
) ENGINE = InnoDB COMMENT = '海外跨区域事件待投递箱' ;
CREATE TABLE IF NOT EXISTS bridge_inbox (
event_id VARCHAR ( 128 ) NOT NULL COMMENT '事件全局标识' ,
idempotency_key VARCHAR ( 191 ) NOT NULL COMMENT '接收幂等键' ,
event_type VARCHAR ( 64 ) NOT NULL COMMENT '事件类型' ,
event_version INT NOT NULL COMMENT '事件契约版本' ,
source_region VARCHAR ( 32 ) NOT NULL COMMENT '来源区域' ,
target_region VARCHAR ( 32 ) NOT NULL COMMENT '目标区域' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户标识' ,
aggregate_type VARCHAR ( 64 ) NOT NULL COMMENT '聚合类型' ,
aggregate_id VARCHAR ( 128 ) NOT NULL COMMENT '聚合标识' ,
aggregate_version BIGINT NOT NULL COMMENT '聚合版本' ,
handover_version BIGINT NULL COMMENT '跨区交接版本' ,
trace_id VARCHAR ( 128 ) NOT NULL COMMENT '链路标识' ,
correlation_id VARCHAR ( 128 ) NOT NULL COMMENT '业务关联标识' ,
causation_id VARCHAR ( 128 ) NULL COMMENT '上游事件标识' ,
occurred_at DATETIME ( 3 ) NOT NULL COMMENT '业务事实发生时间' ,
payload_hash VARCHAR ( 71 ) NOT NULL COMMENT '规范化负载摘要' ,
payload_json JSON NOT NULL COMMENT '事件负载' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'RECEIVED' COMMENT '消费状态' ,
lease_owner VARCHAR ( 128 ) NULL COMMENT '消费租约持有者' ,
lease_until DATETIME ( 3 ) NULL COMMENT '消费租约截止时间' ,
retry_count INT NOT NULL DEFAULT 0 COMMENT '消费重试次数' ,
next_retry_at DATETIME ( 3 ) NULL COMMENT '下次消费时间' ,
last_error VARCHAR ( 1000 ) NULL COMMENT '最后错误' ,
received_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '接收时间' ,
processed_at DATETIME ( 3 ) NULL COMMENT '消费完成时间' ,
PRIMARY KEY ( event_id ),
UNIQUE KEY uk_bridge_inbox_idempotency ( idempotency_key ),
KEY idx_bridge_inbox_consume ( status , next_retry_at , lease_until )
) ENGINE = InnoDB COMMENT = '海外跨区域事件已接收箱' ;
CREATE TABLE IF NOT EXISTS bridge_delivery_attempt (
id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键' ,
event_id VARCHAR ( 128 ) NOT NULL COMMENT '事件全局标识' ,
source_region VARCHAR ( 32 ) NOT NULL COMMENT '来源区域' ,
target_region VARCHAR ( 32 ) NOT NULL COMMENT '目标区域' ,
attempt_no INT NOT NULL COMMENT '投递序号' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '投递结果' ,
response_code VARCHAR ( 64 ) NULL COMMENT '对端响应码' ,
error_message VARCHAR ( 1000 ) NULL COMMENT '错误信息' ,
started_at DATETIME ( 3 ) NOT NULL COMMENT '开始时间' ,
finished_at DATETIME ( 3 ) NULL COMMENT '完成时间' ,
PRIMARY KEY ( id ),
UNIQUE KEY uk_bridge_attempt ( event_id , attempt_no ),
KEY idx_bridge_attempt_event ( event_id , started_at )
) ENGINE = InnoDB COMMENT = '海外跨区域事件投递尝试记录' ;
DROP PROCEDURE IF EXISTS assert_overseas_event_bridge_schema ;
DELIMITER $$
CREATE PROCEDURE assert_overseas_event_bridge_schema ()
BEGIN
IF ( SELECT COUNT ( * ) FROM information_schema . tables
WHERE table_schema = 'baiyue_event_bridge_overseas'
AND table_name IN ( 'bridge_outbox' , 'bridge_inbox' , 'bridge_delivery_attempt' )) <> 3 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '海外区域初始化失败:Event Bridge 三张表未完整创建' ;
END IF ;
IF ( SELECT COUNT ( DISTINCT CONCAT ( table_name , ':' , index_name )) FROM information_schema . statistics
WHERE table_schema = 'baiyue_event_bridge_overseas'
AND (( table_name = 'bridge_outbox' AND index_name IN ( 'PRIMARY' , 'uk_bridge_outbox_idempotency' , 'idx_bridge_outbox_schedule' ))
OR ( table_name = 'bridge_inbox' AND index_name IN ( 'PRIMARY' , 'uk_bridge_inbox_idempotency' , 'idx_bridge_inbox_consume' ))
OR ( table_name = 'bridge_delivery_attempt' AND index_name IN ( 'PRIMARY' , 'uk_bridge_attempt' , 'idx_bridge_attempt_event' )))) <> 9 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '海外区域初始化失败:Event Bridge 索引未完整创建' ;
END IF ;
END $$
DELIMITER ;
CALL assert_overseas_event_bridge_schema ();
DROP PROCEDURE IF EXISTS assert_overseas_event_bridge_schema ;
2026-08-20 19:55:21 +08:00
CREATE DATABASE IF NOT EXISTS baiyue_lastleg
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ;
2026-08-20 18:02:38 +08:00
USE baiyue_lastleg ;
CREATE TABLE IF NOT EXISTS ll_event_outbox (
id BIGINT NOT NULL COMMENT '事件主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
aggregate_type VARCHAR ( 64 ) NOT NULL COMMENT '聚合类型' , aggregate_id VARCHAR ( 128 ) NOT NULL COMMENT '聚合标识' ,
event_type VARCHAR ( 64 ) NOT NULL COMMENT '事件类型' , event_version INT NOT NULL COMMENT '事件版本' ,
event_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , payload_json LONGTEXT NOT NULL COMMENT '事件载荷JSON' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '发布状态' , retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数' ,
next_retry_at DATETIME ( 3 ) NULL COMMENT '下次重试时间' , published_at DATETIME ( 3 ) NULL COMMENT '发布时间' ,
locked_at DATETIME ( 3 ) NULL COMMENT '投递租约获取时间' , locked_by VARCHAR ( 128 ) NULL COMMENT '投递租约持有者' ,
last_error VARCHAR ( 1000 ) NULL COMMENT '最后一次发布错误' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_event_outbox_key ( event_key ),
KEY idx_ll_event_outbox_publish ( status , next_retry_at , created_at )
) ENGINE = InnoDB COMMENT = '尾程跨区业务事件发件箱' ;
CREATE TABLE IF NOT EXISTS ll_overseas_quote (
id BIGINT NOT NULL COMMENT '报价ID' , name VARCHAR ( 128 ) NOT NULL COMMENT '报价名称' ,
warehouse_id BIGINT NOT NULL COMMENT '国内平台海外合作仓ID' , warehouse_code VARCHAR ( 64 ) NOT NULL COMMENT '合作仓编码快照' ,
warehouse_name VARCHAR ( 128 ) NOT NULL COMMENT '合作仓名称快照' , country_code VARCHAR ( 2 ) NOT NULL COMMENT '国家二字码快照' ,
provider_name VARCHAR ( 128 ) NOT NULL COMMENT '报价方' , currency CHAR ( 3 ) NOT NULL COMMENT '币种' ,
effective_start DATE NOT NULL COMMENT '生效开始日期' , effective_end DATE NOT NULL COMMENT '生效结束日期' ,
version_code VARCHAR ( 64 ) NOT NULL COMMENT '业务版本号' , status VARCHAR ( 16 ) NOT NULL DEFAULT 'INACTIVE' COMMENT '状态:ACTIVE/INACTIVE' ,
remark VARCHAR ( 1000 ) NULL COMMENT '备注' , record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建人' , updated_by VARCHAR ( 128 ) NOT NULL COMMENT '更新人' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_quote_warehouse_provider_version ( warehouse_id , provider_name , version_code ),
KEY idx_ll_quote_page ( status , updated_at , id ), KEY idx_ll_quote_effective ( warehouse_id , provider_name , currency , effective_start , effective_end )
) ENGINE = InnoDB COMMENT = '海外仓报价主表' ;
CREATE TABLE IF NOT EXISTS ll_overseas_quote_fee (
id BIGINT NOT NULL COMMENT '费用明细ID' , quote_id BIGINT NOT NULL COMMENT '报价ID' , sequence_no INT NOT NULL COMMENT '显示顺序' ,
item VARCHAR ( 128 ) NOT NULL COMMENT '费用项目' , billing_unit VARCHAR ( 64 ) NOT NULL COMMENT '计费单位' ,
unit_price DECIMAL ( 18 , 4 ) NOT NULL COMMENT '单价' , minimum_charge DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '最低收费' ,
remark VARCHAR ( 500 ) NULL COMMENT '备注' , PRIMARY KEY ( id ), UNIQUE KEY uk_ll_quote_fee_sequence ( quote_id , sequence_no ),
KEY idx_ll_quote_fee_quote ( quote_id )
) ENGINE = InnoDB COMMENT = '海外仓报价仓库费用' ;
CREATE TABLE IF NOT EXISTS ll_overseas_quote_transit_price (
id BIGINT NOT NULL COMMENT '中转价格ID' , quote_id BIGINT NOT NULL COMMENT '报价ID' , sequence_no INT NOT NULL COMMENT '显示顺序' ,
fba_warehouse_code VARCHAR ( 64 ) NOT NULL COMMENT 'FBA仓编码' , delivery_method VARCHAR ( 64 ) NOT NULL COMMENT '报价运输方式' ,
estimated_miles DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '预估英里数' , price DECIMAL ( 18 , 4 ) NOT NULL COMMENT '报价金额' ,
minimum_charge DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '最低收费' , remark VARCHAR ( 500 ) NULL COMMENT '备注' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_quote_transit_sequence ( quote_id , sequence_no ),
KEY idx_ll_quote_transit_quote ( quote_id )
) ENGINE = InnoDB COMMENT = '海外仓报价中转价格明细' ;
CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate (
id BIGINT NOT NULL COMMENT '月度汇率ID' , rate_month CHAR ( 7 ) NOT NULL COMMENT '汇率月份,格式yyyy-MM' ,
base_currency CHAR ( 3 ) NOT NULL DEFAULT 'USD' COMMENT '基准币种' , quote_currency CHAR ( 3 ) NOT NULL DEFAULT 'CNY' COMMENT '报价币种' ,
usd_to_cny_average DECIMAL ( 18 , 8 ) NOT NULL COMMENT '美元兑人民币月平均汇率' , status VARCHAR ( 16 ) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态:ACTIVE/INACTIVE' ,
remark VARCHAR ( 1000 ) NULL COMMENT '备注' , record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建人' , updated_by VARCHAR ( 128 ) NOT NULL COMMENT '更新人' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_exchange_rate_month ( rate_month ), KEY idx_ll_exchange_rate_page ( status , rate_month )
) ENGINE = InnoDB COMMENT = '美元兑人民币月度平均汇率' ;
CREATE TABLE IF NOT EXISTS ll_monthly_exchange_rate_history (
id BIGINT NOT NULL COMMENT '汇率变更历史ID' , exchange_rate_id BIGINT NOT NULL COMMENT '月度汇率ID' ,
before_rate DECIMAL ( 18 , 8 ) NULL COMMENT '变更前汇率' , after_rate DECIMAL ( 18 , 8 ) NOT NULL COMMENT '变更后汇率' ,
before_status VARCHAR ( 16 ) NULL COMMENT '变更前状态' , after_status VARCHAR ( 16 ) NOT NULL COMMENT '变更后状态' ,
operator_id VARCHAR ( 128 ) NOT NULL COMMENT '操作人' , remark VARCHAR ( 1000 ) NULL COMMENT '变更说明' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , PRIMARY KEY ( id ), KEY idx_ll_exchange_rate_history ( exchange_rate_id , created_at )
) ENGINE = InnoDB COMMENT = '月度汇率变更历史' ;
CREATE TABLE IF NOT EXISTS ll_vehicle (
id BIGINT NOT NULL COMMENT '车辆档案ID' , plate_number VARCHAR ( 64 ) NOT NULL COMMENT '车牌号' ,
model VARCHAR ( 128 ) NOT NULL COMMENT '车型' , fuel_consumption_per100_km DECIMAL ( 10 , 2 ) NOT NULL COMMENT '百公里油耗,单位升' ,
mileage_km BIGINT NOT NULL COMMENT '当前公里码,单位公里' , driver_or_dispatch_company VARCHAR ( 128 ) NULL COMMENT '司机姓名或外派单位' ,
phone VARCHAR ( 64 ) NULL COMMENT '司机或外派单位联系电话' , region VARCHAR ( 16 ) NOT NULL COMMENT '区域:DOMESTIC/OVERSEAS' ,
ownership VARCHAR ( 16 ) NOT NULL COMMENT '车辆归属:OWNED/DISPATCHED' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '状态:IN_SERVICE/DISPATCHED/MAINTENANCE/INACTIVE/RETURNED' ,
remark VARCHAR ( 1000 ) NULL COMMENT '备注' , record_version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建人' , updated_by VARCHAR ( 128 ) NOT NULL COMMENT '更新人' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_vehicle_plate ( plate_number ), KEY idx_ll_vehicle_page ( ownership , region , status , updated_at , id )
) ENGINE = InnoDB COMMENT = '平台车辆主数据' ;
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_order (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
customer_name VARCHAR ( 255 ) NULL COMMENT '客户名称快照' , order_no VARCHAR ( 64 ) NOT NULL COMMENT '订单号' ,
purchase_category VARCHAR ( 128 ) NOT NULL COMMENT '采购品类' , product_name VARCHAR ( 255 ) NOT NULL COMMENT '产品名称' ,
product_specification VARCHAR ( 500 ) NULL COMMENT '产品规格' , product_url VARCHAR ( 2000 ) NULL COMMENT '产品链接' ,
purchase_quantity BIGINT NOT NULL COMMENT '采购数量' , budget_unit_price DECIMAL ( 18 , 2 ) NULL COMMENT '预算单价' ,
currency CHAR ( 3 ) NOT NULL DEFAULT 'USD' COMMENT '币种' , receiving_address VARCHAR ( 1000 ) NULL COMMENT '收货地址' ,
contact_name VARCHAR ( 128 ) NOT NULL COMMENT '联系人姓名' , contact_phone VARCHAR ( 64 ) NOT NULL COMMENT '联系人电话' ,
2026-08-28 14:55:18 +08:00
purchase_warehouse_id VARCHAR ( 128 ) NULL COMMENT '采购入仓仓库ID' , purchase_warehouse_name VARCHAR ( 255 ) NULL COMMENT '采购入仓仓库名称' , outbound_details JSON NULL COMMENT '出库明细' ,
2026-08-20 18:02:38 +08:00
inbound_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '采购单据累计入库数量' , domestic_carrier VARCHAR ( 128 ) NULL COMMENT '境内承运商' ,
domestic_tracking_no VARCHAR ( 128 ) NULL COMMENT '境内物流单号' , overseas_carrier VARCHAR ( 128 ) NULL COMMENT '海外承运商' ,
overseas_tracking_no VARCHAR ( 128 ) NULL COMMENT '海外物流单号' , estimated_arrival_at DATETIME ( 3 ) NULL COMMENT '预计到达时间' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_REVIEW' COMMENT '业务状态' , remark VARCHAR ( 1000 ) NULL COMMENT '备注' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容哈希' ,
created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' , reviewed_by VARCHAR ( 128 ) NULL COMMENT '审核人ID' ,
2026-08-25 13:07:01 +08:00
review_remark VARCHAR ( 1000 ) NULL COMMENT '审核备注' , review_idempotency_key VARCHAR ( 255 ) NULL COMMENT '审核幂等键' ,
review_request_hash CHAR ( 64 ) NULL COMMENT '审核请求内容哈希' , reviewed_at DATETIME ( 3 ) NULL COMMENT '审核时间' ,
2026-08-20 18:02:38 +08:00
version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_overseas_procurement_order_no ( customer_id , order_no ),
UNIQUE KEY uk_ll_overseas_procurement_order_key ( customer_id , idempotency_key ),
KEY idx_ll_overseas_procurement_list ( customer_id , status , created_at ),
KEY idx_ll_overseas_procurement_warehouse ( customer_id , purchase_warehouse_id , created_at )
) ENGINE = InnoDB COMMENT = '海外采购订单' ;
2026-08-28 14:55:18 +08:00
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 = 'outbound_details' ), 'SELECT 1' , 'ALTER TABLE ll_overseas_procurement_order ADD COLUMN outbound_details JSON NULL COMMENT ''出库明细'' AFTER inbound_quantity' ));
PREPARE procurement_outbound_stmt FROM @ ddl ; EXECUTE procurement_outbound_stmt ; DEALLOCATE PREPARE procurement_outbound_stmt ;
2026-08-20 18:02:38 +08:00
2026-08-25 13:07:01 +08:00
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_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 ;
2026-09-07 23:58:18 +08:00
2026-08-25 13:07:01 +08:00
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'
), 'SELECT 1' , 'ALTER TABLE ll_overseas_procurement_order ADD COLUMN review_request_hash CHAR(64) NULL COMMENT ''审核请求内容哈希'' AFTER review_idempotency_key' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-08-20 18:02:38 +08:00
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_status_history (
id BIGINT NOT NULL COMMENT '主键ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
operation_type VARCHAR ( 32 ) NOT NULL COMMENT '操作类型:CREATE、REVIEW或UPDATE' , from_status VARCHAR ( 32 ) NULL COMMENT '变更前状态' ,
to_status VARCHAR ( 32 ) NOT NULL COMMENT '变更后状态' , operator_id VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
2026-08-25 13:07:01 +08:00
idempotency_key VARCHAR ( 255 ) NULL COMMENT '操作幂等键' , change_detail JSON NULL COMMENT '字段变更前后值JSON' , remark VARCHAR ( 1000 ) NULL COMMENT '备注' ,
2026-08-20 18:02:38 +08:00
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
KEY idx_ll_overseas_procurement_history ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '海外采购操作流水' ;
2026-08-25 13:07:01 +08:00
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_overseas_procurement_status_history' AND column_name = 'idempotency_key'
), 'SELECT 1' , 'ALTER TABLE ll_overseas_procurement_status_history ADD COLUMN idempotency_key VARCHAR(255) NULL COMMENT ''操作幂等键'' AFTER operator_id' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-08-20 18:02:38 +08:00
CREATE TABLE IF NOT EXISTS ll_us_truck_order (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , order_no VARCHAR ( 64 ) NOT NULL COMMENT '订单号' ,
transport_type VARCHAR ( 32 ) NOT NULL COMMENT '运输类型' , origin VARCHAR ( 255 ) NOT NULL COMMENT '起运地' , origin_address VARCHAR ( 500 ) NULL COMMENT '起运地址' ,
destination VARCHAR ( 255 ) NOT NULL COMMENT '目的地' , destination_address VARCHAR ( 500 ) NULL COMMENT '目的地址' ,
container_type VARCHAR ( 32 ) NULL COMMENT '历史兼容设备类型,零担托盘业务不采集' , pallet_count INT NOT NULL DEFAULT 1 COMMENT '客户申报托盘数' ,
package_count INT NULL COMMENT '可选箱数,零或空值均有效' , received_pallet_count INT NOT NULL DEFAULT 0 COMMENT 'PDA实收托盘数' ,
allocated_pallet_count INT NOT NULL DEFAULT 0 COMMENT '已分配到合车行程的托盘数' , shipped_pallet_count INT NOT NULL DEFAULT 0 COMMENT '已出库托盘数' ,
total_weight_kg DECIMAL ( 18 , 3 ) NOT NULL DEFAULT 0 COMMENT '总重量(千克)' , total_volume_cbm DECIMAL ( 18 , 6 ) NOT NULL DEFAULT 0 COMMENT '总体积(立方米)' ,
budget_amount DECIMAL ( 18 , 2 ) NULL COMMENT '预算金额' , currency VARCHAR ( 3 ) NOT NULL DEFAULT 'USD' COMMENT '币种' ,
contact_name VARCHAR ( 128 ) NOT NULL COMMENT '联系人姓名' , contact_info VARCHAR ( 128 ) NOT NULL COMMENT '联系人联系方式' ,
requested_date DATE NOT NULL COMMENT '要求服务日期' , status VARCHAR ( 32 ) NOT NULL COMMENT '美国卡车订单状态' , remark VARCHAR ( 1000 ) NULL COMMENT '备注' ,
receipt_idempotency_key VARCHAR ( 255 ) NULL COMMENT '实物收货幂等键' , receipt_request_hash CHAR ( 64 ) NULL COMMENT '实物收货请求哈希' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容哈希' , created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' ,
version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_us_truck_order_no ( customer_id , order_no ), UNIQUE KEY uk_ll_us_truck_order_key ( customer_id , idempotency_key ),
UNIQUE KEY uk_ll_us_truck_receipt_key ( customer_id , receipt_idempotency_key ), KEY idx_ll_us_truck_order_list ( customer_id , status , created_at ),
KEY idx_ll_us_truck_order_date ( customer_id , requested_date , created_at )
) ENGINE = InnoDB COMMENT = '美国卡车运输订单' ;
CREATE TABLE IF NOT EXISTS ll_us_truck_order_pallet (
id BIGINT NOT NULL COMMENT '托盘记录ID' , order_id BIGINT NOT NULL COMMENT '美国卡车订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
pallet_no VARCHAR ( 128 ) NOT NULL COMMENT '业务托盘号' , sequence_no INT NOT NULL COMMENT '订单内托盘序号' ,
source VARCHAR ( 32 ) NOT NULL COMMENT '托盘来源:订单计划或PDA超收' , status VARCHAR ( 32 ) NOT NULL COMMENT '托盘状态:待收、已收或超收待审核' ,
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘资源ID' , package_count INT NULL COMMENT '托盘箱数' , received_at DATETIME ( 3 ) NULL COMMENT '实收时间' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_us_truck_order_pallet_no ( customer_id , order_id , pallet_no ), UNIQUE KEY uk_ll_us_truck_order_pallet_seq ( customer_id , order_id , sequence_no ),
KEY idx_ll_us_truck_order_pallet_list ( customer_id , order_id , status )
) ENGINE = InnoDB COMMENT = '美国卡车订单托盘实收记录' ;
CREATE TABLE IF NOT EXISTS ll_us_truck_order_status_history (
id BIGINT NOT NULL COMMENT '主键ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
2026-08-25 13:07:01 +08:00
operation_type VARCHAR ( 64 ) NOT NULL COMMENT '具名操作类型' , from_status VARCHAR ( 32 ) NULL COMMENT '变更前状态' ,
to_status VARCHAR ( 32 ) NOT NULL COMMENT '变更后状态' , operator_id VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
idempotency_key VARCHAR ( 255 ) NULL COMMENT '操作幂等键' ,
2026-08-20 18:02:38 +08:00
remark VARCHAR ( 1000 ) NULL COMMENT '备注' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
KEY idx_ll_us_truck_history ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '美国卡车订单状态历史' ;
2026-08-25 13:07:01 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_us_truck_order_status_history' AND column_name = 'operation_type' ), 'SELECT 1' ,
'ALTER TABLE ll_us_truck_order_status_history ADD COLUMN operation_type VARCHAR(64) NOT NULL DEFAULT ''UPDATE'' COMMENT ''具名操作类型'' AFTER customer_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_us_truck_order_status_history' AND column_name = 'idempotency_key' ), 'SELECT 1' ,
'ALTER TABLE ll_us_truck_order_status_history ADD COLUMN idempotency_key VARCHAR(255) NULL COMMENT ''操作幂等键'' AFTER operator_id' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
CREATE TABLE IF NOT EXISTS ll_us_truck_order_operation (
id BIGINT NOT NULL COMMENT '操作记录ID' , order_id BIGINT NOT NULL COMMENT '美国卡车订单ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , operation_type VARCHAR ( 64 ) NOT NULL COMMENT '具名操作类型' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '操作幂等键' , request_hash CHAR ( 64 ) NOT NULL COMMENT '操作请求内容哈希' ,
result_version BIGINT NOT NULL COMMENT '操作完成后的订单版本' , created_by VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_us_truck_operation_key ( customer_id , order_id , idempotency_key ),
KEY idx_ll_us_truck_operation_order ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '美国卡车订单幂等操作账' ;
2026-08-20 18:02:38 +08:00
CREATE TABLE IF NOT EXISTS ll_local_looseboard_order (
2026-08-22 12:35:32 +08:00
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , lastleg_order_id BIGINT NULL COMMENT '关联尾程主订单ID' , order_no VARCHAR ( 64 ) NOT NULL COMMENT '本土散板订单号' ,
2026-08-20 18:02:38 +08:00
transport_mode VARCHAR ( 32 ) NOT NULL COMMENT '运输方式:拼车或优先拼载' , pallet_required VARCHAR ( 8 ) NOT NULL COMMENT '是否需要打盘:YES或NO' ,
transport_type VARCHAR ( 32 ) NOT NULL COMMENT '运输类型' , origin VARCHAR ( 255 ) NOT NULL COMMENT '起运地' , origin_address VARCHAR ( 500 ) NULL COMMENT '起运详细地址' ,
destination VARCHAR ( 255 ) NOT NULL COMMENT '目的地' , destination_address VARCHAR ( 500 ) NULL COMMENT '目的详细地址、码头或仓号' ,
container_type VARCHAR ( 32 ) NULL COMMENT '柜型' , package_count INT NOT NULL DEFAULT 0 COMMENT '货物件数' ,
total_weight_kg DECIMAL ( 18 , 3 ) NOT NULL DEFAULT 0 COMMENT '总重量(千克)' , total_volume_cbm DECIMAL ( 18 , 6 ) NOT NULL DEFAULT 0 COMMENT '总体积(立方米)' ,
budget_amount DECIMAL ( 18 , 2 ) NULL COMMENT '预算总价' , currency CHAR ( 3 ) NOT NULL DEFAULT 'USD' COMMENT '预算币种' ,
contact_name VARCHAR ( 128 ) NULL COMMENT '联系人姓名' , contact_info VARCHAR ( 128 ) NULL COMMENT '联系人联系方式' ,
requested_date DATE NULL COMMENT '要求服务日期' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_ACCEPTANCE' COMMENT '本土散板订单状态' ,
remark VARCHAR ( 1000 ) NULL COMMENT '备注' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '创建幂等键' , request_hash CHAR ( 64 ) NOT NULL COMMENT '创建请求内容哈希' ,
created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' , version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_local_looseboard_no ( customer_id , order_no ), UNIQUE KEY uk_ll_local_looseboard_key ( customer_id , idempotency_key ),
2026-08-22 12:35:32 +08:00
UNIQUE KEY uk_ll_local_looseboard_lastleg ( lastleg_order_id ),
2026-08-20 18:02:38 +08:00
KEY idx_ll_local_looseboard_list ( customer_id , status , created_at ), KEY idx_ll_local_looseboard_date ( customer_id , requested_date , created_at )
) ENGINE = InnoDB COMMENT = '本土散板订单' ;
2026-08-22 12:35:32 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_local_looseboard_order' AND column_name = 'lastleg_order_id' ), 'SELECT 1' ,
'ALTER TABLE ll_local_looseboard_order ADD COLUMN lastleg_order_id BIGINT NULL COMMENT ''关联尾程主订单ID'' AFTER customer_id' ));
PREPARE phase4_looseboard_tail_stmt FROM @ ddl ; EXECUTE phase4_looseboard_tail_stmt ; DEALLOCATE PREPARE phase4_looseboard_tail_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_local_looseboard_order' AND index_name = 'uk_ll_local_looseboard_lastleg' ), 'SELECT 1' ,
'ALTER TABLE ll_local_looseboard_order ADD UNIQUE KEY uk_ll_local_looseboard_lastleg(lastleg_order_id)' ));
PREPARE phase4_looseboard_tail_stmt FROM @ ddl ; EXECUTE phase4_looseboard_tail_stmt ; DEALLOCATE PREPARE phase4_looseboard_tail_stmt ;
2026-08-20 18:02:38 +08:00
CREATE TABLE IF NOT EXISTS ll_local_looseboard_history (
id BIGINT NOT NULL COMMENT '主键ID' , order_id BIGINT NOT NULL COMMENT '本土散板订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
operation_type VARCHAR ( 32 ) NOT NULL COMMENT '操作类型:CREATE、UPDATE或STATUS' , from_status VARCHAR ( 32 ) NULL COMMENT '变更前状态' ,
to_status VARCHAR ( 32 ) NOT NULL COMMENT '变更后状态' , operator_id VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
2026-08-25 13:07:01 +08:00
idempotency_key VARCHAR ( 255 ) NULL COMMENT '操作幂等键' , change_detail JSON NULL COMMENT '字段变更前后值JSON' , remark VARCHAR ( 1000 ) NULL COMMENT '操作备注' ,
2026-08-20 18:02:38 +08:00
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
KEY idx_ll_local_looseboard_history ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '本土散板操作流水' ;
2026-08-25 13:07:01 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_local_looseboard_history' AND column_name = 'idempotency_key' ), 'SELECT 1' ,
'ALTER TABLE ll_local_looseboard_history ADD COLUMN idempotency_key VARCHAR(255) NULL COMMENT ''操作幂等键'' AFTER operator_id' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
CREATE TABLE IF NOT EXISTS ll_local_looseboard_operation (
id BIGINT NOT NULL COMMENT '操作记录ID' , order_id BIGINT NOT NULL COMMENT '本土散板订单ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , operation_type VARCHAR ( 32 ) NOT NULL COMMENT '操作类型' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '操作幂等键' , request_hash CHAR ( 64 ) NOT NULL COMMENT '操作请求内容哈希' ,
result_version BIGINT NOT NULL COMMENT '操作完成后的订单版本' , created_by VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_local_looseboard_operation_key ( customer_id , order_id , idempotency_key ),
KEY idx_ll_local_looseboard_operation_order ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '本土散板订单幂等操作账' ;
2026-08-24 10:33:05 +08:00
-- 尾程主订单状态历史补齐客户隔离键。代码写入 customer_id,已有表需显式升级;
-- 先允许 NULL 以便从主订单回填,再收紧为 NOT NULL,脚本可重复执行。
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_loading_order_status_history' AND column_name = 'customer_id' ), 'SELECT 1' ,
'ALTER TABLE ll_loading_order_status_history ADD COLUMN customer_id VARCHAR(128) NULL COMMENT ''客户数据隔离键'' AFTER id' ));
PREPARE phase4_loading_history_customer_stmt FROM @ ddl ; EXECUTE phase4_loading_history_customer_stmt ; DEALLOCATE PREPARE phase4_loading_history_customer_stmt ;
UPDATE ll_loading_order_status_history history
JOIN ll_order orders ON orders . id = history . order_id
SET history . customer_id = orders . customer_id
WHERE history . customer_id IS NULL ;
ALTER TABLE ll_loading_order_status_history
MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_loading_order_status_history' AND index_name = 'idx_ll_loading_history_customer_order' ), 'SELECT 1' ,
'ALTER TABLE ll_loading_order_status_history ADD KEY idx_ll_loading_history_customer_order(customer_id,order_id,created_at)' ));
PREPARE phase4_loading_history_customer_stmt FROM @ ddl ; EXECUTE phase4_loading_history_customer_stmt ; DEALLOCATE PREPARE phase4_loading_history_customer_stmt ;
2026-08-24 11:55:50 +08:00
-- 尾程订单明细实体、事件消费者和详情查询均使用 customer_id;已有开发库需从主订单回填。
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_order_detail' AND column_name = 'customer_id' ), 'SELECT 1' ,
'ALTER TABLE ll_order_detail ADD COLUMN customer_id VARCHAR(128) NULL COMMENT ''客户数据隔离键'' AFTER id' ));
PREPARE phase4_order_detail_customer_stmt FROM @ ddl ; EXECUTE phase4_order_detail_customer_stmt ; DEALLOCATE PREPARE phase4_order_detail_customer_stmt ;
UPDATE ll_order_detail detail
JOIN ll_order orders ON orders . id = detail . order_id
SET detail . customer_id = orders . customer_id
WHERE detail . customer_id IS NULL ;
ALTER TABLE ll_order_detail
MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_order_detail' AND index_name = 'idx_ll_detail_customer_order' ), 'SELECT 1' ,
'ALTER TABLE ll_order_detail ADD KEY idx_ll_detail_customer_order(customer_id,order_id,id)' ));
PREPARE phase4_order_detail_customer_stmt FROM @ ddl ; EXECUTE phase4_order_detail_customer_stmt ; DEALLOCATE PREPARE phase4_order_detail_customer_stmt ;
2026-08-22 10:20:38 +08:00
-- 四期平台排车查询、智能预排与草稿锁;不开放编辑、发车、PDA 出库或派送。
CREATE TABLE IF NOT EXISTS ll_dispatch_order (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
dispatch_no VARCHAR ( 64 ) NOT NULL COMMENT '派车单号' , overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外仓ID' ,
overseas_warehouse_name VARCHAR ( 255 ) NULL COMMENT '海外仓名称快照' , vehicle_plate VARCHAR ( 64 ) NULL COMMENT '车牌号' ,
driver_name VARCHAR ( 128 ) NULL COMMENT '司机姓名' , driver_phone VARCHAR ( 64 ) NULL COMMENT '司机电话' ,
carrier_name VARCHAR ( 255 ) NULL COMMENT '承运商名称' , route VARCHAR ( 255 ) NULL COMMENT '运输路线' ,
depart_at DATETIME ( 3 ) NULL COMMENT '发车时间' , fba_appointment_no VARCHAR ( 64 ) NULL COMMENT 'FBA预约号' ,
fba_appointment_status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT 'FBA预约状态' ,
vehicle_appointment_status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '车辆预约状态' ,
estimated_arrival_at DATETIME ( 3 ) NULL COMMENT '预计到达时间' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_DEPARTURE' COMMENT '业务状态' ,
item_count INT NOT NULL DEFAULT 0 COMMENT '明细数量' , pallet_count INT NOT NULL DEFAULT 0 COMMENT '托盘数' ,
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数' , picked_package_count INT NOT NULL DEFAULT 0 COMMENT 'PDA累计已拣箱数' ,
shipped_package_count INT NOT NULL DEFAULT 0 COMMENT '累计已出库箱数' , partial_completion_reason VARCHAR ( 1000 ) NULL COMMENT '部分完成原因' ,
created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
2026-09-01 14:24:59 +08:00
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_dispatch_order_no ( dispatch_no ),
2026-08-22 10:20:38 +08:00
KEY idx_ll_dispatch_order_list ( customer_id , status , depart_at ), KEY idx_ll_dispatch_order_vehicle ( customer_id , vehicle_plate )
) ENGINE = InnoDB COMMENT = '尾程派车单' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_item (
id BIGINT NOT NULL COMMENT '主键ID' , dispatch_order_id BIGINT NOT NULL COMMENT '派车单ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , plan_id BIGINT NULL COMMENT '入仓计划ID' ,
plan_pallet_id BIGINT NULL COMMENT '计划托盘ID' , warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID' ,
order_id BIGINT NULL COMMENT '订单ID' , order_no VARCHAR ( 64 ) NULL COMMENT '订单号' ,
order_refs VARCHAR ( 2000 ) NULL COMMENT '关联订单信息' , inbound_code VARCHAR ( 128 ) NULL COMMENT '入仓单号快照' ,
pallet_no VARCHAR ( 128 ) NOT NULL COMMENT '托盘号' , overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外仓ID' ,
overseas_warehouse_name VARCHAR ( 255 ) NULL COMMENT '海外仓名称快照' , destination_warehouse_id VARCHAR ( 128 ) NULL COMMENT '目的仓ID' ,
destination_warehouse_code VARCHAR ( 128 ) NULL COMMENT '目的仓编码快照' , destination_warehouse_name VARCHAR ( 255 ) NULL COMMENT '目的仓名称快照' ,
fba_warehouse_code VARCHAR ( 128 ) NULL COMMENT 'FBA仓库编码' , package_count INT NOT NULL DEFAULT 0 COMMENT '箱数' ,
volume_cbm DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '体积(立方米)' , source_stage VARCHAR ( 32 ) NOT NULL COMMENT '数据来源阶段' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dispatch_item_source ( dispatch_order_id , plan_pallet_id , warehouse_pallet_id ),
KEY idx_ll_dispatch_item_order ( customer_id , order_id ), KEY idx_ll_dispatch_item_inbound ( customer_id , inbound_code ),
KEY idx_ll_dispatch_item_pallet ( customer_id , plan_pallet_id , warehouse_pallet_id )
) ENGINE = InnoDB COMMENT = '派车货物冻结明细' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_pallet_lock (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
source_pallet_key VARCHAR ( 160 ) NOT NULL COMMENT '来源托盘业务键' , active_key VARCHAR ( 160 ) NULL COMMENT '生效中的资源排他键' ,
plan_id BIGINT NULL COMMENT '入仓计划ID' , plan_pallet_id BIGINT NULL COMMENT '计划托盘ID' ,
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID' , dispatch_order_id BIGINT NULL COMMENT '正式派车单ID,草稿锁阶段为空' ,
draft_container_id BIGINT NULL COMMENT '智能排车草稿装车托盘ID' , draft_token VARCHAR ( 64 ) NULL COMMENT '智能排车草稿随机标识' ,
operator_id VARCHAR ( 128 ) NULL COMMENT '草稿锁操作人ID' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'ACTIVE' COMMENT '业务状态' ,
locked_at DATETIME ( 3 ) NOT NULL COMMENT '锁定时间' , expires_at DATETIME ( 3 ) NULL COMMENT '草稿锁失效时间,正式派车锁为空' ,
released_at DATETIME ( 3 ) NULL COMMENT '释放时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_dispatch_active_pallet ( customer_id , active_key ),
KEY idx_ll_dispatch_pallet_lock_order ( customer_id , dispatch_order_id , status ),
KEY idx_ll_dispatch_pallet_lock_source ( customer_id , source_pallet_key , status )
) ENGINE = InnoDB COMMENT = '派车托盘排他锁' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_draft (
id BIGINT NOT NULL COMMENT '主键ID' , draft_token VARCHAR ( 64 ) NOT NULL COMMENT '智能排车草稿随机标识' ,
customer_id VARCHAR ( 128 ) NULL COMMENT '客户租户ID' , operator_id VARCHAR ( 128 ) NULL COMMENT '草稿操作人ID' ,
plan_ids_json VARCHAR ( 4000 ) NULL COMMENT '所选入仓计划ID列表JSON' , containers_json LONGTEXT NULL COMMENT '草稿装车布局JSON快照' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'ACTIVE' COMMENT '草稿状态' , expires_at DATETIME ( 3 ) NULL COMMENT '草稿失效时间' ,
released_at DATETIME ( 3 ) NULL COMMENT '草稿释放时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dispatch_draft_token ( draft_token ), KEY idx_ll_dispatch_draft_operator ( operator_id , status )
) ENGINE = InnoDB COMMENT = '智能排车草稿' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_draft_container (
id BIGINT NOT NULL COMMENT '主键ID' , draft_id BIGINT NOT NULL COMMENT '智能排车草稿ID' ,
draft_token VARCHAR ( 64 ) NOT NULL COMMENT '智能排车草稿随机标识' , sequence_no INT NOT NULL COMMENT '草稿车厢顺序号' ,
capacity INT NOT NULL COMMENT '草稿车厢托盘容量' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
KEY idx_ll_dispatch_draft_container_token ( draft_token )
) ENGINE = InnoDB COMMENT = '智能排车草稿装车托盘' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_item' AND column_name = 'order_refs' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_item ADD COLUMN order_refs VARCHAR(2000) NULL COMMENT ''关联订单信息'' AFTER order_no' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pallet_lock' AND column_name = 'draft_container_id' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_pallet_lock ADD COLUMN draft_container_id BIGINT NULL COMMENT ''智能排车草稿装车托盘ID'' AFTER dispatch_order_id' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pallet_lock' AND column_name = 'draft_token' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_pallet_lock ADD COLUMN draft_token VARCHAR(64) NULL COMMENT ''智能排车草稿随机标识'' AFTER draft_container_id' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pallet_lock' AND column_name = 'operator_id' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_pallet_lock ADD COLUMN operator_id VARCHAR(128) NULL COMMENT ''草稿锁操作人ID'' AFTER draft_token' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pallet_lock' AND column_name = 'expires_at' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_pallet_lock ADD COLUMN expires_at DATETIME(3) NULL COMMENT ''草稿锁失效时间,正式派车锁为空'' AFTER locked_at' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pallet_lock' AND column_name = 'dispatch_order_id' AND is_nullable = 'YES' ),
'SELECT 1' , 'ALTER TABLE ll_dispatch_pallet_lock MODIFY COLUMN dispatch_order_id BIGINT NULL COMMENT ''正式派车单ID,草稿锁阶段为空''' ));
PREPARE phase4_dispatch_stmt FROM @ ddl ; EXECUTE phase4_dispatch_stmt ; DEALLOCATE PREPARE phase4_dispatch_stmt ;
2026-08-20 18:02:38 +08:00
-- 入仓库存按 SKU 冻结维度;旧环境只补结构,不由部署自动执行。
CREATE TABLE IF NOT EXISTS ll_inbound_plan_carton (
id BIGINT NOT NULL COMMENT '箱唛作业主键' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' ,
order_id BIGINT NULL COMMENT '海外首扫确权后的尾程订单ID' , source_inbound_detail_id VARCHAR ( 128 ) NOT NULL COMMENT '来源入库明细ID' ,
sku_code VARCHAR ( 128 ) NULL COMMENT 'SKU编码快照' , carton_mark VARCHAR ( 128 ) NOT NULL COMMENT '国内冻结箱唛' ,
destination_warehouse_id VARCHAR ( 128 ) NULL COMMENT '目的仓ID快照' , destination_warehouse_code VARCHAR ( 128 ) NULL COMMENT '目的仓编码快照' ,
destination_warehouse_name VARCHAR ( 255 ) NULL COMMENT '目的仓名称快照' , plan_id BIGINT NULL COMMENT '海外入库计划ID' ,
line_id BIGINT NULL COMMENT '入库计划明细ID' , plan_pallet_id BIGINT NULL COMMENT '海外计划托盘ID' , warehouse_pallet_id BIGINT NULL COMMENT '海外实物托盘ID' ,
warehouse_location_id BIGINT NULL COMMENT '海外库位ID' , pda_task_id BIGINT NULL COMMENT '首次扫码PDA任务ID' ,
2026-08-24 17:15:48 +08:00
status VARCHAR ( 32 ) NOT NULL COMMENT '箱唛状态:UNASSIGNED、ON_PALLET、BULK_RECEIVED、AVAILABLE' , version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
2026-08-20 18:02:38 +08:00
bound_at DATETIME ( 3 ) NULL COMMENT '绑定托盘时间' , received_at DATETIME ( 3 ) NULL COMMENT '完成入库时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_inbound_carton_mark ( customer_id , carton_mark ),
KEY idx_ll_inbound_carton_plan ( plan_id , status ), KEY idx_ll_inbound_carton_pallet ( plan_pallet_id , status ), KEY idx_ll_inbound_carton_order ( order_id , status )
) ENGINE = InnoDB COMMENT = '柜次冻结箱唛及海外入库箱级作业账' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'source_container_booking_id' ),
'ALTER TABLE ll_order MODIFY COLUMN source_container_booking_id VARCHAR(128) NULL COMMENT ''来源头程货柜预订ID''' ,
'ALTER TABLE ll_order ADD COLUMN source_container_booking_id VARCHAR(128) NULL COMMENT ''来源头程货柜预订ID'' AFTER source_loading_plan_id' ));
PREPARE phase4_event_stmt FROM @ ddl ; EXECUTE phase4_event_stmt ; DEALLOCATE PREPARE phase4_event_stmt ;
2026-08-28 13:54:32 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_order' AND index_name = 'idx_ll_order_pending_container' ),
'ALTER TABLE ll_order DROP INDEX idx_ll_order_pending_container' , 'SELECT 1' ));
PREPARE phase4_container_progress_idx_stmt FROM @ ddl ; EXECUTE phase4_container_progress_idx_stmt ; DEALLOCATE PREPARE phase4_container_progress_idx_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_order' AND index_name = 'idx_ll_order_container_progress' ),
'SELECT 1' , 'ALTER TABLE ll_order ADD INDEX idx_ll_order_container_progress(source_container_booking_id,estimated_warehouse_at,created_at,id)' ));
PREPARE phase4_container_progress_idx_stmt FROM @ ddl ; EXECUTE phase4_container_progress_idx_stmt ; DEALLOCATE PREPARE phase4_container_progress_idx_stmt ;
DROP PROCEDURE IF EXISTS assert_container_progress_index_ready ;
DELIMITER $$
CREATE PROCEDURE assert_container_progress_index_ready ()
BEGIN
IF NOT EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_order' AND index_name = 'idx_ll_order_container_progress' ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外区域初始化失败:柜级入库计划进度索引缺失' ;
END IF ;
END $$
DELIMITER ;
CALL assert_container_progress_index_ready ();
DROP PROCEDURE assert_container_progress_index_ready ;
2026-08-20 18:02:38 +08:00
2026-08-24 17:15:48 +08:00
-- 头程 V2 事件冻结目的类型;只补结构,不由部署脚本自动执行历史数据回填。
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'destination_type' ),
'ALTER TABLE ll_order MODIFY COLUMN destination_type VARCHAR(32) NULL COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码''' ,
'ALTER TABLE ll_order ADD COLUMN destination_type VARCHAR(32) NULL COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码'' AFTER order_type' ));
PREPARE phase4_destination_type_stmt FROM @ ddl ; EXECUTE phase4_destination_type_stmt ; DEALLOCATE PREPARE phase4_destination_type_stmt ;
2026-09-07 12:30:17 +08:00
ALTER TABLE ll_order
MODIFY COLUMN inbound_code VARCHAR ( 128 ) NULL COMMENT '真实来源入仓码;无入仓关系的海外本土业务为空' ;
2026-08-24 17:15:48 +08:00
2026-08-27 15:56:14 +08:00
CREATE TABLE IF NOT EXISTS ll_order_no_daily_sequence (
business_date DATE NOT NULL COMMENT '业务日期(Asia/Shanghai) ' ,
last_sequence INT NOT NULL COMMENT '当日已分配尾程单流水号' ,
PRIMARY KEY ( business_date )
) ENGINE = InnoDB COMMENT = '尾程单号按日原子流水' ;
2026-08-24 17:15:48 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_line' AND column_name = 'customer_id' ),
2026-08-24 17:37:15 +08:00
'SELECT 1' ,
2026-08-24 17:15:48 +08:00
'ALTER TABLE ll_inbound_plan_line ADD COLUMN customer_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''客户账号标识'' AFTER id' ));
PREPARE phase4_receiving_line_stmt FROM @ ddl ; EXECUTE phase4_receiving_line_stmt ; DEALLOCATE PREPARE phase4_receiving_line_stmt ;
2026-08-24 17:48:08 +08:00
UPDATE ll_inbound_plan_line l JOIN ll_inbound_plan p ON p . id = l . plan_id SET l . customer_id = p . customer_id WHERE l . customer_id IS NULL OR l . customer_id = '' ;
2026-08-24 17:15:48 +08:00
ALTER TABLE ll_inbound_plan_line MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户账号标识' ;
2026-08-24 17:37:15 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_line' AND index_name = 'idx_ll_inbound_line_customer_plan' ), 'SELECT 1' , 'ALTER TABLE ll_inbound_plan_line ADD KEY idx_ll_inbound_line_customer_plan(customer_id,plan_id)' ));
PREPARE phase4_receiving_scope_stmt FROM @ ddl ; EXECUTE phase4_receiving_scope_stmt ; DEALLOCATE PREPARE phase4_receiving_scope_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 = 'customer_id' ),
'SELECT 1' ,
'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN customer_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''客户账号标识'' AFTER id' ));
PREPARE phase4_receiving_scope_stmt FROM @ ddl ; EXECUTE phase4_receiving_scope_stmt ; DEALLOCATE PREPARE phase4_receiving_scope_stmt ;
2026-08-24 17:48:08 +08:00
UPDATE ll_inbound_plan_pallet v JOIN ll_inbound_plan p ON p . id = v . plan_id SET v . customer_id = p . customer_id WHERE v . customer_id IS NULL OR v . customer_id = '' ;
2026-08-24 17:37:15 +08:00
ALTER TABLE ll_inbound_plan_pallet MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户账号标识' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_pallet' AND index_name = 'idx_ll_inbound_pallet_customer_plan' ), 'SELECT 1' , 'ALTER TABLE ll_inbound_plan_pallet ADD KEY idx_ll_inbound_pallet_customer_plan(customer_id,plan_id)' ));
PREPARE phase4_receiving_scope_stmt FROM @ ddl ; EXECUTE phase4_receiving_scope_stmt ; DEALLOCATE PREPARE phase4_receiving_scope_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_pallet_allocation' AND column_name = 'customer_id' ),
'SELECT 1' ,
'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN customer_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''客户账号标识'' AFTER id' ));
PREPARE phase4_receiving_scope_stmt FROM @ ddl ; EXECUTE phase4_receiving_scope_stmt ; DEALLOCATE PREPARE phase4_receiving_scope_stmt ;
2026-08-24 17:48:08 +08:00
UPDATE ll_inbound_plan_pallet_allocation a JOIN ll_inbound_plan p ON p . id = a . plan_id SET a . customer_id = p . customer_id WHERE a . customer_id IS NULL OR a . customer_id = '' ;
2026-08-24 17:37:15 +08:00
ALTER TABLE ll_inbound_plan_pallet_allocation MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户账号标识' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_pallet_allocation' AND index_name = 'idx_ll_inbound_allocation_customer_plan' ), 'SELECT 1' , 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD KEY idx_ll_inbound_allocation_customer_plan(customer_id,plan_id)' ));
PREPARE phase4_receiving_scope_stmt FROM @ ddl ; EXECUTE phase4_receiving_scope_stmt ; DEALLOCATE PREPARE phase4_receiving_scope_stmt ;
2026-08-24 17:48:08 +08:00
DROP PROCEDURE IF EXISTS assert_phase4_inbound_plan_customer_scope_ready ;
DELIMITER $$
CREATE PROCEDURE assert_phase4_inbound_plan_customer_scope_ready ()
BEGIN
IF EXISTS ( SELECT 1 FROM ll_inbound_plan_line l LEFT JOIN ll_inbound_plan p ON p . id = l . plan_id WHERE l . customer_id IS NULL OR l . customer_id = '' OR p . id IS NULL OR l . customer_id <> p . customer_id )
OR EXISTS ( SELECT 1 FROM ll_inbound_plan_pallet v LEFT JOIN ll_inbound_plan p ON p . id = v . plan_id WHERE v . customer_id IS NULL OR v . customer_id = '' OR p . id IS NULL OR v . customer_id <> p . customer_id )
OR EXISTS ( SELECT 1 FROM ll_inbound_plan_pallet_allocation a LEFT JOIN ll_inbound_plan p ON p . id = a . plan_id WHERE a . customer_id IS NULL OR a . customer_id = '' OR p . id IS NULL OR a . customer_id <> p . customer_id ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Inbound plan child customer scope migration is incomplete' ;
END IF ;
END $$
DELIMITER ;
CALL assert_phase4_inbound_plan_customer_scope_ready ();
DROP PROCEDURE assert_phase4_inbound_plan_customer_scope_ready ;
2026-08-24 17:15:48 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_line' AND column_name = 'fba_warehouse_code' ),
'ALTER TABLE ll_inbound_plan_line MODIFY COLUMN fba_warehouse_code VARCHAR(128) NULL COMMENT ''FBA仓库编码''' ,
'ALTER TABLE ll_inbound_plan_line ADD COLUMN fba_warehouse_code VARCHAR(128) NULL COMMENT ''FBA仓库编码'' AFTER inbound_code' ));
PREPARE phase4_receiving_line_stmt FROM @ ddl ; EXECUTE phase4_receiving_line_stmt ; DEALLOCATE PREPARE phase4_receiving_line_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan_line' AND column_name = 'destination_type' ),
'ALTER TABLE ll_inbound_plan_line MODIFY COLUMN destination_type VARCHAR(32) NOT NULL DEFAULT ''OVERSEAS'' COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码''' ,
'ALTER TABLE ll_inbound_plan_line ADD COLUMN destination_type VARCHAR(32) NOT NULL DEFAULT ''OVERSEAS'' COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码'' AFTER inbound_code' ));
PREPARE phase4_receiving_line_stmt FROM @ ddl ; EXECUTE phase4_receiving_line_stmt ; DEALLOCATE PREPARE phase4_receiving_line_stmt ;
UPDATE ll_inbound_plan_line l JOIN ll_order o ON o . id = l . order_id
SET l . destination_type = COALESCE ( NULLIF ( o . destination_type , '' ), CASE WHEN NULLIF ( l . fba_warehouse_code , '' ) IS NULL THEN 'OVERSEAS' ELSE 'FBA' END )
WHERE l . destination_type IS NULL OR l . destination_type = '' OR l . destination_type = 'OVERSEAS' ;
2026-08-24 21:46:19 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'source_warehouse_id' ),
'SELECT 1' , 'ALTER TABLE ll_order ADD COLUMN source_warehouse_id VARCHAR(128) NULL COMMENT ''来源国内装柜仓ID快照'' AFTER customer_name' ));
PREPARE phase4_source_warehouse_id_stmt FROM @ ddl ; EXECUTE phase4_source_warehouse_id_stmt ; DEALLOCATE PREPARE phase4_source_warehouse_id_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'source_warehouse_name' ),
'SELECT 1' , 'ALTER TABLE ll_order ADD COLUMN source_warehouse_name VARCHAR(255) NULL COMMENT ''来源国内装柜仓名称快照'' AFTER source_warehouse_id' ));
PREPARE phase4_source_warehouse_name_stmt FROM @ ddl ; EXECUTE phase4_source_warehouse_name_stmt ; DEALLOCATE PREPARE phase4_source_warehouse_name_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 = 'overseas_warehouse_id' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_plan ADD COLUMN overseas_warehouse_id BIGINT NULL COMMENT ''海外实际收货共享物理仓ID,由PDA认领柜号时冻结'' AFTER container_no' ));
PREPARE phase4_plan_receiving_warehouse_stmt FROM @ ddl ; EXECUTE phase4_plan_receiving_warehouse_stmt ; DEALLOCATE PREPARE phase4_plan_receiving_warehouse_stmt ;
UPDATE ll_order o JOIN ll_loading_event_inbox i ON i . event_id = o . source_event_id
SET o . source_warehouse_id = COALESCE ( o . source_warehouse_id , JSON_UNQUOTE ( JSON_EXTRACT ( i . payload_json , '$.warehouseId' ))),
o . source_warehouse_name = COALESCE ( o . source_warehouse_name , JSON_UNQUOTE ( JSON_EXTRACT ( i . payload_json , '$.warehouseName' ))),
o . overseas_warehouse_id = NULL , o . overseas_warehouse_name = NULL
WHERE o . current_status <> 'INBOUND_COMPLETED'
AND o . overseas_warehouse_id = JSON_UNQUOTE ( JSON_EXTRACT ( i . payload_json , '$.warehouseId' ));
DROP PROCEDURE IF EXISTS assert_pending_orders_do_not_use_source_warehouse ;
DELIMITER $$
CREATE PROCEDURE assert_pending_orders_do_not_use_source_warehouse ()
BEGIN
IF EXISTS ( SELECT 1 FROM ll_order o JOIN ll_loading_event_inbox i ON i . event_id = o . source_event_id
WHERE o . current_status <> 'INBOUND_COMPLETED' AND o . overseas_warehouse_id IS NOT NULL
AND o . overseas_warehouse_id = JSON_UNQUOTE ( JSON_EXTRACT ( i . payload_json , '$.warehouseId' ))) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '未完成尾程单仍将国内来源仓冒充海外实际收货仓' ;
END IF ;
END $$
DELIMITER ;
CALL assert_pending_orders_do_not_use_source_warehouse ();
DROP PROCEDURE assert_pending_orders_do_not_use_source_warehouse ;
2026-08-24 17:15:48 +08:00
CREATE TABLE IF NOT EXISTS ll_receiving_container_session (
2026-08-28 13:54:32 +08:00
id BIGINT NOT NULL COMMENT '柜号签收会话ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '所选柜解析出的客户标识' ,
source_container_booking_id VARCHAR ( 128 ) NOT NULL COMMENT '稳定来源柜预订ID' , container_fact_hash VARCHAR ( 64 ) NOT NULL COMMENT '领取时整柜订单与计划事实摘要' , container_no VARCHAR ( 64 ) NOT NULL COMMENT '集装箱号' ,
2026-08-24 21:46:19 +08:00
overseas_warehouse_id BIGINT NOT NULL COMMENT '操作员Token绑定并冻结的海外实际收货共享物理仓ID' , overseas_warehouse_name VARCHAR ( 255 ) NOT NULL COMMENT '仓库服务校验后的海外实际收货共享物理仓名称快照' ,
2026-08-24 21:00:22 +08:00
operator_key VARCHAR ( 128 ) NOT NULL COMMENT '操作账号唯一标识' , operator_name VARCHAR ( 255 ) NULL COMMENT '操作账号名称' , active_operator_key VARCHAR ( 255 ) NULL COMMENT '未完成会话平台操作账号全局唯一锁键' ,
active_container_key VARCHAR ( 255 ) NULL COMMENT '未完成会话柜号全局唯一锁键' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'WAIT_SIGN' COMMENT '会话状态:WAIT_SIGN、SIGNED、RECEIVING、COMPLETED' ,
2026-08-24 19:28:32 +08:00
sign_photos JSON NULL COMMENT '签收卸柜照片角色与文件ID列表' , prepared_at DATETIME ( 3 ) NULL COMMENT '选择柜号时间' , signed_at DATETIME ( 3 ) NULL COMMENT '签收时间' ,
2026-08-24 17:15:48 +08:00
receiving_at DATETIME ( 3 ) NULL COMMENT '首次收货时间' , completed_at DATETIME ( 3 ) NULL COMMENT '完成时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_receiving_active_operator ( active_operator_key ), UNIQUE KEY uk_ll_receiving_active_container ( active_container_key ),
KEY idx_ll_receiving_container ( customer_id , container_no , status ), KEY idx_ll_receiving_operator ( customer_id , operator_key , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA柜号签收收货会话' ;
2026-08-28 13:54:32 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'source_container_booking_id' ),
'SELECT 1' , 'ALTER TABLE ll_receiving_container_session ADD COLUMN source_container_booking_id VARCHAR(128) NULL COMMENT ''稳定来源柜预订ID'' AFTER customer_id' ));
PREPARE phase4_receiving_fact_stmt FROM @ ddl ; EXECUTE phase4_receiving_fact_stmt ; DEALLOCATE PREPARE phase4_receiving_fact_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'container_fact_hash' ),
'SELECT 1' , 'ALTER TABLE ll_receiving_container_session ADD COLUMN container_fact_hash VARCHAR(64) NULL COMMENT ''领取时整柜订单与计划事实摘要'' AFTER source_container_booking_id' ));
PREPARE phase4_receiving_fact_stmt FROM @ ddl ; EXECUTE phase4_receiving_fact_stmt ; DEALLOCATE PREPARE phase4_receiving_fact_stmt ;
2026-08-24 21:46:19 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'overseas_warehouse_id' ),
'SELECT 1' , 'ALTER TABLE ll_receiving_container_session ADD COLUMN overseas_warehouse_id BIGINT NULL COMMENT ''操作员Token绑定并冻结的海外实际收货共享物理仓ID'' AFTER container_no' ));
PREPARE phase4_session_receiving_warehouse_stmt FROM @ ddl ; EXECUTE phase4_session_receiving_warehouse_stmt ; DEALLOCATE PREPARE phase4_session_receiving_warehouse_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'overseas_warehouse_name' ),
'SELECT 1' , 'ALTER TABLE ll_receiving_container_session ADD COLUMN overseas_warehouse_name VARCHAR(255) NULL COMMENT ''仓库服务校验后的海外实际收货共享物理仓名称快照'' AFTER overseas_warehouse_id' ));
PREPARE phase4_session_receiving_warehouse_name_stmt FROM @ ddl ; EXECUTE phase4_session_receiving_warehouse_name_stmt ; DEALLOCATE PREPARE phase4_session_receiving_warehouse_name_stmt ;
DROP PROCEDURE IF EXISTS assert_active_receiving_session_has_warehouse ;
DELIMITER $$
CREATE PROCEDURE assert_active_receiving_session_has_warehouse ()
BEGIN
IF EXISTS ( SELECT 1 FROM ll_receiving_container_session WHERE active_container_key IS NOT NULL
AND ( overseas_warehouse_id IS NULL OR overseas_warehouse_name IS NULL OR overseas_warehouse_name = '' )) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '存在无法安全推断海外实际收货仓的未完成PDA柜会话' ;
END IF ;
END $$
DELIMITER ;
CALL assert_active_receiving_session_has_warehouse ();
DROP PROCEDURE assert_active_receiving_session_has_warehouse ;
ALTER TABLE ll_receiving_container_session
MODIFY COLUMN overseas_warehouse_id BIGINT NOT NULL COMMENT '操作员Token绑定并冻结的海外实际收货共享物理仓ID' ,
MODIFY COLUMN overseas_warehouse_name VARCHAR ( 255 ) NOT NULL COMMENT '仓库服务校验后的海外实际收货共享物理仓名称快照' ;
2026-08-24 19:28:32 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'sign_photos' ),
'ALTER TABLE ll_receiving_container_session MODIFY COLUMN sign_photos JSON NULL COMMENT ''签收卸柜照片角色与文件ID列表''' ,
'ALTER TABLE ll_receiving_container_session ADD COLUMN sign_photos JSON NULL COMMENT ''签收卸柜照片角色与文件ID列表'' AFTER status' ));
PREPARE phase4_receiving_sign_photos_stmt FROM @ ddl ; EXECUTE phase4_receiving_sign_photos_stmt ; DEALLOCATE PREPARE phase4_receiving_sign_photos_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_session' AND column_name = 'photo_file_ids' ),
'ALTER TABLE ll_receiving_container_session DROP COLUMN photo_file_ids' , 'SELECT 1' ));
PREPARE phase4_receiving_drop_raw_photos_stmt FROM @ ddl ; EXECUTE phase4_receiving_drop_raw_photos_stmt ; DEALLOCATE PREPARE phase4_receiving_drop_raw_photos_stmt ;
2026-08-24 21:00:22 +08:00
DROP PROCEDURE IF EXISTS assert_receiving_global_locks_migratable ;
2026-08-24 22:14:41 +08:00
UPDATE ll_receiving_container_session
SET active_operator_key = NULL , active_container_key = NULL
WHERE status = 'COMPLETED' AND ( active_operator_key IS NOT NULL OR active_container_key IS NOT NULL );
2026-08-24 21:00:22 +08:00
DELIMITER $$
CREATE PROCEDURE assert_receiving_global_locks_migratable ()
BEGIN
IF EXISTS ( SELECT operator_key FROM ll_receiving_container_session
WHERE active_operator_key IS NOT NULL GROUP BY operator_key HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA全局账号锁迁移失败:同一账号存在多个未完成柜' ;
END IF ;
IF EXISTS ( SELECT UPPER ( TRIM ( container_no )) FROM ll_receiving_container_session
WHERE active_container_key IS NOT NULL GROUP BY UPPER ( TRIM ( container_no )) HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA全局柜号锁迁移失败:同一柜存在多个未完成会话' ;
END IF ;
END $$
DELIMITER ;
CALL assert_receiving_global_locks_migratable ();
DROP PROCEDURE assert_receiving_global_locks_migratable ;
UPDATE ll_receiving_container_session
SET active_operator_key = CONCAT ( 'OPERATOR:' , operator_key ),
active_container_key = CONCAT ( 'CONTAINER:' , UPPER ( TRIM ( container_no )))
WHERE active_operator_key IS NOT NULL OR active_container_key IS NOT NULL ;
ALTER TABLE ll_receiving_container_session
MODIFY COLUMN customer_id VARCHAR ( 128 ) NOT NULL COMMENT '所选柜解析出的客户标识' ,
MODIFY COLUMN active_operator_key VARCHAR ( 255 ) NULL COMMENT '未完成会话平台操作账号全局唯一锁键' ,
MODIFY COLUMN active_container_key VARCHAR ( 255 ) NULL COMMENT '未完成会话柜号全局唯一锁键' ;
2026-08-24 19:28:32 +08:00
CREATE TABLE IF NOT EXISTS ll_receiving_sku_receipt (
id BIGINT NOT NULL COMMENT 'FBA SKU实收进度ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户账号标识' ,
session_id BIGINT NOT NULL COMMENT '柜号签收会话ID' , plan_id BIGINT NOT NULL COMMENT '入仓计划ID' ,
line_id BIGINT NOT NULL COMMENT '入仓计划明细ID' , pallet_id BIGINT NOT NULL COMMENT '计划托盘ID' ,
order_id BIGINT NOT NULL COMMENT '尾程订单ID' , inbound_code VARCHAR ( 128 ) NOT NULL COMMENT '入仓码快照' ,
sku_code VARCHAR ( 128 ) NOT NULL COMMENT 'SKU编码快照' , product_name VARCHAR ( 255 ) NULL COMMENT '产品名称快照' ,
received_packages INT NOT NULL COMMENT 'SKU实收箱数' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_receiving_sku_pallet ( customer_id , line_id , pallet_id , sku_code ),
KEY idx_ll_receiving_sku_session ( customer_id , session_id , line_id ),
KEY idx_ll_receiving_sku_plan ( customer_id , plan_id , line_id )
) ENGINE = InnoDB COMMENT = '海外PDA柜号FBA SKU实收进度' ;
2026-08-24 17:15:48 +08:00
CREATE TABLE IF NOT EXISTS ll_receiving_container_operation (
id BIGINT NOT NULL COMMENT '柜号收货操作ID' , session_id BIGINT NOT NULL COMMENT '柜号签收会话ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户账号标识' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT '操作账号唯一标识' , action VARCHAR ( 32 ) NOT NULL COMMENT '操作动作' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '客户端幂等键' ,
request_hash VARCHAR ( 128 ) NOT NULL COMMENT '请求内容哈希' , request_json LONGTEXT NOT NULL COMMENT '请求内容快照' , result_json LONGTEXT NOT NULL COMMENT '响应内容快照' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
2026-08-24 21:00:22 +08:00
UNIQUE KEY uk_ll_receiving_operation ( operator_key , idempotency_key ), KEY idx_ll_receiving_operation_session ( session_id , created_at )
2026-08-24 17:15:48 +08:00
) ENGINE = InnoDB COMMENT = '海外PDA柜号收货幂等审计记录' ;
2026-08-24 21:00:22 +08:00
DROP PROCEDURE IF EXISTS assert_receiving_operation_global_key_migratable ;
DELIMITER $$
CREATE PROCEDURE assert_receiving_operation_global_key_migratable ()
BEGIN
IF EXISTS ( SELECT operator_key , idempotency_key FROM ll_receiving_container_operation
GROUP BY operator_key , idempotency_key HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA全局幂等键迁移失败:同一操作账号存在重复幂等键' ;
END IF ;
END $$
DELIMITER ;
CALL assert_receiving_operation_global_key_migratable ();
DROP PROCEDURE assert_receiving_operation_global_key_migratable ;
SET @ receiving_operation_global_index = (
SELECT COUNT ( * ) FROM (
SELECT index_name FROM information_schema . statistics
WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_operation'
AND index_name = 'uk_ll_receiving_operation'
GROUP BY index_name
HAVING GROUP_CONCAT ( column_name ORDER BY seq_in_index ) = 'operator_key,idempotency_key'
) ready_index
);
SET @ receiving_operation_named_index = (
SELECT COUNT ( * ) FROM information_schema . statistics
WHERE table_schema = DATABASE () AND table_name = 'll_receiving_container_operation'
AND index_name = 'uk_ll_receiving_operation'
);
SET @ ddl = IF ( @ receiving_operation_global_index = 1 , 'SELECT 1' ,
IF ( @ receiving_operation_named_index > 0 ,
'ALTER TABLE ll_receiving_container_operation DROP INDEX uk_ll_receiving_operation, ADD UNIQUE KEY uk_ll_receiving_operation(operator_key,idempotency_key)' ,
'ALTER TABLE ll_receiving_container_operation ADD UNIQUE KEY uk_ll_receiving_operation(operator_key,idempotency_key)' ));
PREPARE phase4_receiving_operation_index_stmt FROM @ ddl ; EXECUTE phase4_receiving_operation_index_stmt ; DEALLOCATE PREPARE phase4_receiving_operation_index_stmt ;
2026-08-24 17:15:48 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_order' AND column_name = 'destination_type' ),
'ALTER TABLE ll_inbound_order MODIFY COLUMN destination_type VARCHAR(32) NULL COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码''' ,
'ALTER TABLE ll_inbound_order ADD COLUMN destination_type VARCHAR(32) NULL COMMENT ''目的类型:FBA按箱数接收、OVERSEAS逐箱扫码'' AFTER destination_warehouse_name' ));
PREPARE phase4_destination_type_stmt FROM @ ddl ; EXECUTE phase4_destination_type_stmt ; DEALLOCATE PREPARE phase4_destination_type_stmt ;
2026-08-21 10:43:25 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'sub_order_status' ),
'SELECT 1' ,
'ALTER TABLE ll_order ADD COLUMN sub_order_status VARCHAR(255) NULL COMMENT ''子单据状态汇总'' AFTER current_status' ));
PREPARE phase4_sub_order_status_stmt FROM @ ddl ; EXECUTE phase4_sub_order_status_stmt ; DEALLOCATE PREPARE phase4_sub_order_status_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'order_type' AND COALESCE ( column_comment , '' ) LIKE '订单类型:%' ),
'SELECT 1' ,
'ALTER TABLE ll_order MODIFY COLUMN order_type VARCHAR(32) NOT NULL DEFAULT ''FIRST_LEG'' COMMENT ''订单类型:FIRST_LEG头程订单、RELABEL_APPLICATION换标下单、WAREHOUSE_TRANSFER仓储转运、LOCAL_LOOSEBOARD本土散板、RETURN_RELABEL退货换标、ONE_CLICK_DROPSHIP一件代发''' ));
PREPARE phase4_order_type_comment_stmt FROM @ ddl ; EXECUTE phase4_order_type_comment_stmt ; DEALLOCATE PREPARE phase4_order_type_comment_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'current_status' AND COALESCE ( column_comment , '' ) LIKE '当前业务状态:%' ),
'SELECT 1' ,
'ALTER TABLE ll_order MODIFY COLUMN current_status VARCHAR(32) NOT NULL DEFAULT ''PENDING_ASSIGNMENT'' COMMENT ''当前业务状态:PENDING_ASSIGNMENT待分配、PENDING_INBOUND待入库、INBOUND_COMPLETED入库完成、PENDING_DELIVERY待派送、DELIVERING派送中、DELIVERED派送完成''' ));
PREPARE phase4_order_status_comment_stmt FROM @ ddl ; EXECUTE phase4_order_status_comment_stmt ; DEALLOCATE PREPARE phase4_order_status_comment_stmt ;
2026-08-20 18:02:38 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_pda_task' AND column_name = 'unload_photo_file_ids' ),
'ALTER TABLE ll_inbound_pda_task MODIFY COLUMN unload_photo_file_ids JSON NULL COMMENT ''卸柜照片文件ID列表''' ,
'ALTER TABLE ll_inbound_pda_task ADD COLUMN unload_photo_file_ids JSON NULL COMMENT ''卸柜照片文件ID列表'' AFTER completed_at' ));
PREPARE phase4_event_stmt FROM @ ddl ; EXECUTE phase4_event_stmt ; DEALLOCATE PREPARE phase4_event_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_pda_task' AND column_name = 'unload_photo_uploaded_at' ),
'ALTER TABLE ll_inbound_pda_task MODIFY COLUMN unload_photo_uploaded_at DATETIME(3) NULL COMMENT ''卸柜照片上传成功时间''' ,
'ALTER TABLE ll_inbound_pda_task ADD COLUMN unload_photo_uploaded_at DATETIME(3) NULL COMMENT ''卸柜照片上传成功时间'' AFTER unload_photo_file_ids' ));
PREPARE phase4_event_stmt FROM @ ddl ; EXECUTE phase4_event_stmt ; DEALLOCATE PREPARE phase4_event_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_pda_task' AND column_name = 'estimated_empty_return_at' ),
'ALTER TABLE ll_inbound_pda_task MODIFY COLUMN estimated_empty_return_at DATETIME(3) NULL COMMENT ''预计报空时间(卸柜照片上传成功后两天)''' ,
'ALTER TABLE ll_inbound_pda_task ADD COLUMN estimated_empty_return_at DATETIME(3) NULL COMMENT ''预计报空时间(卸柜照片上传成功后两天)'' AFTER unload_photo_uploaded_at' ));
PREPARE phase4_event_stmt FROM @ ddl ; EXECUTE phase4_event_stmt ; DEALLOCATE PREPARE phase4_event_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan' AND index_name = 'uk_ll_inbound_plan_container' ),
'ALTER TABLE ll_inbound_plan DROP INDEX uk_ll_inbound_plan_container' , 'SELECT 1' ));
PREPARE phase4_inbound_stmt FROM @ ddl ; EXECUTE phase4_inbound_stmt ; DEALLOCATE PREPARE phase4_inbound_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan' AND index_name = 'idx_ll_inbound_plan_container' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_plan ADD KEY idx_ll_inbound_plan_container (customer_id,container_no)' ));
PREPARE phase4_inbound_stmt FROM @ ddl ; EXECUTE phase4_inbound_stmt ; DEALLOCATE PREPARE phase4_inbound_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND column_name = 'sku_code' ),
2026-08-22 10:16:45 +08:00
'ALTER TABLE ll_inventory_balance MODIFY COLUMN sku_code VARCHAR(128) NOT NULL DEFAULT ''UNSPECIFIED'' COMMENT ''SKU快照;多SKU汇总时为MIXED,不参与当前库存唯一维度''' ,
'ALTER TABLE ll_inventory_balance ADD COLUMN sku_code VARCHAR(128) NOT NULL DEFAULT ''UNSPECIFIED'' COMMENT ''SKU快照;多SKU汇总时为MIXED,不参与当前库存唯一维度'' AFTER inbound_code' ));
2026-08-20 18:02:38 +08:00
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
2026-08-28 10:03:32 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND column_name = 'customer_name' ),
'ALTER TABLE ll_inventory_balance MODIFY COLUMN customer_name VARCHAR(255) NOT NULL COMMENT ''客户名称不可变快照''' ,
'ALTER TABLE ll_inventory_balance ADD COLUMN customer_name VARCHAR(255) NOT NULL COMMENT ''客户名称不可变快照'' AFTER customer_id' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inventory_ledger' AND column_name = 'customer_name' ),
'ALTER TABLE ll_inventory_ledger MODIFY COLUMN customer_name VARCHAR(255) NOT NULL COMMENT ''客户名称不可变快照''' ,
'ALTER TABLE ll_inventory_ledger ADD COLUMN customer_name VARCHAR(255) NOT NULL COMMENT ''客户名称不可变快照'' AFTER customer_id' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
2026-08-20 18:02:38 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND column_name = 'product_name_zh' ),
'SELECT 1' , 'ALTER TABLE ll_inventory_balance ADD COLUMN product_name_zh VARCHAR(255) NULL COMMENT ''中文品名快照'' AFTER sku_code' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND column_name = 'product_name_en' ),
'SELECT 1' , 'ALTER TABLE ll_inventory_balance ADD COLUMN product_name_en VARCHAR(255) NULL COMMENT ''英文品名快照'' AFTER product_name_zh' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND index_name = 'uk_ll_inventory_dimension' ),
'ALTER TABLE ll_inventory_balance DROP INDEX uk_ll_inventory_dimension' , 'SELECT 1' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND index_name = 'uk_ll_inventory_dimension' ),
2026-08-22 10:16:45 +08:00
'SELECT 1' , 'ALTER TABLE ll_inventory_balance ADD UNIQUE KEY uk_ll_inventory_dimension (customer_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code)' ));
2026-08-20 18:02:38 +08:00
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
2026-08-22 10:16:45 +08:00
ALTER TABLE ll_inventory_balance COMMENT = '客户入仓单与海外目的仓维度实时库存余额' ;
2026-08-20 18:02:38 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inventory_balance' AND index_name = 'idx_ll_inventory_sku' ),
'SELECT 1' , 'ALTER TABLE ll_inventory_balance ADD KEY idx_ll_inventory_sku (customer_id,sku_code,updated_at)' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_stock_receipt' AND column_name = 'sku_code' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_stock_receipt ADD COLUMN sku_code VARCHAR(128) NOT NULL DEFAULT ''UNSPECIFIED'' COMMENT ''SKU编码快照'' AFTER inbound_code' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_stock_receipt' AND column_name = 'product_name_zh' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_stock_receipt ADD COLUMN product_name_zh VARCHAR(255) NULL COMMENT ''中文品名快照'' AFTER sku_code' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_inbound_stock_receipt' AND column_name = 'product_name_en' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_stock_receipt ADD COLUMN product_name_en VARCHAR(255) NULL COMMENT ''英文品名快照'' AFTER product_name_zh' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_stock_receipt' AND index_name = 'uk_ll_stock_receipt_task_allocation' ),
'ALTER TABLE ll_inbound_stock_receipt DROP INDEX uk_ll_stock_receipt_task_allocation' , 'SELECT 1' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_inbound_stock_receipt' AND index_name = 'uk_ll_stock_receipt_task_allocation_sku' ),
'SELECT 1' , 'ALTER TABLE ll_inbound_stock_receipt ADD UNIQUE KEY uk_ll_stock_receipt_task_allocation_sku (customer_id,task_id,allocation_id,sku_code)' ));
PREPARE phase4_inventory_stmt FROM @ ddl ; EXECUTE phase4_inventory_stmt ; DEALLOCATE PREPARE phase4_inventory_stmt ;
2026-08-25 10:31:04 +08:00
-- 海运节点达到可提柜后才允许海外 PDA 认领;装柜完成只建立等待门禁快照。
CREATE TABLE IF NOT EXISTS ll_container_shipping_gate (
container_booking_id VARCHAR ( 128 ) NOT NULL COMMENT '来源头程柜预订ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户标识' ,
ocean_booking_id VARCHAR ( 128 ) NOT NULL COMMENT '来源海运订舱ID' ,
container_no VARCHAR ( 64 ) NOT NULL COMMENT '实际集装箱号' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'AWAITING_PICKUP_READY' COMMENT '海外收货门禁状态:AWAITING_PICKUP_READY、RECEIVING_AVAILABLE' ,
standard_node VARCHAR ( 64 ) NULL COMMENT '最新有效标准船节点' ,
node_sequence INT NOT NULL DEFAULT 0 COMMENT '最新有效节点单调序号' ,
observed_at DATETIME ( 3 ) NULL COMMENT '供应商节点观测时间' ,
actual_at DATETIME ( 3 ) NULL COMMENT '节点实际发生时间' ,
location_code VARCHAR ( 128 ) NULL COMMENT '节点地点编码' ,
location_name VARCHAR ( 255 ) NULL COMMENT '节点地点名称' ,
provider_code VARCHAR ( 64 ) NULL COMMENT '船节点供应商编码' ,
provider_event_id VARCHAR ( 128 ) NULL COMMENT '供应商事件ID' ,
provider_node_code VARCHAR ( 128 ) NULL COMMENT '供应商原始节点编码' ,
source_reference VARCHAR ( 255 ) NULL COMMENT '供应商来源引用' ,
raw_payload_hash VARCHAR ( 64 ) NULL COMMENT '供应商原始负载SHA-256' ,
aggregate_version BIGINT NOT NULL DEFAULT 0 COMMENT '来源查询聚合版本' ,
handover_version BIGINT NOT NULL DEFAULT 1 COMMENT '跨区交接版本' ,
last_event_id VARCHAR ( 128 ) NULL COMMENT '最近采纳的跨区事件ID' ,
payload_hash VARCHAR ( 71 ) NULL COMMENT '最近采纳事件规范化负载摘要' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( container_booking_id ),
KEY idx_ll_shipping_gate_candidate ( customer_id , container_no , status ),
KEY idx_ll_shipping_gate_version ( container_booking_id , aggregate_version , node_sequence )
) ENGINE = InnoDB COMMENT = '海外PDA柜号船节点收货资格快照' ;
INSERT IGNORE INTO ll_container_shipping_gate (
container_booking_id , customer_id , ocean_booking_id , container_no , status ,
node_sequence , aggregate_version , handover_version , created_at , updated_at
)
SELECT source_container_booking_id , customer_id , '' , container_no , 'AWAITING_PICKUP_READY' ,
0 , COALESCE ( MAX ( source_loading_plan_version ), 0 ), COALESCE ( MAX ( source_handover_version ), 1 ), NOW ( 3 ), NOW ( 3 )
FROM ll_order
WHERE source_container_booking_id IS NOT NULL AND source_container_booking_id <> ''
AND container_no IS NOT NULL AND container_no <> ''
GROUP BY source_container_booking_id , customer_id , container_no ;
CREATE TABLE IF NOT EXISTS ll_pda_operation_history (
id BIGINT NOT NULL COMMENT 'PDA作业历史ID' ,
overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID' ,
customer_id VARCHAR ( 128 ) NULL COMMENT '作业涉及的客户标识' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT 'PDA操作账号标识' ,
operation_type VARCHAR ( 64 ) NOT NULL COMMENT '作业类型' ,
business_key VARCHAR ( 255 ) NOT NULL COMMENT '作业业务键' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '作业结果状态' ,
idempotency_key VARCHAR ( 255 ) NULL COMMENT '写操作幂等键' ,
request_hash VARCHAR ( 128 ) NULL COMMENT '写请求内容哈希' ,
summary VARCHAR ( 1000 ) NULL COMMENT '作业结果摘要' ,
occurred_at DATETIME ( 3 ) NOT NULL COMMENT '作业发生时间' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_pda_history_idempotency ( operator_key , idempotency_key ),
KEY idx_ll_pda_history_operator ( overseas_warehouse_id , operator_key , occurred_at ),
KEY idx_ll_pda_history_business ( overseas_warehouse_id , operation_type , business_key )
) ENGINE = InnoDB COMMENT = '海外PDA真实作业历史' ;
2026-08-25 11:20:36 +08:00
CREATE TABLE IF NOT EXISTS ll_pda_pallet_operation (
id BIGINT NOT NULL COMMENT 'PDA托盘作业ID' , overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT 'PDA操作账号标识' , idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '设备幂等键' ,
operation_type VARCHAR ( 64 ) NOT NULL COMMENT '托盘作业类型' , request_hash VARCHAR ( 128 ) NOT NULL COMMENT '请求内容摘要' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '处理状态:PROCESSING、COMPLETED、FAILED_COMPENSATED、COMPENSATION_REQUIRED' ,
result_json LONGTEXT NULL COMMENT '成功响应快照' , remote_transitions_json LONGTEXT NULL COMMENT '实物托盘状态变更回执' ,
last_error VARCHAR ( 2000 ) NULL COMMENT '最后失败原因' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_pda_pallet_idempotency ( operator_key , idempotency_key ),
KEY idx_ll_pda_pallet_warehouse ( overseas_warehouse_id , status , updated_at )
) ENGINE = InnoDB COMMENT = '海外PDA托盘作业幂等、补偿与结果记录' ;
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_task (
id BIGINT NOT NULL COMMENT '盘点任务ID' , task_no VARCHAR ( 64 ) NOT NULL COMMENT '盘点任务号' ,
overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID' , scope_type VARCHAR ( 16 ) NOT NULL COMMENT '盘点范围类型LOCATION或PALLET' ,
scope_resource_id BIGINT NOT NULL COMMENT '盘点库位或托盘资源ID' , scope_code VARCHAR ( 128 ) NOT NULL COMMENT '盘点库位码或托盘码快照' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '盘点任务状态' , position_count INT NOT NULL COMMENT '库存位置总数' ,
counted_count INT NOT NULL DEFAULT 0 COMMENT '已盘库存位置数' , difference_count INT NOT NULL DEFAULT 0 COMMENT '存在差异的库存位置数' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建操作账号标识' , submitted_by VARCHAR ( 128 ) NULL COMMENT '提交操作账号标识' ,
submit_reason VARCHAR ( 500 ) NULL COMMENT '盘点差异提交原因' , idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '创建幂等键' ,
request_hash VARCHAR ( 128 ) NOT NULL COMMENT '创建请求哈希' , version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' ,
submitted_at DATETIME ( 3 ) NULL COMMENT '提交完成时间' , PRIMARY KEY ( id ), UNIQUE KEY uk_ll_pda_stocktake_no ( task_no ),
UNIQUE KEY uk_ll_pda_stocktake_create ( overseas_warehouse_id , created_by , idempotency_key ),
KEY idx_ll_pda_stocktake_list ( overseas_warehouse_id , status , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA库存盘点任务' ;
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_item (
id BIGINT NOT NULL COMMENT '盘点明细ID' , task_id BIGINT NOT NULL COMMENT '盘点任务ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '库存所属客户标识' ,
balance_id BIGINT NOT NULL COMMENT '库存余额ID' , position_id BIGINT NOT NULL COMMENT '库存位置ID' , sku_code VARCHAR ( 128 ) NULL COMMENT 'SKU快照' ,
product_name VARCHAR ( 255 ) NULL COMMENT '品名快照' , inbound_code VARCHAR ( 128 ) NULL COMMENT '入仓码快照' , pallet_id BIGINT NOT NULL COMMENT '实物托盘ID' ,
pallet_code VARCHAR ( 128 ) NOT NULL COMMENT '实物托盘码快照' , location_id BIGINT NOT NULL COMMENT '库位ID快照' , location_code VARCHAR ( 128 ) NOT NULL COMMENT '库位码快照' ,
book_packages BIGINT NOT NULL COMMENT '任务创建时账面总箱数' , actual_packages BIGINT NULL COMMENT '现场实盘总箱数' ,
difference_packages BIGINT NULL COMMENT '实盘与账面箱数差异' , status VARCHAR ( 32 ) NOT NULL COMMENT '盘点明细状态' ,
position_version BIGINT NOT NULL COMMENT '任务创建时库存位置版本' , counted_by VARCHAR ( 128 ) NULL COMMENT '盘点操作账号标识' ,
version BIGINT NOT NULL DEFAULT 0 COMMENT '明细乐观锁版本' , counted_at DATETIME ( 3 ) NULL COMMENT '盘点时间' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_pda_stocktake_item ( task_id , position_id ), KEY idx_ll_pda_stocktake_item_task ( task_id , status , id )
) ENGINE = InnoDB COMMENT = '海外PDA库存盘点位置明细' ;
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_action (
id BIGINT NOT NULL COMMENT '盘点动作ID' , overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT 'PDA操作账号标识' , idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '动作幂等键' ,
action_type VARCHAR ( 32 ) NOT NULL COMMENT '盘点动作类型' , task_id BIGINT NULL COMMENT '盘点任务ID' , request_hash VARCHAR ( 128 ) NOT NULL COMMENT '动作请求哈希' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '动作处理状态' , result_json LONGTEXT NULL COMMENT '成功响应JSON' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_pda_stocktake_action ( overseas_warehouse_id , operator_key , idempotency_key ), KEY idx_ll_pda_stocktake_action_task ( task_id , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA盘点动作幂等记录' ;
CREATE TABLE IF NOT EXISTS ll_pda_inventory_move (
id BIGINT NOT NULL COMMENT '移库操作ID' , move_no VARCHAR ( 64 ) NOT NULL COMMENT '移库操作单号' ,
overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID' , pallet_id BIGINT NOT NULL COMMENT '整托移库的实物托盘ID' ,
pallet_code VARCHAR ( 128 ) NOT NULL COMMENT '实物托盘码快照' , source_location_id BIGINT NOT NULL COMMENT '来源库位ID' ,
source_location_code VARCHAR ( 128 ) NOT NULL COMMENT '来源库位码快照' , target_location_id BIGINT NOT NULL COMMENT '目标库位ID' ,
target_location_code VARCHAR ( 128 ) NOT NULL COMMENT '目标库位码快照' , customer_count INT NOT NULL COMMENT '托盘涉及客户数' ,
position_count INT NOT NULL COMMENT '迁移库存位置数' , package_count BIGINT NOT NULL COMMENT '迁移总箱数' ,
pallet_version_before INT NOT NULL COMMENT '迁移前托盘版本' , pallet_version_after INT NULL COMMENT '迁移后托盘版本' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT 'PDA操作账号标识' , reason VARCHAR ( 500 ) NOT NULL COMMENT '移库原因' ,
idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '移库幂等键' , request_hash VARCHAR ( 128 ) NOT NULL COMMENT '移库请求哈希' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '移库处理状态' , result_json LONGTEXT NULL COMMENT '成功响应JSON' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , completed_at DATETIME ( 3 ) NULL COMMENT '完成时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_pda_inventory_move_no ( move_no ),
UNIQUE KEY uk_ll_pda_inventory_move_key ( overseas_warehouse_id , operator_key , idempotency_key ),
KEY idx_ll_pda_inventory_move_pallet ( overseas_warehouse_id , pallet_id , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA同仓整托移库记录' ;
CREATE TABLE IF NOT EXISTS ll_relabel_pda_task (
id BIGINT NOT NULL COMMENT '换标PDA任务ID' , application_id BIGINT NOT NULL COMMENT '换标申请单ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , relabel_no VARCHAR ( 64 ) NOT NULL COMMENT '换标申请单号快照' ,
overseas_warehouse_id BIGINT NOT NULL COMMENT 'PDA令牌冻结的海外实际作业仓ID' ,
status VARCHAR ( 32 ) NOT NULL COMMENT '任务状态:PROCESSING、WAIT_REVIEW或COMPLETED' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT '认领操作账号标识' , operator_name VARCHAR ( 255 ) NOT NULL COMMENT '认领操作员名称快照' ,
reviewer_key VARCHAR ( 128 ) NULL COMMENT '复核账号标识' , reviewer_name VARCHAR ( 255 ) NULL COMMENT '复核员名称快照' ,
expected_packages INT NOT NULL COMMENT '申请单通知的应换标箱数' , relabelled_packages INT NOT NULL DEFAULT 0 COMMENT '已正常换标箱数' ,
skipped_packages INT NOT NULL DEFAULT 0 COMMENT '已说明原因跳过箱数' , exception_packages INT NOT NULL DEFAULT 0 COMMENT '已登记异常箱数' ,
completion_photo_file_ids JSON NULL COMMENT '换标完成现场照片文件ID列表' , completion_remark VARCHAR ( 1000 ) NULL COMMENT '完成提交备注' ,
review_decision VARCHAR ( 16 ) NULL COMMENT '最近复核结论:APPROVE或REWORK' , review_remark VARCHAR ( 1000 ) NULL COMMENT '最近复核备注' ,
claimed_at DATETIME ( 3 ) NOT NULL COMMENT '任务认领时间' , submitted_at DATETIME ( 3 ) NULL COMMENT '提交复核时间' ,
reviewed_at DATETIME ( 3 ) NULL COMMENT '最近复核时间' , version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_relabel_pda_task_application ( customer_id , application_id ),
UNIQUE KEY uk_ll_relabel_pda_task_no ( relabel_no ), KEY idx_ll_relabel_pda_task_warehouse ( overseas_warehouse_id , status , updated_at ),
KEY idx_ll_relabel_pda_task_operator ( operator_key , status , updated_at )
) ENGINE = InnoDB COMMENT = '海外PDA换标现场作业任务' ;
CREATE TABLE IF NOT EXISTS ll_relabel_pda_unit_fact (
id BIGINT NOT NULL COMMENT '逐件换标事实ID' , task_id BIGINT NOT NULL COMMENT '换标PDA任务ID' ,
application_id BIGINT NOT NULL COMMENT '换标申请单ID' , item_id BIGINT NOT NULL COMMENT '换标申请明细ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , old_label VARCHAR ( 255 ) NULL COMMENT '扫描的实物旧标签或箱标' ,
new_label VARCHAR ( 255 ) NULL COMMENT '扫描的换标后新标签' , result VARCHAR ( 32 ) NOT NULL COMMENT '逐件结果:RELABELLED、SKIPPED或EXCEPTION' ,
exception_code VARCHAR ( 32 ) NULL COMMENT '异常编码' , reason VARCHAR ( 1000 ) NULL COMMENT '跳过或异常原因' ,
operator_key VARCHAR ( 128 ) NOT NULL COMMENT '操作账号标识' , operator_name VARCHAR ( 255 ) NOT NULL COMMENT '操作员名称快照' ,
occurred_at DATETIME ( 3 ) NOT NULL COMMENT '逐件事实发生时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_relabel_pda_old_label ( old_label ), KEY idx_ll_relabel_pda_unit_task ( customer_id , task_id , occurred_at , id ),
KEY idx_ll_relabel_pda_unit_item ( customer_id , application_id , item_id )
) ENGINE = InnoDB COMMENT = '海外PDA逐件换标扫码与异常事实' ;
CREATE TABLE IF NOT EXISTS ll_relabel_pda_operation (
id BIGINT NOT NULL COMMENT '换标PDA幂等操作ID' , task_id BIGINT NOT NULL COMMENT '换标PDA任务ID' ,
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , operator_key VARCHAR ( 128 ) NOT NULL COMMENT '请求操作账号标识' ,
action VARCHAR ( 32 ) NOT NULL COMMENT '幂等操作动作' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '设备生成的幂等键' ,
request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容哈希' , result_json LONGTEXT NOT NULL COMMENT '成功响应快照JSON' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_relabel_pda_operation_key ( operator_key , idempotency_key ),
KEY idx_ll_relabel_pda_operation_task ( customer_id , task_id , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA换标写操作幂等记录' ;
CREATE TABLE IF NOT EXISTS ll_relabel_pda_history (
id BIGINT NOT NULL COMMENT '换标PDA任务历史ID' , task_id BIGINT NOT NULL COMMENT '换标PDA任务ID' ,
application_id BIGINT NOT NULL COMMENT '换标申请单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' ,
action VARCHAR ( 32 ) NOT NULL COMMENT '现场动作类型' , from_status VARCHAR ( 32 ) NULL COMMENT '动作前任务状态' ,
to_status VARCHAR ( 32 ) NOT NULL COMMENT '动作后任务状态' , operator_key VARCHAR ( 128 ) NOT NULL COMMENT '操作账号标识' ,
operator_name VARCHAR ( 255 ) NOT NULL COMMENT '操作员名称快照' , detail_json LONGTEXT NULL COMMENT '动作详情JSON' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
KEY idx_ll_relabel_pda_history_task ( customer_id , task_id , created_at , id ),
KEY idx_ll_relabel_pda_history_application ( customer_id , application_id , created_at )
) ENGINE = InnoDB COMMENT = '海外PDA换标任务不可变操作历史' ;
2026-08-25 10:31:04 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_cargo_discard_application' AND column_name = 'review_idempotency_key' ),
'SELECT 1' , 'ALTER TABLE ll_cargo_discard_application ADD COLUMN review_idempotency_key VARCHAR(255) NULL COMMENT ''审核幂等键'' AFTER request_hash' ));
PREPARE phase4_discard_review_stmt FROM @ ddl ; EXECUTE phase4_discard_review_stmt ; DEALLOCATE PREPARE phase4_discard_review_stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_cargo_discard_application' AND column_name = 'review_request_hash' ),
'SELECT 1' , 'ALTER TABLE ll_cargo_discard_application ADD COLUMN review_request_hash CHAR(64) NULL COMMENT ''审核请求内容哈希'' AFTER review_idempotency_key' ));
PREPARE phase4_discard_review_stmt FROM @ ddl ; EXECUTE phase4_discard_review_stmt ; DEALLOCATE PREPARE phase4_discard_review_stmt ;
2026-08-24 15:10:10 +08:00
-- Warehouse Overseas 与 Lastleg 使用同一海外区域发布入口但保持独立数据库。
-- 公共托盘详情实体读取 fba_warehouse_code;旧库缺列时创建可成功但详情会 S0500。
USE baiyue_lastlag_warehouse ;
2026-08-26 13:58:33 +08:00
-- 仓库主档唯一权威已收口至国内 baiyue_warehouse;海外库只保留 warehouse_id 引用。
-- 当前开发阶段不兼容旧海外主档数据,按依赖顺序移除重复表。
DROP TABLE IF EXISTS wh_service_capability ;
DROP TABLE IF EXISTS wh_warehouse_address ;
DROP TABLE IF EXISTS wh_warehouse ;
2026-08-25 11:20:36 +08:00
CREATE TABLE IF NOT EXISTS wh_pallet_operation (
id BIGINT NOT NULL COMMENT '托盘状态操作ID' , operation_key VARCHAR ( 128 ) NOT NULL COMMENT '跨服务幂等操作键' ,
request_hash VARCHAR ( 128 ) NOT NULL COMMENT '状态变更请求摘要' , warehouse_id BIGINT NOT NULL COMMENT '实际海外仓ID' ,
pallet_id BIGINT NOT NULL COMMENT '实物托盘ID' , pallet_code VARCHAR ( 128 ) NOT NULL COMMENT '实物托盘码快照' ,
before_status VARCHAR ( 20 ) NOT NULL COMMENT '变更前托盘状态' , after_status VARCHAR ( 20 ) NOT NULL COMMENT '变更后托盘状态' ,
before_location_id BIGINT NOT NULL COMMENT '变更前库位ID' , after_location_id BIGINT NOT NULL COMMENT '变更后库位ID' ,
before_version INT NOT NULL COMMENT '变更前托盘版本' , after_version INT NOT NULL COMMENT '变更后托盘版本' ,
operation_status VARCHAR ( 32 ) NOT NULL COMMENT '操作状态:APPLIED已应用、COMPENSATED已补偿' ,
reason VARCHAR ( 500 ) NULL COMMENT '操作原因' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_wh_pallet_operation_key ( operation_key ),
KEY idx_wh_pallet_operation_pallet ( warehouse_id , pallet_id , created_at )
) ENGINE = InnoDB COMMENT = '实物托盘状态幂等变更与补偿记录' ;
2026-08-24 15:10:10 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'wh_pallet' AND column_name = 'fba_warehouse_code' ),
'SELECT 1' ,
'ALTER TABLE wh_pallet ADD COLUMN fba_warehouse_code VARCHAR(128) NULL COMMENT ''所属FBA仓编码'' AFTER remark' ));
PREPARE phase4_warehouse_pallet_stmt FROM @ ddl ;
EXECUTE phase4_warehouse_pallet_stmt ;
DEALLOCATE PREPARE phase4_warehouse_pallet_stmt ;
SET @ warehouse_pallet_fba_ready = ( SELECT COUNT ( * ) FROM information_schema . columns
WHERE table_schema = 'baiyue_lastlag_warehouse' AND table_name = 'wh_pallet'
AND column_name = 'fba_warehouse_code' AND column_type = 'varchar(128)' );
DROP PROCEDURE IF EXISTS assert_phase4_warehouse_pallet_ready ;
DELIMITER $$
CREATE PROCEDURE assert_phase4_warehouse_pallet_ready ()
BEGIN
IF @ warehouse_pallet_fba_ready <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'wh_pallet.fba_warehouse_code migration is incomplete' ;
END IF ;
END $$
DELIMITER ;
CALL assert_phase4_warehouse_pallet_ready ();
DROP PROCEDURE assert_phase4_warehouse_pallet_ready ;
USE baiyue_lastleg ;
2026-08-25 11:20:36 +08:00
DROP PROCEDURE IF EXISTS assert_phase4_pda_operations_ready ;
DELIMITER $$
CREATE PROCEDURE assert_phase4_pda_operations_ready ()
BEGIN
IF ( SELECT COUNT ( * ) FROM information_schema . tables
WHERE table_schema = 'baiyue_lastleg' AND table_name IN (
'll_pda_pallet_operation' , 'll_pda_stocktake_task' , 'll_pda_stocktake_item' ,
'll_pda_stocktake_action' , 'll_pda_inventory_move' , 'll_relabel_pda_task' ,
'll_relabel_pda_unit_fact' , 'll_relabel_pda_operation' , 'll_relabel_pda_history' )) <> 9 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA盘点、移库、托盘或换标表未完整部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . tables
WHERE table_schema = 'baiyue_lastlag_warehouse' AND table_name = 'wh_pallet_operation' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA实物托盘操作表未部署' ;
END IF ;
END $$
DELIMITER ;
CALL assert_phase4_pda_operations_ready ();
DROP PROCEDURE assert_phase4_pda_operations_ready ;
2026-08-25 14:46:06 +08:00
2026-08-26 11:05:26 +08:00
CREATE TABLE IF NOT EXISTS ll_order_fee (
id BIGINT NOT NULL COMMENT '费用明细主键' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' ,
order_id BIGINT NOT NULL COMMENT '尾程订单ID' , fee_item VARCHAR ( 128 ) NOT NULL COMMENT '费用项目' ,
currency VARCHAR ( 3 ) NOT NULL COMMENT '币种代码' , amount DECIMAL ( 18 , 2 ) NOT NULL COMMENT '费用金额' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_REVIEW' COMMENT '费用状态:PENDING_REVIEW待审核、APPROVED审核通过、REJECTED已驳回' ,
supplier_description VARCHAR ( 500 ) NULL COMMENT '供应商或费用说明' , created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建操作人' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), KEY idx_ll_order_fee_customer_order ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '尾程订单费用明细' ;
CREATE TABLE IF NOT EXISTS ll_order_operation_log (
id BIGINT NOT NULL COMMENT '操作记录主键' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' ,
order_id BIGINT NOT NULL COMMENT '尾程订单ID' , operation_node VARCHAR ( 64 ) NOT NULL COMMENT '操作节点' ,
operator_name VARCHAR ( 128 ) NOT NULL COMMENT '操作人名称' , result VARCHAR ( 500 ) NOT NULL COMMENT '处理结果' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '操作时间' ,
PRIMARY KEY ( id ), KEY idx_ll_order_operation_customer_order ( customer_id , order_id , created_at )
) ENGINE = InnoDB COMMENT = '尾程订单操作记录' ;
2026-09-01 20:20:25 +08:00
-- 五期正式结构必须由海外固定入口自行补齐;既有四期库不得依赖当前基线或历史脚本。
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_task (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , dispatch_order_id BIGINT NOT NULL COMMENT '派车单ID' ,
task_no VARCHAR ( 64 ) NOT NULL COMMENT 'PDA任务号' , status VARCHAR ( 32 ) NOT NULL COMMENT '业务状态' , operator_id VARCHAR ( 128 ) NULL COMMENT '操作人ID' ,
warehouse_id VARCHAR ( 128 ) NOT NULL COMMENT 'Token绑定的海外仓库ID' , operator_name VARCHAR ( 128 ) NULL COMMENT '操作人姓名' ,
pushed_at DATETIME ( 3 ) NOT NULL COMMENT '任务下发时间' , completed_at DATETIME ( 3 ) NULL COMMENT '完成时间' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_dispatch_pda_task_dispatch ( customer_id , dispatch_order_id ),
UNIQUE KEY uk_ll_dispatch_pda_task_no ( task_no )
) ENGINE = InnoDB COMMENT = '派车PDA拣货任务' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , task_id BIGINT NOT NULL COMMENT 'PDA任务ID' ,
dispatch_item_id BIGINT NOT NULL COMMENT '派车明细ID' , inventory_position_id BIGINT NOT NULL COMMENT '库存仓位记录ID' ,
packages BIGINT NOT NULL COMMENT '本次操作箱数' , product_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '产品数量' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , picked_at DATETIME ( 3 ) NOT NULL COMMENT '拣货时间' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dispatch_pda_pick_key ( customer_id , idempotency_key ),
KEY idx_ll_dispatch_pda_pick_item ( customer_id , task_id , dispatch_item_id )
) ENGINE = InnoDB COMMENT = '派车PDA拣货记录' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_operation (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , task_id BIGINT NULL COMMENT 'PDA任务ID' ,
operation_type VARCHAR ( 32 ) NOT NULL COMMENT 'PDA操作类型' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' ,
request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容哈希' , result_json LONGTEXT NULL COMMENT '处理结果JSON' ,
status VARCHAR ( 32 ) NOT NULL COMMENT 'PDA操作处理状态' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_dispatch_pda_operation_key ( customer_id , idempotency_key )
) ENGINE = InnoDB COMMENT = '派车PDA操作幂等记录' ;
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick_order (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , pick_id BIGINT NOT NULL COMMENT 'PDA拣货记录ID' ,
receipt_id BIGINT NOT NULL COMMENT '入仓实收记录ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , packages BIGINT NOT NULL COMMENT '本次操作箱数' ,
product_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '产品数量' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
PRIMARY KEY ( id ), KEY idx_ll_dispatch_pick_order_pick ( customer_id , pick_id ),
KEY idx_ll_dispatch_pick_order_receipt ( customer_id , receipt_id )
) ENGINE = InnoDB COMMENT = 'PDA拣货订单归属记录' ;
CREATE TABLE IF NOT EXISTS ll_outbound_order (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , outbound_no VARCHAR ( 64 ) NOT NULL COMMENT '出库单号' ,
dispatch_order_id BIGINT NULL COMMENT '派车单ID,一件代发为空' , dispatch_no VARCHAR ( 64 ) NULL COMMENT '派车单号,一件代发为空' ,
overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外仓ID' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'WAIT_OUTBOUND' COMMENT '业务状态' ,
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数' , pallet_count INT NOT NULL DEFAULT 0 COMMENT '托盘数' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
outbound_type VARCHAR ( 32 ) NOT NULL DEFAULT 'DISPATCH_DELIVERY' COMMENT '出库类型:派送转出库、一件代发' ,
2026-09-07 11:48:49 +08:00
lx_codes VARCHAR ( 1000 ) NULL COMMENT '关联一件代发领星入库单代码汇总' ,
2026-09-01 20:20:25 +08:00
recipient_info VARCHAR ( 1000 ) NULL COMMENT '一件代发收件信息' , PRIMARY KEY ( id ), UNIQUE KEY uk_ll_outbound_no ( outbound_no ),
UNIQUE KEY uk_ll_outbound_idempotency ( customer_id , idempotency_key ), UNIQUE KEY uk_ll_outbound_dispatch ( customer_id , dispatch_order_id ),
KEY idx_ll_outbound_list ( customer_id , status , created_at )
) ENGINE = InnoDB COMMENT = '尾程出库单' ;
CREATE TABLE IF NOT EXISTS ll_outbound_pallet_item (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , outbound_order_id BIGINT NOT NULL COMMENT '出库单ID' ,
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID' , pallet_no VARCHAR ( 128 ) NULL COMMENT '托盘号' ,
destination_warehouse_id VARCHAR ( 128 ) NULL COMMENT '目的仓ID' , destination_warehouse_code VARCHAR ( 128 ) NULL COMMENT '目的仓编码快照' ,
destination_warehouse_name VARCHAR ( 255 ) NULL COMMENT '目的仓名称快照' , package_count INT NOT NULL DEFAULT 0 COMMENT '箱数' ,
picked_package_count INT NOT NULL DEFAULT 0 COMMENT '已拣箱数' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'WAIT_PICK' COMMENT '拣货状态' ,
sku_code VARCHAR ( 128 ) NULL COMMENT '一件代发SKU' , order_refs VARCHAR ( 2000 ) NULL COMMENT '关联订单信息' , inbound_code VARCHAR ( 128 ) NULL COMMENT '入仓单号快照' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_outbound_pallet ( customer_id , outbound_order_id , warehouse_pallet_id ),
KEY idx_ll_outbound_pallet_list ( customer_id , outbound_order_id ), KEY idx_ll_outbound_pallet_destination ( customer_id , destination_warehouse_code )
) ENGINE = InnoDB COMMENT = '出库托盘明细' ;
2026-09-01 11:09:14 +08:00
CREATE TABLE IF NOT EXISTS ll_outbound_pda_task (
2026-09-01 20:20:25 +08:00
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , outbound_order_id BIGINT NOT NULL COMMENT '出库单ID' ,
task_no VARCHAR ( 64 ) NOT NULL COMMENT 'PDA任务号' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态:待拣货、拣货中、已完成' ,
completion_idempotency_key VARCHAR ( 255 ) NULL COMMENT '完成命令幂等键' , pushed_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '推送时间' ,
completed_at DATETIME ( 3 ) NULL COMMENT '完成时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_outbound_pda_task_order ( customer_id , outbound_order_id ), UNIQUE KEY uk_ll_outbound_pda_task_no ( task_no ),
2026-09-01 14:24:59 +08:00
UNIQUE KEY uk_ll_outbound_pda_complete_key ( customer_id , completion_idempotency_key )
2026-09-01 11:09:14 +08:00
) ENGINE = InnoDB COMMENT = '一件代发出库PDA拣货任务' ;
CREATE TABLE IF NOT EXISTS ll_outbound_pda_pick (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , task_id BIGINT NOT NULL COMMENT 'PDA任务ID' ,
2026-09-01 20:20:25 +08:00
outbound_pallet_item_id BIGINT NOT NULL COMMENT '出库托盘明细ID' , inventory_position_id BIGINT NOT NULL COMMENT '库存仓位ID' ,
packages BIGINT NOT NULL COMMENT '拣货箱数' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '拣货幂等键' ,
picked_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '拣货时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_outbound_pda_pick_key ( customer_id , idempotency_key )
2026-09-01 11:09:14 +08:00
) ENGINE = InnoDB COMMENT = '一件代发出库PDA托盘拣货记录' ;
2026-09-01 20:20:25 +08:00
CREATE TABLE IF NOT EXISTS ll_delivery_order (
id BIGINT NOT NULL COMMENT '派送单主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , delivery_no VARCHAR ( 64 ) NOT NULL COMMENT '派送单号' ,
outbound_order_id BIGINT NOT NULL COMMENT '关联出库单ID' , outbound_no VARCHAR ( 64 ) NOT NULL COMMENT '关联出库单号' ,
dispatch_order_id BIGINT NOT NULL COMMENT '关联派车单ID' , dispatch_no VARCHAR ( 64 ) NOT NULL COMMENT '关联派车单号' ,
overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外仓ID' , overseas_warehouse_name VARCHAR ( 255 ) NULL COMMENT '海外仓名称快照' , customer_name VARCHAR ( 255 ) NULL COMMENT '客户名称快照' ,
status VARCHAR ( 32 ) NOT NULL DEFAULT 'WAIT_DELIVERY' COMMENT '派送状态:WAIT_DELIVERY待派送及后续正式状态' ,
waybill_no VARCHAR ( 128 ) NULL COMMENT '承运运单号' , delivery_method VARCHAR ( 32 ) NULL COMMENT '派送方式' , carrier_name VARCHAR ( 255 ) NULL COMMENT '派送承运商' ,
pickup_method VARCHAR ( 64 ) NULL COMMENT '提货方式' , loading_type VARCHAR ( 64 ) NULL COMMENT '装车类型' , vehicle_type VARCHAR ( 64 ) NULL COMMENT '车辆类型' ,
vehicle_size VARCHAR ( 64 ) NULL COMMENT '车辆大小' , vehicle_plate VARCHAR ( 64 ) NULL COMMENT '车牌号' , driver_name VARCHAR ( 128 ) NULL COMMENT '司机或车队名称' ,
driver_phone VARCHAR ( 64 ) NULL COMMENT '车队联系电话' , appointment_account VARCHAR ( 128 ) NULL COMMENT '预约账号' , seller_name VARCHAR ( 128 ) NULL COMMENT '卖家姓名' ,
package_count INT NOT NULL DEFAULT 0 COMMENT '派送箱数' , pallet_count INT NOT NULL DEFAULT 0 COMMENT '派送托盘数' ,
total_weight_kg DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '总重量(千克)' , total_volume_cbm DECIMAL ( 18 , 4 ) NOT NULL DEFAULT 0 COMMENT '总体积(立方米)' ,
planned_delivery_at DATETIME ( 3 ) NULL COMMENT '预计派送时间' , dispatched_at DATETIME ( 3 ) NULL COMMENT '实际派送时间' ,
expected_arrival_at DATETIME ( 3 ) NULL COMMENT '预计到达时间' , signed_at DATETIME ( 3 ) NULL COMMENT '签收时间' , remark VARCHAR ( 1000 ) NULL COMMENT '派送备注' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_delivery_no ( customer_id , delivery_no ), UNIQUE KEY uk_ll_delivery_idempotency ( customer_id , idempotency_key ),
UNIQUE KEY uk_ll_delivery_outbound ( customer_id , outbound_order_id ), KEY idx_ll_delivery_list ( customer_id , status , created_at )
) ENGINE = InnoDB COMMENT = '尾程派送单' ;
CREATE TABLE IF NOT EXISTS ll_delivery_fee (
id BIGINT NOT NULL COMMENT '派送费用主键' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , delivery_order_id BIGINT NOT NULL COMMENT '派送单ID' ,
fee_direction VARCHAR ( 16 ) NOT NULL DEFAULT 'PAYABLE' COMMENT '应收应付方向' , fee_type VARCHAR ( 64 ) NOT NULL COMMENT '费用类型' , currency VARCHAR ( 8 ) NOT NULL COMMENT '币种' ,
amount DECIMAL ( 18 , 2 ) NOT NULL COMMENT '费用金额' , remark VARCHAR ( 500 ) NULL COMMENT '费用备注' , created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ), KEY idx_ll_delivery_fee_order ( customer_id , delivery_order_id , id )
) ENGINE = InnoDB COMMENT = '派送单费用明细' ;
CREATE TABLE IF NOT EXISTS ll_delivery_operation (
id BIGINT NOT NULL COMMENT '派送操作主键' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , delivery_order_id BIGINT NOT NULL COMMENT '派送单ID' ,
operation_node VARCHAR ( 64 ) NOT NULL COMMENT '操作节点' , operator_id VARCHAR ( 128 ) NULL COMMENT '操作人ID' , operator_name VARCHAR ( 128 ) NULL COMMENT '操作人名称' ,
result VARCHAR ( 500 ) NOT NULL COMMENT '处理结果' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '操作时间' ,
PRIMARY KEY ( id ), KEY idx_ll_delivery_operation_order ( customer_id , delivery_order_id , created_at , id )
) ENGINE = InnoDB COMMENT = '派送单操作记录' ;
CREATE TABLE IF NOT EXISTS ll_dropship_order_profile (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , order_id BIGINT NOT NULL COMMENT '订单ID' ,
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID' , pallet_no VARCHAR ( 128 ) NULL COMMENT '托盘号' , source_pallet_no VARCHAR ( 128 ) NOT NULL COMMENT '来源托盘号快照' ,
inventory_position_id BIGINT NULL COMMENT '库存仓位记录ID' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_INBOUND' COMMENT '业务状态' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dropship_profile_order_pallet ( customer_id , order_id , source_pallet_no ),
UNIQUE KEY uk_ll_dropship_profile_key ( customer_id , idempotency_key ), KEY idx_ll_dropship_profile_order ( customer_id , order_id )
) ENGINE = InnoDB COMMENT = '一件代发托盘档案' ;
CREATE TABLE IF NOT EXISTS ll_dropship_carton (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , profile_id BIGINT NOT NULL COMMENT '托盘档案ID' ,
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID' , pallet_no VARCHAR ( 128 ) NULL COMMENT '托盘号' , sku_code VARCHAR ( 128 ) NOT NULL COMMENT 'SKU编码' ,
carton_mark VARCHAR ( 128 ) NOT NULL COMMENT '箱唛' , carton_sequence INT NOT NULL COMMENT '箱唛序号' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING_INBOUND' COMMENT '业务状态' ,
outbound_order_no VARCHAR ( 128 ) NULL COMMENT '出库单号' , version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dropship_carton ( customer_id , order_id , carton_mark ), KEY idx_ll_dropship_carton_status ( customer_id , status ),
KEY idx_ll_dropship_carton_sku ( customer_id , sku_code , status )
) ENGINE = InnoDB COMMENT = '一件代发箱唛明细' ;
CREATE TABLE IF NOT EXISTS ll_dropship_sku_inventory (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , profile_id BIGINT NOT NULL COMMENT '托盘档案ID' ,
sku_code VARCHAR ( 128 ) NOT NULL COMMENT 'SKU编码' , product_name VARCHAR ( 255 ) NULL COMMENT '产品名称' , package_count BIGINT NOT NULL COMMENT '箱数' ,
product_quantity BIGINT NOT NULL COMMENT '产品数量' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dropship_sku_inventory ( profile_id , sku_code ), KEY idx_ll_dropship_sku_order ( customer_id , order_id , sku_code )
) ENGINE = InnoDB COMMENT = '一件代发SKU库存汇总' ;
CREATE TABLE IF NOT EXISTS ll_dropship_carton_ledger (
id BIGINT NOT NULL COMMENT '主键ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户租户ID' , order_id BIGINT NOT NULL COMMENT '订单ID' , carton_id BIGINT NOT NULL COMMENT '箱唛记录ID' ,
carton_mark VARCHAR ( 128 ) NOT NULL COMMENT '箱唛' , sku_code VARCHAR ( 128 ) NOT NULL COMMENT 'SKU编码' , operation_type VARCHAR ( 32 ) NOT NULL COMMENT '操作类型' ,
before_packages BIGINT NOT NULL COMMENT '变动前箱数' , delta_packages BIGINT NOT NULL COMMENT '箱数变动量' , after_packages BIGINT NOT NULL COMMENT '变动后箱数' ,
business_order_no VARCHAR ( 128 ) NULL COMMENT '业务单号' , idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '业务幂等键' , remark VARCHAR ( 1000 ) NULL COMMENT '备注' ,
occurred_at DATETIME ( 3 ) NOT NULL COMMENT '业务发生时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_dropship_ledger_key ( customer_id , idempotency_key ), KEY idx_ll_dropship_ledger_sku ( customer_id , sku_code , carton_mark )
) ENGINE = InnoDB COMMENT = '一件代发箱唛库存流水' ;
2026-09-02 16:55:38 +08:00
CREATE TABLE IF NOT EXISTS ll_finance_fee_source (
id BIGINT NOT NULL COMMENT '费用版本记录ID' , source_fee_id BIGINT NOT NULL COMMENT '跨版本稳定费用来源ID' ,
source_version INT NOT NULL COMMENT '费用来源版本,从1递增' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID和隔离键' ,
customer_name VARCHAR ( 200 ) NULL COMMENT '客户名称快照' , source_type VARCHAR ( 64 ) NOT NULL COMMENT '海外费用来源类型' ,
source_no VARCHAR ( 128 ) NOT NULL COMMENT '来源业务编号或入仓码快照' , business_type VARCHAR ( 32 ) NOT NULL COMMENT '来源业务类型' ,
business_id BIGINT NULL COMMENT '来源业务记录ID' , business_no VARCHAR ( 128 ) NOT NULL COMMENT '来源业务编号' ,
order_id BIGINT NULL COMMENT '关联订单ID' , inbound_id BIGINT NULL COMMENT '关联海外入仓计划或入仓记录ID' ,
inbound_code VARCHAR ( 64 ) NULL COMMENT '关联入仓码;并非所有费用必填' , container_id BIGINT NULL COMMENT '关联柜次ID' ,
container_booking_id BIGINT NULL COMMENT '来源订舱柜ID' , container_no VARCHAR ( 64 ) NULL COMMENT '真实集装箱号快照' ,
warehouse_id BIGINT NULL COMMENT '关联海外仓ID' , fee_item_code VARCHAR ( 64 ) NOT NULL COMMENT '费用项目编码快照' ,
fee_item_name VARCHAR ( 200 ) NOT NULL COMMENT '费用项目名称快照' , direction VARCHAR ( 16 ) NOT NULL COMMENT 'RECEIVABLE应收或PAYABLE应付' ,
supplier_id BIGINT NULL COMMENT '应付供应商ID' , supplier_name VARCHAR ( 200 ) NULL COMMENT '应付供应商名称快照' ,
supplier_category VARCHAR ( 32 ) NULL COMMENT '应付供应商类别约束' , settlement_mode VARCHAR ( 16 ) NULL COMMENT 'ON_ACCOUNT账期应付或DIRECT_PAID业务已付' ,
paid_at DATETIME ( 3 ) NULL COMMENT '直接已付时间' , payment_method VARCHAR ( 32 ) NULL COMMENT '直接已付方式' ,
payment_reference_no VARCHAR ( 128 ) NULL COMMENT '直接已付流水号' , payment_voucher_file_ids JSON NULL COMMENT '直接已付凭证文件ID快照' ,
business_date DATE NOT NULL COMMENT '费用业务日期' , currency CHAR ( 3 ) NOT NULL DEFAULT 'CNY' COMMENT '财务结算币种,当前固定CNY' ,
amount DECIMAL ( 20 , 6 ) NOT NULL COMMENT '费用金额' , review_status VARCHAR ( 16 ) NOT NULL COMMENT 'DRAFT、PENDING、APPROVED或REJECTED' ,
publication_status VARCHAR ( 16 ) NOT NULL COMMENT 'UNPUBLISHED或PUBLISHED' , source_status VARCHAR ( 16 ) NOT NULL COMMENT 'ACTIVE、SUPERSEDED或VOIDED' ,
review_reason VARCHAR ( 500 ) NULL COMMENT '审核或作废原因' , reviewer_id VARCHAR ( 128 ) NULL COMMENT '审核人ID' , reviewed_at DATETIME ( 3 ) NULL COMMENT '审核时间' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建人ID' , updated_by VARCHAR ( 128 ) NOT NULL COMMENT '最后更新人ID' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '最后更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_finance_fee_version ( source_fee_id , source_version ),
KEY idx_ll_finance_fee_customer ( customer_id , source_status , created_at ), KEY idx_ll_finance_fee_business ( business_type , business_no , created_at ),
2026-09-08 21:45:57 +08:00
KEY idx_ll_finance_fee_container_customer ( container_booking_id , customer_id , source_status , created_at ),
2026-09-02 16:55:38 +08:00
CONSTRAINT chk_ll_finance_fee_amount CHECK ( amount > 0 ), CONSTRAINT chk_ll_finance_fee_currency CHECK ( currency = 'CNY' ),
CONSTRAINT chk_ll_finance_fee_direction CHECK ( direction IN ( 'RECEIVABLE' , 'PAYABLE' )),
CONSTRAINT chk_ll_finance_fee_review CHECK ( review_status IN ( 'DRAFT' , 'PENDING' , 'APPROVED' , 'REJECTED' )),
CONSTRAINT chk_ll_finance_fee_publication CHECK ( publication_status IN ( 'UNPUBLISHED' , 'PUBLISHED' )),
CONSTRAINT chk_ll_finance_fee_status CHECK ( source_status IN ( 'ACTIVE' , 'SUPERSEDED' , 'VOIDED' ))
) ENGINE = InnoDB COMMENT = '海外业务不可变费用来源版本;发布后经跨区事件进入Finance' ;
2026-09-08 21:45:57 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_finance_fee_source' AND index_name = 'idx_ll_finance_fee_container_customer' ), 'SELECT 1' , 'ALTER TABLE ll_finance_fee_source ADD KEY idx_ll_finance_fee_container_customer(container_booking_id,customer_id,source_status,created_at)' ));
PREPARE ll_finance_fee_ddl FROM @ ddl ; EXECUTE ll_finance_fee_ddl ; DEALLOCATE PREPARE ll_finance_fee_ddl ;
2026-09-02 16:55:38 +08:00
CREATE TABLE IF NOT EXISTS ll_finance_fee_command (
id BIGINT NOT NULL COMMENT '幂等命令ID' , operator_id VARCHAR ( 128 ) NOT NULL COMMENT '操作人ID' ,
action VARCHAR ( 16 ) NOT NULL COMMENT 'CREATE、SUBMIT、REVIEW、ADJUST或VOID' , idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '操作幂等键' ,
request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容SHA-256' , source_fee_id BIGINT NOT NULL COMMENT '稳定费用来源ID' ,
source_version INT NOT NULL COMMENT '命令结果版本' , created_at DATETIME ( 3 ) NOT NULL COMMENT '命令创建时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_finance_fee_command ( operator_id , action , idempotency_key ),
KEY idx_ll_finance_fee_command_source ( source_fee_id , source_version )
) ENGINE = InnoDB COMMENT = '海外费用来源写操作幂等审计' ;
2026-09-01 20:20:25 +08:00
CREATE TABLE IF NOT EXISTS ll_exception_order (
id BIGINT NOT NULL COMMENT '异常订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , exception_no VARCHAR ( 64 ) NOT NULL COMMENT '异常订单号' ,
exception_type VARCHAR ( 32 ) NOT NULL COMMENT '异常类型' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '异常处理状态' , reason VARCHAR ( 1000 ) NOT NULL COMMENT '异常原因' ,
last_mile_order_id BIGINT NULL COMMENT '关联尾程订单ID' , last_mile_order_no VARCHAR ( 64 ) NULL COMMENT '关联尾程订单号' , inbound_order_id BIGINT NULL COMMENT '关联入仓单ID' , inbound_code VARCHAR ( 128 ) NULL COMMENT '关联入仓码' ,
delivery_order_id BIGINT NULL COMMENT '关联派送单ID' , delivery_no VARCHAR ( 64 ) NULL COMMENT '关联派送单号' , outbound_no VARCHAR ( 64 ) NULL COMMENT '关联出库单号' ,
customer_name VARCHAR ( 255 ) NULL COMMENT '客户名称快照' , overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外仓ID快照' , overseas_warehouse_name VARCHAR ( 255 ) NULL COMMENT '海外仓名称快照' ,
sku_code VARCHAR ( 128 ) NULL COMMENT '异常货物SKU' , package_count INT NULL COMMENT '异常箱数' , return_direction VARCHAR ( 32 ) NULL COMMENT '退回方向' , return_logistics_no VARCHAR ( 128 ) NULL COMMENT '退回物流单号' ,
handling_action VARCHAR ( 500 ) NULL COMMENT '异常处理措施' , handler_id VARCHAR ( 128 ) NULL COMMENT '处理人ID' , handler_name VARCHAR ( 128 ) NULL COMMENT '处理人名称' ,
source_type VARCHAR ( 32 ) NOT NULL DEFAULT 'MANUAL' COMMENT '异常来源类型' , created_by VARCHAR ( 128 ) NULL COMMENT '创建人ID' ,
exception_at DATETIME ( 3 ) NOT NULL COMMENT '异常发生时间' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_exception_no ( customer_id , exception_no ), UNIQUE KEY uk_ll_exception_delivery_return ( customer_id , delivery_order_id , exception_type ),
KEY idx_ll_exception_list ( customer_id , status , exception_at ), KEY idx_ll_exception_tail ( customer_id , last_mile_order_no ), KEY idx_ll_exception_inbound ( customer_id , inbound_code )
) ENGINE = InnoDB COMMENT = '海外仓异常订单' ;
CREATE TABLE IF NOT EXISTS ll_customer_visit (
id BIGINT NOT NULL COMMENT '客户回访记录ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户数据隔离键' , delivery_order_id BIGINT NOT NULL COMMENT '关联派送单ID' ,
delivery_no VARCHAR ( 64 ) NOT NULL COMMENT '关联派送单号' , customer_name VARCHAR ( 255 ) NULL COMMENT '客户名称快照' , contact_name VARCHAR ( 128 ) NULL COMMENT '客户联系人姓名快照' ,
contact_phone VARCHAR ( 64 ) NULL COMMENT '客户联系人电话快照' , destination VARCHAR ( 500 ) NULL COMMENT '派送目的仓编码汇总快照' ,
delivery_completed_at DATETIME ( 3 ) NOT NULL COMMENT '派送完成时间' , status VARCHAR ( 32 ) NOT NULL DEFAULT 'PENDING' COMMENT '回访状态:PENDING待回访或COMPLETED已回访' ,
selected_last_mile_order_id BIGINT NULL COMMENT '本次回访选择的尾程订单ID' , selected_last_mile_order_no VARCHAR ( 64 ) NULL COMMENT '本次回访选择的尾程订单号' ,
selected_inbound_order_id BIGINT NULL COMMENT '本次回访选择的入仓单ID' , selected_inbound_code VARCHAR ( 128 ) NULL COMMENT '本次回访选择的入仓码' ,
visit_result VARCHAR ( 32 ) NULL COMMENT '最近一次回访结果' , customer_feedback VARCHAR ( 2000 ) NULL COMMENT '最近一次客户反馈' , remark VARCHAR ( 1000 ) NULL COMMENT '最近一次回访备注' ,
attachment_json JSON NULL COMMENT '当前回访资料文件元数据列表' , visited_by VARCHAR ( 128 ) NULL COMMENT '最近一次回访操作人ID' , visited_at DATETIME ( 3 ) NULL COMMENT '最近一次回访时间' ,
visit_count INT NOT NULL DEFAULT 0 COMMENT '累计保存回访次数' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_customer_visit_delivery ( customer_id , delivery_order_id ), KEY idx_ll_customer_visit_list ( customer_id , status , delivery_completed_at ),
KEY idx_ll_customer_visit_delivery_no ( customer_id , delivery_no )
) ENGINE = InnoDB COMMENT = '派送单维度客户回访记录' ;
-- 收敛曾由历史局部脚本建立的五期中间结构;只补结构,不回填或修复旧数据。
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_order' AND column_name = 'customer_id' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_order RENAME COLUMN tenant_id TO customer_id' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pallet_item' AND column_name = 'customer_id' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_pallet_item RENAME COLUMN tenant_id TO customer_id' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_delivery_order' AND column_name = 'customer_id' ), 'SELECT 1' , 'ALTER TABLE ll_delivery_order RENAME COLUMN tenant_id TO customer_id' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_order' AND column_name = 'outbound_type' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_order ADD COLUMN outbound_type VARCHAR(32) NOT NULL DEFAULT ''DISPATCH_DELIVERY'' COMMENT ''出库类型:派送转出库、一件代发'' AFTER status' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
2026-09-07 11:48:49 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_order' AND column_name = 'lx_codes' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_order ADD COLUMN lx_codes VARCHAR(1000) NULL COMMENT ''关联一件代发领星入库单代码汇总'' AFTER outbound_type' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_order' AND column_name = 'recipient_info' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_order ADD COLUMN recipient_info VARCHAR(1000) NULL COMMENT ''一件代发收件信息'' AFTER lx_codes' ));
2026-09-01 20:20:25 +08:00
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pallet_item' AND column_name = 'sku_code' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_pallet_item ADD COLUMN sku_code VARCHAR(128) NULL COMMENT ''一件代发SKU''' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pallet_item' AND column_name = 'picked_package_count' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_pallet_item ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 COMMENT ''已拣箱数'' AFTER package_count' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pallet_item' AND column_name = 'status' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_pallet_item ADD COLUMN status VARCHAR(32) NOT NULL DEFAULT ''WAIT_PICK'' COMMENT ''拣货状态'' AFTER picked_package_count' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pallet_item' AND column_name = 'warehouse_pallet_id' AND is_nullable = 'NO' ), 'ALTER TABLE ll_outbound_pallet_item MODIFY COLUMN warehouse_pallet_id BIGINT NULL COMMENT ''仓库实物托盘ID'', MODIFY COLUMN pallet_no VARCHAR(128) NULL COMMENT ''托盘号''' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_outbound_order' AND column_name = 'dispatch_order_id' AND is_nullable = 'YES' ), 'SELECT 1' , 'ALTER TABLE ll_outbound_order MODIFY COLUMN dispatch_order_id BIGINT NULL COMMENT ''派车单ID,一件代发为空'', MODIFY COLUMN dispatch_no VARCHAR(64) NULL COMMENT ''派车单号,一件代发为空''' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_delivery_order' AND column_name = 'overseas_warehouse_name' ), 'SELECT 1' , 'ALTER TABLE ll_delivery_order ADD COLUMN overseas_warehouse_name VARCHAR(255) NULL COMMENT ''海外仓名称快照'' AFTER overseas_warehouse_id' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_delivery_order' AND column_name = 'customer_name' ), 'SELECT 1' , 'ALTER TABLE ll_delivery_order ADD COLUMN customer_name VARCHAR(255) NULL COMMENT ''客户名称快照'' AFTER overseas_warehouse_name' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_delivery_order' AND column_name = 'waybill_no' ), 'SELECT 1' , 'ALTER TABLE ll_delivery_order ADD COLUMN waybill_no VARCHAR(128) NULL COMMENT ''承运运单号'', ADD COLUMN delivery_method VARCHAR(32) NULL COMMENT ''派送方式'', ADD COLUMN carrier_name VARCHAR(255) NULL COMMENT ''派送承运商'', ADD COLUMN pickup_method VARCHAR(64) NULL COMMENT ''提货方式'', ADD COLUMN loading_type VARCHAR(64) NULL COMMENT ''装车类型'', ADD COLUMN vehicle_type VARCHAR(64) NULL COMMENT ''车辆类型'', ADD COLUMN vehicle_size VARCHAR(64) NULL COMMENT ''车辆大小'', ADD COLUMN vehicle_plate VARCHAR(64) NULL COMMENT ''车牌号'', ADD COLUMN driver_name VARCHAR(128) NULL COMMENT ''司机或车队名称'', ADD COLUMN driver_phone VARCHAR(64) NULL COMMENT ''车队联系电话'', ADD COLUMN appointment_account VARCHAR(128) NULL COMMENT ''预约账号'', ADD COLUMN seller_name VARCHAR(128) NULL COMMENT ''卖家姓名'' AFTER status' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_delivery_order' AND column_name = 'total_weight_kg' ), 'SELECT 1' , 'ALTER TABLE ll_delivery_order ADD COLUMN total_weight_kg DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''总重量(千克)'', ADD COLUMN total_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''总体积(立方米)'', ADD COLUMN planned_delivery_at DATETIME(3) NULL COMMENT ''预计派送时间'', ADD COLUMN dispatched_at DATETIME(3) NULL COMMENT ''实际派送时间'', ADD COLUMN expected_arrival_at DATETIME(3) NULL COMMENT ''预计到达时间'', ADD COLUMN signed_at DATETIME(3) NULL COMMENT ''签收时间'', ADD COLUMN remark VARCHAR(1000) NULL COMMENT ''派送备注'' AFTER pallet_count' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND column_name = 'source_pallet_no' ), 'SELECT 1' , 'ALTER TABLE ll_dropship_order_profile ADD COLUMN source_pallet_no VARCHAR(128) NULL COMMENT ''来源托盘号快照'' AFTER pallet_no' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND index_name = 'uk_ll_dropship_profile_order' ), 'ALTER TABLE ll_dropship_order_profile DROP INDEX uk_ll_dropship_profile_order' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND index_name = 'uk_ll_dropship_profile_order_pallet' ), 'SELECT 1' , 'ALTER TABLE ll_dropship_order_profile ADD UNIQUE KEY uk_ll_dropship_profile_order_pallet(customer_id,order_id,source_pallet_no)' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND index_name = 'idx_ll_dropship_profile_order' ), 'SELECT 1' , 'ALTER TABLE ll_dropship_order_profile ADD KEY idx_ll_dropship_profile_order(customer_id,order_id)' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_dropship_sku_inventory' AND index_name = 'uk_ll_dropship_sku_profile' ), 'ALTER TABLE ll_dropship_sku_inventory DROP INDEX uk_ll_dropship_sku_profile' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ index_ready = ( SELECT COUNT ( * ) = 2 AND MIN ( non_unique ) = 0
AND SUM ( seq_in_index = 1 AND column_name = 'profile_id' ) = 1
AND SUM ( seq_in_index = 2 AND column_name = 'sku_code' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dropship_sku_inventory' AND index_name = 'uk_ll_dropship_sku_inventory' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dropship_sku_inventory' AND index_name = 'uk_ll_dropship_sku_inventory' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_dropship_sku_inventory DROP INDEX uk_ll_dropship_sku_inventory, ADD UNIQUE KEY uk_ll_dropship_sku_inventory(profile_id,sku_code)' ,
'ALTER TABLE ll_dropship_sku_inventory ADD UNIQUE KEY uk_ll_dropship_sku_inventory(profile_id,sku_code)' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_dropship_sku_inventory' AND index_name = 'idx_ll_dropship_sku_order' ), 'SELECT 1' , 'ALTER TABLE ll_dropship_sku_inventory ADD KEY idx_ll_dropship_sku_order(customer_id,order_id,sku_code)' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND column_name = 'warehouse_pallet_id' AND is_nullable = 'NO' ), 'ALTER TABLE ll_dropship_order_profile MODIFY COLUMN warehouse_pallet_id BIGINT NULL COMMENT ''仓库实物托盘ID'', MODIFY COLUMN pallet_no VARCHAR(128) NULL COMMENT ''托盘号''' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dropship_carton' AND column_name = 'warehouse_pallet_id' AND is_nullable = 'NO' ), 'ALTER TABLE ll_dropship_carton MODIFY COLUMN warehouse_pallet_id BIGINT NULL COMMENT ''仓库实物托盘ID'', MODIFY COLUMN pallet_no VARCHAR(128) NULL COMMENT ''托盘号''' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND column_name = 'status' AND column_default <> 'PENDING_INBOUND' ), 'ALTER TABLE ll_dropship_order_profile MODIFY COLUMN status VARCHAR(32) NOT NULL DEFAULT ''PENDING_INBOUND'' COMMENT ''业务状态''' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_dropship_carton' AND column_name = 'status' AND column_default <> 'PENDING_INBOUND' ), 'ALTER TABLE ll_dropship_carton MODIFY COLUMN status VARCHAR(32) NOT NULL DEFAULT ''PENDING_INBOUND'' COMMENT ''业务状态''' , 'SELECT 1' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
2026-09-01 14:24:59 +08:00
-- 五期排车、出库与海外PDA正式业务号/幂等约束。只补结构并 fail-fast 校验开发数据,不回填或修复旧行。
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pda_task' AND column_name = 'warehouse_id'
), 'SELECT 1' ,
'ALTER TABLE ll_dispatch_pda_task ADD COLUMN warehouse_id VARCHAR(128) NULL COMMENT ''Token绑定的海外仓库ID'' AFTER operator_id' ));
PREPARE phase5_pda_scope_ddl FROM @ ddl ; EXECUTE phase5_pda_scope_ddl ; DEALLOCATE PREPARE phase5_pda_scope_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_outbound_pda_task' AND column_name = 'completion_idempotency_key'
), 'SELECT 1' ,
'ALTER TABLE ll_outbound_pda_task ADD COLUMN completion_idempotency_key VARCHAR(255) NULL COMMENT ''完成命令幂等键'' AFTER status' ));
PREPARE phase5_pda_scope_ddl FROM @ ddl ; EXECUTE phase5_pda_scope_ddl ; DEALLOCATE PREPARE phase5_pda_scope_ddl ;
DROP PROCEDURE IF EXISTS assert_phase5_lastleg_identifiers_migratable ;
DELIMITER $$
CREATE PROCEDURE assert_phase5_lastleg_identifiers_migratable ()
BEGIN
IF ( SELECT COUNT ( * ) FROM information_schema . tables
WHERE table_schema = 'baiyue_lastleg' AND table_name IN (
2026-09-01 20:20:25 +08:00
'll_dispatch_order' , 'll_dispatch_item' , 'll_dispatch_pallet_lock' , 'll_dispatch_draft' , 'll_dispatch_draft_container' ,
'll_dispatch_pda_task' , 'll_dispatch_pda_pick' , 'll_dispatch_pda_operation' , 'll_dispatch_pda_pick_order' ,
'll_outbound_order' , 'll_outbound_pallet_item' , 'll_outbound_pda_task' , 'll_outbound_pda_pick' ,
'll_delivery_order' , 'll_delivery_fee' , 'll_delivery_operation' ,
'll_dropship_order_profile' , 'll_dropship_carton' , 'll_dropship_sku_inventory' , 'll_dropship_carton_ledger' ,
'll_exception_order' , 'll_customer_visit' )) <> 22 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '五期排车、出库、派送、一件代发、异常或回访表未完整部署' ;
2026-09-01 14:24:59 +08:00
END IF ;
IF EXISTS ( SELECT dispatch_no FROM ll_dispatch_order GROUP BY dispatch_no HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dispatch_order存在跨客户重复dispatch_no,无法收敛全局唯一' ;
END IF ;
IF EXISTS ( SELECT outbound_no FROM ll_outbound_order GROUP BY outbound_no HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_outbound_order存在跨客户重复outbound_no,无法收敛全局唯一' ;
END IF ;
IF EXISTS ( SELECT task_no FROM ll_dispatch_pda_task GROUP BY task_no HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dispatch_pda_task存在跨客户重复task_no,无法收敛全局唯一' ;
END IF ;
IF EXISTS ( SELECT task_no FROM ll_outbound_pda_task GROUP BY task_no HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_outbound_pda_task存在跨客户重复task_no,无法收敛全局唯一' ;
END IF ;
IF EXISTS ( SELECT customer_id , completion_idempotency_key FROM ll_outbound_pda_task
WHERE completion_idempotency_key IS NOT NULL
GROUP BY customer_id , completion_idempotency_key HAVING COUNT ( * ) > 1 ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_outbound_pda_task存在重复完成幂等键,无法创建客户范围唯一约束' ;
END IF ;
IF EXISTS ( SELECT 1 FROM ll_dispatch_pda_task
WHERE warehouse_id IS NULL OR TRIM ( warehouse_id ) = '' OR TRIM ( warehouse_id ) = '0' ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dispatch_pda_task存在空或0仓库范围;请重新造数后重跑,脚本不回填旧行' ;
END IF ;
2026-09-01 20:20:25 +08:00
IF EXISTS ( SELECT 1 FROM ll_dropship_order_profile
WHERE source_pallet_no IS NULL OR TRIM ( source_pallet_no ) = '' ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dropship_order_profile存在空来源托盘号;请重新造数后重跑,脚本不回填旧行' ;
END IF ;
2026-09-01 14:24:59 +08:00
END $$
DELIMITER ;
CALL assert_phase5_lastleg_identifiers_migratable ();
DROP PROCEDURE assert_phase5_lastleg_identifiers_migratable ;
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_dispatch_pda_task' AND column_name = 'warehouse_id'
AND is_nullable = 'NO' AND column_type = 'varchar(128)' AND column_comment = 'Token绑定的海外仓库ID'
), 'SELECT 1' ,
'ALTER TABLE ll_dispatch_pda_task MODIFY COLUMN warehouse_id VARCHAR(128) NOT NULL COMMENT ''Token绑定的海外仓库ID''' ));
PREPARE phase5_pda_scope_ddl FROM @ ddl ; EXECUTE phase5_pda_scope_ddl ; DEALLOCATE PREPARE phase5_pda_scope_ddl ;
2026-09-01 20:20:25 +08:00
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_dropship_order_profile' AND column_name = 'source_pallet_no'
AND is_nullable = 'NO' AND column_type = 'varchar(128)' AND column_comment = '来源托盘号快照'
), 'SELECT 1' ,
'ALTER TABLE ll_dropship_order_profile MODIFY COLUMN source_pallet_no VARCHAR(128) NOT NULL COMMENT ''来源托盘号快照''' ));
PREPARE phase5_structure_ddl FROM @ ddl ; EXECUTE phase5_structure_ddl ; DEALLOCATE PREPARE phase5_structure_ddl ;
2026-09-01 14:24:59 +08:00
SET @ index_ready = ( SELECT COUNT ( * ) = 1 AND MIN ( non_unique ) = 0
AND MAX ( seq_in_index = 1 AND column_name = 'dispatch_no' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dispatch_order' AND index_name = 'uk_ll_dispatch_order_no' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dispatch_order' AND index_name = 'uk_ll_dispatch_order_no' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_dispatch_order DROP INDEX uk_ll_dispatch_order_no, ADD UNIQUE KEY uk_ll_dispatch_order_no(dispatch_no)' ,
'ALTER TABLE ll_dispatch_order ADD UNIQUE KEY uk_ll_dispatch_order_no(dispatch_no)' ));
PREPARE phase5_identifier_ddl FROM @ ddl ; EXECUTE phase5_identifier_ddl ; DEALLOCATE PREPARE phase5_identifier_ddl ;
SET @ index_ready = ( SELECT COUNT ( * ) = 1 AND MIN ( non_unique ) = 0
AND MAX ( seq_in_index = 1 AND column_name = 'outbound_no' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_order' AND index_name = 'uk_ll_outbound_no' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_order' AND index_name = 'uk_ll_outbound_no' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_outbound_order DROP INDEX uk_ll_outbound_no, ADD UNIQUE KEY uk_ll_outbound_no(outbound_no)' ,
'ALTER TABLE ll_outbound_order ADD UNIQUE KEY uk_ll_outbound_no(outbound_no)' ));
PREPARE phase5_identifier_ddl FROM @ ddl ; EXECUTE phase5_identifier_ddl ; DEALLOCATE PREPARE phase5_identifier_ddl ;
SET @ index_ready = ( SELECT COUNT ( * ) = 1 AND MIN ( non_unique ) = 0
AND MAX ( seq_in_index = 1 AND column_name = 'task_no' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dispatch_pda_task' AND index_name = 'uk_ll_dispatch_pda_task_no' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_dispatch_pda_task' AND index_name = 'uk_ll_dispatch_pda_task_no' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_dispatch_pda_task DROP INDEX uk_ll_dispatch_pda_task_no, ADD UNIQUE KEY uk_ll_dispatch_pda_task_no(task_no)' ,
'ALTER TABLE ll_dispatch_pda_task ADD UNIQUE KEY uk_ll_dispatch_pda_task_no(task_no)' ));
PREPARE phase5_identifier_ddl FROM @ ddl ; EXECUTE phase5_identifier_ddl ; DEALLOCATE PREPARE phase5_identifier_ddl ;
SET @ index_ready = ( SELECT COUNT ( * ) = 1 AND MIN ( non_unique ) = 0
AND MAX ( seq_in_index = 1 AND column_name = 'task_no' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_task_no' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_task_no' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_outbound_pda_task DROP INDEX uk_ll_outbound_pda_task_no, ADD UNIQUE KEY uk_ll_outbound_pda_task_no(task_no)' ,
'ALTER TABLE ll_outbound_pda_task ADD UNIQUE KEY uk_ll_outbound_pda_task_no(task_no)' ));
PREPARE phase5_identifier_ddl FROM @ ddl ; EXECUTE phase5_identifier_ddl ; DEALLOCATE PREPARE phase5_identifier_ddl ;
SET @ index_ready = ( SELECT COUNT ( * ) = 2 AND MIN ( non_unique ) = 0
AND SUM ( seq_in_index = 1 AND column_name = 'customer_id' ) = 1
AND SUM ( seq_in_index = 2 AND column_name = 'completion_idempotency_key' ) = 1
FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_complete_key' );
SET @ index_exists = ( SELECT COUNT ( * ) > 0 FROM information_schema . statistics WHERE table_schema = DATABASE ()
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_complete_key' );
SET @ ddl = IF ( @ index_ready , 'SELECT 1' , IF ( @ index_exists ,
'ALTER TABLE ll_outbound_pda_task DROP INDEX uk_ll_outbound_pda_complete_key, ADD UNIQUE KEY uk_ll_outbound_pda_complete_key(customer_id,completion_idempotency_key)' ,
'ALTER TABLE ll_outbound_pda_task ADD UNIQUE KEY uk_ll_outbound_pda_complete_key(customer_id,completion_idempotency_key)' ));
PREPARE phase5_identifier_ddl FROM @ ddl ; EXECUTE phase5_identifier_ddl ; DEALLOCATE PREPARE phase5_identifier_ddl ;
DROP PROCEDURE IF EXISTS assert_phase5_lastleg_identifiers_ready ;
DELIMITER $$
CREATE PROCEDURE assert_phase5_lastleg_identifiers_ready ()
BEGIN
2026-09-01 20:20:25 +08:00
IF ( SELECT COUNT ( * ) FROM information_schema . tables
WHERE table_schema = 'baiyue_lastleg' AND table_name IN (
'll_dispatch_order' , 'll_dispatch_item' , 'll_dispatch_pallet_lock' , 'll_dispatch_draft' , 'll_dispatch_draft_container' ,
'll_dispatch_pda_task' , 'll_dispatch_pda_pick' , 'll_dispatch_pda_operation' , 'll_dispatch_pda_pick_order' ,
'll_outbound_order' , 'll_outbound_pallet_item' , 'll_outbound_pda_task' , 'll_outbound_pda_pick' ,
'll_delivery_order' , 'll_delivery_fee' , 'll_delivery_operation' ,
'll_dropship_order_profile' , 'll_dropship_carton' , 'll_dropship_sku_inventory' , 'll_dropship_carton_ledger' ,
'll_exception_order' , 'll_customer_visit' )) <> 22 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '五期完整业务表集合未部署' ;
END IF ;
2026-09-01 14:24:59 +08:00
IF ( SELECT COUNT ( * ) FROM information_schema . columns WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dispatch_pda_task' AND column_name = 'warehouse_id' AND is_nullable = 'NO' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dispatch_pda_task.warehouse_id未收敛为非空' ;
END IF ;
IF EXISTS ( SELECT 1 FROM ll_dispatch_pda_task
WHERE warehouse_id IS NULL OR TRIM ( warehouse_id ) = '' OR TRIM ( warehouse_id ) = '0' ) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_dispatch_pda_task仍存在空或0仓库范围' ;
END IF ;
2026-09-01 20:20:25 +08:00
IF ( SELECT COUNT ( * ) FROM information_schema . columns WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dropship_order_profile' AND column_name = 'source_pallet_no'
AND column_type = 'varchar(128)' AND is_nullable = 'NO' AND column_comment = '来源托盘号快照' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '一件代发来源托盘号字段未收敛' ;
END IF ;
2026-09-01 14:24:59 +08:00
IF ( SELECT COUNT ( * ) FROM information_schema . columns WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND column_name = 'completion_idempotency_key'
AND column_type = 'varchar(255)' AND is_nullable = 'YES' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'll_outbound_pda_task完成幂等字段未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dispatch_order' AND index_name = 'uk_ll_dispatch_order_no' ) <> 1
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dispatch_order' AND index_name = 'uk_ll_dispatch_order_no'
AND non_unique = 0 AND seq_in_index = 1 AND column_name = 'dispatch_no' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'dispatch_no全局唯一索引未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_order' AND index_name = 'uk_ll_outbound_no' ) <> 1
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_order' AND index_name = 'uk_ll_outbound_no'
AND non_unique = 0 AND seq_in_index = 1 AND column_name = 'outbound_no' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'outbound_no全局唯一索引未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dispatch_pda_task' AND index_name = 'uk_ll_dispatch_pda_task_no' ) <> 1
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_dispatch_pda_task' AND index_name = 'uk_ll_dispatch_pda_task_no'
AND non_unique = 0 AND seq_in_index = 1 AND column_name = 'task_no' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '排车PDA task_no全局唯一索引未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_task_no' ) <> 1
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_task_no'
AND non_unique = 0 AND seq_in_index = 1 AND column_name = 'task_no' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '出库PDA task_no全局唯一索引未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_complete_key' ) <> 2
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_complete_key'
AND non_unique = 0 AND seq_in_index = 1 AND column_name = 'customer_id' ) <> 1
OR ( SELECT COUNT ( * ) FROM information_schema . statistics WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_outbound_pda_task' AND index_name = 'uk_ll_outbound_pda_complete_key'
AND non_unique = 0 AND seq_in_index = 2 AND column_name = 'completion_idempotency_key' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '出库PDA客户范围完成幂等唯一索引未部署' ;
END IF ;
END $$
DELIMITER ;
CALL assert_phase5_lastleg_identifiers_ready ();
DROP PROCEDURE assert_phase5_lastleg_identifiers_ready ;
2026-08-25 16:40:48 +08:00
USE baiyue_lastleg ;
2026-08-31 14:39:40 +08:00
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_inbound_plan' AND column_name = 'version'
), 'SELECT 1' , 'ALTER TABLE ll_inbound_plan ADD COLUMN version INT NOT NULL DEFAULT 0 COMMENT ''入库计划乐观锁版本'' AFTER updated_at' ));
PREPARE ll_inbound_plan_version_ddl FROM @ ddl ;
EXECUTE ll_inbound_plan_version_ddl ;
DEALLOCATE PREPARE ll_inbound_plan_version_ddl ;
SET @ ddl = ( SELECT IF ( EXISTS (
SELECT 1 FROM information_schema . columns
WHERE table_schema = DATABASE () AND table_name = 'll_order' AND column_name = 'pallet_merge_batch_id'
), 'SELECT 1' , 'ALTER TABLE ll_order ADD COLUMN pallet_merge_batch_id VARCHAR(64) NULL COMMENT ''平台预标记合托分组号'' AFTER pallet_merge_flag' ));
PREPARE ll_order_merge_batch_ddl FROM @ ddl ;
EXECUTE ll_order_merge_batch_ddl ;
DEALLOCATE PREPARE ll_order_merge_batch_ddl ;
2026-08-25 16:40:48 +08:00
CREATE TABLE IF NOT EXISTS ll_security_event_inbox (
event_id VARCHAR ( 64 ) NOT NULL COMMENT '跨区安全事件ID' , event_type VARCHAR ( 96 ) NOT NULL COMMENT 'IAM安全事件类型' ,
payload_hash CHAR ( 64 ) NOT NULL COMMENT '规范化载荷SHA-256哈希' , payload_json JSON NOT NULL COMMENT '冻结事件载荷JSON' ,
status VARCHAR ( 16 ) NOT NULL COMMENT '消费状态:RECEIVED或PROCESSED' ,
result VARCHAR ( 32 ) NULL COMMENT '处理结果:APPLIED、STALE、DUPLICATE或DUPLICATE_VERSION' ,
received_at DATETIME ( 3 ) NOT NULL COMMENT '接收时间' , processed_at DATETIME ( 3 ) NULL COMMENT '处理完成时间' ,
2026-08-25 14:46:06 +08:00
PRIMARY KEY ( event_id ), KEY idx_security_inbox_type_time ( event_type , received_at )
2026-08-25 16:40:48 +08:00
) ENGINE = InnoDB COMMENT = '海外IAM安全事件消费者收件箱' ;
CREATE TABLE IF NOT EXISTS ll_security_projection (
aggregate_type VARCHAR ( 32 ) NOT NULL COMMENT '聚合类型:USER、TENANT或AUTHORIZATION' ,
aggregate_id VARCHAR ( 64 ) NOT NULL COMMENT '用户或客户聚合ID' , tenant_id BIGINT NOT NULL COMMENT '平台0或客户ID' ,
security_status VARCHAR ( 24 ) NULL COMMENT '当前安全状态:ACTIVE或DISABLED' ,
permission_version BIGINT NULL COMMENT '当前单调权限版本' ,
2026-09-07 11:37:06 +08:00
roles_json JSON NOT NULL COMMENT 'IAM投影的当前角色快照' ,
authorities_json JSON NOT NULL COMMENT 'IAM投影的当前海外权限快照' ,
2026-08-25 16:40:48 +08:00
aggregate_version BIGINT NOT NULL COMMENT '事件聚合单调版本' , payload_hash CHAR ( 64 ) NOT NULL COMMENT '当前版本载荷哈希' ,
last_event_id VARCHAR ( 64 ) NOT NULL COMMENT '最后应用的事件ID' ,
changed_at DATETIME ( 3 ) NOT NULL COMMENT '国内IAM事实发生时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '投影更新时间' ,
2026-08-25 14:46:06 +08:00
PRIMARY KEY ( aggregate_type , aggregate_id ), KEY idx_security_projection_tenant ( tenant_id ),
KEY idx_security_projection_permission ( aggregate_id , permission_version )
) ENGINE = InnoDB COMMENT = '海外IAM安全状态与权限版本投影' ;
2026-09-07 11:37:06 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_security_projection' AND column_name = 'roles_json' ), 'SELECT 1' ,
'ALTER TABLE ll_security_projection ADD COLUMN roles_json JSON NULL COMMENT ''IAM投影的当前角色快照'' AFTER permission_version' ));
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_security_projection' AND column_name = 'authorities_json' ), 'SELECT 1' ,
'ALTER TABLE ll_security_projection ADD COLUMN authorities_json JSON NULL COMMENT ''IAM投影的当前海外权限快照'' AFTER roles_json' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
UPDATE ll_security_projection SET roles_json = JSON_ARRAY () WHERE roles_json IS NULL ;
UPDATE ll_security_projection SET authorities_json = JSON_ARRAY () WHERE authorities_json IS NULL ;
ALTER TABLE ll_security_projection
MODIFY COLUMN roles_json JSON NOT NULL COMMENT 'IAM投影的当前角色快照' ,
MODIFY COLUMN authorities_json JSON NOT NULL COMMENT 'IAM投影的当前海外权限快照' ;
2026-08-25 16:40:48 +08:00
-- 与国内固定 auth_account.id=1000001、tenant_id=0 的 platform_admin 一致;真实事件从版本1覆盖。
INSERT IGNORE INTO ll_security_projection (
2026-09-07 11:37:06 +08:00
aggregate_type , aggregate_id , tenant_id , security_status , permission_version , roles_json , authorities_json , aggregate_version ,
2026-08-25 16:40:48 +08:00
payload_hash , last_event_id , changed_at , updated_at
) VALUES
2026-09-07 11:37:06 +08:00
( 'USER' , '1000001' , 0 , 'ACTIVE' , 0 , JSON_ARRAY (), JSON_ARRAY (), 0 , SHA2 ( 'lastleg-baseline:platform_admin:USER:0' , 256 ),
2026-08-25 16:40:48 +08:00
'baseline-platform-admin-user-v0' , '1970-01-01 00:00:00.000' , '1970-01-01 00:00:00.000' ),
2026-09-07 11:37:06 +08:00
( 'AUTHORIZATION' , '1000001' , 0 , NULL , 0 , JSON_ARRAY (), JSON_ARRAY (), 0 , SHA2 ( 'lastleg-baseline:platform_admin:AUTHORIZATION:0' , 256 ),
2026-08-25 16:40:48 +08:00
'baseline-platform-admin-authorization-v0' , '1970-01-01 00:00:00.000' , '1970-01-01 00:00:00.000' );
DROP PROCEDURE IF EXISTS assert_lastleg_security_projection_ready ;
2026-08-25 14:46:06 +08:00
DELIMITER $$
2026-08-25 16:40:48 +08:00
CREATE PROCEDURE assert_lastleg_security_projection_ready ()
2026-08-25 14:46:06 +08:00
BEGIN
2026-08-25 16:40:48 +08:00
IF ( SELECT COUNT ( * ) FROM information_schema . tables WHERE table_schema = 'baiyue_lastleg'
AND table_name IN ( 'll_security_event_inbox' , 'll_security_projection' )) <> 2 THEN
2026-08-25 14:46:06 +08:00
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外IAM安全Inbox或投影表未完整部署' ;
END IF ;
END $$
DELIMITER ;
2026-08-25 16:40:48 +08:00
CALL assert_lastleg_security_projection_ready ();
DROP PROCEDURE assert_lastleg_security_projection_ready ;
2026-09-02 17:07:03 +08:00
CREATE TABLE IF NOT EXISTS ll_finance_fee_source (
id BIGINT NOT NULL COMMENT '费用版本记录ID' , source_fee_id BIGINT NOT NULL COMMENT '跨版本稳定费用来源ID' ,
source_version INT NOT NULL COMMENT '费用来源版本,从1递增' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID和隔离键' ,
customer_name VARCHAR ( 200 ) NULL COMMENT '客户名称快照' , source_type VARCHAR ( 64 ) NOT NULL COMMENT '海外费用来源类型' ,
source_no VARCHAR ( 128 ) NOT NULL COMMENT '来源业务编号或入仓码快照' , business_type VARCHAR ( 32 ) NOT NULL COMMENT '来源业务类型' ,
business_id BIGINT NULL COMMENT '来源业务记录ID' , business_no VARCHAR ( 128 ) NOT NULL COMMENT '来源业务编号' ,
order_id BIGINT NULL COMMENT '关联订单ID' , inbound_id BIGINT NULL COMMENT '关联海外入仓计划或入仓记录ID' ,
inbound_code VARCHAR ( 64 ) NULL COMMENT '关联入仓码;并非所有费用必填' , container_id BIGINT NULL COMMENT '关联柜次ID' ,
container_booking_id BIGINT NULL COMMENT '来源订舱柜ID' , container_no VARCHAR ( 64 ) NULL COMMENT '真实集装箱号快照' ,
warehouse_id BIGINT NULL COMMENT '关联海外仓ID' , fee_item_code VARCHAR ( 64 ) NOT NULL COMMENT '费用项目编码快照' ,
fee_item_name VARCHAR ( 200 ) NOT NULL COMMENT '费用项目名称快照' , direction VARCHAR ( 16 ) NOT NULL COMMENT 'RECEIVABLE应收或PAYABLE应付' ,
supplier_id BIGINT NULL COMMENT '应付供应商ID' , supplier_name VARCHAR ( 200 ) NULL COMMENT '应付供应商名称快照' ,
supplier_category VARCHAR ( 32 ) NULL COMMENT '应付供应商类别约束' , settlement_mode VARCHAR ( 16 ) NULL COMMENT 'ON_ACCOUNT账期应付或DIRECT_PAID业务已付' ,
paid_at DATETIME ( 3 ) NULL COMMENT '直接已付时间' , payment_method VARCHAR ( 32 ) NULL COMMENT '直接已付方式' ,
payment_reference_no VARCHAR ( 128 ) NULL COMMENT '直接已付流水号' , payment_voucher_file_ids JSON NULL COMMENT '直接已付凭证文件ID快照' ,
business_date DATE NOT NULL COMMENT '费用业务日期' , currency CHAR ( 3 ) NOT NULL DEFAULT 'CNY' COMMENT '财务结算币种,当前固定CNY' ,
amount DECIMAL ( 20 , 6 ) NOT NULL COMMENT '费用金额' , review_status VARCHAR ( 16 ) NOT NULL COMMENT 'DRAFT、PENDING、APPROVED或REJECTED' ,
publication_status VARCHAR ( 16 ) NOT NULL COMMENT 'UNPUBLISHED或PUBLISHED' , source_status VARCHAR ( 16 ) NOT NULL COMMENT 'ACTIVE、SUPERSEDED或VOIDED' ,
review_reason VARCHAR ( 500 ) NULL COMMENT '审核或作废原因' , reviewer_id VARCHAR ( 128 ) NULL COMMENT '审核人ID' , reviewed_at DATETIME ( 3 ) NULL COMMENT '审核时间' ,
created_by VARCHAR ( 128 ) NOT NULL COMMENT '创建人ID' , updated_by VARCHAR ( 128 ) NOT NULL COMMENT '最后更新人ID' ,
created_at DATETIME ( 3 ) NOT NULL COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL COMMENT '最后更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_finance_fee_version ( source_fee_id , source_version ),
KEY idx_ll_finance_fee_customer ( customer_id , source_status , created_at ), KEY idx_ll_finance_fee_business ( business_type , business_no , created_at ),
CONSTRAINT chk_ll_finance_fee_amount CHECK ( amount > 0 ), CONSTRAINT chk_ll_finance_fee_currency CHECK ( currency = 'CNY' ),
CONSTRAINT chk_ll_finance_fee_direction CHECK ( direction IN ( 'RECEIVABLE' , 'PAYABLE' )),
CONSTRAINT chk_ll_finance_fee_review CHECK ( review_status IN ( 'DRAFT' , 'PENDING' , 'APPROVED' , 'REJECTED' )),
CONSTRAINT chk_ll_finance_fee_publication CHECK ( publication_status IN ( 'UNPUBLISHED' , 'PUBLISHED' )),
CONSTRAINT chk_ll_finance_fee_status CHECK ( source_status IN ( 'ACTIVE' , 'SUPERSEDED' , 'VOIDED' ))
) ENGINE = InnoDB COMMENT = '海外业务不可变费用来源版本;发布后经跨区事件进入Finance' ;
2026-09-08 21:45:57 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_finance_fee_source' AND index_name = 'idx_ll_finance_fee_container_customer' ), 'SELECT 1' , 'ALTER TABLE ll_finance_fee_source ADD KEY idx_ll_finance_fee_container_customer(container_booking_id,customer_id,source_status,created_at)' ));
PREPARE ll_finance_fee_ddl FROM @ ddl ; EXECUTE ll_finance_fee_ddl ; DEALLOCATE PREPARE ll_finance_fee_ddl ;
2026-09-02 17:07:03 +08:00
CREATE TABLE IF NOT EXISTS ll_finance_fee_command (
id BIGINT NOT NULL COMMENT '幂等命令ID' , operator_id VARCHAR ( 128 ) NOT NULL COMMENT '操作人ID' ,
action VARCHAR ( 16 ) NOT NULL COMMENT 'CREATE、SUBMIT、REVIEW、ADJUST或VOID' , idempotency_key VARCHAR ( 128 ) NOT NULL COMMENT '操作幂等键' ,
request_hash CHAR ( 64 ) NOT NULL COMMENT '请求内容SHA-256' , source_fee_id BIGINT NOT NULL COMMENT '稳定费用来源ID' ,
source_version INT NOT NULL COMMENT '命令结果版本' , created_at DATETIME ( 3 ) NOT NULL COMMENT '命令创建时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_finance_fee_command ( operator_id , action , idempotency_key ),
KEY idx_ll_finance_fee_command_source ( source_fee_id , source_version )
) ENGINE = InnoDB COMMENT = '海外费用来源写操作幂等审计' ;
2026-08-25 14:46:06 +08:00
SELECT 'PASS' AS migration_status , '海外仓业务、海外仓资源与IAM安全投影结构已就绪' AS message ;
2026-09-05 22:26:25 +08:00
CREATE TABLE IF NOT EXISTS ll_wallet_event_inbox (
event_id VARCHAR ( 64 ) NOT NULL COMMENT '国内Finance资金结果事件ID' ,
command_event_id VARCHAR ( 64 ) NOT NULL COMMENT '原海外资金指令事件ID' ,
2026-09-05 23:32:31 +08:00
payload_hash VARCHAR ( 71 ) NOT NULL COMMENT '规范化载荷SHA-256,包含sha256:前缀' ,
2026-09-05 22:26:25 +08:00
payload_json JSON NOT NULL COMMENT '冻结事件信封' ,
status VARCHAR ( 16 ) NOT NULL COMMENT 'RECEIVED或PROCESSED' ,
received_at DATETIME ( 3 ) NOT NULL COMMENT '接收时间' ,
processed_at DATETIME ( 3 ) NULL COMMENT '处理完成时间' ,
PRIMARY KEY ( event_id ),
UNIQUE KEY uk_ll_wallet_command_result ( command_event_id ),
KEY idx_ll_wallet_event_status ( status , received_at )
) ENGINE = InnoDB COMMENT = '跨区客户资金结果幂等收件箱' ;
2026-09-05 23:32:31 +08:00
ALTER TABLE ll_wallet_event_inbox
MODIFY COLUMN payload_hash VARCHAR ( 71 ) NOT NULL COMMENT '规范化载荷SHA-256,包含sha256:前缀' ;
2026-09-05 22:26:25 +08:00
CREATE TABLE IF NOT EXISTS ll_procurement_daily_sequence (
customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID' ,
business_date DATE NOT NULL COMMENT '北京时间业务日期' ,
sequence_value INT NOT NULL COMMENT '客户当日已分配最大序号' ,
PRIMARY KEY ( customer_id , business_date ),
CONSTRAINT chk_ll_procurement_sequence CHECK ( sequence_value BETWEEN 1 AND 9999 )
) ENGINE = InnoDB COMMENT = '海外采购客户日序列' ;
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_file (
id BIGINT NOT NULL COMMENT '主键ID' , order_id BIGINT NOT NULL COMMENT '采购订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID' ,
category VARCHAR ( 16 ) NOT NULL COMMENT 'RECEIPT签收文件或VOUCHER费用凭证' , file_id BIGINT NOT NULL COMMENT 'File服务文件ID' ,
file_name VARCHAR ( 255 ) NOT NULL COMMENT '文件名快照' , content_type VARCHAR ( 128 ) NULL COMMENT '媒体类型' , size_bytes BIGINT NOT NULL DEFAULT 0 COMMENT '文件大小' ,
created_by VARCHAR ( 128 ) NULL COMMENT '上传人' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '上传时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_procurement_file ( order_id , file_id ), KEY idx_ll_procurement_file_order ( customer_id , order_id , category , created_at ),
CONSTRAINT chk_ll_procurement_file_category CHECK ( category IN ( 'RECEIPT' , 'VOUCHER' ))
) ENGINE = InnoDB COMMENT = '海外采购签收文件及费用凭证' ;
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_fee (
id BIGINT NOT NULL COMMENT '主键ID' , order_id BIGINT NOT NULL COMMENT '采购订单ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID' ,
fee_no VARCHAR ( 64 ) NOT NULL COMMENT '费用业务号' , fee_item_code VARCHAR ( 32 ) NOT NULL COMMENT '费用项编码' , fee_item_name VARCHAR ( 128 ) NOT NULL COMMENT '费用项名称' ,
amount DECIMAL ( 20 , 2 ) NOT NULL COMMENT 'CNY金额' , currency CHAR ( 3 ) NOT NULL DEFAULT 'CNY' COMMENT '费用币种' , voucher_file_id BIGINT NOT NULL COMMENT '凭证文件ID' ,
voucher_file_name VARCHAR ( 255 ) NOT NULL COMMENT '凭证文件名' , remark VARCHAR ( 500 ) NULL COMMENT '说明' ,
wallet_status VARCHAR ( 32 ) NOT NULL COMMENT '资金状态' , wallet_error_code VARCHAR ( 64 ) NULL COMMENT '资金错误码' , wallet_error_message VARCHAR ( 500 ) NULL COMMENT '资金错误说明' ,
wallet_command_event_id VARCHAR ( 64 ) NULL COMMENT '当前资金指令事件ID' , created_by VARCHAR ( 128 ) NULL COMMENT '登记人' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , updated_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) ON UPDATE CURRENT_TIMESTAMP ( 3 ) COMMENT '更新时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_procurement_fee_no ( fee_no ), KEY idx_ll_procurement_fee_order ( customer_id , order_id , created_at ),
CONSTRAINT chk_ll_procurement_fee_amount CHECK ( amount > 0 ), CONSTRAINT chk_ll_procurement_fee_currency CHECK ( currency = 'CNY' )
) ENGINE = InnoDB COMMENT = '海外采购费用明细及资金生命周期' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_relabel_application' AND column_name = 'charge_amount' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN charge_amount DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT ''换标费用CNY'' AFTER notified_package_count' )); 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_relabel_application' AND column_name = 'charge_currency' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN charge_currency CHAR(3) NOT NULL DEFAULT ''CNY'' COMMENT ''费用币种'' AFTER charge_amount' )); 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_relabel_application' AND column_name = 'wallet_status' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN wallet_status VARCHAR(32) NOT NULL DEFAULT ''FREEZE_PENDING'' COMMENT ''资金状态'' AFTER charge_currency' )); 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_relabel_application' AND column_name = 'wallet_error_code' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN wallet_error_code VARCHAR(64) NULL COMMENT ''资金错误码'' AFTER wallet_status' )); 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_relabel_application' AND column_name = 'wallet_error_message' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN wallet_error_message VARCHAR(500) NULL COMMENT ''资金错误说明'' AFTER wallet_error_code' )); 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_relabel_application' AND column_name = 'wallet_command_event_id' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_application ADD COLUMN wallet_command_event_id VARCHAR(64) NULL COMMENT ''当前资金指令事件ID'' AFTER wallet_error_message' )); PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-09-07 12:30:17 +08:00
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE () AND table_name = 'll_relabel_item' AND column_name = 'remark' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_item ADD COLUMN remark VARCHAR(1000) NULL COMMENT ''货物明细备注'' AFTER label_requirement' )); 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_relabel_item' AND column_name = 'carton_mark' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_item ADD COLUMN carton_mark VARCHAR(255) NULL COMMENT ''客户自有箱唛'' AFTER relabel_file_url' )); 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_relabel_item' AND column_name = 'fba_carton_mark' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_item ADD COLUMN fba_carton_mark VARCHAR(255) NULL COMMENT ''关联FBA箱唛'' AFTER carton_mark' )); 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_relabel_item' AND column_name = 'destination_warehouse_id' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_item ADD COLUMN destination_warehouse_id VARCHAR(128) NULL COMMENT ''该箱目的海外仓ID'' AFTER fba_carton_mark' )); PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . statistics WHERE table_schema = DATABASE () AND table_name = 'll_relabel_item' AND index_name = 'idx_ll_relabel_item_destination' ), 'SELECT 1' , 'ALTER TABLE ll_relabel_item ADD KEY idx_ll_relabel_item_destination (customer_id,destination_warehouse_id,application_id)' )); PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
2026-09-05 22:26:25 +08:00
CREATE TABLE IF NOT EXISTS ll_destuff_pallet_cost (
id BIGINT NOT NULL COMMENT '主键ID' , source_container_booking_id VARCHAR ( 128 ) NOT NULL COMMENT '来源柜次业务ID' , container_no VARCHAR ( 64 ) NOT NULL COMMENT '集装箱号' , warehouse_id BIGINT NULL COMMENT '海外仓ID' ,
pallet_count INT NOT NULL COMMENT '实际打托数' , total_actual_volume_cbm DECIMAL ( 20 , 6 ) NOT NULL COMMENT '客户实收总体积' , total_cost DECIMAL ( 20 , 2 ) NOT NULL COMMENT '打托总成本' , currency CHAR ( 3 ) NOT NULL DEFAULT 'CNY' COMMENT '成本币种' ,
status VARCHAR ( 16 ) NOT NULL COMMENT '生成状态' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' , PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_destuff_cost_booking ( source_container_booking_id ), CONSTRAINT chk_ll_destuff_cost CHECK ( pallet_count > 0 AND total_actual_volume_cbm > 0 AND total_cost > 0 AND currency = 'CNY' )
) ENGINE = InnoDB COMMENT = '拆柜打托实际成本汇总' ;
CREATE TABLE IF NOT EXISTS ll_destuff_pallet_cost_allocation (
id BIGINT NOT NULL COMMENT '主键ID' , cost_id BIGINT NOT NULL COMMENT '打托成本汇总ID' , customer_id VARCHAR ( 128 ) NOT NULL COMMENT '客户ID' , actual_volume_cbm DECIMAL ( 20 , 6 ) NOT NULL COMMENT '客户实收体积' ,
allocated_amount DECIMAL ( 20 , 2 ) NOT NULL COMMENT '客户分摊金额' , fee_source_id BIGINT NOT NULL COMMENT '海外费用来源ID' , created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '创建时间' ,
PRIMARY KEY ( id ), UNIQUE KEY uk_ll_destuff_customer ( cost_id , customer_id ), UNIQUE KEY uk_ll_destuff_fee_source ( fee_source_id ),
CONSTRAINT chk_ll_destuff_allocation CHECK ( actual_volume_cbm > 0 AND allocated_amount >= 0 )
) ENGINE = InnoDB COMMENT = '拆柜打托成本按客户实收体积分摊' ;
2026-09-07 15:07:34 +08:00
-- 海外接柜仓由平台在尾程建单时预分配;历史测试数据不回填,缺失事实由业务接口失败关闭。
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 = 'overseas_warehouse_code' ),
'ALTER TABLE ll_order MODIFY COLUMN overseas_warehouse_code VARCHAR(128) NULL COMMENT ''海外接柜仓业务编码快照''' ,
'ALTER TABLE ll_order ADD COLUMN overseas_warehouse_code VARCHAR(128) 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_order' AND column_name = 'receiving_warehouse_version' ),
'ALTER TABLE ll_order MODIFY COLUMN receiving_warehouse_version INT NOT NULL DEFAULT 0 COMMENT ''柜级接柜仓分配乐观锁版本''' ,
'ALTER TABLE ll_order ADD COLUMN receiving_warehouse_version INT NOT NULL DEFAULT 0 COMMENT ''柜级接柜仓分配乐观锁版本'' AFTER overseas_warehouse_name' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
ALTER TABLE ll_order
MODIFY COLUMN overseas_warehouse_id VARCHAR ( 128 ) NULL COMMENT '海外接柜仓ID;新建尾程订单默认洛杉矶仓' ,
MODIFY COLUMN overseas_warehouse_name VARCHAR ( 255 ) NULL COMMENT '海外接柜仓名称快照' ;
ALTER TABLE ll_inbound_plan
MODIFY COLUMN overseas_warehouse_id BIGINT NULL COMMENT '从尾程订单继承的平台预分配海外接柜仓ID' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_receiving_container_session' AND column_name = 'overseas_warehouse_code' ),
'ALTER TABLE ll_receiving_container_session MODIFY COLUMN overseas_warehouse_code VARCHAR(128) NULL COMMENT ''海外接柜仓业务编码快照''' ,
'ALTER TABLE ll_receiving_container_session ADD COLUMN overseas_warehouse_code VARCHAR(128) NULL COMMENT ''海外接柜仓业务编码快照'' AFTER overseas_warehouse_id' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
ALTER TABLE ll_receiving_container_session
MODIFY COLUMN overseas_warehouse_id BIGINT NOT NULL COMMENT '平台预分配并由操作员Token匹配的海外接柜仓ID' ,
MODIFY COLUMN overseas_warehouse_name VARCHAR ( 255 ) NOT NULL COMMENT '仓库服务校验后的海外接柜仓名称快照' ;
CREATE TABLE IF NOT EXISTS ll_receiving_warehouse_operation (
id BIGINT NOT NULL COMMENT '柜级接柜仓修改操作ID' ,
source_container_booking_id VARCHAR ( 128 ) NOT NULL COMMENT '稳定来源柜预订ID' ,
idempotency_key VARCHAR ( 255 ) NOT NULL COMMENT '平台请求幂等键' ,
request_hash VARCHAR ( 64 ) NOT NULL COMMENT '规范化修改请求SHA-256摘要' ,
result_version INT NOT NULL COMMENT '修改成功后的柜级分配版本' ,
operator_name VARCHAR ( 128 ) NOT NULL COMMENT '平台操作人名称' ,
remark VARCHAR ( 500 ) NULL COMMENT '接柜仓修改备注' ,
created_at DATETIME ( 3 ) NOT NULL DEFAULT CURRENT_TIMESTAMP ( 3 ) COMMENT '操作时间' ,
PRIMARY KEY ( id ),
UNIQUE KEY uk_ll_receiving_warehouse_idempotency ( idempotency_key ),
KEY idx_ll_receiving_warehouse_container ( source_container_booking_id , created_at )
) ENGINE = InnoDB COMMENT = '柜级海外接柜仓修改幂等审计记录' ;
DROP PROCEDURE IF EXISTS assert_receiving_warehouse_assignment_ready ;
DELIMITER $$
CREATE PROCEDURE assert_receiving_warehouse_assignment_ready ()
BEGIN
IF ( SELECT COUNT ( * ) FROM information_schema . columns WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_order' AND column_name IN ( 'overseas_warehouse_code' , 'receiving_warehouse_version' )) <> 2 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_receiving_container_session' AND column_name = 'overseas_warehouse_code' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '海外PDA接柜会话仓库编码字段未部署' ;
END IF ;
IF ( SELECT COUNT ( * ) FROM information_schema . tables WHERE table_schema = 'baiyue_lastleg'
AND table_name = 'll_receiving_warehouse_operation' ) <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '柜级海外接柜仓修改幂等审计表未部署' ;
END IF ;
END $$
DELIMITER ;
CALL assert_receiving_warehouse_assignment_ready ();
DROP PROCEDURE assert_receiving_warehouse_assignment_ready ;
SELECT 'PASS' AS migration_status , '海外接柜仓预分配与柜级修改结构已就绪' AS message ;
2026-09-07 21:10:43 +08:00
-- 一件代发来源托盘与海外仓实物托盘分离,实物绑定不得覆盖来源身份。
USE baiyue_lastleg ;
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 = 'source_pallet_no' ),
'SELECT 1' ,
'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN source_pallet_no VARCHAR(128) NULL COMMENT ''一件代发不可变来源托盘号快照'' AFTER pallet_no' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
ALTER TABLE ll_inbound_plan_pallet
MODIFY COLUMN pallet_no VARCHAR ( 64 ) NOT NULL COMMENT '当前托盘编号:分配前为计划占位码,分配后为海外仓实物托盘码' ;
SET @ ddl = ( SELECT IF ( EXISTS ( SELECT 1 FROM information_schema . columns WHERE table_schema = DATABASE ()
AND table_name = 'll_inbound_stock_receipt' AND column_name = 'source_pallet_no' ),
'SELECT 1' ,
'ALTER TABLE ll_inbound_stock_receipt ADD COLUMN source_pallet_no VARCHAR(128) NULL COMMENT ''一件代发不可变来源托盘号快照'' AFTER pallet_no' ));
PREPARE stmt FROM @ ddl ; EXECUTE stmt ; DEALLOCATE PREPARE stmt ;
ALTER TABLE ll_inbound_stock_receipt
MODIFY COLUMN pallet_no VARCHAR ( 64 ) NOT NULL COMMENT '海外仓实物托盘码' ;
2026-09-07 23:58:18 +08:00
-- 尾程单票人工计划、暂扣与人工展示节点。
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 ;