From e72e74b21e79afedcddef929a47bacb67bb23ef3 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Thu, 10 Sep 2026 10:25:16 +0800 Subject: [PATCH] fix: stabilize overseas initialization and PDA acceptance --- deploy/sql/头程数据库统一增量-MySQL8.sql | 6 - deploy/sql/海外区域统一增量-MySQL8.sql | 453 ++++-------------- .../main/resources/db/lastleg-permissions.sql | 8 +- ...erseasPhase4PermissionSqlContractTest.java | 2 +- .../warehouse/mapper/PdaWarehouseMapper.java | 2 +- .../lastleg/security/OverseasPermissions.java | 2 + .../src/main/resources/db/lastleg.sql | 27 +- .../delivery/DeliverySchemaContractTest.java | 2 +- .../warehouse/PdaWarehouseContractTest.java | 8 + scripts/admin-test-env-acceptance.mjs | 4 +- .../initialization-baseline-contract.test.mjs | 18 +- ...-phase4-producer-fixture-contract.test.mjs | 3 + 12 files changed, 160 insertions(+), 375 deletions(-) diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index 84e2180ba..a4d3ee7be 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -16942,12 +16942,6 @@ VALUES (5107061,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:create','创建海外库位',NULL,'POST',761,'ACTIVE',1,0), (5107062,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:edit','编辑海外库位',NULL,'PUT',762,'ACTIVE',1,0), (5107063,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:delete','删除海外库位',NULL,'DELETE',763,'ACTIVE',1,0), - (5107230,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:carton:list','海外箱号','/overseas-warehouse/cartons','GET',930,'ACTIVE',1,0), - (5107231,0,'PLATFORM','BUTTON',5107230,'platform:overseas-warehouse:carton:create','创建海外箱号',NULL,'POST',931,'ACTIVE',1,0), - (5107232,0,'PLATFORM','BUTTON',5107230,'platform:overseas-warehouse:carton:edit','编辑海外箱号',NULL,'PUT',932,'ACTIVE',1,0), - (5107240,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:product:list','海外产品库','/overseas-warehouse/products','GET',940,'ACTIVE',1,0), - (5107241,0,'PLATFORM','BUTTON',5107240,'platform:overseas-warehouse:product:create','创建海外产品',NULL,'POST',941,'ACTIVE',1,0), - (5107242,0,'PLATFORM','BUTTON',5107240,'platform:overseas-warehouse:product:edit','编辑海外产品',NULL,'PUT',942,'ACTIVE',1,0), (5107090,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:outbound:list','海外出库单','/overseas-warehouse/outbounds','GET',765,'ACTIVE',1,0), (5107091,0,'PLATFORM','BUTTON',5107090,'platform:overseas-warehouse:outbound:create','创建海外出库单',NULL,'POST',766,'ACTIVE',1,0), (5107092,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:delivery:list','海外派送单','/overseas-warehouse/delivery-orders','GET',767,'ACTIVE',1,0), diff --git a/deploy/sql/海外区域统一增量-MySQL8.sql b/deploy/sql/海外区域统一增量-MySQL8.sql index c435347a6..a899a53a6 100644 --- a/deploy/sql/海外区域统一增量-MySQL8.sql +++ b/deploy/sql/海外区域统一增量-MySQL8.sql @@ -3,6 +3,92 @@ -- 本文件只由人工审核执行,服务部署默认不自动执行 SQL。 SET NAMES utf8mb4; +-- 海外 Event Bridge 空库基线必须先于业务服务表初始化。 +CREATE DATABASE IF NOT EXISTS baiyue_event_bridge_overseas + DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +USE baiyue_event_bridge_overseas; + +CREATE TABLE IF NOT EXISTS bridge_outbox ( + event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', + idempotency_key VARCHAR(191) NOT NULL COMMENT '发送幂等键', + event_type VARCHAR(64) NOT NULL COMMENT '事件类型', + event_version INT NOT NULL COMMENT '事件契约版本', + source_region VARCHAR(32) NOT NULL COMMENT '来源区域', + target_region VARCHAR(32) NOT NULL COMMENT '目标区域', + customer_id VARCHAR(128) NOT NULL COMMENT '客户标识', + aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型', + aggregate_id VARCHAR(128) NOT NULL COMMENT '聚合标识', + aggregate_version BIGINT NOT NULL COMMENT '聚合版本', + handover_version BIGINT NULL COMMENT '跨区交接版本', + trace_id VARCHAR(128) NOT NULL COMMENT '链路标识', + correlation_id VARCHAR(128) NOT NULL COMMENT '业务关联标识', + causation_id VARCHAR(128) NULL COMMENT '上游事件标识', + occurred_at DATETIME(3) NOT NULL COMMENT '业务事实发生时间', + payload_hash VARCHAR(71) NOT NULL COMMENT '规范化负载摘要', + payload_json JSON NOT NULL COMMENT '事件负载', + status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '投递状态', + retry_count INT NOT NULL DEFAULT 0 COMMENT '已重试次数', + next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', + lease_owner VARCHAR(128) NULL COMMENT '租约持有者', + lease_until DATETIME(3) NULL COMMENT '租约截止时间', + last_error VARCHAR(1000) NULL COMMENT '最后错误', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', + delivered_at DATETIME(3) NULL COMMENT '投递成功时间', + PRIMARY KEY (event_id), + UNIQUE KEY uk_bridge_outbox_idempotency (idempotency_key), + KEY idx_bridge_outbox_schedule (target_region,status,next_retry_at,lease_until) +) ENGINE=InnoDB COMMENT='海外跨区域事件待投递箱'; + +CREATE TABLE IF NOT EXISTS bridge_inbox ( + event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', + idempotency_key VARCHAR(191) NOT NULL COMMENT '接收幂等键', + event_type VARCHAR(64) NOT NULL COMMENT '事件类型', + event_version INT NOT NULL COMMENT '事件契约版本', + source_region VARCHAR(32) NOT NULL COMMENT '来源区域', + target_region VARCHAR(32) NOT NULL COMMENT '目标区域', + customer_id VARCHAR(128) NOT NULL COMMENT '客户标识', + aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型', + aggregate_id VARCHAR(128) NOT NULL COMMENT '聚合标识', + aggregate_version BIGINT NOT NULL COMMENT '聚合版本', + handover_version BIGINT NULL COMMENT '跨区交接版本', + trace_id VARCHAR(128) NOT NULL COMMENT '链路标识', + correlation_id VARCHAR(128) NOT NULL COMMENT '业务关联标识', + causation_id VARCHAR(128) NULL COMMENT '上游事件标识', + occurred_at DATETIME(3) NOT NULL COMMENT '业务事实发生时间', + payload_hash VARCHAR(71) NOT NULL COMMENT '规范化负载摘要', + payload_json JSON NOT NULL COMMENT '事件负载', + status VARCHAR(32) NOT NULL DEFAULT 'RECEIVED' COMMENT '消费状态', + lease_owner VARCHAR(128) NULL COMMENT '消费租约持有者', + lease_until DATETIME(3) NULL COMMENT '消费租约截止时间', + retry_count INT NOT NULL DEFAULT 0 COMMENT '消费重试次数', + next_retry_at DATETIME(3) NULL COMMENT '下次消费时间', + last_error VARCHAR(1000) NULL COMMENT '最后错误', + received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '接收时间', + processed_at DATETIME(3) NULL COMMENT '消费完成时间', + PRIMARY KEY (event_id), + UNIQUE KEY uk_bridge_inbox_idempotency (idempotency_key), + KEY idx_bridge_inbox_consume (status,next_retry_at,lease_until) +) ENGINE=InnoDB COMMENT='海外跨区域事件已接收箱'; + +CREATE TABLE IF NOT EXISTS bridge_delivery_attempt ( + id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', + event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', + source_region VARCHAR(32) NOT NULL COMMENT '来源区域', + target_region VARCHAR(32) NOT NULL COMMENT '目标区域', + attempt_no INT NOT NULL COMMENT '投递序号', + status VARCHAR(32) NOT NULL COMMENT '投递结果', + response_code VARCHAR(64) NULL COMMENT '对端响应码', + error_message VARCHAR(1000) NULL COMMENT '错误信息', + started_at DATETIME(3) NOT NULL COMMENT '开始时间', + finished_at DATETIME(3) NULL COMMENT '完成时间', + PRIMARY KEY (id), + UNIQUE KEY uk_bridge_attempt (event_id,attempt_no), + KEY idx_bridge_attempt_event (event_id,started_at) +) ENGINE=InnoDB COMMENT='海外跨区域事件投递尝试记录'; + +DROP PROCEDURE IF EXISTS assert_overseas_event_bridge_schema; + + -- BEGIN INLINE EMPTY-DATABASE BASELINE: LASTLEG SET NAMES utf8mb4; @@ -958,7 +1044,7 @@ CREATE TABLE IF NOT EXISTS ll_inbound_pallet_merge ( KEY idx_ll_inbound_merge_task (customer_id, task_id), KEY idx_ll_inbound_merge_group (merge_group_no) ) ENGINE=InnoDB COMMENT='入仓托盘合托记录'; -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')); +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 COMMENT ''FBA仓库编码'' AFTER inbound_code')); PREPARE inbound_schema_stmt FROM @ddl; EXECUTE inbound_schema_stmt; DEALLOCATE PREPARE inbound_schema_stmt; SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan_line' AND column_name='customer_id'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_line ADD COLUMN customer_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''客户账号标识'' AFTER id')); PREPARE receiving_container_line_stmt FROM @ddl; EXECUTE receiving_container_line_stmt; DEALLOCATE PREPARE receiving_container_line_stmt; @@ -1362,7 +1448,7 @@ PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_pallet_lock' AND column_name='dispatch_order_id' AND is_nullable='YES'), 'SELECT 1', 'ALTER TABLE ll_dispatch_pallet_lock MODIFY COLUMN dispatch_order_id BIGINT NULL COMMENT ''正式派车单ID,草稿锁阶段为空''')); PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE PREPARE dispatch_schema_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='order_refs'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN order_refs VARCHAR(2000) NULL AFTER order_no')); +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_item' AND column_name='order_refs'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN order_refs VARCHAR(2000) NULL COMMENT ''关联订单信息'' AFTER order_no')); PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE PREPARE dispatch_schema_stmt; CREATE TABLE IF NOT EXISTS ll_dispatch_pda_task ( @@ -2064,6 +2150,21 @@ CREATE TABLE IF NOT EXISTS ll_security_projection ( KEY idx_security_projection_permission (aggregate_id,permission_version) ) ENGINE=InnoDB COMMENT='海外IAM安全状态与权限版本投影'; +-- 收敛尚未具备授权快照字段的开发/测试库,CREATE TABLE IF NOT EXISTS 不会补充已存在表的字段。 +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='ll_security_projection' AND column_name='roles_json'), 'SELECT 1', + 'ALTER TABLE ll_security_projection ADD COLUMN roles_json JSON NULL COMMENT ''IAM投影的当前角色快照'' AFTER permission_version')); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='ll_security_projection' AND column_name='authorities_json'), 'SELECT 1', + 'ALTER TABLE ll_security_projection ADD COLUMN authorities_json JSON NULL COMMENT ''IAM投影的当前海外权限快照'' AFTER roles_json')); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +UPDATE ll_security_projection SET roles_json=JSON_ARRAY() WHERE roles_json IS NULL; +UPDATE ll_security_projection SET authorities_json=JSON_ARRAY() WHERE authorities_json IS NULL; +ALTER TABLE ll_security_projection + MODIFY COLUMN roles_json JSON NOT NULL COMMENT 'IAM投影的当前角色快照', + MODIFY COLUMN authorities_json JSON NOT NULL COMMENT 'IAM投影的当前海外权限快照'; + -- 空库基线固定管理员必须携带当前海外授权快照;后续真实 IAM 事件从 aggregate_version=1 单调覆盖该 version=0 投影。 SET @platform_admin_overseas_roles = JSON_ARRAY('PLATFORM_ADMIN'); SET @platform_admin_overseas_authorities = JSON_ARRAY( @@ -2127,9 +2228,6 @@ SET @platform_admin_overseas_authorities = JSON_ARRAY( 'platform:overseas-master-data:vehicle:export', 'platform:overseas-master-data:vehicle:list', 'platform:overseas-master-data:vehicle:status', - 'platform:overseas-warehouse:carton:create', - 'platform:overseas-warehouse:carton:edit', - 'platform:overseas-warehouse:carton:list', 'platform:overseas-warehouse:customer-visit:edit', 'platform:overseas-warehouse:customer-visit:list', 'platform:overseas-warehouse:delivery:documents', @@ -2166,12 +2264,11 @@ SET @platform_admin_overseas_authorities = JSON_ARRAY( 'platform:overseas-warehouse:pallet:delete', 'platform:overseas-warehouse:pallet:edit', 'platform:overseas-warehouse:pallet:list', - 'platform:overseas-warehouse:product:create', - 'platform:overseas-warehouse:product:edit', - 'platform:overseas-warehouse:product:list', 'platform:overseas-warehouse:relabel-order:create', 'platform:overseas-warehouse:relabel-order:list', 'platform:overseas-warehouse:relabel-order:status', + 'platform:overseas-warehouse:return-cartons:list', + 'platform:overseas-warehouse:return-inventory:list', 'platform:overseas-warehouse:warehouse:create', 'platform:overseas-warehouse:warehouse:edit', 'platform:overseas-warehouse:warehouse:list', @@ -2454,89 +2551,6 @@ ALTER TABLE wh_pallet -- END INLINE EMPTY-DATABASE BASELINE: OVERSEAS WAREHOUSE -- BEGIN UNIFIED OVERSEAS INCREMENTAL AND FINAL ASSERTIONS -CREATE DATABASE IF NOT EXISTS baiyue_event_bridge_overseas - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -USE baiyue_event_bridge_overseas; - -CREATE TABLE IF NOT EXISTS bridge_outbox ( - event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', - idempotency_key VARCHAR(191) NOT NULL COMMENT '发送幂等键', - event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - event_version INT NOT NULL COMMENT '事件契约版本', - source_region VARCHAR(32) NOT NULL COMMENT '来源区域', - target_region VARCHAR(32) NOT NULL COMMENT '目标区域', - customer_id VARCHAR(128) NOT NULL COMMENT '客户标识', - aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型', - aggregate_id VARCHAR(128) NOT NULL COMMENT '聚合标识', - aggregate_version BIGINT NOT NULL COMMENT '聚合版本', - handover_version BIGINT NULL COMMENT '跨区交接版本', - trace_id VARCHAR(128) NOT NULL COMMENT '链路标识', - correlation_id VARCHAR(128) NOT NULL COMMENT '业务关联标识', - causation_id VARCHAR(128) NULL COMMENT '上游事件标识', - occurred_at DATETIME(3) NOT NULL COMMENT '业务事实发生时间', - payload_hash VARCHAR(71) NOT NULL COMMENT '规范化负载摘要', - payload_json JSON NOT NULL COMMENT '事件负载', - status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '投递状态', - retry_count INT NOT NULL DEFAULT 0 COMMENT '已重试次数', - next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', - lease_owner VARCHAR(128) NULL COMMENT '租约持有者', - lease_until DATETIME(3) NULL COMMENT '租约截止时间', - last_error VARCHAR(1000) NULL COMMENT '最后错误', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - delivered_at DATETIME(3) NULL COMMENT '投递成功时间', - PRIMARY KEY (event_id), - UNIQUE KEY uk_bridge_outbox_idempotency (idempotency_key), - KEY idx_bridge_outbox_schedule (target_region,status,next_retry_at,lease_until) -) ENGINE=InnoDB COMMENT='海外跨区域事件待投递箱'; - -CREATE TABLE IF NOT EXISTS bridge_inbox ( - event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', - idempotency_key VARCHAR(191) NOT NULL COMMENT '接收幂等键', - event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - event_version INT NOT NULL COMMENT '事件契约版本', - source_region VARCHAR(32) NOT NULL COMMENT '来源区域', - target_region VARCHAR(32) NOT NULL COMMENT '目标区域', - customer_id VARCHAR(128) NOT NULL COMMENT '客户标识', - aggregate_type VARCHAR(64) NOT NULL COMMENT '聚合类型', - aggregate_id VARCHAR(128) NOT NULL COMMENT '聚合标识', - aggregate_version BIGINT NOT NULL COMMENT '聚合版本', - handover_version BIGINT NULL COMMENT '跨区交接版本', - trace_id VARCHAR(128) NOT NULL COMMENT '链路标识', - correlation_id VARCHAR(128) NOT NULL COMMENT '业务关联标识', - causation_id VARCHAR(128) NULL COMMENT '上游事件标识', - occurred_at DATETIME(3) NOT NULL COMMENT '业务事实发生时间', - payload_hash VARCHAR(71) NOT NULL COMMENT '规范化负载摘要', - payload_json JSON NOT NULL COMMENT '事件负载', - status VARCHAR(32) NOT NULL DEFAULT 'RECEIVED' COMMENT '消费状态', - lease_owner VARCHAR(128) NULL COMMENT '消费租约持有者', - lease_until DATETIME(3) NULL COMMENT '消费租约截止时间', - retry_count INT NOT NULL DEFAULT 0 COMMENT '消费重试次数', - next_retry_at DATETIME(3) NULL COMMENT '下次消费时间', - last_error VARCHAR(1000) NULL COMMENT '最后错误', - received_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '接收时间', - processed_at DATETIME(3) NULL COMMENT '消费完成时间', - PRIMARY KEY (event_id), - UNIQUE KEY uk_bridge_inbox_idempotency (idempotency_key), - KEY idx_bridge_inbox_consume (status,next_retry_at,lease_until) -) ENGINE=InnoDB COMMENT='海外跨区域事件已接收箱'; - -CREATE TABLE IF NOT EXISTS bridge_delivery_attempt ( - id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', - event_id VARCHAR(128) NOT NULL COMMENT '事件全局标识', - source_region VARCHAR(32) NOT NULL COMMENT '来源区域', - target_region VARCHAR(32) NOT NULL COMMENT '目标区域', - attempt_no INT NOT NULL COMMENT '投递序号', - status VARCHAR(32) NOT NULL COMMENT '投递结果', - response_code VARCHAR(64) NULL COMMENT '对端响应码', - error_message VARCHAR(1000) NULL COMMENT '错误信息', - started_at DATETIME(3) NOT NULL COMMENT '开始时间', - finished_at DATETIME(3) NULL COMMENT '完成时间', - PRIMARY KEY (id), - UNIQUE KEY uk_bridge_attempt (event_id,attempt_no), - KEY idx_bridge_attempt_event (event_id,started_at) -) ENGINE=InnoDB COMMENT='海外跨区域事件投递尝试记录'; - -DROP PROCEDURE IF EXISTS assert_overseas_event_bridge_schema; DELIMITER $$ CREATE PROCEDURE assert_overseas_event_bridge_schema() BEGIN @@ -3584,263 +3598,6 @@ CREATE TABLE IF NOT EXISTS ll_order_operation_log ( ) ENGINE=InnoDB COMMENT='尾程订单操作记录'; -- 五期正式结构必须由海外固定入口自行补齐;既有四期库不得依赖当前基线或历史脚本。 -CREATE TABLE IF NOT EXISTS ll_dispatch_pda_task ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', dispatch_order_id BIGINT NOT NULL COMMENT '派车单ID', - task_no VARCHAR(64) NOT NULL COMMENT 'PDA任务号', status VARCHAR(32) NOT NULL COMMENT '业务状态', operator_id VARCHAR(128) NULL COMMENT '操作人ID', - warehouse_id VARCHAR(128) NOT NULL COMMENT 'Token绑定的海外仓库ID', operator_name VARCHAR(128) NULL COMMENT '操作人姓名', - pushed_at DATETIME(3) NOT NULL COMMENT '任务下发时间', completed_at DATETIME(3) NULL COMMENT '完成时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_dispatch_pda_task_dispatch(customer_id,dispatch_order_id), - UNIQUE KEY uk_ll_dispatch_pda_task_no(task_no) -) ENGINE=InnoDB COMMENT='派车PDA拣货任务'; -CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', task_id BIGINT NOT NULL COMMENT 'PDA任务ID', - dispatch_item_id BIGINT NOT NULL COMMENT '派车明细ID', inventory_position_id BIGINT NOT NULL COMMENT '库存仓位记录ID', - packages BIGINT NOT NULL COMMENT '本次操作箱数', product_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '产品数量', - idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', picked_at DATETIME(3) NOT NULL COMMENT '拣货时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_dispatch_pda_pick_key(customer_id,idempotency_key), - KEY idx_ll_dispatch_pda_pick_item(customer_id,task_id,dispatch_item_id) -) ENGINE=InnoDB COMMENT='派车PDA拣货记录'; -CREATE TABLE IF NOT EXISTS ll_dispatch_pda_operation ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', task_id BIGINT NULL COMMENT 'PDA任务ID', - operation_type VARCHAR(32) NOT NULL COMMENT 'PDA操作类型', idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', - request_hash CHAR(64) NOT NULL COMMENT '请求内容哈希', result_json LONGTEXT NULL COMMENT '处理结果JSON', - status VARCHAR(32) NOT NULL COMMENT 'PDA操作处理状态', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_dispatch_pda_operation_key(customer_id,idempotency_key) -) ENGINE=InnoDB COMMENT='派车PDA操作幂等记录'; -CREATE TABLE IF NOT EXISTS ll_dispatch_pda_pick_order ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', pick_id BIGINT NOT NULL COMMENT 'PDA拣货记录ID', - receipt_id BIGINT NOT NULL COMMENT '入仓实收记录ID', order_id BIGINT NOT NULL COMMENT '订单ID', packages BIGINT NOT NULL COMMENT '本次操作箱数', - product_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '产品数量', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY(id), KEY idx_ll_dispatch_pick_order_pick(customer_id,pick_id), - KEY idx_ll_dispatch_pick_order_receipt(customer_id,receipt_id) -) ENGINE=InnoDB COMMENT='PDA拣货订单归属记录'; - -CREATE TABLE IF NOT EXISTS ll_outbound_order ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', outbound_no VARCHAR(64) NOT NULL COMMENT '出库单号', - dispatch_order_id BIGINT NULL COMMENT '派车单ID,一件代发为空', dispatch_no VARCHAR(64) NULL COMMENT '派车单号,一件代发为空', - overseas_warehouse_id VARCHAR(128) NULL COMMENT '海外仓ID', status VARCHAR(32) NOT NULL DEFAULT 'WAIT_OUTBOUND' COMMENT '业务状态', - package_count INT NOT NULL DEFAULT 0 COMMENT '箱数', pallet_count INT NOT NULL DEFAULT 0 COMMENT '托盘数', - idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', created_by VARCHAR(128) NULL COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - outbound_type VARCHAR(32) NOT NULL DEFAULT 'DISPATCH_DELIVERY' COMMENT '出库类型:派送转出库、一件代发', - lx_codes VARCHAR(1000) NULL COMMENT '关联一件代发领星入库单代码汇总', - recipient_info VARCHAR(1000) NULL COMMENT '一件代发收件信息', PRIMARY KEY(id), UNIQUE KEY uk_ll_outbound_no(outbound_no), - UNIQUE KEY uk_ll_outbound_idempotency(customer_id,idempotency_key), UNIQUE KEY uk_ll_outbound_dispatch(customer_id,dispatch_order_id), - KEY idx_ll_outbound_list(customer_id,status,created_at) -) ENGINE=InnoDB COMMENT='尾程出库单'; -CREATE TABLE IF NOT EXISTS ll_outbound_pallet_item ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', outbound_order_id BIGINT NOT NULL COMMENT '出库单ID', - warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(128) NULL COMMENT '托盘号', - destination_warehouse_id VARCHAR(128) NULL COMMENT '目的仓ID', destination_warehouse_code VARCHAR(128) NULL COMMENT '目的仓编码快照', - destination_warehouse_name VARCHAR(255) NULL COMMENT '目的仓名称快照', package_count INT NOT NULL DEFAULT 0 COMMENT '箱数', - picked_package_count INT NOT NULL DEFAULT 0 COMMENT '已拣箱数', status VARCHAR(32) NOT NULL DEFAULT 'WAIT_PICK' COMMENT '拣货状态', - sku_code VARCHAR(128) NULL COMMENT '一件代发SKU', order_refs VARCHAR(2000) NULL COMMENT '关联订单信息', inbound_code VARCHAR(128) NULL COMMENT '入仓单号快照', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_outbound_pallet(customer_id,outbound_order_id,warehouse_pallet_id), - KEY idx_ll_outbound_pallet_list(customer_id,outbound_order_id), KEY idx_ll_outbound_pallet_destination(customer_id,destination_warehouse_code) -) ENGINE=InnoDB COMMENT='出库托盘明细'; -CREATE TABLE IF NOT EXISTS ll_outbound_pda_task ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', outbound_order_id BIGINT NOT NULL COMMENT '出库单ID', - task_no VARCHAR(64) NOT NULL COMMENT 'PDA任务号', status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态:待拣货、拣货中、已完成', - completion_idempotency_key VARCHAR(255) NULL COMMENT '完成命令幂等键', pushed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '推送时间', - completed_at DATETIME(3) NULL COMMENT '完成时间', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_outbound_pda_task_order(customer_id,outbound_order_id), UNIQUE KEY uk_ll_outbound_pda_task_no(task_no), - UNIQUE KEY uk_ll_outbound_pda_complete_key(customer_id,completion_idempotency_key) -) ENGINE=InnoDB COMMENT='一件代发出库PDA拣货任务'; -CREATE TABLE IF NOT EXISTS ll_outbound_pda_pick ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', task_id BIGINT NOT NULL COMMENT 'PDA任务ID', - outbound_pallet_item_id BIGINT NOT NULL COMMENT '出库托盘明细ID', inventory_position_id BIGINT NOT NULL COMMENT '库存仓位ID', - packages BIGINT NOT NULL COMMENT '拣货箱数', idempotency_key VARCHAR(255) NOT NULL COMMENT '拣货幂等键', - picked_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '拣货时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_outbound_pda_pick_key(customer_id,idempotency_key) -) ENGINE=InnoDB COMMENT='一件代发出库PDA托盘拣货记录'; - -CREATE TABLE IF NOT EXISTS ll_delivery_order ( - id BIGINT NOT NULL COMMENT '派送单主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', delivery_no VARCHAR(64) NOT NULL COMMENT '派送单号', - outbound_order_id BIGINT NOT NULL COMMENT '关联出库单ID', outbound_no VARCHAR(64) NOT NULL COMMENT '关联出库单号', - dispatch_order_id BIGINT NOT NULL COMMENT '关联派车单ID', dispatch_no VARCHAR(64) NOT NULL COMMENT '关联派车单号', - overseas_warehouse_id VARCHAR(128) NULL COMMENT '海外仓ID', overseas_warehouse_name VARCHAR(255) NULL COMMENT '海外仓名称快照', customer_name VARCHAR(255) NULL COMMENT '客户名称快照', - status VARCHAR(32) NOT NULL DEFAULT 'WAIT_DELIVERY' COMMENT '派送状态:WAIT_DELIVERY待派送及后续正式状态', - waybill_no VARCHAR(128) NULL COMMENT '承运运单号', - bol_no VARCHAR(128) NULL COMMENT '派送资料BOL号,不作为文件归属标识', - documents_json JSON NULL COMMENT '派送三类资料当前绑定及权威文件元数据快照', - delivery_method VARCHAR(32) NULL COMMENT '派送方式', carrier_name VARCHAR(255) NULL COMMENT '派送承运商', - pickup_method VARCHAR(64) NULL COMMENT '提货方式', loading_type VARCHAR(64) NULL COMMENT '装车类型', vehicle_type VARCHAR(64) NULL COMMENT '车辆类型', - vehicle_size VARCHAR(64) NULL COMMENT '车辆大小', vehicle_plate VARCHAR(64) NULL COMMENT '车牌号', driver_name VARCHAR(128) NULL COMMENT '司机或车队名称', - driver_phone VARCHAR(64) NULL COMMENT '车队联系电话', appointment_account VARCHAR(128) NULL COMMENT '预约账号', seller_name VARCHAR(128) NULL COMMENT '卖家姓名', - package_count INT NOT NULL DEFAULT 0 COMMENT '派送箱数', pallet_count INT NOT NULL DEFAULT 0 COMMENT '派送托盘数', - total_weight_kg DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '总重量(千克)', total_volume_cbm DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '总体积(立方米)', - planned_delivery_at DATETIME(3) NULL COMMENT '预计派送时间', dispatched_at DATETIME(3) NULL COMMENT '实际派送时间', - expected_arrival_at DATETIME(3) NULL COMMENT '预计到达时间', signed_at DATETIME(3) NULL COMMENT '签收时间', remark VARCHAR(1000) NULL COMMENT '派送备注', - idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', created_by VARCHAR(128) NULL COMMENT '创建人ID', - version BIGINT NOT NULL DEFAULT 0 COMMENT '派送单乐观锁版本', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_delivery_no(customer_id,delivery_no), UNIQUE KEY uk_ll_delivery_idempotency(customer_id,idempotency_key), - UNIQUE KEY uk_ll_delivery_outbound(customer_id,outbound_order_id), KEY idx_ll_delivery_list(customer_id,status,created_at) -) ENGINE=InnoDB COMMENT='尾程派送单'; -CREATE TABLE IF NOT EXISTS ll_delivery_fee ( - id BIGINT NOT NULL COMMENT '派送费用主键', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', delivery_order_id BIGINT NOT NULL COMMENT '派送单ID', - fee_direction VARCHAR(16) NOT NULL DEFAULT 'PAYABLE' COMMENT '应收应付方向', fee_type VARCHAR(64) NOT NULL COMMENT '费用类型', currency VARCHAR(8) NOT NULL COMMENT '币种', - amount DECIMAL(18,2) NOT NULL COMMENT '费用金额', remark VARCHAR(500) NULL COMMENT '费用备注', created_by VARCHAR(128) NULL COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id), KEY idx_ll_delivery_fee_order(customer_id,delivery_order_id,id) -) ENGINE=InnoDB COMMENT='派送单费用明细'; -CREATE TABLE IF NOT EXISTS ll_delivery_document_revision ( - id BIGINT NOT NULL COMMENT '派送资料历史ID', - customer_id VARCHAR(128) NOT NULL COMMENT '派送所属客户隔离键', - delivery_order_id BIGINT NOT NULL COMMENT '派送单ID', - version BIGINT NOT NULL COMMENT '保存成功时派送单版本', - idempotency_key VARCHAR(128) NOT NULL COMMENT '资料保存幂等键', - request_hash VARCHAR(64) NOT NULL COMMENT '完整保存请求哈希', - snapshot_json JSON NOT NULL COMMENT '不可变三类资料及BOL号结果快照', - operator_id VARCHAR(128) NOT NULL COMMENT '保存操作人ID', - created_at DATETIME(3) NOT NULL COMMENT '资料保存时间', - PRIMARY KEY(id), - UNIQUE KEY uk_delivery_document_command(customer_id,delivery_order_id,idempotency_key), - UNIQUE KEY uk_delivery_document_version(customer_id,delivery_order_id,version) -) ENGINE=InnoDB COMMENT='派送资料版本历史与幂等保存记录'; - -CREATE TABLE IF NOT EXISTS ll_delivery_operation ( - id BIGINT NOT NULL COMMENT '派送操作主键', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', delivery_order_id BIGINT NOT NULL COMMENT '派送单ID', - operation_node VARCHAR(64) NOT NULL COMMENT '操作节点', operator_id VARCHAR(128) NULL COMMENT '操作人ID', operator_name VARCHAR(128) NULL COMMENT '操作人名称', - result VARCHAR(500) NOT NULL COMMENT '处理结果', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY(id), KEY idx_ll_delivery_operation_order(customer_id,delivery_order_id,created_at,id) -) ENGINE=InnoDB COMMENT='派送单操作记录'; - -CREATE TABLE IF NOT EXISTS ll_dropship_order_profile ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', order_id BIGINT NOT NULL COMMENT '订单ID', - warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(128) NULL COMMENT '托盘号', source_pallet_no VARCHAR(128) NOT NULL COMMENT '来源托盘号快照', - inventory_position_id BIGINT NULL COMMENT '库存仓位记录ID', status VARCHAR(32) NOT NULL DEFAULT 'PENDING_INBOUND' COMMENT '业务状态', - idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_dropship_profile_order_pallet(customer_id,order_id,source_pallet_no), - UNIQUE KEY uk_ll_dropship_profile_key(customer_id,idempotency_key), KEY idx_ll_dropship_profile_order(customer_id,order_id) -) ENGINE=InnoDB COMMENT='一件代发托盘档案'; -CREATE TABLE IF NOT EXISTS ll_dropship_carton ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', order_id BIGINT NOT NULL COMMENT '订单ID', profile_id BIGINT NOT NULL COMMENT '托盘档案ID', - warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(128) NULL COMMENT '托盘号', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', - carton_mark VARCHAR(128) NOT NULL COMMENT '箱唛', carton_sequence INT NOT NULL COMMENT '箱唛序号', status VARCHAR(32) NOT NULL DEFAULT 'PENDING_INBOUND' COMMENT '业务状态', - outbound_order_no VARCHAR(128) NULL COMMENT '出库单号', version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_dropship_carton(customer_id,order_id,carton_mark), KEY idx_ll_dropship_carton_status(customer_id,status), - KEY idx_ll_dropship_carton_sku(customer_id,sku_code,status) -) ENGINE=InnoDB COMMENT='一件代发箱唛明细'; -CREATE TABLE IF NOT EXISTS ll_dropship_sku_inventory ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', order_id BIGINT NOT NULL COMMENT '订单ID', profile_id BIGINT NOT NULL COMMENT '托盘档案ID', - sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', product_name VARCHAR(255) NULL COMMENT '产品名称', package_count BIGINT NOT NULL COMMENT '箱数', - product_quantity BIGINT NOT NULL COMMENT '产品数量', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_dropship_sku_inventory(profile_id,sku_code), KEY idx_ll_dropship_sku_order(customer_id,order_id,sku_code) -) ENGINE=InnoDB COMMENT='一件代发SKU库存汇总'; -CREATE TABLE IF NOT EXISTS ll_dropship_carton_ledger ( - id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', order_id BIGINT NOT NULL COMMENT '订单ID', carton_id BIGINT NOT NULL COMMENT '箱唛记录ID', - carton_mark VARCHAR(128) NOT NULL COMMENT '箱唛', sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码', operation_type VARCHAR(32) NOT NULL COMMENT '操作类型', - before_packages BIGINT NOT NULL COMMENT '变动前箱数', delta_packages BIGINT NOT NULL COMMENT '箱数变动量', after_packages BIGINT NOT NULL COMMENT '变动后箱数', - business_order_no VARCHAR(128) NULL COMMENT '业务单号', idempotency_key VARCHAR(255) NOT NULL COMMENT '业务幂等键', remark VARCHAR(1000) NULL COMMENT '备注', - occurred_at DATETIME(3) NOT NULL COMMENT '业务发生时间', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_dropship_ledger_key(customer_id,idempotency_key), KEY idx_ll_dropship_ledger_sku(customer_id,sku_code,carton_mark) -) ENGINE=InnoDB COMMENT='一件代发箱唛库存流水'; - -CREATE TABLE IF NOT EXISTS ll_finance_fee_source ( - id BIGINT NOT NULL COMMENT '费用版本记录ID', source_fee_id BIGINT NOT NULL COMMENT '跨版本稳定费用来源ID', - source_version INT NOT NULL COMMENT '费用来源版本,从1递增', customer_id VARCHAR(128) NOT NULL COMMENT '客户ID和隔离键', - customer_name VARCHAR(200) NULL COMMENT '客户名称快照', source_type VARCHAR(64) NOT NULL COMMENT '海外费用来源类型', - source_no VARCHAR(128) NOT NULL COMMENT '来源业务编号或入仓码快照', business_type VARCHAR(32) NOT NULL COMMENT '来源业务类型', - business_id BIGINT NULL COMMENT '来源业务记录ID', business_no VARCHAR(128) NOT NULL COMMENT '来源业务编号', - order_id BIGINT NULL COMMENT '关联订单ID', inbound_id BIGINT NULL COMMENT '关联海外入仓计划或入仓记录ID', - inbound_code VARCHAR(64) NULL COMMENT '关联入仓码;并非所有费用必填', container_id BIGINT NULL COMMENT '关联柜次ID', - container_booking_id BIGINT NULL COMMENT '来源订舱柜ID', container_no VARCHAR(64) NULL COMMENT '真实集装箱号快照', - warehouse_id BIGINT NULL COMMENT '关联海外仓ID', fee_item_code VARCHAR(64) NOT NULL COMMENT '费用项目编码快照', - fee_item_name VARCHAR(200) NOT NULL COMMENT '费用项目名称快照', direction VARCHAR(16) NOT NULL COMMENT 'RECEIVABLE应收或PAYABLE应付', - supplier_id BIGINT NULL COMMENT '应付供应商ID', supplier_name VARCHAR(200) NULL COMMENT '应付供应商名称快照', - supplier_category VARCHAR(32) NULL COMMENT '应付供应商类别约束', settlement_mode VARCHAR(16) NULL COMMENT 'ON_ACCOUNT账期应付或DIRECT_PAID业务已付', - paid_at DATETIME(3) NULL COMMENT '直接已付时间', payment_method VARCHAR(32) NULL COMMENT '直接已付方式', - payment_reference_no VARCHAR(128) NULL COMMENT '直接已付流水号', payment_voucher_file_ids JSON NULL COMMENT '直接已付凭证文件ID快照', - business_date DATE NOT NULL COMMENT '费用业务日期', currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '财务结算币种,当前固定CNY', - amount DECIMAL(20,6) NOT NULL COMMENT '费用金额', review_status VARCHAR(16) NOT NULL COMMENT 'DRAFT、PENDING、APPROVED或REJECTED', - publication_status VARCHAR(16) NOT NULL COMMENT 'UNPUBLISHED或PUBLISHED', source_status VARCHAR(16) NOT NULL COMMENT 'ACTIVE、SUPERSEDED或VOIDED', - review_reason VARCHAR(500) NULL COMMENT '审核或作废原因', reviewer_id VARCHAR(128) NULL COMMENT '审核人ID', reviewed_at DATETIME(3) NULL COMMENT '审核时间', - created_by VARCHAR(128) NOT NULL COMMENT '创建人ID', updated_by VARCHAR(128) NOT NULL COMMENT '最后更新人ID', - created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '最后更新时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_finance_fee_version(source_fee_id,source_version), - KEY idx_ll_finance_fee_customer(customer_id,source_status,created_at), KEY idx_ll_finance_fee_business(business_type,business_no,created_at), - KEY idx_ll_finance_fee_container_customer(container_booking_id,customer_id,source_status,created_at), - CONSTRAINT chk_ll_finance_fee_amount CHECK(amount>0), CONSTRAINT chk_ll_finance_fee_currency CHECK(currency='CNY'), - CONSTRAINT chk_ll_finance_fee_direction CHECK(direction IN('RECEIVABLE','PAYABLE')), - CONSTRAINT chk_ll_finance_fee_review CHECK(review_status IN('DRAFT','PENDING','APPROVED','REJECTED')), - CONSTRAINT chk_ll_finance_fee_publication CHECK(publication_status IN('UNPUBLISHED','PUBLISHED')), - CONSTRAINT chk_ll_finance_fee_status CHECK(source_status IN('ACTIVE','SUPERSEDED','VOIDED')) -) ENGINE=InnoDB COMMENT='海外业务不可变费用来源版本;发布后经跨区事件进入Finance'; - -SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_finance_fee_source' AND index_name='idx_ll_finance_fee_container_customer'), 'SELECT 1', 'ALTER TABLE ll_finance_fee_source ADD KEY idx_ll_finance_fee_container_customer(container_booking_id,customer_id,source_status,created_at)')); -PREPARE ll_finance_fee_ddl FROM @ddl; EXECUTE ll_finance_fee_ddl; DEALLOCATE PREPARE ll_finance_fee_ddl; - -CREATE TABLE IF NOT EXISTS ll_finance_fee_command ( - id BIGINT NOT NULL COMMENT '幂等命令ID', operator_id VARCHAR(128) NOT NULL COMMENT '操作人ID', - action VARCHAR(16) NOT NULL COMMENT 'CREATE、SUBMIT、REVIEW、ADJUST或VOID', idempotency_key VARCHAR(128) NOT NULL COMMENT '操作幂等键', - request_hash CHAR(64) NOT NULL COMMENT '请求内容SHA-256', source_fee_id BIGINT NOT NULL COMMENT '稳定费用来源ID', - source_version INT NOT NULL COMMENT '命令结果版本', created_at DATETIME(3) NOT NULL COMMENT '命令创建时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_finance_fee_command(operator_id,action,idempotency_key), - KEY idx_ll_finance_fee_command_source(source_fee_id,source_version) -) ENGINE=InnoDB COMMENT='海外费用来源写操作幂等审计'; - -CREATE TABLE IF NOT EXISTS ll_exception_order ( - id BIGINT NOT NULL COMMENT '异常订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', exception_no VARCHAR(64) NOT NULL COMMENT '异常订单号', - exception_type VARCHAR(32) NOT NULL COMMENT '异常类型', status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '异常处理状态', reason VARCHAR(1000) NOT NULL COMMENT '异常原因', - last_mile_order_id BIGINT NULL COMMENT '关联尾程订单ID', last_mile_order_no VARCHAR(64) NULL COMMENT '关联尾程订单号', inbound_order_id BIGINT NULL COMMENT '关联入仓单ID', inbound_code VARCHAR(128) NULL COMMENT '关联入仓码', - delivery_order_id BIGINT NULL COMMENT '关联派送单ID', delivery_no VARCHAR(64) NULL COMMENT '关联派送单号', outbound_no VARCHAR(64) NULL COMMENT '关联出库单号', - customer_name VARCHAR(255) NULL COMMENT '客户名称快照', overseas_warehouse_id VARCHAR(128) NULL COMMENT '海外仓ID快照', overseas_warehouse_name VARCHAR(255) NULL COMMENT '海外仓名称快照', - sku_code VARCHAR(128) NULL COMMENT '异常货物SKU', package_count INT NULL COMMENT '异常箱数', return_direction VARCHAR(32) NULL COMMENT '退回方向', return_logistics_no VARCHAR(128) NULL COMMENT '退回物流单号', - handling_action VARCHAR(500) NULL COMMENT '异常处理措施', handling_result VARCHAR(2000) NULL COMMENT '异常处理结果', - evidence_file_ids_json JSON NULL COMMENT '异常处理证据文件ID列表', inventory_adjustment_id BIGINT NULL COMMENT '退回库存恢复操作ID', - handler_id VARCHAR(128) NULL COMMENT '处理人ID', handler_name VARCHAR(128) NULL COMMENT '处理人名称', - source_type VARCHAR(32) NOT NULL DEFAULT 'MANUAL' COMMENT '异常来源类型', created_by VARCHAR(128) NULL COMMENT '创建人ID', - exception_at DATETIME(3) NOT NULL COMMENT '异常发生时间', completed_at DATETIME(3) NULL COMMENT '异常处理完成时间', - version BIGINT NOT NULL DEFAULT 0 COMMENT '异常订单乐观锁版本', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_exception_no(customer_id,exception_no), UNIQUE KEY uk_ll_exception_delivery_return(customer_id,delivery_order_id,exception_type), - KEY idx_ll_exception_list(customer_id,status,exception_at), KEY idx_ll_exception_tail(customer_id,last_mile_order_no), KEY idx_ll_exception_inbound(customer_id,inbound_code) -) ENGINE=InnoDB COMMENT='海外仓异常订单'; -CREATE TABLE IF NOT EXISTS ll_exception_return_item ( - id BIGINT NOT NULL COMMENT '异常退回明细ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', - exception_order_id BIGINT NOT NULL COMMENT '异常订单ID', outbound_pallet_item_id BIGINT NOT NULL COMMENT '原出库托盘明细ID', - inventory_position_id BIGINT NOT NULL COMMENT '原出库库存位置ID', pallet_no VARCHAR(128) NULL COMMENT '原出库托盘码快照', - sku_code VARCHAR(128) NULL COMMENT '原出库SKU快照', max_return_packages BIGINT NOT NULL COMMENT '原出库可退箱数上限', - approved_return_packages BIGINT NOT NULL COMMENT '批准退回箱数', created_at DATETIME(3) NOT NULL COMMENT '创建时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_exception_return_source(customer_id,exception_order_id,outbound_pallet_item_id,inventory_position_id), - KEY idx_ll_exception_return_order(customer_id,exception_order_id) -) ENGINE=InnoDB COMMENT='异常退回原出库库存冻结明细'; -CREATE TABLE IF NOT EXISTS ll_exception_order_command ( - id BIGINT NOT NULL COMMENT '异常处理命令ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', - exception_order_id BIGINT NOT NULL COMMENT '异常订单ID', action VARCHAR(32) NOT NULL COMMENT '异常处理动作', - idempotency_key VARCHAR(255) NOT NULL COMMENT '幂等键', request_hash VARCHAR(64) NOT NULL COMMENT '请求内容SHA256哈希', - result_json JSON NOT NULL COMMENT '命令结果快照', created_at DATETIME(3) NOT NULL COMMENT '创建时间', - PRIMARY KEY(id), UNIQUE KEY uk_ll_exception_command_key(customer_id,action,idempotency_key), - KEY idx_ll_exception_command_order(customer_id,exception_order_id,created_at) -) ENGINE=InnoDB COMMENT='异常处理命令幂等审计'; -CREATE TABLE IF NOT EXISTS ll_customer_visit ( - id BIGINT NOT NULL COMMENT '客户回访记录ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键', delivery_order_id BIGINT NOT NULL COMMENT '关联派送单ID', - delivery_no VARCHAR(64) NOT NULL COMMENT '关联派送单号', customer_name VARCHAR(255) NULL COMMENT '客户名称快照', contact_name VARCHAR(128) NULL COMMENT '客户联系人姓名快照', - contact_phone VARCHAR(64) NULL COMMENT '客户联系人电话快照', destination VARCHAR(500) NULL COMMENT '派送目的仓编码汇总快照', - delivery_completed_at DATETIME(3) NOT NULL COMMENT '派送完成时间', status VARCHAR(32) NOT NULL DEFAULT 'PENDING' COMMENT '回访状态:PENDING待回访或COMPLETED已回访', - selected_last_mile_order_id BIGINT NULL COMMENT '本次回访选择的尾程订单ID', selected_last_mile_order_no VARCHAR(64) NULL COMMENT '本次回访选择的尾程订单号', - selected_inbound_order_id BIGINT NULL COMMENT '本次回访选择的入仓单ID', selected_inbound_code VARCHAR(128) NULL COMMENT '本次回访选择的入仓码', - visit_result VARCHAR(32) NULL COMMENT '最近一次回访结果', customer_feedback VARCHAR(2000) NULL COMMENT '最近一次客户反馈', remark VARCHAR(1000) NULL COMMENT '最近一次回访备注', - attachment_json JSON NULL COMMENT '当前回访资料文件元数据列表', visited_by VARCHAR(128) NULL COMMENT '最近一次回访操作人ID', visited_at DATETIME(3) NULL COMMENT '最近一次回访时间', - visit_count INT NOT NULL DEFAULT 0 COMMENT '累计保存回访次数', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY(id), - UNIQUE KEY uk_ll_customer_visit_delivery(customer_id,delivery_order_id), KEY idx_ll_customer_visit_list(customer_id,status,delivery_completed_at), - KEY idx_ll_customer_visit_delivery_no(customer_id,delivery_no) -) ENGINE=InnoDB COMMENT='派送单维度客户回访记录'; - -- 收敛曾由历史局部脚本建立的五期中间结构;只补结构,不回填或修复旧数据。 SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_outbound_order' AND column_name='customer_id'), 'SELECT 1', 'ALTER TABLE ll_outbound_order RENAME COLUMN tenant_id TO customer_id')); PREPARE phase5_structure_ddl FROM @ddl; EXECUTE phase5_structure_ddl; DEALLOCATE PREPARE phase5_structure_ddl; diff --git a/iam/src/main/resources/db/lastleg-permissions.sql b/iam/src/main/resources/db/lastleg-permissions.sql index 1f17c177c..3ff8d9f52 100644 --- a/iam/src/main/resources/db/lastleg-permissions.sql +++ b/iam/src/main/resources/db/lastleg-permissions.sql @@ -39,12 +39,8 @@ VALUES (5107061,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:create','创建海外库位',NULL,'POST',761,'ACTIVE',1,0), (5107062,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:edit','编辑海外库位',NULL,'PUT',762,'ACTIVE',1,0), (5107063,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:delete','删除海外库位',NULL,'DELETE',763,'ACTIVE',1,0), - (5107230,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:carton:list','海外箱号','/overseas-warehouse/cartons','GET',930,'ACTIVE',1,0), - (5107231,0,'PLATFORM','BUTTON',5107230,'platform:overseas-warehouse:carton:create','创建海外箱号',NULL,'POST',931,'ACTIVE',1,0), - (5107232,0,'PLATFORM','BUTTON',5107230,'platform:overseas-warehouse:carton:edit','编辑海外箱号',NULL,'PUT',932,'ACTIVE',1,0), - (5107240,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:product:list','海外产品库','/overseas-warehouse/products','GET',940,'ACTIVE',1,0), - (5107241,0,'PLATFORM','BUTTON',5107240,'platform:overseas-warehouse:product:create','创建海外产品',NULL,'POST',941,'ACTIVE',1,0), - (5107242,0,'PLATFORM','BUTTON',5107240,'platform:overseas-warehouse:product:edit','编辑海外产品',NULL,'PUT',942,'ACTIVE',1,0), + (5107190,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:return-inventory:list','退货库存管理','/overseas-warehouse/return-inventory','GET',890,'ACTIVE',1,0), + (5107191,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:return-cartons:list','退货箱号管理','/overseas-warehouse/return-cartons','GET',891,'ACTIVE',1,0), (5107090,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:outbound:list','海外出库单','/overseas-warehouse/outbounds','GET',765,'ACTIVE',1,0), (5107091,0,'PLATFORM','BUTTON',5107090,'platform:overseas-warehouse:outbound:create','创建海外出库单',NULL,'POST',766,'ACTIVE',1,0), (5107092,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:delivery:list','海外派送单','/overseas-warehouse/delivery-orders','GET',767,'ACTIVE',1,0), diff --git a/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java index 073da84a4..29b1469dd 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java @@ -41,7 +41,7 @@ class OverseasPhase4PermissionSqlContractTest { assertThat(sql).contains(REQUIRED.toArray(String[]::new)); assertThat(sql).contains("'lastleg:pda:operate'"); assertPdaPickerGrant(sql); - assertThat(catalog).hasSize(56).noneMatch(code -> code.endsWith(":view")); + assertThat(catalog).hasSize(58).noneMatch(code -> code.endsWith(":view")); assertThat(sql).contains("permission_code LIKE 'platform:lastleg:%'", "status='INACTIVE'", "deleted=1"); assertThat(sql).doesNotContain(":carton:", ":product:"); assertThat(catalog).contains("platform:overseas-warehouse:delivery:list"); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/mapper/PdaWarehouseMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/mapper/PdaWarehouseMapper.java index 586d7dde6..47af11c35 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/mapper/PdaWarehouseMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/pda/warehouse/mapper/PdaWarehouseMapper.java @@ -52,7 +52,7 @@ public interface PdaWarehouseMapper extends BaseMapper { "FROM ll_pda_operation_history h WHERE h.overseas_warehouse_id=#{warehouseId} AND h.operator_key=#{operatorKey} " + "AND h.operation_type=#{operationType} " + "UNION ALL SELECT o.id,CONCAT('RECEIVING_',o.action),s.container_no,'COMPLETED'," + - "CONCAT('柜号作业 ',s.container_no),s.customer_id,o.created_at " + + "CONCAT('柜号作业 ',s.container_no),NULL customer_id,o.created_at " + "FROM ll_receiving_container_operation o JOIN ll_receiving_container_session s ON s.id=o.session_id " + "WHERE s.overseas_warehouse_id=#{warehouseId} AND o.operator_key=#{operatorKey} " + "AND CONCAT('RECEIVING_',o.action)=#{operationType} " + diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java b/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java index 5a4efd302..ce50bb094 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java @@ -15,6 +15,8 @@ public final class OverseasPermissions { public static final String RELABEL_ORDER_LIST = "platform:overseas-warehouse:relabel-order:list"; public static final String RELABEL_ORDER_CREATE = "platform:overseas-warehouse:relabel-order:create"; public static final String RELABEL_ORDER_STATUS = "platform:overseas-warehouse:relabel-order:status"; + public static final String RETURN_INVENTORY_LIST = "platform:overseas-warehouse:return-inventory:list"; + public static final String RETURN_CARTONS_LIST = "platform:overseas-warehouse:return-cartons:list"; public static final String INVENTORY_LIST = "platform:overseas-warehouse:inventory:list"; public static final String INVENTORY_EXPORT = "platform:overseas-warehouse:inventory:export"; public static final String INVENTORY_EDIT = "platform:overseas-warehouse:inventory:edit"; diff --git a/lastleg-service/src/main/resources/db/lastleg.sql b/lastleg-service/src/main/resources/db/lastleg.sql index 4d39e0b4f..0b4c9ec47 100644 --- a/lastleg-service/src/main/resources/db/lastleg.sql +++ b/lastleg-service/src/main/resources/db/lastleg.sql @@ -952,7 +952,7 @@ CREATE TABLE IF NOT EXISTS ll_inbound_pallet_merge ( KEY idx_ll_inbound_merge_task (customer_id, task_id), KEY idx_ll_inbound_merge_group (merge_group_no) ) ENGINE=InnoDB COMMENT='入仓托盘合托记录'; -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')); +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 COMMENT ''FBA仓库编码'' AFTER inbound_code')); PREPARE inbound_schema_stmt FROM @ddl; EXECUTE inbound_schema_stmt; DEALLOCATE PREPARE inbound_schema_stmt; SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_inbound_plan_line' AND column_name='customer_id'), 'SELECT 1', 'ALTER TABLE ll_inbound_plan_line ADD COLUMN customer_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''客户账号标识'' AFTER id')); PREPARE receiving_container_line_stmt FROM @ddl; EXECUTE receiving_container_line_stmt; DEALLOCATE PREPARE receiving_container_line_stmt; @@ -1356,7 +1356,7 @@ PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_pallet_lock' AND column_name='dispatch_order_id' AND is_nullable='YES'), 'SELECT 1', 'ALTER TABLE ll_dispatch_pallet_lock MODIFY COLUMN dispatch_order_id BIGINT NULL COMMENT ''正式派车单ID,草稿锁阶段为空''')); PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE PREPARE dispatch_schema_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='order_refs'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN order_refs VARCHAR(2000) NULL AFTER order_no')); +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_dispatch_item' AND column_name='order_refs'), 'SELECT 1', 'ALTER TABLE ll_dispatch_item ADD COLUMN order_refs VARCHAR(2000) NULL COMMENT ''关联订单信息'' AFTER order_no')); PREPARE dispatch_schema_stmt FROM @ddl; EXECUTE dispatch_schema_stmt; DEALLOCATE PREPARE dispatch_schema_stmt; CREATE TABLE IF NOT EXISTS ll_dispatch_pda_task ( @@ -2058,6 +2058,21 @@ CREATE TABLE IF NOT EXISTS ll_security_projection ( KEY idx_security_projection_permission (aggregate_id,permission_version) ) ENGINE=InnoDB COMMENT='海外IAM安全状态与权限版本投影'; +-- 收敛尚未具备授权快照字段的开发/测试库,CREATE TABLE IF NOT EXISTS 不会补充已存在表的字段。 +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='ll_security_projection' AND column_name='roles_json'), 'SELECT 1', + 'ALTER TABLE ll_security_projection ADD COLUMN roles_json JSON NULL COMMENT ''IAM投影的当前角色快照'' AFTER permission_version')); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='ll_security_projection' AND column_name='authorities_json'), 'SELECT 1', + 'ALTER TABLE ll_security_projection ADD COLUMN authorities_json JSON NULL COMMENT ''IAM投影的当前海外权限快照'' AFTER roles_json')); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +UPDATE ll_security_projection SET roles_json=JSON_ARRAY() WHERE roles_json IS NULL; +UPDATE ll_security_projection SET authorities_json=JSON_ARRAY() WHERE authorities_json IS NULL; +ALTER TABLE ll_security_projection + MODIFY COLUMN roles_json JSON NOT NULL COMMENT 'IAM投影的当前角色快照', + MODIFY COLUMN authorities_json JSON NOT NULL COMMENT 'IAM投影的当前海外权限快照'; + -- 空库基线固定管理员必须携带当前海外授权快照;后续真实 IAM 事件从 aggregate_version=1 单调覆盖该 version=0 投影。 SET @platform_admin_overseas_roles = JSON_ARRAY('PLATFORM_ADMIN'); SET @platform_admin_overseas_authorities = JSON_ARRAY( @@ -2121,9 +2136,6 @@ SET @platform_admin_overseas_authorities = JSON_ARRAY( 'platform:overseas-master-data:vehicle:export', 'platform:overseas-master-data:vehicle:list', 'platform:overseas-master-data:vehicle:status', - 'platform:overseas-warehouse:carton:create', - 'platform:overseas-warehouse:carton:edit', - 'platform:overseas-warehouse:carton:list', 'platform:overseas-warehouse:customer-visit:edit', 'platform:overseas-warehouse:customer-visit:list', 'platform:overseas-warehouse:delivery:documents', @@ -2160,12 +2172,11 @@ SET @platform_admin_overseas_authorities = JSON_ARRAY( 'platform:overseas-warehouse:pallet:delete', 'platform:overseas-warehouse:pallet:edit', 'platform:overseas-warehouse:pallet:list', - 'platform:overseas-warehouse:product:create', - 'platform:overseas-warehouse:product:edit', - 'platform:overseas-warehouse:product:list', 'platform:overseas-warehouse:relabel-order:create', 'platform:overseas-warehouse:relabel-order:list', 'platform:overseas-warehouse:relabel-order:status', + 'platform:overseas-warehouse:return-cartons:list', + 'platform:overseas-warehouse:return-inventory:list', 'platform:overseas-warehouse:warehouse:create', 'platform:overseas-warehouse:warehouse:edit', 'platform:overseas-warehouse:warehouse:list', diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/delivery/DeliverySchemaContractTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/delivery/DeliverySchemaContractTest.java index 9dca12033..1c69473d7 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/delivery/DeliverySchemaContractTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/delivery/DeliverySchemaContractTest.java @@ -64,7 +64,7 @@ class DeliverySchemaContractTest { String overseas = Files.readString(Path.of("..", "deploy", "sql", "海外区域统一增量-MySQL8.sql"), StandardCharsets.UTF_8).toLowerCase(); - assertTrue(overseas.contains("空库先执行 lastleg-service/src/main/resources/db/lastleg.sql 基线")); + assertTrue(overseas.contains("begin inline empty-database baseline: lastleg")); assertTrue(overseas.contains(createToken)); assertTrue(overseas.indexOf(createToken) < overseas.indexOf("assert_phase5_lastleg_identifiers_migratable")); assertTrue(overseas.contains("alter table ll_delivery_order add column overseas_warehouse_name")); diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/pda/warehouse/PdaWarehouseContractTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/pda/warehouse/PdaWarehouseContractTest.java index 7d999d81c..a31c6267b 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/pda/warehouse/PdaWarehouseContractTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/pda/warehouse/PdaWarehouseContractTest.java @@ -60,6 +60,14 @@ class PdaWarehouseContractTest { .contains("unique key uk_ll_pda_history_idempotency(operator_key,idempotency_key)"); } + @Test + void sharedContainerHistoryDoesNotReadRemovedCustomerScope() throws Exception { + String mapper = Files.readString(Path.of( + "src/main/java/com/baiyue/lastleg/pda/warehouse/mapper/PdaWarehouseMapper.java")); + assertThat(mapper).contains("NULL customer_id") + .doesNotContain("s.customer_id"); + } + @Test void openApiAndGatewayPublishOnlyStablePdaPaths() throws Exception { String openapi = Files.readString(Path.of("src/main/resources/openapi/overseas-pda-operations-v1.yaml")); diff --git a/scripts/admin-test-env-acceptance.mjs b/scripts/admin-test-env-acceptance.mjs index e5b216507..a92d0ef0b 100644 --- a/scripts/admin-test-env-acceptance.mjs +++ b/scripts/admin-test-env-acceptance.mjs @@ -1582,7 +1582,9 @@ export class AcceptanceRun { if (Number(readiness().overseasContainerCount || 0) < 1) { await this.runPhase4ProducerVariant('OVERSEAS-PRIMARY', 'OVERSEAS', 'ONE_CLICK_DROPSHIP', true) } - if (Number(readiness().distinctContainerCount || 0) < 4) { + const hasSecondaryProducer = () => (this.createdResources.phase4InboundProducerFixtures?.containers || []) + .some((item) => String(item?.resourceKey || '').includes('-P4-SECONDARY:')) + if (!hasSecondaryProducer()) { await this.runPhase4ProducerVariant('SECONDARY', 'FBA', 'STANDARD', false) } const matrix = this.createdResources.phase4InboundProducerFixtures diff --git a/scripts/admin-test-env-modules/initialization-baseline-contract.test.mjs b/scripts/admin-test-env-modules/initialization-baseline-contract.test.mjs index a5a501293..dd3633d11 100644 --- a/scripts/admin-test-env-modules/initialization-baseline-contract.test.mjs +++ b/scripts/admin-test-env-modules/initialization-baseline-contract.test.mjs @@ -92,18 +92,26 @@ test('海外空库基线为固定平台管理员提供完整version0授权投影 )?.[1] assert.ok(authorityBlock, 'missing platform_admin overseas authority snapshot') const authorities = [...authorityBlock.matchAll(/'([^']+)'/g)].map((match) => match[1]) - assert.equal(authorities.length, 109) + const deferred = new Set([ + 'platform:overseas-warehouse:carton:list', + 'platform:overseas-warehouse:carton:create', + 'platform:overseas-warehouse:carton:edit', + 'platform:overseas-warehouse:product:list', + 'platform:overseas-warehouse:product:create', + 'platform:overseas-warehouse:product:edit', + ]) + assert.equal(authorities.length, 105) assert.equal(new Set(authorities).size, authorities.length, 'baseline authorities must not contain duplicates') assert.equal(authorities.filter((item) => item.startsWith('platform:finance:')).length, 34) assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-business:')).length, 11) assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-master-data:')).length, 15) - assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-warehouse:')).length, 49) + assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-warehouse:')).length, 45) for (const authority of authorities) { assert.ok(sql.includes(`'${authority}'`), `authority is absent from the domestic IAM baseline: ${authority}`) } for (const source of [overseasWarehousePermissions, overseasBusinessPermissions, overseasMasterDataPermissions]) { const declared = [...source.matchAll(/'((?:platform:overseas-warehouse|platform:overseas-business|platform:overseas-master-data):[^']+)'/g)] - .map((match) => match[1]) + .map((match) => match[1]).filter((authority) => !deferred.has(authority)) for (const authority of declared) { assert.ok( [lastlegPermissionSeed, phase5DeliveryPermissionSeed].some((seed) => seed.includes(`'${authority}'`)), @@ -112,6 +120,10 @@ test('海外空库基线为固定平台管理员提供完整version0授权投影 assert.ok(authorities.includes(authority), `Admin permission is absent from the fixed-admin overseas snapshot: ${authority}`) } } + for (const authority of deferred) { + assert.ok(!lastlegPermissionSeed.includes(`'${authority}'`), `deferred permission entered the IAM source seed: ${authority}`) + assert.ok(!authorities.includes(authority), `deferred permission entered the fixed-admin snapshot: ${authority}`) + } for (const required of [ 'platform:overseas-warehouse:last-mile-order:list', 'platform:overseas-warehouse:inbound-order:list', diff --git a/scripts/admin-test-env-modules/phase3-phase4-producer-fixture-contract.test.mjs b/scripts/admin-test-env-modules/phase3-phase4-producer-fixture-contract.test.mjs index 83d107f6c..74b0a5af0 100644 --- a/scripts/admin-test-env-modules/phase3-phase4-producer-fixture-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase3-phase4-producer-fixture-contract.test.mjs @@ -120,6 +120,9 @@ test('only PDA-operated variants traverse real outbound and carrier nodes before assert.match(entry, /runPhase4ProducerVariant\('OVERSEAS-PRIMARY', 'OVERSEAS', 'ONE_CLICK_DROPSHIP', true\)/) assert.match(entry, /runPhase4ProducerVariant\('FBA-STANDARD', 'FBA', 'STANDARD', true\)/) assert.match(entry, /runPhase4ProducerVariant\('SECONDARY', 'FBA', 'STANDARD', false\)/) + assert.match(entry, /const hasSecondaryProducer =/) + assert.match(entry, /if \(!hasSecondaryProducer\(\)\)/) + assert.doesNotMatch(entry, /if \(Number\(readiness\(\)\.distinctContainerCount \|\| 0\) < 4\)/) const start = entry.indexOf('if (pickupRequired && producerKey)') const end = entry.indexOf('} finally {', start) const pickupChain = entry.slice(start, end)