1418 lines
130 KiB
SQL
1418 lines
130 KiB
SQL
-- Baiyue last-leg platform incremental database archive
|
||
-- Encoding: UTF-8 without BOM
|
||
-- Policy:
|
||
-- 1. Append new numbered sections; never rewrite an applied section.
|
||
-- 2. DDL must be repeatable and must preserve existing business rows.
|
||
-- 3. Every new column and index must use an information_schema guard.
|
||
-- 4. Do not place test fixtures, DELETE, TRUNCATE or business-data UPDATE here.
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 001
|
||
-- Event Bridge inbox and delivery-attempt baseline
|
||
-- ============================================================================
|
||
|
||
CREATE DATABASE IF NOT EXISTS baiyue_event_bridge
|
||
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
USE baiyue_event_bridge;
|
||
|
||
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 '目标区域',
|
||
tenant_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='跨区域事件投递尝试记录';
|
||
|
||
-- Upgrade an existing bridge_inbox without replacing payload JSON or other rows.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND column_name='lease_owner'), 'SELECT 1', 'ALTER TABLE bridge_inbox ADD COLUMN lease_owner VARCHAR(128) NULL COMMENT ''消费租约持有者'' AFTER status'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 002
|
||
-- Warehouse locations, pallets, resource locks and UTF-8 descriptions
|
||
-- ============================================================================
|
||
|
||
CREATE DATABASE IF NOT EXISTS baiyue_lastlag_warehouse
|
||
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
USE baiyue_lastlag_warehouse;
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_location (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '库位ID(雪花ID)',
|
||
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
zone_code VARCHAR(50) NOT NULL COMMENT '仓库分区编码',
|
||
location_code VARCHAR(64) NOT NULL COMMENT '仓库内唯一库位编码',
|
||
location_type VARCHAR(32) NOT NULL COMMENT '库位类型',
|
||
max_load_kg DECIMAL(18,3) NOT NULL COMMENT '最大承重(千克)',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '库位状态:ACTIVE启用、INACTIVE停用',
|
||
remark VARCHAR(500) NULL COMMENT '备注',
|
||
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_location_code (tenant_id,warehouse_id,location_code,deleted),
|
||
KEY idx_location_query (tenant_id,warehouse_id,zone_code,status,deleted)
|
||
) ENGINE=InnoDB COMMENT='仓库库位表:按租户和仓库维护库位及承重信息';
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_pallet (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID(雪花ID)',
|
||
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
location_id BIGINT UNSIGNED NULL COMMENT '同仓库内绑定的库位ID,可为空',
|
||
pallet_code VARCHAR(128) NOT NULL COMMENT '仓库内唯一托盘编码',
|
||
pallet_type VARCHAR(32) NOT NULL COMMENT '托盘类型',
|
||
capacity_cbm DECIMAL(18,4) NOT NULL DEFAULT 2.0000 COMMENT '托盘容量(立方米)',
|
||
unit_price DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '托盘单价',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'IDLE' COMMENT '托盘状态:IDLE闲置、OCCUPIED占用、SCRAPPED废弃',
|
||
remark VARCHAR(500) NULL COMMENT '备注',
|
||
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_pallet_code (tenant_id,warehouse_id,pallet_code,deleted),
|
||
KEY idx_pallet_query (tenant_id,warehouse_id,status,deleted),
|
||
KEY idx_pallet_location (tenant_id,warehouse_id,location_id,deleted)
|
||
) ENGINE=InnoDB COMMENT='仓库托盘表:按租户和仓库维护托盘、容量、单价及状态';
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_resource_lock (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '资源锁ID(雪花ID)',
|
||
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
pallet_id BIGINT UNSIGNED NOT NULL COMMENT '锁定的托盘ID',
|
||
location_id BIGINT UNSIGNED NOT NULL COMMENT '锁定的库位ID',
|
||
business_type VARCHAR(50) NOT NULL COMMENT '调用方业务类型',
|
||
business_id VARCHAR(100) NOT NULL COMMENT '调用方业务标识',
|
||
reservation_key VARCHAR(160) NOT NULL COMMENT '调用方资源预留幂等键',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '资源锁状态:ACTIVE有效、RELEASED释放、SCRAPPED报废',
|
||
locked_at DATETIME(3) NOT 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_resource_lock_reservation (tenant_id,reservation_key),
|
||
KEY idx_resource_lock_pallet (tenant_id,warehouse_id,pallet_id,status),
|
||
KEY idx_resource_lock_location (tenant_id,warehouse_id,location_id,status),
|
||
KEY idx_resource_lock_business (tenant_id,business_type,business_id)
|
||
) ENGINE=InnoDB COMMENT='仓库托盘与库位资源锁表:支持跨服务幂等预留和释放';
|
||
|
||
-- Fix legacy mojibake/English descriptions without changing row values.
|
||
ALTER TABLE wh_location COMMENT='仓库库位表:按租户和仓库维护库位及承重信息';
|
||
ALTER TABLE wh_location
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '库位ID(雪花ID)',
|
||
MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
MODIFY COLUMN warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
MODIFY COLUMN zone_code VARCHAR(50) NOT NULL COMMENT '仓库分区编码',
|
||
MODIFY COLUMN location_code VARCHAR(64) NOT NULL COMMENT '仓库内唯一库位编码',
|
||
MODIFY COLUMN location_type VARCHAR(32) NOT NULL COMMENT '库位类型',
|
||
MODIFY COLUMN max_load_kg DECIMAL(18,3) NOT NULL COMMENT '最大承重(千克)',
|
||
MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '库位状态:ACTIVE启用、INACTIVE停用',
|
||
MODIFY COLUMN remark VARCHAR(500) NULL COMMENT '备注',
|
||
MODIFY COLUMN created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
|
||
MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
MODIFY COLUMN updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
|
||
MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
MODIFY COLUMN deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
|
||
MODIFY COLUMN version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号';
|
||
|
||
ALTER TABLE wh_pallet COMMENT='仓库托盘表:按租户和仓库维护托盘、容量、单价及状态';
|
||
ALTER TABLE wh_pallet
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID(雪花ID)',
|
||
MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
MODIFY COLUMN warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
MODIFY COLUMN location_id BIGINT UNSIGNED NULL COMMENT '同仓库内绑定的库位ID,可为空',
|
||
MODIFY COLUMN pallet_code VARCHAR(128) NOT NULL COMMENT '仓库内唯一托盘编码',
|
||
MODIFY COLUMN pallet_type VARCHAR(32) NOT NULL COMMENT '托盘类型',
|
||
MODIFY COLUMN capacity_cbm DECIMAL(18,4) NOT NULL DEFAULT 2.0000 COMMENT '托盘容量(立方米)',
|
||
MODIFY COLUMN unit_price DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '托盘单价',
|
||
MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'IDLE' COMMENT '托盘状态:IDLE闲置、OCCUPIED占用、SCRAPPED废弃',
|
||
MODIFY COLUMN remark VARCHAR(500) NULL COMMENT '备注',
|
||
MODIFY COLUMN created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
|
||
MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
MODIFY COLUMN updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
|
||
MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
MODIFY COLUMN deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
|
||
MODIFY COLUMN version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号';
|
||
|
||
ALTER TABLE wh_resource_lock COMMENT='仓库托盘与库位资源锁表:支持跨服务幂等预留和释放';
|
||
ALTER TABLE wh_resource_lock
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '资源锁ID(雪花ID)',
|
||
MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
MODIFY COLUMN warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID',
|
||
MODIFY COLUMN pallet_id BIGINT UNSIGNED NOT NULL COMMENT '锁定的托盘ID',
|
||
MODIFY COLUMN location_id BIGINT UNSIGNED NOT NULL COMMENT '锁定的库位ID',
|
||
MODIFY COLUMN business_type VARCHAR(50) NOT NULL COMMENT '调用方业务类型',
|
||
MODIFY COLUMN business_id VARCHAR(100) NOT NULL COMMENT '调用方业务标识',
|
||
MODIFY COLUMN reservation_key VARCHAR(160) NOT NULL COMMENT '调用方资源预留幂等键',
|
||
MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '资源锁状态:ACTIVE有效、RELEASED释放、SCRAPPED报废',
|
||
MODIFY COLUMN locked_at DATETIME(3) NOT NULL COMMENT '锁定时间',
|
||
MODIFY COLUMN released_at DATETIME(3) NULL COMMENT '释放或报废时间',
|
||
MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间';
|
||
|
||
-- Guard every operational index for existing installations.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_location' AND index_name='uk_location_code'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_location_code ON wh_location(tenant_id,warehouse_id,location_code,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_location' AND index_name='idx_location_query'), 'SELECT 1', 'CREATE INDEX idx_location_query ON wh_location(tenant_id,warehouse_id,zone_code,status,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_pallet' AND index_name='uk_pallet_code'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_pallet_code ON wh_pallet(tenant_id,warehouse_id,pallet_code,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_pallet' AND index_name='idx_pallet_query'), 'SELECT 1', 'CREATE INDEX idx_pallet_query ON wh_pallet(tenant_id,warehouse_id,status,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_pallet' AND index_name='idx_pallet_location'), 'SELECT 1', 'CREATE INDEX idx_pallet_location ON wh_pallet(tenant_id,warehouse_id,location_id,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_resource_lock' AND index_name='uk_resource_lock_reservation'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_resource_lock_reservation ON wh_resource_lock(tenant_id,reservation_key)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_resource_lock' AND index_name='idx_resource_lock_pallet'), 'SELECT 1', 'CREATE INDEX idx_resource_lock_pallet ON wh_resource_lock(tenant_id,warehouse_id,pallet_id,status)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_resource_lock' AND index_name='idx_resource_lock_location'), 'SELECT 1', 'CREATE INDEX idx_resource_lock_location ON wh_resource_lock(tenant_id,warehouse_id,location_id,status)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_resource_lock' AND index_name='idx_resource_lock_business'), 'SELECT 1', 'CREATE INDEX idx_resource_lock_business ON wh_resource_lock(tenant_id,business_type,business_id)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 003
|
||
-- Last-leg inbound plan, pallet allocation and PDA workflow
|
||
-- ============================================================================
|
||
|
||
CREATE DATABASE IF NOT EXISTS baiyue_lastleg
|
||
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_plan (
|
||
id BIGINT NOT NULL COMMENT '入库计划ID(雪花ID)',
|
||
plan_no VARCHAR(32) NOT NULL COMMENT '入库单号',
|
||
tenant_id VARCHAR(128) NOT NULL COMMENT '租户/客户账号标识',
|
||
container_no VARCHAR(64) NOT NULL COMMENT '实际集装箱号',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING_ASSIGNMENT' COMMENT '入库计划状态',
|
||
line_count INT NOT NULL DEFAULT 0 COMMENT '入仓码明细数量',
|
||
pallet_count INT NOT NULL DEFAULT 0 COMMENT '系统自动分配托盘数量',
|
||
total_volume_cbm DECIMAL(18,4) 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_inbound_plan_no (plan_no),
|
||
UNIQUE KEY uk_ll_inbound_plan_container (tenant_id,container_no)
|
||
) ENGINE=InnoDB COMMENT='尾程入库计划表:每个租户的每个集装箱生成一张入库单';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_plan_line (
|
||
id BIGINT NOT NULL COMMENT '入库计划明细ID(雪花ID)',
|
||
plan_id BIGINT NOT NULL COMMENT '入库计划ID',
|
||
order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||
inbound_code 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 '目的仓名称快照',
|
||
volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '入仓码体积(立方米)',
|
||
planned_pallet_count INT NOT NULL DEFAULT 0 COMMENT '该明细分配的托盘数量',
|
||
required_package_count INT NOT NULL DEFAULT 0 COMMENT '计划应收箱数',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_inbound_line_order (plan_id,order_id),
|
||
KEY idx_ll_inbound_line_plan (plan_id)
|
||
) ENGINE=InnoDB COMMENT='尾程入库计划明细表:按入仓码和尾程订单维度记录';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_plan_pallet (
|
||
id BIGINT NOT NULL COMMENT '计划托盘ID(雪花ID)',
|
||
plan_id BIGINT NOT NULL COMMENT '入库计划ID',
|
||
pallet_no VARCHAR(64) 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 '目的仓名称快照',
|
||
capacity_cbm DECIMAL(18,4) NOT NULL DEFAULT 2.0000 COMMENT '托盘容量(立方米)',
|
||
allocated_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '已分配体积(立方米)',
|
||
sequence_no INT NOT NULL COMMENT '计划内托盘序号',
|
||
warehouse_pallet_id BIGINT NULL COMMENT '仓库托盘ID',
|
||
warehouse_location_id BIGINT NULL COMMENT '仓库库位ID',
|
||
warehouse_resource_lock_id BIGINT NULL COMMENT '仓库资源锁ID',
|
||
assignment_status VARCHAR(32) NOT NULL DEFAULT 'UNASSIGNED' COMMENT '仓库资源分配状态',
|
||
locked_at DATETIME(3) NULL COMMENT '资源锁定时间',
|
||
actual_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '实际入托体积(立方米)',
|
||
actual_package_count INT NOT NULL DEFAULT 0 COMMENT '实际入托箱数',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_inbound_pallet_no (pallet_no),
|
||
UNIQUE KEY uk_ll_inbound_pallet_sequence (plan_id,sequence_no),
|
||
KEY idx_ll_inbound_pallet_plan (plan_id)
|
||
) ENGINE=InnoDB COMMENT='尾程入库计划托盘表:按目的仓隔离合托';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_plan_pallet_allocation (
|
||
id BIGINT NOT NULL COMMENT '托盘分配记录ID(雪花ID)',
|
||
plan_id BIGINT NOT NULL COMMENT '入库计划ID',
|
||
line_id BIGINT NOT NULL COMMENT '入库计划明细ID',
|
||
pallet_id BIGINT NOT NULL COMMENT '计划托盘ID',
|
||
allocated_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '计划分配体积(立方米)',
|
||
planned_package_count INT NOT NULL DEFAULT 0 COMMENT '计划分配箱数',
|
||
counted_package_count INT NOT NULL DEFAULT 0 COMMENT '清点箱数',
|
||
picked_package_count INT NOT NULL DEFAULT 0 COMMENT '上架箱数',
|
||
actual_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '实际分配体积(立方米)',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING_COUNT' COMMENT 'PDA作业状态',
|
||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_inbound_allocation (line_id,pallet_id),
|
||
KEY idx_ll_inbound_allocation_plan (plan_id),
|
||
KEY idx_ll_inbound_allocation_pallet (pallet_id)
|
||
) ENGINE=InnoDB COMMENT='尾程入库计划托盘分配表:记录入仓码明细与计划托盘的分配关系';
|
||
|
||
-- Columns introduced after the initial inbound-plan release.
|
||
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='required_package_count'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_line ADD COLUMN required_package_count INT NOT NULL DEFAULT 0 COMMENT ''计划应收箱数'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='warehouse_pallet_id'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN warehouse_pallet_id BIGINT NULL COMMENT ''仓库托盘ID'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='warehouse_location_id'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN warehouse_location_id BIGINT NULL COMMENT ''仓库库位ID'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='warehouse_resource_lock_id'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN warehouse_resource_lock_id BIGINT NULL COMMENT ''仓库资源锁ID'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='assignment_status'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN assignment_status VARCHAR(32) NOT NULL DEFAULT ''UNASSIGNED'' COMMENT ''仓库资源分配状态'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='locked_at'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN locked_at DATETIME(3) NULL COMMENT ''资源锁定时间'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='actual_volume_cbm'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN actual_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''实际入托体积(立方米)'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='actual_package_count'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet ADD COLUMN actual_package_count INT NOT NULL DEFAULT 0 COMMENT ''实际入托箱数'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='planned_package_count'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN planned_package_count INT NOT NULL DEFAULT 0 COMMENT ''计划分配箱数'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='counted_package_count'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN counted_package_count INT NOT NULL DEFAULT 0 COMMENT ''清点箱数'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='picked_package_count'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 COMMENT ''上架箱数'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='actual_volume_cbm'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN actual_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''实际分配体积(立方米)'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='status'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN status VARCHAR(32) NOT NULL DEFAULT ''PENDING_COUNT'' COMMENT ''PDA作业状态'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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='version'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_pallet_allocation ADD COLUMN version INT NOT NULL DEFAULT 0 COMMENT ''乐观锁版本号'''));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_pda_task (
|
||
id BIGINT NOT NULL COMMENT 'PDA任务ID', tenant_id VARCHAR(128) NOT NULL COMMENT '租户ID',
|
||
plan_id BIGINT NOT NULL COMMENT '入库计划ID', task_no VARCHAR(64) NOT NULL COMMENT 'PDA任务号',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态', operator_id VARCHAR(128) NULL COMMENT '操作人ID',
|
||
operator_name VARCHAR(255) NULL COMMENT '操作人名称', pushed_at DATETIME(3) NULL COMMENT '推送时间',
|
||
started_at DATETIME(3) NULL COMMENT '开始时间', completed_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_inbound_pda_task_plan (tenant_id,plan_id),
|
||
UNIQUE KEY uk_ll_inbound_pda_task_no (task_no)
|
||
) ENGINE=InnoDB COMMENT='尾程入库PDA任务表';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_pda_operation (
|
||
id BIGINT NOT NULL COMMENT 'PDA操作记录ID', tenant_id VARCHAR(128) NOT NULL COMMENT '租户ID',
|
||
task_id BIGINT NOT NULL COMMENT 'PDA任务ID', allocation_id BIGINT NULL COMMENT '托盘分配记录ID',
|
||
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 '请求JSON',
|
||
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_inbound_pda_operation_key (tenant_id,idempotency_key),
|
||
KEY idx_ll_inbound_pda_operation_task (task_id), KEY idx_ll_inbound_pda_operation_allocation (allocation_id)
|
||
) ENGINE=InnoDB COMMENT='尾程入库PDA幂等操作记录';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_pallet_merge (
|
||
id BIGINT NOT NULL COMMENT '合托记录ID', tenant_id VARCHAR(128) NOT NULL COMMENT '租户ID',
|
||
task_id BIGINT NOT NULL COMMENT 'PDA任务ID', merge_group_no VARCHAR(64) NOT NULL COMMENT '合托组号',
|
||
source_pallet_id BIGINT NOT NULL COMMENT '来源托盘ID', target_pallet_id BIGINT NOT NULL COMMENT '目标托盘ID',
|
||
source_allocation_id BIGINT NOT NULL COMMENT '来源分配ID', target_allocation_id BIGINT NOT NULL COMMENT '目标分配ID',
|
||
source_line_id BIGINT NOT NULL COMMENT '来源计划明细ID', target_line_id BIGINT NOT NULL COMMENT '目标计划明细ID',
|
||
source_order_id BIGINT NOT NULL COMMENT '来源订单ID', target_order_id BIGINT NOT NULL COMMENT '目标订单ID',
|
||
moved_package_count INT NOT NULL COMMENT '移动箱数', moved_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '移动体积(立方米)',
|
||
source_pallet_scrapped TINYINT NOT NULL DEFAULT 0 COMMENT '来源托盘是否报废', status VARCHAR(32) NOT NULL COMMENT '合托状态',
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY (id),
|
||
KEY idx_ll_inbound_merge_task (tenant_id,task_id), KEY idx_ll_inbound_merge_group (merge_group_no)
|
||
) ENGINE=InnoDB COMMENT='尾程入库PDA合托记录';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 004
|
||
-- Upgrade an existing Event Bridge inbox with retry/lease fields and indexes
|
||
-- ============================================================================
|
||
USE baiyue_event_bridge;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND column_name='lease_until'), 'SELECT 1', 'ALTER TABLE bridge_inbox ADD COLUMN lease_until DATETIME(3) NULL COMMENT ''消费租约截止时间'' AFTER lease_owner'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND column_name='retry_count'), 'SELECT 1', 'ALTER TABLE bridge_inbox ADD COLUMN retry_count INT NOT NULL DEFAULT 0 COMMENT ''消费重试次数'' AFTER lease_until'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND column_name='next_retry_at'), 'SELECT 1', 'ALTER TABLE bridge_inbox ADD COLUMN next_retry_at DATETIME(3) NULL COMMENT ''下次消费时间'' AFTER retry_count'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND column_name='last_error'), 'SELECT 1', 'ALTER TABLE bridge_inbox ADD COLUMN last_error VARCHAR(1000) NULL COMMENT ''最后错误'' AFTER next_retry_at'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND index_name='idx_bridge_inbox_consume'), 'SELECT 1', 'CREATE INDEX idx_bridge_inbox_consume ON bridge_inbox(status,next_retry_at,lease_until)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='bridge_inbox' AND index_name='uk_bridge_inbox_idempotency'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_bridge_inbox_idempotency ON bridge_inbox(idempotency_key)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 005
|
||
-- FirstLegLoadingPlanCompleted -> last-leg order projection
|
||
-- ============================================================================
|
||
|
||
CREATE DATABASE IF NOT EXISTS baiyue_lastleg
|
||
DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_loading_event_inbox (
|
||
event_id VARCHAR(128) NOT NULL COMMENT '事件全局唯一标识',
|
||
tenant_id VARCHAR(128) NOT NULL COMMENT '租户/客户账号标识',
|
||
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
|
||
event_version INT NOT NULL COMMENT '事件契约版本',
|
||
payload_hash VARCHAR(71) NOT NULL COMMENT '规范化事件负载SHA-256摘要',
|
||
payload_json JSON NOT NULL COMMENT '事件冻结负载JSON',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'RECEIVED' COMMENT '消费状态:RECEIVED/PROCESSED',
|
||
received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '接收时间',
|
||
processed_at DATETIME(3) NULL COMMENT '处理完成时间',
|
||
last_error VARCHAR(1000) NULL COMMENT '最近一次处理错误',
|
||
PRIMARY KEY (event_id),
|
||
UNIQUE KEY uk_ll_loading_inbox_tenant_key (tenant_id,event_type,event_id)
|
||
) ENGINE=InnoDB COMMENT='头程装柜完成事件接收幂等箱';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_order (
|
||
id BIGINT NOT NULL COMMENT '雪花ID',
|
||
order_no VARCHAR(32) NOT NULL COMMENT '尾程单号,同柜入仓单共享',
|
||
tenant_id VARCHAR(128) NOT NULL COMMENT '租户/客户账号标识',
|
||
order_type VARCHAR(32) NOT NULL DEFAULT 'FIRST_LEG' COMMENT '订单类型',
|
||
inbound_code VARCHAR(128) NOT NULL COMMENT '入仓码',
|
||
source_region VARCHAR(32) NOT NULL COMMENT '来源区域/系统',
|
||
source_inbound_id VARCHAR(128) NOT NULL COMMENT '最终实装LOADED分片ID,建单幂等键',
|
||
root_inbound_id VARCHAR(128) NULL COMMENT '根入仓单ID',
|
||
source_order_id VARCHAR(128) NULL COMMENT '来源订单ID',
|
||
source_order_no VARCHAR(128) NULL COMMENT '来源订单号',
|
||
root_order_id VARCHAR(128) NULL COMMENT '根订单ID',
|
||
customer_name VARCHAR(255) NULL COMMENT '货主名称',
|
||
overseas_warehouse_id VARCHAR(128) NULL COMMENT '海外仓ID',
|
||
overseas_warehouse_name VARCHAR(255) NULL COMMENT '海外仓名称',
|
||
transfer_warehouse_id VARCHAR(128) NULL COMMENT '转入目的仓ID',
|
||
transfer_warehouse_code VARCHAR(128) NULL COMMENT '转入目的仓编码',
|
||
transfer_warehouse_name VARCHAR(255) NULL COMMENT '转入目的仓名称',
|
||
fba_warehouse_code VARCHAR(128) NULL COMMENT 'FBA仓库编码',
|
||
container_no VARCHAR(64) NULL COMMENT '实际集装箱号',
|
||
container_status VARCHAR(32) NULL DEFAULT '待转柜' COMMENT '货柜状态',
|
||
abnormal TINYINT NOT NULL DEFAULT 0 COMMENT '是否异常:0否1是',
|
||
detained TINYINT NOT NULL DEFAULT 0 COMMENT '是否暂扣:0否1是',
|
||
pallet_count INT NOT NULL DEFAULT 0 COMMENT '托数',
|
||
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数',
|
||
volume_cbm DECIMAL(18,4) NULL COMMENT '体积(立方米)',
|
||
product_quantity INT NULL COMMENT '货物数量',
|
||
volume_weight_kg DECIMAL(18,4) NULL COMMENT '体积重量(千克)',
|
||
estimated_arrival_at DATETIME(3) NULL COMMENT '预计到港时间',
|
||
actual_arrival_at DATETIME(3) NULL COMMENT '实际到港时间',
|
||
estimated_warehouse_at DATETIME(3) NULL COMMENT '预计到仓时间',
|
||
inbound_order_no VARCHAR(128) NULL COMMENT '入库单号',
|
||
outbound_order_no VARCHAR(128) NULL COMMENT '出库单号',
|
||
delivery_order_no VARCHAR(128) NULL COMMENT '派送单号',
|
||
relabel_order_no VARCHAR(128) NULL COMMENT '换标单号',
|
||
relabel_status VARCHAR(32) NULL COMMENT '换标状态',
|
||
pallet_merge_flag VARCHAR(32) NULL COMMENT '合托标记',
|
||
current_status VARCHAR(32) NOT NULL DEFAULT 'PENDING_ASSIGNMENT' COMMENT '当前业务状态',
|
||
private_remark VARCHAR(1000) NULL COMMENT '备注(仅自己)',
|
||
customer_remark VARCHAR(1000) NULL COMMENT '备注(客户)',
|
||
warehouse_remark VARCHAR(1000) NULL COMMENT '备注(仓库)',
|
||
source_event_id VARCHAR(128) NOT NULL COMMENT '来源事件ID',
|
||
source_loading_plan_id VARCHAR(128) NOT NULL COMMENT '来源装柜计划ID',
|
||
source_loading_plan_version BIGINT NULL COMMENT '来源装柜计划版本',
|
||
source_handover_version BIGINT NULL COMMENT '交接版本',
|
||
source_payload_hash VARCHAR(71) 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_order_source (tenant_id,source_region,source_inbound_id),
|
||
KEY idx_ll_order_group (tenant_id,order_no),
|
||
KEY idx_ll_order_list (tenant_id,current_status,created_at)
|
||
) ENGINE=InnoDB COMMENT='尾程订单主表';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_order_detail (
|
||
id BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单明细主键',
|
||
order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||
source_inbound_detail_id VARCHAR(128) NOT NULL COMMENT '来源入仓明细ID',
|
||
sku_code VARCHAR(128) NULL COMMENT 'SKU编码',
|
||
product_name_zh VARCHAR(255) NULL COMMENT '中文品名',
|
||
product_name_en VARCHAR(255) NULL COMMENT '英文品名',
|
||
package_count INT NOT NULL DEFAULT 0 COMMENT '箱数',
|
||
product_quantity INT NULL COMMENT '数量',
|
||
pallet_count INT NULL COMMENT '托数',
|
||
gross_weight_kg DECIMAL(18,4) NULL COMMENT '毛重(千克)',
|
||
net_weight_kg DECIMAL(18,4) NULL COMMENT '净重(千克)',
|
||
dimensional_weight_kg DECIMAL(18,4) NULL COMMENT '体积重量(千克)',
|
||
volume_cbm DECIMAL(18,4) 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_tracking_no VARCHAR(255) NULL COMMENT 'FBA跟踪号',
|
||
shipment_no VARCHAR(255) NULL COMMENT '货件编号',
|
||
shipping_mark VARCHAR(255) NULL COMMENT '唛头',
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_detail_source (order_id,source_inbound_detail_id),
|
||
KEY idx_ll_detail_order (order_id)
|
||
) ENGINE=InnoDB COMMENT='尾程订单实装商品冻结明细';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_loading_order_status_history (
|
||
id BIGINT NOT NULL AUTO_INCREMENT COMMENT '状态历史主键',
|
||
order_id BIGINT NOT NULL COMMENT '尾程订单ID',
|
||
from_status VARCHAR(32) NULL COMMENT '变更前状态',
|
||
to_status VARCHAR(32) NOT NULL COMMENT '变更后状态',
|
||
event_id VARCHAR(128) NULL COMMENT '触发事件ID',
|
||
remark VARCHAR(500) NULL COMMENT '状态变更备注',
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '记录时间',
|
||
PRIMARY KEY (id),
|
||
KEY idx_ll_loading_history_order (order_id,created_at)
|
||
) ENGINE=InnoDB COMMENT='尾程订单状态变更历史';
|
||
|
||
-- Existing order installations: add transfer fields without replacing row data.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='transfer_warehouse_id'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN transfer_warehouse_id VARCHAR(128) NULL COMMENT ''转入目的仓ID'' AFTER overseas_warehouse_name'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='transfer_warehouse_code'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN transfer_warehouse_code VARCHAR(128) NULL COMMENT ''转入目的仓编码'' AFTER transfer_warehouse_id'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='transfer_warehouse_name'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN transfer_warehouse_name VARCHAR(255) NULL COMMENT ''转入目的仓名称'' AFTER transfer_warehouse_code'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- One container/loading-plan number groups multiple inbound-code rows, so order_no
|
||
-- must not be unique. Source inbound identity remains uniquely constrained.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_order' AND index_name='uk_ll_order_no' AND non_unique=0), 'ALTER TABLE ll_order DROP INDEX uk_ll_order_no', 'SELECT 1'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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_group'), 'SELECT 1', 'CREATE INDEX idx_ll_order_group ON ll_order(tenant_id,order_no)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_order' AND index_name='uk_ll_order_source'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_ll_order_source ON ll_order(tenant_id,source_region,source_inbound_id)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_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_list'), 'SELECT 1', 'CREATE INDEX idx_ll_order_list ON ll_order(tenant_id,current_status,created_at)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_loading_event_inbox' AND index_name='uk_ll_loading_inbox_tenant_key'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_ll_loading_inbox_tenant_key ON ll_loading_event_inbox(tenant_id,event_type,event_id)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-15 / 006
|
||
-- Warehouse master-data descriptions and query indexes
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastlag_warehouse;
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_warehouse (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID(雪花ID)', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓库所属租户ID',
|
||
warehouse_code VARCHAR(50) NOT NULL COMMENT '租户内唯一仓库编码', warehouse_name VARCHAR(120) NOT NULL COMMENT '仓库名称',
|
||
warehouse_type VARCHAR(32) NOT NULL DEFAULT 'OVERSEAS' COMMENT '仓库类型', country_code CHAR(2) NOT NULL COMMENT '所在国家二字码',
|
||
timezone VARCHAR(64) NOT NULL COMMENT '仓库所在地IANA时区', contact_name VARCHAR(64) NULL COMMENT '仓库联系人',
|
||
contact_phone VARCHAR(32) NULL COMMENT '联系电话', contact_email VARCHAR(128) NULL COMMENT '联系邮箱',
|
||
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '仓库状态', remark VARCHAR(500) NULL COMMENT '仓库备注',
|
||
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id), UNIQUE KEY uk_wh_tenant_code (tenant_id,warehouse_code,deleted),
|
||
KEY idx_wh_tenant_status (tenant_id,status,deleted), KEY idx_wh_country (tenant_id,country_code,deleted)
|
||
) ENGINE=InnoDB COMMENT='仓库主数据表:以租户为边界维护仓库编码、名称、国家、时区和启停状态';
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_warehouse_address (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '仓库地址ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', address_type VARCHAR(20) NOT NULL DEFAULT 'OPERATING' COMMENT '地址类型:OPERATING运营、RETURN退货',
|
||
country_code CHAR(2) NOT NULL COMMENT '国家二字码', state_province VARCHAR(100) NULL COMMENT '省或州',
|
||
city VARCHAR(100) NOT NULL COMMENT '城市', district VARCHAR(100) NULL COMMENT '区县', postal_code VARCHAR(20) NULL COMMENT '邮政编码',
|
||
address_line1 VARCHAR(255) NOT NULL COMMENT '主地址行', address_line2 VARCHAR(255) NULL COMMENT '补充地址行',
|
||
latitude DECIMAL(10,7) NULL COMMENT '纬度', longitude DECIMAL(10,7) NULL COMMENT '经度',
|
||
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id), UNIQUE KEY uk_address_type (tenant_id,warehouse_id,address_type,deleted),
|
||
KEY idx_address_warehouse (tenant_id,warehouse_id,deleted)
|
||
) ENGINE=InnoDB COMMENT='仓库地址表:保存运营、退货等不同用途的地址及可选经纬度';
|
||
|
||
CREATE TABLE IF NOT EXISTS wh_service_capability (
|
||
id BIGINT UNSIGNED NOT NULL COMMENT '服务能力ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', capability_code VARCHAR(50) NOT NULL COMMENT '能力编码',
|
||
capability_name VARCHAR(100) NOT NULL COMMENT '能力名称', enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
|
||
cutoff_time TIME NULL COMMENT '当日作业截单时间', description VARCHAR(500) NULL COMMENT '能力说明',
|
||
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||
PRIMARY KEY (id), UNIQUE KEY uk_capability (tenant_id,warehouse_id,capability_code,deleted),
|
||
KEY idx_capability_query (tenant_id,warehouse_id,enabled,deleted)
|
||
) ENGINE=InnoDB COMMENT='仓库服务能力表:声明仓库可提供的收货、仓储、拣包、退货等能力及截单时间';
|
||
|
||
ALTER TABLE wh_warehouse COMMENT='仓库主数据表:以租户为边界维护仓库编码、名称、国家、时区和启停状态';
|
||
ALTER TABLE wh_warehouse
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID(雪花ID)', MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓库所属租户ID',
|
||
MODIFY COLUMN warehouse_code VARCHAR(50) NOT NULL COMMENT '租户内唯一仓库编码', MODIFY COLUMN warehouse_name VARCHAR(120) NOT NULL COMMENT '仓库名称',
|
||
MODIFY COLUMN warehouse_type VARCHAR(32) NOT NULL DEFAULT 'OVERSEAS' COMMENT '仓库类型', MODIFY COLUMN country_code CHAR(2) NOT NULL COMMENT '所在国家二字码',
|
||
MODIFY COLUMN timezone VARCHAR(64) NOT NULL COMMENT '仓库所在地IANA时区', MODIFY COLUMN contact_name VARCHAR(64) NULL COMMENT '仓库联系人',
|
||
MODIFY COLUMN contact_phone VARCHAR(32) NULL COMMENT '联系电话', MODIFY COLUMN contact_email VARCHAR(128) NULL COMMENT '联系邮箱',
|
||
MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '仓库状态', MODIFY COLUMN remark VARCHAR(500) NULL COMMENT '仓库备注',
|
||
MODIFY COLUMN created_by BIGINT UNSIGNED NULL COMMENT '创建人ID', MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
MODIFY COLUMN updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID', MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
MODIFY COLUMN deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', MODIFY COLUMN version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号';
|
||
|
||
ALTER TABLE wh_warehouse_address COMMENT='仓库地址表:保存运营、退货等不同用途的地址及可选经纬度';
|
||
ALTER TABLE wh_warehouse_address
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '仓库地址ID', MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
MODIFY COLUMN warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', MODIFY COLUMN address_type VARCHAR(20) NOT NULL DEFAULT 'OPERATING' COMMENT '地址类型:OPERATING运营、RETURN退货',
|
||
MODIFY COLUMN country_code CHAR(2) NOT NULL COMMENT '国家二字码', MODIFY COLUMN state_province VARCHAR(100) NULL COMMENT '省或州',
|
||
MODIFY COLUMN city VARCHAR(100) NOT NULL COMMENT '城市', MODIFY COLUMN district VARCHAR(100) NULL COMMENT '区县',
|
||
MODIFY COLUMN postal_code VARCHAR(20) NULL COMMENT '邮政编码', MODIFY COLUMN address_line1 VARCHAR(255) NOT NULL COMMENT '主地址行',
|
||
MODIFY COLUMN address_line2 VARCHAR(255) NULL COMMENT '补充地址行', MODIFY COLUMN latitude DECIMAL(10,7) NULL COMMENT '纬度',
|
||
MODIFY COLUMN longitude DECIMAL(10,7) NULL COMMENT '经度', MODIFY COLUMN created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
|
||
MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', MODIFY COLUMN updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
|
||
MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
MODIFY COLUMN deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', MODIFY COLUMN version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号';
|
||
|
||
ALTER TABLE wh_service_capability COMMENT='仓库服务能力表:声明仓库可提供的收货、仓储、拣包、退货等能力及截单时间';
|
||
ALTER TABLE wh_service_capability
|
||
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '服务能力ID', MODIFY COLUMN tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID',
|
||
MODIFY COLUMN warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', MODIFY COLUMN capability_code VARCHAR(50) NOT NULL COMMENT '能力编码:RECEIVING收货、STORAGE仓储、PICK_PACK拣包、RETURN退货',
|
||
MODIFY COLUMN capability_name VARCHAR(100) NOT NULL COMMENT '能力名称', MODIFY COLUMN enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否启用',
|
||
MODIFY COLUMN cutoff_time TIME NULL COMMENT '当日作业截单时间', MODIFY COLUMN description VARCHAR(500) NULL COMMENT '能力说明',
|
||
MODIFY COLUMN created_by BIGINT UNSIGNED NULL COMMENT '创建人ID', MODIFY COLUMN created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||
MODIFY COLUMN updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID', MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||
MODIFY COLUMN deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', MODIFY COLUMN version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号';
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_warehouse' AND index_name='uk_wh_tenant_code'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_wh_tenant_code ON wh_warehouse(tenant_id,warehouse_code,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_warehouse' AND index_name='idx_wh_tenant_status'), 'SELECT 1', 'CREATE INDEX idx_wh_tenant_status ON wh_warehouse(tenant_id,status,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_warehouse' AND index_name='idx_wh_country'), 'SELECT 1', 'CREATE INDEX idx_wh_country ON wh_warehouse(tenant_id,country_code,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_warehouse_address' AND index_name='uk_address_type'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_address_type ON wh_warehouse_address(tenant_id,warehouse_id,address_type,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_warehouse_address' AND index_name='idx_address_warehouse'), 'SELECT 1', 'CREATE INDEX idx_address_warehouse ON wh_warehouse_address(tenant_id,warehouse_id,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_service_capability' AND index_name='uk_capability'), 'SELECT 1', 'CREATE UNIQUE INDEX uk_capability ON wh_service_capability(tenant_id,warehouse_id,capability_code,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='wh_service_capability' AND index_name='idx_capability_query'), 'SELECT 1', 'CREATE INDEX idx_capability_query ON wh_service_capability(tenant_id,warehouse_id,enabled,deleted)'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 007
|
||
-- Last-leg batch FBA appointments
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
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'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_line ADD COLUMN fba_warehouse_code VARCHAR(128) NULL AFTER inbound_code'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
UPDATE ll_inbound_plan_line l JOIN ll_order o ON o.id=l.order_id
|
||
SET l.fba_warehouse_code=o.fba_warehouse_code
|
||
WHERE l.fba_warehouse_code IS NULL AND o.fba_warehouse_code IS NOT NULL;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID',
|
||
tenant_id VARCHAR(128) NOT NULL,
|
||
appointment_no VARCHAR(64) NOT NULL,
|
||
appointment_at DATETIME(3) NOT NULL,
|
||
appointment_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
||
appointment_remark VARCHAR(1000) NULL,
|
||
fba_warehouse_code VARCHAR(128) NOT NULL,
|
||
selected_count INT NOT NULL DEFAULT 0,
|
||
created_by VARCHAR(128) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_fba_appointment_no (tenant_id, appointment_no),
|
||
KEY idx_ll_fba_appointment_list (tenant_id, appointment_status, fba_warehouse_code, created_at)
|
||
) ENGINE=InnoDB COMMENT='Batch FBA appointment';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment_item (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID',
|
||
appointment_id BIGINT NOT NULL,
|
||
plan_id BIGINT NOT NULL,
|
||
line_id BIGINT NOT NULL,
|
||
order_id BIGINT NOT NULL,
|
||
inbound_code VARCHAR(128) NOT NULL,
|
||
fba_warehouse_code VARCHAR(128) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_fba_appointment_item_line (appointment_id, line_id),
|
||
KEY idx_ll_fba_appointment_item_plan (plan_id),
|
||
KEY idx_ll_fba_appointment_item_order (order_id)
|
||
) ENGINE=InnoDB COMMENT='FBA appointment line snapshot';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 008
|
||
-- Last-leg inbound-order/package inventory balances, positions and immutable ledger
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inventory_balance (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL, customer_name VARCHAR(255) NULL,
|
||
overseas_warehouse_id VARCHAR(128) NOT NULL, overseas_warehouse_code VARCHAR(128) NULL,
|
||
overseas_warehouse_name VARCHAR(255) NULL, destination_warehouse_id VARCHAR(128) NULL,
|
||
destination_warehouse_code VARCHAR(128) NOT NULL DEFAULT '', destination_warehouse_name VARCHAR(255) NULL,
|
||
inbound_order_id BIGINT NOT NULL, inbound_order_no VARCHAR(128) NULL, inbound_code VARCHAR(128) NOT NULL,
|
||
available_packages BIGINT NOT NULL DEFAULT 0, hold_packages BIGINT NOT NULL DEFAULT 0,
|
||
allocated_packages BIGINT NOT NULL DEFAULT 0, picked_packages BIGINT NOT NULL DEFAULT 0,
|
||
in_transit_packages BIGINT NOT NULL DEFAULT 0, receiving_packages BIGINT NOT NULL DEFAULT 0,
|
||
procurement_packages BIGINT NOT NULL DEFAULT 0, version BIGINT NOT NULL DEFAULT 0,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_inventory_dimension (tenant_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code),
|
||
KEY idx_ll_inventory_list (tenant_id,overseas_warehouse_id,updated_at),
|
||
KEY idx_ll_inventory_inbound (tenant_id,inbound_code)
|
||
) ENGINE=InnoDB COMMENT='Real-time inbound-order package inventory balance';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inventory_position (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL, balance_id BIGINT NOT NULL,
|
||
overseas_warehouse_id VARCHAR(128) NOT NULL, destination_warehouse_code VARCHAR(128) NOT NULL DEFAULT '',
|
||
pallet_id BIGINT NOT NULL, pallet_no VARCHAR(64) NOT NULL,
|
||
batch_no VARCHAR(128) NOT NULL DEFAULT '', warehouse_location_id BIGINT NULL,
|
||
warehouse_location_code VARCHAR(128) NOT NULL,
|
||
available_packages BIGINT NOT NULL DEFAULT 0, hold_packages BIGINT NOT NULL DEFAULT 0,
|
||
allocated_packages BIGINT NOT NULL DEFAULT 0, picked_packages BIGINT NOT NULL DEFAULT 0,
|
||
receiving_packages BIGINT NOT NULL DEFAULT 0,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', version BIGINT NOT NULL DEFAULT 0,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_inventory_position (balance_id,pallet_id,batch_no),
|
||
KEY idx_ll_inventory_position_pallet (tenant_id,pallet_id),
|
||
KEY idx_ll_inventory_position_location (tenant_id,overseas_warehouse_id,warehouse_location_code)
|
||
) ENGINE=InnoDB COMMENT='Inbound-order package stock by pallet, default location and batch';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inventory_ledger (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
balance_id BIGINT NOT NULL, position_id BIGINT NULL, overseas_warehouse_id VARCHAR(128) NOT NULL,
|
||
destination_warehouse_code VARCHAR(128) NOT NULL DEFAULT '', inbound_order_id BIGINT NOT NULL,
|
||
pallet_id BIGINT NULL, pallet_no VARCHAR(64) NULL, batch_no VARCHAR(128) NULL,
|
||
warehouse_location_code VARCHAR(128) NULL, business_type VARCHAR(32) NOT NULL,
|
||
business_order_id BIGINT NULL, business_order_no VARCHAR(128) NULL, inbound_code VARCHAR(128) NULL,
|
||
inbound_order_no VARCHAR(128) NULL, outbound_order_no VARCHAR(128) NULL,
|
||
source_event_id VARCHAR(128) NULL, idempotency_key VARCHAR(255) NOT NULL,
|
||
status_from VARCHAR(32) NULL, status_to VARCHAR(32) NULL,
|
||
before_packages BIGINT NOT NULL, delta_packages BIGINT NOT NULL, after_packages BIGINT NOT NULL,
|
||
operator_id VARCHAR(128) NULL, remark VARCHAR(1000) NULL,
|
||
occurred_at DATETIME(3) NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_inventory_ledger_idempotency (tenant_id,idempotency_key),
|
||
KEY idx_ll_inventory_ledger_query (tenant_id,overseas_warehouse_id,occurred_at),
|
||
KEY idx_ll_inventory_ledger_inbound (tenant_id,inbound_code,occurred_at),
|
||
KEY idx_ll_inventory_ledger_business (tenant_id,business_type,business_order_no)
|
||
) ENGINE=InnoDB COMMENT='Immutable inbound-order package inventory ledger';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inventory_operation (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
idempotency_key VARCHAR(255) NOT NULL, operation_type VARCHAR(32) NOT NULL,
|
||
request_hash VARCHAR(128) NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'PROCESSING',
|
||
result_json LONGTEXT NULL, last_error VARCHAR(2000) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_inventory_operation_key (tenant_id,idempotency_key),
|
||
KEY idx_ll_inventory_operation_status (tenant_id,status,updated_at)
|
||
) ENGINE=InnoDB COMMENT='Inventory command idempotency record';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 009
|
||
-- PDA SKU/pallet receipt snapshots for stock-in closure
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_inbound_stock_receipt (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
plan_id BIGINT NOT NULL, task_id BIGINT NOT NULL, allocation_id BIGINT NOT NULL,
|
||
line_id BIGINT NOT NULL, order_id BIGINT NOT NULL, inbound_code VARCHAR(128) NOT NULL,
|
||
sku_code VARCHAR(128) NOT NULL, sku_name_zh VARCHAR(255) NULL, source_detail_ids VARCHAR(2000) NULL,
|
||
warehouse_pallet_id BIGINT NOT NULL, pallet_no VARCHAR(64) NOT NULL,
|
||
warehouse_location_id BIGINT NULL, warehouse_location_code VARCHAR(128) NULL,
|
||
batch_no VARCHAR(128) NOT NULL, received_packages BIGINT NOT NULL, received_quantity BIGINT NOT NULL,
|
||
inventory_balance_id BIGINT NOT NULL, inventory_position_id BIGINT NOT NULL,
|
||
inventory_operation_key VARCHAR(255) NOT NULL, received_at DATETIME(3) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_stock_receipt_task_allocation_sku (tenant_id,task_id,allocation_id,sku_code),
|
||
KEY idx_ll_stock_receipt_plan (tenant_id,plan_id,line_id), KEY idx_ll_stock_receipt_inventory (inventory_balance_id,inventory_position_id)
|
||
) ENGINE=InnoDB COMMENT='Immutable SKU-pallet PDA stock-in receipt snapshot';
|
||
|
||
-- 2026-08-17 warehouse virtual location and generated pallet code support.
|
||
USE baiyue_lastlag_warehouse;
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE()
|
||
AND table_name='wh_pallet' AND column_name='pallet_code'),
|
||
'ALTER TABLE wh_pallet MODIFY COLUMN pallet_code VARCHAR(128) NOT NULL COMMENT ''Warehouse pallet code''', 'SELECT 1'));
|
||
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||
|
||
INSERT INTO wh_location (id, tenant_id, warehouse_id, zone_code, location_code, location_type,
|
||
max_load_kg, status, remark)
|
||
SELECT UUID_SHORT(), w.tenant_id, w.id, 'DEFAULT', CONCAT('LOC-', w.warehouse_code, '-DEFAULT'),
|
||
'VIRTUAL', 999999999.000, 'ACTIVE', 'System default virtual location'
|
||
FROM wh_warehouse w
|
||
WHERE NOT EXISTS (
|
||
SELECT 1 FROM wh_location l
|
||
WHERE l.tenant_id = w.tenant_id AND l.warehouse_id = w.id
|
||
AND l.location_code = CONCAT('LOC-', w.warehouse_code, '-DEFAULT') AND l.deleted = 0
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 010
|
||
-- Last-leg pre-dispatch orders and pallet locks
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_order (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
dispatch_no VARCHAR(64) NOT NULL, overseas_warehouse_id VARCHAR(128) NULL, overseas_warehouse_name VARCHAR(255) NULL,
|
||
vehicle_plate VARCHAR(64) NULL, driver_name VARCHAR(128) NULL,
|
||
driver_phone VARCHAR(64) NULL, carrier_name VARCHAR(255) NULL, route VARCHAR(255) NULL,
|
||
depart_at DATETIME(3) NULL, fba_appointment_no VARCHAR(64) NULL,
|
||
fba_appointment_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
||
vehicle_appointment_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
||
estimated_arrival_at DATETIME(3) NULL, status VARCHAR(32) NOT NULL DEFAULT 'PENDING_DEPARTURE',
|
||
item_count INT NOT NULL DEFAULT 0, pallet_count INT NOT NULL DEFAULT 0, package_count INT NOT NULL DEFAULT 0,
|
||
created_by VARCHAR(128) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_dispatch_order_no (tenant_id,dispatch_no),
|
||
KEY idx_ll_dispatch_order_list (tenant_id,status,depart_at), KEY idx_ll_dispatch_order_vehicle (tenant_id,vehicle_plate)
|
||
) ENGINE=InnoDB COMMENT='Last-leg pre-dispatch order';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_item (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', dispatch_order_id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL,
|
||
plan_id BIGINT NULL, plan_pallet_id BIGINT NULL, warehouse_pallet_id BIGINT NULL,
|
||
order_id BIGINT NULL, order_no VARCHAR(64) NULL, order_refs VARCHAR(2000) NULL, inbound_code VARCHAR(128) NULL, pallet_no VARCHAR(128) NOT NULL,
|
||
overseas_warehouse_id VARCHAR(128) NULL, overseas_warehouse_name VARCHAR(255) NULL,
|
||
destination_warehouse_id VARCHAR(128) NULL, destination_warehouse_code VARCHAR(128) NULL,
|
||
destination_warehouse_name VARCHAR(255) NULL, fba_warehouse_code VARCHAR(128) NULL,
|
||
package_count INT NOT NULL DEFAULT 0, volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0,
|
||
source_stage VARCHAR(32) NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
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 (tenant_id,order_id), KEY idx_ll_dispatch_item_inbound (tenant_id,inbound_code),
|
||
KEY idx_ll_dispatch_item_pallet (tenant_id,plan_pallet_id,warehouse_pallet_id)
|
||
) ENGINE=InnoDB COMMENT='Frozen pallet and cargo snapshot for a dispatch order';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_pallet_lock (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
source_pallet_key VARCHAR(160) NOT NULL, active_key VARCHAR(160) NULL,
|
||
plan_id BIGINT NULL, plan_pallet_id BIGINT NULL, warehouse_pallet_id BIGINT NULL,
|
||
dispatch_order_id BIGINT NOT NULL, status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE',
|
||
locked_at DATETIME(3) NOT NULL, released_at DATETIME(3) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_dispatch_active_pallet (tenant_id,active_key),
|
||
KEY idx_ll_dispatch_pallet_lock_order (tenant_id,dispatch_order_id,status),
|
||
KEY idx_ll_dispatch_pallet_lock_source (tenant_id,source_pallet_key,status)
|
||
) ENGINE=InnoDB COMMENT='Active dispatch pallet exclusion lock';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 011
|
||
-- Dispatch PDA task and immutable pallet pick operations
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_task (
|
||
id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL, dispatch_order_id BIGINT NOT NULL,
|
||
task_no VARCHAR(64) NOT NULL, status VARCHAR(32) NOT NULL, operator_id VARCHAR(128) NULL,
|
||
operator_name VARCHAR(128) NULL, warehouse_id VARCHAR(128) NULL,
|
||
pushed_at DATETIME(3) NOT NULL, completed_at DATETIME(3) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_dispatch_pda_task_dispatch (tenant_id,dispatch_order_id),
|
||
UNIQUE KEY uk_ll_dispatch_pda_task_no (tenant_id,task_no)
|
||
) ENGINE=InnoDB COMMENT='PDA task for a pre-arranged dispatch';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick (
|
||
id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL, task_id BIGINT NOT NULL,
|
||
dispatch_item_id BIGINT NOT NULL, inventory_position_id BIGINT NOT NULL,
|
||
packages BIGINT NOT NULL, product_quantity BIGINT NOT NULL DEFAULT 0, idempotency_key VARCHAR(255) NOT NULL,
|
||
picked_at DATETIME(3) NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_dispatch_pda_pick_key (tenant_id,idempotency_key),
|
||
KEY idx_ll_dispatch_pda_pick_item (tenant_id,task_id,dispatch_item_id)
|
||
) ENGINE=InnoDB COMMENT='Immutable dispatch PDA pallet package picks';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_operation (
|
||
id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL, task_id BIGINT NULL,
|
||
operation_type VARCHAR(32) NOT NULL, idempotency_key VARCHAR(255) NOT NULL, request_hash CHAR(64) NOT NULL,
|
||
result_json LONGTEXT NULL, status VARCHAR(32) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_dispatch_pda_operation_key (tenant_id,idempotency_key)
|
||
) ENGINE=InnoDB COMMENT='Idempotent dispatch PDA operations';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 012
|
||
-- Preserve all tail-leg orders included in one merged dispatch pallet
|
||
-- ============================================================================
|
||
|
||
USE baiyue_lastleg;
|
||
|
||
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 AFTER order_no'));
|
||
PREPARE migration_stmt FROM @ddl; EXECUTE migration_stmt; DEALLOCATE PREPARE migration_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 013
|
||
-- Partial dispatch completion and cumulative package counters
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='overseas_warehouse_id'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN overseas_warehouse_id VARCHAR(128) NULL AFTER dispatch_no'));
|
||
PREPARE warehouse_scope_stmt FROM @ddl; EXECUTE warehouse_scope_stmt; DEALLOCATE PREPARE warehouse_scope_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='overseas_warehouse_name'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN overseas_warehouse_name VARCHAR(255) NULL AFTER overseas_warehouse_id'));
|
||
PREPARE warehouse_scope_stmt FROM @ddl; EXECUTE warehouse_scope_stmt; DEALLOCATE PREPARE warehouse_scope_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_item' AND column_name='overseas_warehouse_id'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN overseas_warehouse_id VARCHAR(128) NULL AFTER pallet_no'));
|
||
PREPARE warehouse_scope_stmt FROM @ddl; EXECUTE warehouse_scope_stmt; DEALLOCATE PREPARE warehouse_scope_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_item' AND column_name='overseas_warehouse_name'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN overseas_warehouse_name VARCHAR(255) NULL AFTER overseas_warehouse_id'));
|
||
PREPARE warehouse_scope_stmt FROM @ddl; EXECUTE warehouse_scope_stmt; DEALLOCATE PREPARE warehouse_scope_stmt;
|
||
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 AFTER operator_name'));
|
||
PREPARE warehouse_scope_stmt FROM @ddl; EXECUTE warehouse_scope_stmt; DEALLOCATE PREPARE warehouse_scope_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='picked_package_count'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 AFTER package_count'));
|
||
PREPARE dispatch_partial_stmt FROM @ddl; EXECUTE dispatch_partial_stmt; DEALLOCATE PREPARE dispatch_partial_stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick_order (
|
||
id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL, pick_id BIGINT NOT NULL,
|
||
receipt_id BIGINT NOT NULL, order_id BIGINT NOT NULL, packages BIGINT NOT NULL,
|
||
product_quantity BIGINT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), KEY idx_ll_dispatch_pick_order_pick (tenant_id,pick_id),
|
||
KEY idx_ll_dispatch_pick_order_receipt (tenant_id,receipt_id)
|
||
) ENGINE=InnoDB COMMENT='PDA pick attribution to frozen inbound receipt and tail order';
|
||
|
||
-- Tail order cumulative picking/shipping counters. Original package_count is immutable.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='picked_package_count'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 AFTER package_count'));
|
||
PREPARE tail_order_partial_stmt FROM @ddl; EXECUTE tail_order_partial_stmt; DEALLOCATE PREPARE tail_order_partial_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='shipped_package_count'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN shipped_package_count INT NOT NULL DEFAULT 0 AFTER picked_package_count'));
|
||
PREPARE tail_order_partial_stmt FROM @ddl; EXECUTE tail_order_partial_stmt; DEALLOCATE PREPARE tail_order_partial_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='shipped_package_count'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN shipped_package_count INT NOT NULL DEFAULT 0 AFTER picked_package_count'));
|
||
PREPARE dispatch_partial_stmt FROM @ddl; EXECUTE dispatch_partial_stmt; DEALLOCATE PREPARE dispatch_partial_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='partial_completion_reason'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN partial_completion_reason VARCHAR(1000) NULL AFTER shipped_package_count'));
|
||
PREPARE dispatch_partial_stmt FROM @ddl; EXECUTE dispatch_partial_stmt; DEALLOCATE PREPARE dispatch_partial_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 014
|
||
-- Dispatch transfer to outbound and delivery documents
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_outbound_order (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
outbound_no VARCHAR(64) NOT NULL, dispatch_order_id BIGINT NOT NULL, dispatch_no VARCHAR(64) NOT NULL,
|
||
overseas_warehouse_id VARCHAR(128) NULL, status VARCHAR(32) NOT NULL DEFAULT 'WAIT_OUTBOUND',
|
||
package_count INT NOT NULL DEFAULT 0, pallet_count INT NOT NULL DEFAULT 0,
|
||
idempotency_key VARCHAR(255) NOT NULL, created_by VARCHAR(128) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_outbound_no (tenant_id,outbound_no),
|
||
UNIQUE KEY uk_ll_outbound_idempotency (tenant_id,idempotency_key), UNIQUE KEY uk_ll_outbound_dispatch (tenant_id,dispatch_order_id),
|
||
KEY idx_ll_outbound_list (tenant_id,status,created_at)
|
||
) ENGINE=InnoDB COMMENT='Outbound document generated from a dispatch';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_outbound_pallet_item (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL, outbound_order_id BIGINT NOT NULL,
|
||
warehouse_pallet_id BIGINT NOT NULL, pallet_no VARCHAR(128) NOT NULL,
|
||
destination_warehouse_id VARCHAR(128) NULL, destination_warehouse_code VARCHAR(128) NULL, destination_warehouse_name VARCHAR(255) NULL,
|
||
package_count INT NOT NULL DEFAULT 0, order_refs VARCHAR(2000) NULL, inbound_code VARCHAR(128) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id),
|
||
UNIQUE KEY uk_ll_outbound_pallet (tenant_id,outbound_order_id,warehouse_pallet_id),
|
||
KEY idx_ll_outbound_pallet_list (tenant_id,outbound_order_id), KEY idx_ll_outbound_pallet_destination (tenant_id,destination_warehouse_code)
|
||
) ENGINE=InnoDB COMMENT='Pallet detail snapshot for an outbound document';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_delivery_order (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
delivery_no VARCHAR(64) NOT NULL, outbound_order_id BIGINT NOT NULL, outbound_no VARCHAR(64) NOT NULL,
|
||
dispatch_order_id BIGINT NOT NULL, dispatch_no VARCHAR(64) NOT NULL, overseas_warehouse_id VARCHAR(128) NULL,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'WAIT_DELIVERY', package_count INT NOT NULL DEFAULT 0, pallet_count INT NOT NULL DEFAULT 0,
|
||
idempotency_key VARCHAR(255) NOT NULL, created_by VARCHAR(128) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id), UNIQUE KEY uk_ll_delivery_no (tenant_id,delivery_no),
|
||
UNIQUE KEY uk_ll_delivery_idempotency (tenant_id,idempotency_key), UNIQUE KEY uk_ll_delivery_outbound (tenant_id,outbound_order_id),
|
||
KEY idx_ll_delivery_list (tenant_id,status,created_at)
|
||
) ENGINE=InnoDB COMMENT='Delivery document linked to an outbound document';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 015
|
||
-- Change inventory ownership from SKU/quantity to inbound-order/package count.
|
||
-- Legacy SKU columns become nullable and quantity columns remain untouched so original data is preserved.
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_order_id'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_order_id BIGINT NULL AFTER destination_warehouse_name'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_order_no'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_order_no VARCHAR(128) NULL AFTER inbound_order_id'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_code'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_code VARCHAR(128) NULL AFTER inbound_order_no'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
|
||
-- One legacy balance row represented one SKU. Keep each row intact and give it a
|
||
-- collision-free migration identity while retaining the best known inbound snapshots.
|
||
UPDATE ll_inventory_balance b
|
||
LEFT JOIN (
|
||
SELECT balance_id, MAX(inbound_order_no) AS inbound_order_no, MAX(inbound_code) AS inbound_code
|
||
FROM ll_inventory_ledger GROUP BY balance_id
|
||
) l ON l.balance_id=b.id
|
||
SET b.inbound_order_id=COALESCE(b.inbound_order_id,b.id),
|
||
b.inbound_order_no=COALESCE(b.inbound_order_no,l.inbound_order_no),
|
||
b.inbound_code=COALESCE(NULLIF(b.inbound_code,''),NULLIF(l.inbound_code,''),CONCAT('LEGACY-',b.id))
|
||
WHERE b.inbound_order_id IS NULL OR b.inbound_code IS NULL OR b.inbound_code='';
|
||
|
||
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'), 'ALTER TABLE ll_inventory_balance MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_order_id'), 'ALTER TABLE ll_inventory_balance MODIFY COLUMN inbound_order_id BIGINT NOT NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_code'), 'ALTER TABLE ll_inventory_balance MODIFY COLUMN inbound_code VARCHAR(128) NOT NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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 inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD UNIQUE KEY uk_ll_inventory_dimension (tenant_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code)'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='idx_ll_inventory_inbound'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD KEY idx_ll_inventory_inbound (tenant_id,inbound_code)'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='idx_ll_inventory_sku'), 'ALTER TABLE ll_inventory_balance DROP INDEX idx_ll_inventory_sku', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_position' AND column_name='sku_code'), 'ALTER TABLE ll_inventory_position MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_order_id'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD COLUMN inbound_order_id BIGINT NULL AFTER destination_warehouse_code'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
UPDATE ll_inventory_ledger SET inbound_order_id=COALESCE(inbound_order_id,business_order_id,balance_id) WHERE inbound_order_id IS NULL;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='sku_code'), 'ALTER TABLE ll_inventory_ledger MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_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='inbound_order_id'), 'ALTER TABLE ll_inventory_ledger MODIFY COLUMN inbound_order_id BIGINT NOT NULL', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND index_name='idx_ll_inventory_ledger_inbound'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD KEY idx_ll_inventory_ledger_inbound (tenant_id,inbound_code,occurred_at)'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND index_name='idx_ll_inventory_ledger_sku'), 'ALTER TABLE ll_inventory_ledger DROP INDEX idx_ll_inventory_ledger_sku', 'SELECT 1'));
|
||
PREPARE inventory_v2_stmt FROM @ddl; EXECUTE inventory_v2_stmt; DEALLOCATE PREPARE inventory_v2_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 016
|
||
-- PDA stock receipts follow the same inbound-order/package-only inventory model.
|
||
-- Legacy SKU and quantity columns remain in place but become nullable/defaulted.
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
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'), 'ALTER TABLE ll_inbound_stock_receipt MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE stock_receipt_v2_stmt FROM @ddl; EXECUTE stock_receipt_v2_stmt; DEALLOCATE PREPARE stock_receipt_v2_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='received_quantity'), 'ALTER TABLE ll_inbound_stock_receipt MODIFY COLUMN received_quantity BIGINT NULL DEFAULT 0', 'SELECT 1'));
|
||
PREPARE stock_receipt_v2_stmt FROM @ddl; EXECUTE stock_receipt_v2_stmt; DEALLOCATE PREPARE stock_receipt_v2_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'), 'ALTER TABLE ll_inbound_stock_receipt DROP INDEX uk_ll_stock_receipt_task_allocation_sku', 'SELECT 1'));
|
||
PREPARE stock_receipt_v2_stmt FROM @ddl; EXECUTE stock_receipt_v2_stmt; DEALLOCATE PREPARE stock_receipt_v2_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'), 'SELECT 1', 'ALTER TABLE ll_inbound_stock_receipt ADD UNIQUE KEY uk_ll_stock_receipt_task_allocation (tenant_id,task_id,allocation_id)'));
|
||
PREPARE stock_receipt_v2_stmt FROM @ddl; EXECUTE stock_receipt_v2_stmt; DEALLOCATE PREPARE stock_receipt_v2_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 017
|
||
-- Customer relabel applications, cargo snapshots, and process status history
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_relabel_application (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
relabel_no VARCHAR(64) NOT NULL, lastleg_order_id BIGINT NOT NULL,
|
||
customer_order_no VARCHAR(128) NOT NULL, overseas_warehouse_id VARCHAR(128) NOT NULL,
|
||
label_deadline DATETIME(3) NOT NULL, contact_name VARCHAR(128) NOT NULL,
|
||
contact_phone VARCHAR(64) NOT NULL, remark VARCHAR(1000) NULL,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING_PROCESSING', item_count INT NOT NULL DEFAULT 0,
|
||
total_package_count INT NOT NULL DEFAULT 0, notified_package_count INT NOT NULL DEFAULT 0,
|
||
idempotency_key VARCHAR(255) NOT NULL, request_hash CHAR(64) NOT NULL,
|
||
created_by VARCHAR(128) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Customer relabel application header';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_relabel_item (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', application_id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL,
|
||
sku_code VARCHAR(128) NOT NULL, product_image_file_id VARCHAR(128) NULL,
|
||
product_image_file_name VARCHAR(255) NULL, product_image_url VARCHAR(1000) NULL,
|
||
product_name_zh VARCHAR(255) NOT NULL, total_package_count INT NOT NULL, notified_package_count INT NOT NULL,
|
||
shipment_no VARCHAR(128) NOT NULL, tracking_code VARCHAR(255) NULL, new_sku_code VARCHAR(128) NOT NULL,
|
||
label_requirement VARCHAR(1000) NULL, relabel_file_id VARCHAR(128) NULL,
|
||
relabel_file_name VARCHAR(255) NULL, relabel_file_url VARCHAR(1000) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Frozen customer relabel cargo items';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_relabel_status_history (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL, application_id BIGINT NOT NULL,
|
||
from_status VARCHAR(32) NULL, to_status VARCHAR(32) NOT NULL, operator_id VARCHAR(128) NULL,
|
||
remark VARCHAR(1000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Immutable customer relabel process history';
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='uk_ll_relabel_application_no'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD UNIQUE KEY uk_ll_relabel_application_no (tenant_id,relabel_no)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='uk_ll_relabel_application_idempotency'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD UNIQUE KEY uk_ll_relabel_application_idempotency (tenant_id,idempotency_key)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='uk_ll_relabel_application_order'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD UNIQUE KEY uk_ll_relabel_application_order (lastleg_order_id)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='idx_ll_relabel_application_list'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD KEY idx_ll_relabel_application_list (tenant_id,status,created_at)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='idx_ll_relabel_application_customer'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD KEY idx_ll_relabel_application_customer (tenant_id,customer_order_no)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_application' AND index_name='idx_ll_relabel_application_warehouse'), 'SELECT 1', 'ALTER TABLE ll_relabel_application ADD KEY idx_ll_relabel_application_warehouse (tenant_id,overseas_warehouse_id)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_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_application'), 'SELECT 1', 'ALTER TABLE ll_relabel_item ADD KEY idx_ll_relabel_item_application (tenant_id,application_id)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_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_sku'), 'SELECT 1', 'ALTER TABLE ll_relabel_item ADD KEY idx_ll_relabel_item_sku (tenant_id,sku_code)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_relabel_status_history' AND index_name='idx_ll_relabel_status_history_application'), 'SELECT 1', 'ALTER TABLE ll_relabel_status_history ADD KEY idx_ll_relabel_status_history_application (tenant_id,application_id,created_at)'));
|
||
PREPARE relabel_schema_stmt FROM @ddl; EXECUTE relabel_schema_stmt; DEALLOCATE PREPARE relabel_schema_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 018
|
||
-- Existing-table correction: apply schema changes with ADD/UPDATE/ALTER guards
|
||
-- ============================================================================
|
||
-- Sections 008-017 keep CREATE TABLE definitions for fresh databases. This
|
||
-- section is the authoritative path for databases that already contain those
|
||
-- tables. Legacy SKU/quantity columns are retained and made nullable; no
|
||
-- business rows or Outbox rows are deleted.
|
||
USE baiyue_lastleg;
|
||
|
||
-- Tail orders: cumulative PDA picking/shipping counters.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='picked_package_count'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 COMMENT ''累计已拣箱数'' AFTER package_count'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_order' AND column_name='shipped_package_count'), 'SELECT 1', 'ALTER TABLE ll_order ADD COLUMN shipped_package_count INT NOT NULL DEFAULT 0 COMMENT ''累计已出库箱数'' AFTER picked_package_count'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
|
||
-- Inventory balance: add inbound-order identity without dropping legacy SKU data.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_order_id'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_order_id BIGINT NULL COMMENT ''入仓单ID'' AFTER destination_warehouse_name'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_order_no'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_order_no VARCHAR(128) NULL COMMENT ''入库单号快照'' AFTER inbound_order_id'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_code'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD COLUMN inbound_code VARCHAR(128) NULL COMMENT ''入仓码快照'' AFTER inbound_order_no'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
UPDATE ll_inventory_balance
|
||
SET inbound_order_id = COALESCE(inbound_order_id, id),
|
||
inbound_code = COALESCE(NULLIF(inbound_code, ''), CONCAT('LEGACY-', id))
|
||
WHERE inbound_order_id IS NULL OR inbound_code IS NULL OR inbound_code = '';
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_order_id'), 'ALTER TABLE ll_inventory_balance MODIFY COLUMN inbound_order_id BIGINT NOT NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_balance' AND column_name='inbound_code'), 'ALTER TABLE ll_inventory_balance MODIFY COLUMN inbound_code VARCHAR(128) NOT NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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 migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD UNIQUE KEY uk_ll_inventory_dimension (tenant_id,overseas_warehouse_id,destination_warehouse_code,inbound_order_id,inbound_code)'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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'), 'ALTER TABLE ll_inventory_balance DROP INDEX idx_ll_inventory_sku', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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_inbound'), 'SELECT 1', 'ALTER TABLE ll_inventory_balance ADD KEY idx_ll_inventory_inbound (tenant_id,inbound_code)'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
|
||
-- Inventory positions and ledger: preserve SKU columns, add inbound identity.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_position' AND column_name='sku_code'), 'ALTER TABLE ll_inventory_position MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='inbound_order_id'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD COLUMN inbound_order_id BIGINT NULL COMMENT ''入仓单ID'' AFTER destination_warehouse_code'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
UPDATE ll_inventory_ledger
|
||
SET inbound_order_id = COALESCE(inbound_order_id, business_order_id, balance_id)
|
||
WHERE inbound_order_id IS NULL;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='inbound_order_id'), 'ALTER TABLE ll_inventory_ledger MODIFY COLUMN inbound_order_id BIGINT NOT NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='sku_code'), 'ALTER TABLE ll_inventory_ledger MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND index_name='idx_ll_inventory_ledger_sku'), 'ALTER TABLE ll_inventory_ledger DROP INDEX idx_ll_inventory_ledger_sku', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND index_name='idx_ll_inventory_ledger_inbound'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD KEY idx_ll_inventory_ledger_inbound (tenant_id,inbound_code,occurred_at)'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
|
||
-- Stock receipts: keep legacy SKU/quantity snapshots but allow inbound-only rows.
|
||
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'), 'ALTER TABLE ll_inbound_stock_receipt MODIFY COLUMN sku_code VARCHAR(128) NULL', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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='received_quantity'), 'ALTER TABLE ll_inbound_stock_receipt MODIFY COLUMN received_quantity BIGINT NULL DEFAULT 0', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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'), 'ALTER TABLE ll_inbound_stock_receipt DROP INDEX uk_ll_stock_receipt_task_allocation_sku', 'SELECT 1'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
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'), 'SELECT 1', 'ALTER TABLE ll_inbound_stock_receipt ADD UNIQUE KEY uk_ll_stock_receipt_task_allocation (tenant_id,task_id,allocation_id)'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
|
||
-- Dispatch/PDA fields are also ADD operations for existing installations.
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='picked_package_count'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN picked_package_count INT NOT NULL DEFAULT 0 COMMENT ''累计已拣箱数'' AFTER package_count'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='shipped_package_count'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN shipped_package_count INT NOT NULL DEFAULT 0 COMMENT ''累计已出库箱数'' AFTER picked_package_count'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_order' AND column_name='partial_completion_reason'), 'SELECT 1', 'ALTER TABLE ll_dispatch_order ADD COLUMN partial_completion_reason VARCHAR(1000) NULL COMMENT ''部分完成原因'' AFTER shipped_package_count'));
|
||
PREPARE migration_018 FROM @ddl; EXECUTE migration_018; DEALLOCATE PREPARE migration_018;
|
||
|
||
-- No DROP COLUMN is included. Existing columns and business rows remain recoverable.
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-17 / 019
|
||
-- Warehouse transfer orders with historical customer-order/inbound bindings.
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_order (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', tenant_id VARCHAR(128) NOT NULL,
|
||
transfer_no VARCHAR(64) NOT NULL, inbound_order_id BIGINT NOT NULL, inbound_code VARCHAR(128) NOT NULL,
|
||
lastleg_order_id BIGINT NOT NULL, lastleg_order_no VARCHAR(32) NOT NULL,
|
||
operating_warehouse_id VARCHAR(128) NOT NULL, fba_warehouse_code VARCHAR(128) NOT NULL,
|
||
delivery_address VARCHAR(1000) NOT NULL, package_count INT NOT NULL, delivery_method VARCHAR(64) NOT NULL,
|
||
estimated_arrival_at DATETIME(3) NOT NULL, fba_shipment_no VARCHAR(128) NOT NULL,
|
||
tracking_no VARCHAR(255) NULL, fba_box_nos VARCHAR(2000) NULL, remark VARCHAR(1000) NULL,
|
||
need_relabel TINYINT NOT NULL DEFAULT 0, relabel_application_id BIGINT NULL, relabel_no VARCHAR(64) NULL,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING_REVIEW', idempotency_key VARCHAR(255) NOT NULL,
|
||
request_hash CHAR(64) NOT NULL, created_by VARCHAR(128) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Customer warehouse transfer order';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_source_order (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', transfer_order_id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL,
|
||
source_lastleg_order_id BIGINT NOT NULL, source_lastleg_order_no VARCHAR(32) NOT NULL,
|
||
inbound_order_id BIGINT NOT NULL, inbound_code VARCHAR(128) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Selected historical customer orders and inbound bindings';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_warehouse_transfer_item (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', transfer_order_id BIGINT NOT NULL, tenant_id VARCHAR(128) NOT NULL,
|
||
sku_code VARCHAR(128) NOT NULL, product_name_zh VARCHAR(255) NOT NULL,
|
||
package_count INT NOT NULL, shipping_mark VARCHAR(255) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id)
|
||
) ENGINE=InnoDB COMMENT='Frozen warehouse transfer cargo items';
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND index_name='uk_ll_wh_transfer_no'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD UNIQUE KEY uk_ll_wh_transfer_no (tenant_id,transfer_no)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND index_name='uk_ll_wh_transfer_key'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD UNIQUE KEY uk_ll_wh_transfer_key (tenant_id,idempotency_key)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND index_name='uk_ll_wh_transfer_tail_order'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD UNIQUE KEY uk_ll_wh_transfer_tail_order (lastleg_order_id)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND index_name='idx_ll_wh_transfer_list'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD KEY idx_ll_wh_transfer_list (tenant_id,status,created_at)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_order' AND index_name='idx_ll_wh_transfer_inbound'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_order ADD KEY idx_ll_wh_transfer_inbound (tenant_id,inbound_code)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_source_order' AND index_name='uk_ll_wh_transfer_source'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_source_order ADD UNIQUE KEY uk_ll_wh_transfer_source (transfer_order_id,source_lastleg_order_id)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_source_order' AND index_name='idx_ll_wh_transfer_source_list'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_source_order ADD KEY idx_ll_wh_transfer_source_list (tenant_id,transfer_order_id)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_item' AND index_name='idx_ll_wh_transfer_item_list'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_item ADD KEY idx_ll_wh_transfer_item_list (tenant_id,transfer_order_id)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_item' AND index_name='idx_ll_wh_transfer_item_sku'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_item ADD KEY idx_ll_wh_transfer_item_sku (tenant_id,sku_code)'));
|
||
PREPARE transfer_019 FROM @ddl; EXECUTE transfer_019; DEALLOCATE PREPARE transfer_019;
|
||
|
||
-- 2026-08-17 / customer naming and one-click dropship carton inventory.
|
||
-- Rename only existing columns; deployed data and index definitions remain intact.
|
||
DELIMITER //
|
||
CREATE PROCEDURE migrate_tenant_columns_to_customer()
|
||
BEGIN
|
||
DECLARE done INT DEFAULT FALSE;
|
||
DECLARE table_name_value VARCHAR(128);
|
||
DECLARE column_cursor CURSOR FOR
|
||
SELECT c.table_name FROM information_schema.columns c
|
||
WHERE c.table_schema=DATABASE() AND c.column_name='tenant_id'
|
||
AND NOT EXISTS (SELECT 1 FROM information_schema.columns c2
|
||
WHERE c2.table_schema=c.table_schema AND c2.table_name=c.table_name AND c2.column_name='customer_id');
|
||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;
|
||
OPEN column_cursor;
|
||
rename_loop: LOOP
|
||
FETCH column_cursor INTO table_name_value;
|
||
IF done THEN LEAVE rename_loop; END IF;
|
||
SET @rename_sql=CONCAT('ALTER TABLE `', table_name_value, '` RENAME COLUMN tenant_id TO customer_id');
|
||
PREPARE rename_statement FROM @rename_sql;
|
||
EXECUTE rename_statement;
|
||
DEALLOCATE PREPARE rename_statement;
|
||
END LOOP;
|
||
CLOSE column_cursor;
|
||
END//
|
||
DELIMITER ;
|
||
CALL migrate_tenant_columns_to_customer();
|
||
DROP PROCEDURE migrate_tenant_columns_to_customer;
|
||
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='sku_code'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD COLUMN sku_code VARCHAR(128) NULL AFTER batch_no'));
|
||
PREPARE inventory_sku_020 FROM @ddl; EXECUTE inventory_sku_020; DEALLOCATE PREPARE inventory_sku_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='carton_mark'), 'SELECT 1', IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='carton_no'), 'ALTER TABLE ll_inventory_ledger RENAME COLUMN carton_no TO carton_mark', 'ALTER TABLE ll_inventory_ledger ADD COLUMN carton_mark VARCHAR(128) NULL AFTER sku_code'))));
|
||
PREPARE inventory_carton_020 FROM @ddl; EXECUTE inventory_carton_020; DEALLOCATE PREPARE inventory_carton_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inventory_ledger' AND column_name='carton_packages'), 'SELECT 1', 'ALTER TABLE ll_inventory_ledger ADD COLUMN carton_packages BIGINT NULL AFTER carton_mark'));
|
||
PREPARE inventory_carton_qty_020 FROM @ddl; EXECUTE inventory_carton_qty_020; DEALLOCATE PREPARE inventory_carton_qty_020;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_dropship_order_profile (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, order_id BIGINT NOT NULL,
|
||
warehouse_pallet_id BIGINT NOT NULL, pallet_no VARCHAR(128) NOT NULL, inventory_position_id BIGINT NULL,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'RECEIVED', idempotency_key VARCHAR(255) NOT NULL, version BIGINT NOT NULL DEFAULT 0,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY(id), UNIQUE KEY uk_ll_dropship_profile_order(customer_id,order_id), UNIQUE KEY uk_ll_dropship_profile_key(customer_id,idempotency_key)
|
||
) ENGINE=InnoDB;
|
||
CREATE TABLE IF NOT EXISTS ll_dropship_carton (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, order_id BIGINT NOT NULL, profile_id BIGINT NOT NULL,
|
||
warehouse_pallet_id BIGINT NOT NULL, pallet_no VARCHAR(128) NOT NULL, sku_code VARCHAR(128) NOT NULL, carton_mark VARCHAR(128) NOT NULL, carton_sequence INT NOT NULL,
|
||
status VARCHAR(32) NOT NULL DEFAULT 'AVAILABLE', outbound_order_no VARCHAR(128) NULL, version BIGINT NOT NULL DEFAULT 0,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
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;
|
||
CREATE TABLE IF NOT EXISTS ll_dropship_sku_inventory (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, order_id BIGINT NOT NULL, profile_id BIGINT NOT NULL,
|
||
sku_code VARCHAR(128) NOT NULL, product_name VARCHAR(255) NULL, package_count BIGINT NOT NULL, product_quantity BIGINT NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY(id), UNIQUE KEY uk_ll_dropship_sku_inventory(customer_id,order_id,sku_code)
|
||
) ENGINE=InnoDB;
|
||
CREATE TABLE IF NOT EXISTS ll_dropship_carton_ledger (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, order_id BIGINT NOT NULL, carton_id BIGINT NOT NULL,
|
||
carton_mark VARCHAR(128) NOT NULL, sku_code VARCHAR(128) NOT NULL, operation_type VARCHAR(32) NOT NULL,
|
||
before_packages BIGINT NOT NULL, delta_packages BIGINT NOT NULL, after_packages BIGINT NOT NULL,
|
||
business_order_no VARCHAR(128) NULL, idempotency_key VARCHAR(255) NOT NULL, remark VARCHAR(1000) NULL, occurred_at DATETIME(3) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 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;
|
||
-- Dropship profile stores the immutable first-leg pallet number snapshot.
|
||
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 ''Pallet number snapshot supplied by first-leg handover'' AFTER pallet_no'));
|
||
PREPARE dropship_source_pallet_no_stmt FROM @ddl; EXECUTE dropship_source_pallet_no_stmt; DEALLOCATE PREPARE dropship_source_pallet_no_stmt;
|
||
|
||
-- Explicit index upgrades for existing installations. CREATE TABLE IF NOT EXISTS
|
||
-- does not add indexes to tables that already exist.
|
||
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'), 'SELECT 1', 'ALTER TABLE ll_order ADD KEY idx_ll_order_container (customer_id,container_no)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
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_key'), 'SELECT 1', 'ALTER TABLE ll_dropship_order_profile ADD UNIQUE KEY uk_ll_dropship_profile_key (customer_id,idempotency_key)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_dropship_carton' AND index_name='uk_ll_dropship_carton'), 'SELECT 1', 'ALTER TABLE ll_dropship_carton ADD UNIQUE KEY uk_ll_dropship_carton (customer_id,order_id,carton_mark)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_dropship_carton' AND index_name='idx_ll_dropship_carton_status'), 'SELECT 1', 'ALTER TABLE ll_dropship_carton ADD KEY idx_ll_dropship_carton_status (customer_id,status)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_dropship_carton' AND index_name='idx_ll_dropship_carton_sku'), 'SELECT 1', 'ALTER TABLE ll_dropship_carton ADD KEY idx_ll_dropship_carton_sku (customer_id,sku_code,status)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_dropship_carton_ledger' AND index_name='uk_ll_dropship_ledger_key'), 'SELECT 1', 'ALTER TABLE ll_dropship_carton_ledger ADD UNIQUE KEY uk_ll_dropship_ledger_key (customer_id,idempotency_key)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_dropship_carton_ledger' AND index_name='idx_ll_dropship_ledger_sku'), 'SELECT 1', 'ALTER TABLE ll_dropship_carton_ledger ADD KEY idx_ll_dropship_ledger_sku (customer_id,sku_code,carton_mark)'));
|
||
PREPARE lastleg_indexes_020 FROM @ddl; EXECUTE lastleg_indexes_020; DEALLOCATE PREPARE lastleg_indexes_020;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-18 / dropship multi-pallet cardinality
|
||
-- One one-click dropship inbound order may own multiple source pallets.
|
||
-- ============================================================================
|
||
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 dropship_drop_single_pallet_stmt FROM @ddl; EXECUTE dropship_drop_single_pallet_stmt; DEALLOCATE PREPARE dropship_drop_single_pallet_stmt;
|
||
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 dropship_add_order_pallet_stmt FROM @ddl; EXECUTE dropship_add_order_pallet_stmt; DEALLOCATE PREPARE dropship_add_order_pallet_stmt;
|
||
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 dropship_add_order_idx_stmt FROM @ddl; EXECUTE dropship_add_order_idx_stmt; DEALLOCATE PREPARE dropship_add_order_idx_stmt;
|
||
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_inventory'), 'ALTER TABLE ll_dropship_sku_inventory DROP INDEX uk_ll_dropship_sku_inventory', 'SELECT 1'));
|
||
PREPARE dropship_drop_order_sku_stmt FROM @ddl; EXECUTE dropship_drop_order_sku_stmt; DEALLOCATE PREPARE dropship_drop_order_sku_stmt;
|
||
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'), 'SELECT 1', 'ALTER TABLE ll_dropship_sku_inventory ADD UNIQUE KEY uk_ll_dropship_sku_profile(profile_id,sku_code)'));
|
||
PREPARE dropship_add_profile_sku_stmt FROM @ddl; EXECUTE dropship_add_profile_sku_stmt; DEALLOCATE PREPARE dropship_add_profile_sku_stmt;
|
||
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 dropship_add_order_sku_idx_stmt FROM @ddl; EXECUTE dropship_add_order_sku_idx_stmt; DEALLOCATE PREPARE dropship_add_order_sku_idx_stmt;
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-18 / 021 cargo discard application, carton reservation and approval.
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_cargo_discard_application (
|
||
id BIGINT NOT NULL COMMENT 'Snowflake ID', customer_id VARCHAR(128) NOT NULL,
|
||
discard_no VARCHAR(64) NOT NULL, overseas_warehouse_id VARCHAR(128) NOT NULL,
|
||
overseas_warehouse_name VARCHAR(255) NULL, inbound_codes VARCHAR(2000) NOT NULL,
|
||
total_packages INT NOT NULL, fee_per_package DECIMAL(18,2) NOT NULL,
|
||
total_fee DECIMAL(18,2) NOT NULL, currency CHAR(3) NOT NULL DEFAULT 'USD',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'PENDING_REVIEW', remark VARCHAR(1000) NULL,
|
||
idempotency_key VARCHAR(255) NOT NULL, request_hash CHAR(64) NOT NULL,
|
||
created_by VARCHAR(128) NULL, reviewed_by VARCHAR(128) NULL, review_remark VARCHAR(1000) NULL,
|
||
reviewed_at DATETIME(3) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY(id), UNIQUE KEY uk_ll_cargo_discard_no(customer_id,discard_no),
|
||
UNIQUE KEY uk_ll_cargo_discard_key(customer_id,idempotency_key),
|
||
KEY idx_ll_cargo_discard_list(customer_id,status,created_at),
|
||
KEY idx_ll_cargo_discard_warehouse(customer_id,overseas_warehouse_id,created_at)
|
||
) ENGINE=InnoDB COMMENT='Cargo discard application requiring warehouse approval';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_cargo_discard_item (
|
||
id BIGINT NOT NULL, application_id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL,
|
||
order_id BIGINT NOT NULL, inbound_code VARCHAR(128) NOT NULL, profile_id BIGINT NOT NULL,
|
||
sku_inventory_id BIGINT NOT NULL, sku_code VARCHAR(128) NOT NULL, product_name VARCHAR(255) NULL,
|
||
available_packages_snapshot INT NOT NULL, discard_packages INT NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id),
|
||
UNIQUE KEY uk_ll_cargo_discard_item(application_id,profile_id,sku_code),
|
||
KEY idx_ll_cargo_discard_item_list(customer_id,application_id),
|
||
KEY idx_ll_cargo_discard_item_inbound(customer_id,inbound_code,sku_code)
|
||
) ENGINE=InnoDB COMMENT='Frozen SKU quantities in a cargo discard application';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_cargo_discard_carton (
|
||
id BIGINT NOT NULL, application_id BIGINT NOT NULL, item_id BIGINT NOT NULL,
|
||
customer_id VARCHAR(128) NOT NULL, carton_id BIGINT NOT NULL, carton_mark VARCHAR(128) NOT NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id),
|
||
UNIQUE KEY uk_ll_cargo_discard_carton(application_id,carton_id),
|
||
KEY idx_ll_cargo_discard_carton_application(customer_id,application_id,item_id),
|
||
KEY idx_ll_cargo_discard_carton_identity(customer_id,carton_id)
|
||
) ENGINE=InnoDB COMMENT='Cartons reserved while a cargo discard application awaits review';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_cargo_discard_status_history (
|
||
id BIGINT NOT NULL, application_id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL,
|
||
from_status VARCHAR(32) NULL, to_status VARCHAR(32) NOT NULL, operator_id VARCHAR(128) NULL,
|
||
remark VARCHAR(1000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id),
|
||
KEY idx_ll_cargo_discard_history(customer_id,application_id,created_at)
|
||
) ENGINE=InnoDB COMMENT='Immutable cargo discard approval history';
|
||
|
||
-- ============================================================================
|
||
-- 2026-08-18 / 022 overseas procurement approval, inventory and outbound flow.
|
||
-- ============================================================================
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_order (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, customer_name VARCHAR(255) NULL,
|
||
order_no VARCHAR(64) NOT NULL, purchase_category VARCHAR(128) NOT NULL, product_name VARCHAR(255) NOT NULL,
|
||
product_specification VARCHAR(500) NULL, product_url VARCHAR(2000) NULL, purchase_quantity BIGINT NOT NULL,
|
||
budget_unit_price DECIMAL(18,2) NULL, currency CHAR(3) NOT NULL DEFAULT 'USD', receiving_address VARCHAR(1000) NULL,
|
||
contact_name VARCHAR(128) NOT NULL, contact_phone VARCHAR(64) NOT NULL, purchase_warehouse_id VARCHAR(128) NULL,
|
||
purchase_warehouse_name VARCHAR(255) NULL, inbound_quantity BIGINT NOT NULL DEFAULT 0, outbound_quantity BIGINT NOT NULL DEFAULT 0,
|
||
domestic_carrier VARCHAR(128) NULL, domestic_tracking_no VARCHAR(128) NULL, overseas_carrier VARCHAR(128) NULL,
|
||
overseas_tracking_no VARCHAR(128) NULL, estimated_arrival_at DATETIME(3) NULL, status VARCHAR(32) NOT NULL DEFAULT 'PENDING_REVIEW',
|
||
remark VARCHAR(1000) NULL, idempotency_key VARCHAR(255) NOT NULL, request_hash CHAR(64) NOT NULL,
|
||
created_by VARCHAR(128) NULL, reviewed_by VARCHAR(128) NULL, review_remark VARCHAR(1000) NULL, reviewed_at DATETIME(3) NULL,
|
||
version BIGINT NOT NULL DEFAULT 0, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), 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='Overseas procurement order awaiting business approval';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_outbound (
|
||
id BIGINT NOT NULL, order_id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, quantity BIGINT NOT NULL,
|
||
outbound_no VARCHAR(128) NOT NULL, carrier VARCHAR(128) NULL, tracking_no VARCHAR(128) NULL, outbound_at DATETIME(3) NOT NULL,
|
||
remark VARCHAR(1000) NULL, created_by VARCHAR(128) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id),
|
||
UNIQUE KEY uk_ll_overseas_procurement_outbound_no(customer_id,order_id,outbound_no), KEY idx_ll_overseas_procurement_outbound_order(customer_id,order_id,outbound_at)
|
||
) ENGINE=InnoDB COMMENT='Manual outbound records for overseas procurement inventory';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_overseas_procurement_status_history (
|
||
id BIGINT NOT NULL, order_id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL,
|
||
from_status VARCHAR(32) NULL, to_status VARCHAR(32) NOT NULL, operator_id VARCHAR(128) NULL, remark VARCHAR(1000) NULL,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY(id), KEY idx_ll_overseas_procurement_history(customer_id,order_id,created_at)
|
||
) ENGINE=InnoDB COMMENT='Immutable overseas procurement review history';
|
||
|
||
-- 2026-08-18 / 023 US domestic trucking customer and platform workflow.
|
||
USE baiyue_lastleg;
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_us_truck_order (
|
||
id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL, order_no VARCHAR(64) NOT NULL,
|
||
transport_type VARCHAR(32) NOT NULL, origin VARCHAR(255) NOT NULL, origin_address VARCHAR(500) NULL,
|
||
destination VARCHAR(255) NOT NULL, destination_address VARCHAR(500) NULL, container_type VARCHAR(32) NOT NULL,
|
||
package_count INT NOT NULL DEFAULT 0, total_weight_kg DECIMAL(18,3) NOT NULL DEFAULT 0,
|
||
total_volume_cbm DECIMAL(18,6) NOT NULL DEFAULT 0, budget_amount DECIMAL(18,2) NULL,
|
||
currency VARCHAR(3) NOT NULL DEFAULT 'USD', contact_name VARCHAR(128) NOT NULL,
|
||
contact_info VARCHAR(128) NOT NULL, requested_date DATE NOT NULL, status VARCHAR(32) NOT NULL,
|
||
remark VARCHAR(1000) NULL, idempotency_key VARCHAR(255) NOT NULL, request_hash CHAR(64) NOT NULL,
|
||
created_by VARCHAR(128) NULL, version BIGINT NOT NULL DEFAULT 0,
|
||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
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),
|
||
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='US domestic trucking customer order';
|
||
|
||
CREATE TABLE IF NOT EXISTS ll_us_truck_order_status_history (
|
||
id BIGINT NOT NULL, order_id BIGINT NOT NULL, customer_id VARCHAR(128) NOT NULL,
|
||
from_status VARCHAR(32) NULL, to_status VARCHAR(32) NOT NULL, operator_id VARCHAR(128) NULL,
|
||
remark VARCHAR(1000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
PRIMARY KEY(id), KEY idx_ll_us_truck_history(customer_id,order_id,created_at)
|
||
) ENGINE=InnoDB COMMENT='Immutable US trucking order status history';
|