diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index cd224e64f..c9b72af44 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -685,6 +685,33 @@ CREATE TABLE IF NOT EXISTS ord_order_party ( CONSTRAINT fk_party_order FOREIGN KEY (order_id) REFERENCES ord_order (id) ) ENGINE=InnoDB COMMENT='订单收发货方快照表:固化下单时发货人和收货人信息,避免主数据变化影响历史订单'; +CREATE TABLE IF NOT EXISTS ord_customer_address ( + id BIGINT UNSIGNED NOT NULL COMMENT '客户地址ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和数据隔离键', + address_type VARCHAR(32) NOT NULL COMMENT 'PICKUP取货地址或PRIVATE_DESTINATION私人目的仓', + address_name VARCHAR(64) NOT NULL COMMENT '客户自定义地址名称', + company_name VARCHAR(128) NOT NULL COMMENT '公司名称', + contact_name VARCHAR(64) NOT NULL COMMENT '联系人', + phone VARCHAR(32) NOT NULL COMMENT '联系电话', + email VARCHAR(128) NULL COMMENT '联系邮箱', + country_code CHAR(2) NOT NULL COMMENT '国家二字码', + province VARCHAR(64) NULL COMMENT '省州', + city VARCHAR(64) NOT NULL COMMENT '城市', + district VARCHAR(64) NULL COMMENT '区县', + address_line VARCHAR(255) NOT NULL COMMENT '详细地址', + postal_code VARCHAR(20) NULL COMMENT '邮政编码', + default_address TINYINT(1) NOT NULL DEFAULT 0 COMMENT '同类型默认地址', + active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否可选', + created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', + updated_by BIGINT UNSIGNED NOT 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), + KEY idx_customer_address_scope (tenant_id, address_type, active, updated_at) +) ENGINE=InnoDB COMMENT='客户自有下单地址簿;不承载平台仓库主档'; + CREATE TABLE IF NOT EXISTS ord_order_cargo ( id BIGINT UNSIGNED NOT NULL COMMENT '货物明细ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和数据隔离键', @@ -721,6 +748,7 @@ CREATE TABLE IF NOT EXISTS ord_order_cargo ( shipment_id VARCHAR(64) NULL COMMENT '本货物明细对应的Amazon Shipment ID', reference_id VARCHAR(64) NULL COMMENT '本货物明细对应的Amazon Reference ID', product_image_file_id BIGINT UNSIGNED NULL COMMENT 'File服务中的产品图片逻辑文件ID', + wooden_product TINYINT(1) NOT NULL DEFAULT 0 COMMENT '木制品权威判定快照;1时订单必须商检', created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', updated_by BIGINT UNSIGNED NOT NULL COMMENT '最后修改人ID', @@ -1733,6 +1761,7 @@ CALL phase1_add_column('ord_order_cargo', 'product_height_cm', "DECIMAL(12,2) NU CALL phase1_add_column('ord_order_cargo', 'shipment_id', "VARCHAR(64) NULL COMMENT 'Cargo Amazon Shipment ID'"); CALL phase1_add_column('ord_order_cargo', 'reference_id', "VARCHAR(64) NULL COMMENT 'Cargo Amazon Reference ID'"); CALL phase1_add_column('ord_order_cargo', 'product_image_file_id', "BIGINT UNSIGNED NULL COMMENT 'Product image logical file ID'"); +CALL phase1_add_column('ord_order_cargo', 'wooden_product', "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '木制品权威判定快照;1时订单必须商检'"); UPDATE ord_order_cargo cargo JOIN ord_order orders ON orders.id = cargo.order_id AND orders.tenant_id = cargo.tenant_id @@ -2502,6 +2531,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_order ( destination_name VARCHAR(128) NULL COMMENT '目的仓名称快照', hold_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '当前是否扣货', current_hold_reason VARCHAR(500) NULL COMMENT '当前扣货理由快照', + last_overseas_hold_version BIGINT UNSIGNED NULL COMMENT '海外暂扣事件最新聚合版本,用于阻止乱序覆盖', total_package_count INT UNSIGNED NULL COMMENT '确认后的总箱数', actual_gross_weight_kg DECIMAL(18,3) NULL COMMENT '确认后的实际总毛重kg', chargeable_weight_kg DECIMAL(18,3) NULL COMMENT '当前费用快照的计费重量kg', @@ -2791,6 +2821,7 @@ CREATE TABLE IF NOT EXISTS fl_inbound_carton_label ( inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '订单货物明细ID,不建立跨库外键', cargo_item_no INT UNSIGNED NOT NULL COMMENT '订单货物明细序号快照', cargo_name VARCHAR(255) NULL COMMENT '货物名称快照', + sku_code VARCHAR(128) NULL COMMENT '箱唛绑定的SKU快照;二维码内容不变', detail_package_count INT UNSIGNED NOT NULL COMMENT '该订单货物明细箱数快照', inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', box_code VARCHAR(80) NOT NULL COMMENT '固定二维码内容:入仓码#总箱数-箱下标', @@ -2828,6 +2859,7 @@ BEGIN END$$ DELIMITER ; CALL unified_carton_label_add_column('label_version', 'INT UNSIGNED NOT NULL DEFAULT 1 COMMENT ''内部兼容批次字段,固定为1且不进入箱码'' AFTER carton_index'); +CALL unified_carton_label_add_column('sku_code', 'VARCHAR(128) NULL COMMENT ''箱唛绑定的SKU快照;二维码内容不变'' AFTER cargo_name'); CALL unified_carton_label_add_column('batch_status', 'VARCHAR(16) NOT NULL DEFAULT ''ACTIVE'' COMMENT ''批次状态:ACTIVE有效、VOID已作废'' AFTER label_version'); CALL unified_carton_label_add_column('cargo_fingerprint', 'CHAR(64) NULL COMMENT ''影响标签字段的SHA-256指纹'' AFTER batch_status'); CALL unified_carton_label_add_column('voided_at', 'DATETIME(3) NULL COMMENT ''批次作废时间'' AFTER cargo_fingerprint'); @@ -4272,6 +4304,7 @@ DELIMITER ; CALL unified_assert_table('baiyue_auth', 'auth_account'); CALL unified_assert_table('baiyue_iam', 'iam_permission'); CALL unified_assert_table('baiyue_order', 'ord_order'); +CALL unified_assert_table('baiyue_order', 'ord_customer_address'); CALL unified_assert_table('baiyue_warehouse', 'wh_warehouse'); CALL unified_assert_table('baiyue_warehouse', 'wh_pallet'); CALL unified_assert_table('baiyue_warehouse', 'wh_location'); @@ -4287,6 +4320,7 @@ CALL unified_assert_column('baiyue_order', 'ord_order', 'carrier_name'); CALL unified_assert_column('baiyue_order', 'ord_order', 'pricing_tax_mode'); CALL unified_assert_column('baiyue_order', 'ord_order', 'inbound_code'); CALL unified_assert_column('baiyue_order', 'ord_order', 'fulfillment_type'); +CALL unified_assert_column('baiyue_order', 'ord_order_cargo', 'wooden_product'); CALL unified_assert_column('baiyue_firstleg', 'fl_inbound_pallet_allocation', 'warehouse_resource_tenant_id'); CALL unified_assert_column('baiyue_firstleg', 'fl_inbound_order', 'pricing_tax_mode'); CALL unified_assert_column('baiyue_firstleg', 'fl_inbound_order', 'fulfillment_type'); @@ -5424,6 +5458,66 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_history ( CONSTRAINT fk_loading_pick_history_item FOREIGN KEY (pick_item_id) REFERENCES fl_loading_pick_item (id) ) ENGINE=InnoDB COMMENT='PDA拣货幂等和操作审计历史'; +CREATE TABLE IF NOT EXISTS fl_loading_work_pallet ( + id BIGINT UNSIGNED NOT NULL COMMENT '一件代发现场作业托盘ID', + pick_task_id BIGINT UNSIGNED NOT NULL COMMENT 'PDA装柜拣货任务ID', + loading_plan_id BIGINT UNSIGNED NOT NULL COMMENT '装柜计划ID快照', + warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '作业仓库ID', + warehouse_pallet_id BIGINT UNSIGNED NULL COMMENT '仓库实物托盘ID;未绑定仓库资源时为空', + pallet_code VARCHAR(64) NOT NULL COMMENT '现场托盘号', + open_operation_id VARCHAR(128) NOT NULL COMMENT '开托幂等操作号', + seal_operation_id VARCHAR(128) NULL COMMENT '封托幂等操作号', + pallet_status VARCHAR(16) NOT NULL DEFAULT 'OPEN' COMMENT '托盘状态:OPEN打托中、SEALED已封托、CANCELLED已取消', + created_by BIGINT UNSIGNED NOT NULL COMMENT '创建操作人ID', + created_by_name VARCHAR(64) NULL COMMENT '创建操作人名称快照', + sealed_by BIGINT UNSIGNED NULL COMMENT '封托操作人ID', + sealed_by_name VARCHAR(64) NULL COMMENT '封托操作人名称快照', + sealed_at DATETIME(3) NULL COMMENT '封托时间', + version INT UNSIGNED 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_loading_work_pallet_code (pick_task_id, pallet_code), + UNIQUE KEY uk_loading_work_pallet_open_operation (open_operation_id), + UNIQUE KEY uk_loading_work_pallet_seal_operation (seal_operation_id), + KEY idx_loading_work_pallet_plan (loading_plan_id, pallet_status, id), + CONSTRAINT fk_loading_work_pallet_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), + CONSTRAINT fk_loading_work_pallet_plan FOREIGN KEY (loading_plan_id) REFERENCES fl_loading_plan (id), + CONSTRAINT chk_loading_work_pallet_status CHECK (pallet_status IN ('OPEN','SEALED','CANCELLED')) +) ENGINE=InnoDB COMMENT='一件代发PDA现场实际托盘;允许同托盘承载多个客户订单'; + +CREATE TABLE IF NOT EXISTS fl_loading_work_pallet_carton ( + id BIGINT UNSIGNED NOT NULL COMMENT '一件代发现场托盘箱唛绑定ID', + pick_task_id BIGINT UNSIGNED NOT NULL COMMENT 'PDA装柜拣货任务ID', + work_pallet_id BIGINT UNSIGNED NOT NULL COMMENT '现场作业托盘ID', + loading_plan_item_id BIGINT UNSIGNED NOT NULL COMMENT '装柜计划货物明细ID', + pick_item_id BIGINT UNSIGNED NOT NULL COMMENT 'PDA拣货明细ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '箱唛所属客户ID', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '来源入仓单ID', + inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '来源入仓货物明细ID', + carton_label_id BIGINT UNSIGNED NOT NULL COMMENT '稳定箱唛记录ID', + box_code VARCHAR(80) NOT NULL COMMENT '稳定箱唛箱码快照', + sku_code VARCHAR(128) NOT NULL COMMENT 'SKU编码快照', + units_per_carton INT UNSIGNED NULL COMMENT '每箱产品数量快照', + bound_by BIGINT UNSIGNED NOT NULL COMMENT '最后绑定操作人ID', + bound_by_name VARCHAR(64) NULL COMMENT '最后绑定操作人名称快照', + operation_id VARCHAR(128) NOT NULL COMMENT '最近一次绑定或移托幂等操作号', + version INT UNSIGNED 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_loading_work_carton_task_label (pick_task_id, carton_label_id), + UNIQUE KEY uk_loading_work_carton_operation (operation_id), + KEY idx_loading_work_carton_pallet (work_pallet_id, sku_code, id), + KEY idx_loading_work_carton_plan_item (loading_plan_item_id, id), + CONSTRAINT fk_loading_work_carton_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), + CONSTRAINT fk_loading_work_carton_pallet FOREIGN KEY (work_pallet_id) REFERENCES fl_loading_work_pallet (id), + CONSTRAINT fk_loading_work_carton_plan_item FOREIGN KEY (loading_plan_item_id) REFERENCES fl_loading_plan_item (id), + CONSTRAINT fk_loading_work_carton_pick_item FOREIGN KEY (pick_item_id) REFERENCES fl_loading_pick_item (id), + CONSTRAINT fk_loading_work_carton_label FOREIGN KEY (carton_label_id) REFERENCES fl_inbound_carton_label (id), + CONSTRAINT chk_loading_work_carton_units CHECK (units_per_carton IS NULL OR units_per_carton > 0) +) ENGINE=InnoDB COMMENT='一件代发PDA逐箱上托事实;客户订单不合并但实际托盘可混托'; + DROP PROCEDURE IF EXISTS repair_phase3_loading_pick_task_foreign_keys; DELIMITER $$ CREATE PROCEDURE repair_phase3_loading_pick_task_foreign_keys() @@ -9843,25 +9937,182 @@ WHERE role.tenant_id=0 AND role.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR') USE baiyue_firstleg; --- Latest container customs permissions; old case/review/receipt actions are removed. -USE baiyue_iam; -DELETE rp FROM iam_role_permission rp WHERE rp.permission_id IN (5102171,5102173,5102174,5102175); -DELETE FROM iam_permission WHERE id IN (5102171,5102173,5102174,5102175) - AND permission_code IN ('platform:firstleg:customs:view','platform:firstleg:customs:review','platform:firstleg:customs:submit','platform:firstleg:customs:receipt'); -INSERT INTO iam_permission - (id,tenant_id,app_code,permission_type,parent_id,permission_code,permission_name,route_path,http_method,sort_no,status,built_in,deleted) -VALUES - (5102170,0,'PLATFORM','MENU',5102000,'platform:firstleg:customs:list','整柜报关','/first-leg/customs','GET',100,'ACTIVE',1,0), - (5102172,0,'PLATFORM','BUTTON',5102170,'platform:firstleg:customs:manage','维护整柜报关',NULL,'POST',20,'ACTIVE',1,0) -ON DUPLICATE KEY UPDATE tenant_id=0,app_code='PLATFORM',permission_type=VALUES(permission_type), - permission_code=VALUES(permission_code),permission_name=VALUES(permission_name),parent_id=VALUES(parent_id), - route_path=VALUES(route_path),http_method=VALUES(http_method),sort_no=VALUES(sort_no),status='ACTIVE',built_in=1,deleted=0; -INSERT IGNORE INTO iam_role_permission(role_id,permission_id,tenant_id) -SELECT role.id,permission.id,0 FROM iam_role role JOIN iam_permission permission - ON permission.tenant_id=0 AND permission.app_code='PLATFORM' - AND permission.permission_code IN ('platform:firstleg:customs:list','platform:firstleg:customs:manage') -WHERE role.tenant_id=0 AND role.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR'); +-- 来源:firstleg/src/main/resources/db/phase3-container-customs-schema.sql +SET NAMES utf8mb4; USE baiyue_firstleg; + +CREATE TABLE IF NOT EXISTS fl_customs_container ( + id BIGINT UNSIGNED NOT NULL COMMENT '整柜报关聚合ID', + loading_plan_id BIGINT UNSIGNED NOT NULL COMMENT '已完成装柜计划ID;报关柜级聚合唯一键', + container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '物理货柜ID', + status VARCHAR(40) NOT NULL COMMENT '报关状态:WAITING_CUSTOMER_DOCUMENTS待资料、READY_TO_START可开始、DECLARING申报中、COMPLETED已完成', + started_by BIGINT UNSIGNED NULL COMMENT '开始报关操作人ID', + started_by_name VARCHAR(64) NULL COMMENT '开始报关操作人名称快照', + started_at DATETIME(3) NULL COMMENT '开始报关时间', + completed_by BIGINT UNSIGNED NULL COMMENT '完成报关操作人ID', + completed_by_name VARCHAR(64) NULL COMMENT '完成报关操作人名称快照', + completed_at DATETIME(3) NULL COMMENT '报关完成时间', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '聚合创建时间', + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '聚合更新时间', + version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + PRIMARY KEY(id), + UNIQUE KEY uk_customs_container_plan(loading_plan_id), + UNIQUE KEY uk_customs_container_booking(container_booking_id), + KEY idx_customs_container_status(status,updated_at), + CONSTRAINT chk_customs_container_status CHECK(status IN + ('WAITING_CUSTOMER_DOCUMENTS','READY_TO_START','DECLARING','COMPLETED')) +) ENGINE=InnoDB COMMENT='装柜完成后的整柜出口报关聚合'; + +CREATE TABLE IF NOT EXISTS fl_customs_customer_document ( + id BIGINT UNSIGNED NOT NULL COMMENT '客户报送资料ID', + customs_container_id BIGINT UNSIGNED NOT NULL COMMENT '所属整柜报关聚合ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键;只允许关联同客户退税票', + file_id BIGINT UNSIGNED NOT NULL COMMENT 'File服务文件ID', + file_name VARCHAR(255) NOT NULL COMMENT '文件名称快照', + file_hash CHAR(64) NOT NULL COMMENT '文件SHA-256摘要', + content_type VARCHAR(128) NULL COMMENT '文件媒体类型', + size_bytes BIGINT UNSIGNED NOT NULL COMMENT '文件大小(字节)', + status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '资料状态:ACTIVE有效、DELETED已删除', + uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传操作人ID', + uploaded_at DATETIME(3) NOT NULL COMMENT '上传时间', + frozen_version INT UNSIGNED NULL COMMENT '开始报关时冻结的资料版本', + frozen_at DATETIME(3) NULL COMMENT '资料冻结时间', + deleted_by BIGINT UNSIGNED NULL COMMENT '删除操作人ID', + deleted_at DATETIME(3) NULL COMMENT '删除时间', + version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '资料版本号', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '资料创建时间', + updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '资料更新时间', + PRIMARY KEY(id), + KEY idx_customs_customer_document_container(customs_container_id,status,tenant_id), + CONSTRAINT fk_customs_customer_document_container FOREIGN KEY(customs_container_id) REFERENCES fl_customs_container(id), + CONSTRAINT chk_customs_customer_document_status CHECK(status IN('ACTIVE','DELETED')), + CONSTRAINT chk_customs_customer_document_freeze CHECK((frozen_at IS NULL AND frozen_version IS NULL) OR + (frozen_at IS NOT NULL AND frozen_version IS NOT NULL)) +) ENGINE=InnoDB COMMENT='客户整份退税报送资料逻辑根'; + +CREATE TABLE IF NOT EXISTS fl_customs_customer_document_inbound ( + document_id BIGINT UNSIGNED NOT NULL COMMENT '客户报送资料ID', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '覆盖入仓单ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '覆盖入仓单客户ID', + order_id BIGINT UNSIGNED NOT NULL COMMENT '覆盖订单ID', + inbound_code VARCHAR(40) NOT NULL COMMENT '覆盖入仓码快照', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '关联创建时间', + PRIMARY KEY(document_id,inbound_id), + KEY idx_customs_document_inbound(inbound_id,tenant_id), + CONSTRAINT fk_customs_document_inbound_document FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id) +) ENGINE=InnoDB COMMENT='客户报送资料与当前柜退税入仓码多对多关系'; + +CREATE TABLE IF NOT EXISTS fl_customs_customer_document_version ( + id BIGINT UNSIGNED NOT NULL COMMENT '资料版本记录ID', + document_id BIGINT UNSIGNED NOT NULL COMMENT '客户报送资料ID', + document_version INT UNSIGNED NOT NULL COMMENT '资料版本号', + file_id BIGINT UNSIGNED NOT NULL COMMENT '本版本File服务文件ID', + file_name VARCHAR(255) NOT NULL COMMENT '本版本文件名称快照', + file_hash CHAR(64) NOT NULL COMMENT '本版本文件SHA-256摘要', + content_type VARCHAR(128) NULL COMMENT '本版本文件媒体类型', + size_bytes BIGINT UNSIGNED NOT NULL COMMENT '本版本文件大小(字节)', + scope_snapshot_json JSON NOT NULL COMMENT '本版本覆盖入仓码范围快照', + action VARCHAR(24) NOT NULL COMMENT '版本动作:UPLOAD上传、REPLACE替换、SCOPE_CHANGE范围变化、DELETE删除', + operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '版本创建时间', + PRIMARY KEY(id), + UNIQUE KEY uk_customs_customer_document_version(document_id,document_version), + CONSTRAINT fk_customs_customer_document_version FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id), + CONSTRAINT chk_customs_customer_document_version_action CHECK(action IN('UPLOAD','REPLACE','SCOPE_CHANGE','DELETE')) +) ENGINE=InnoDB COMMENT='客户报送资料文件与覆盖范围不可变版本'; + +CREATE TABLE IF NOT EXISTS fl_customs_frozen_document_inbound ( + document_id BIGINT UNSIGNED NOT NULL COMMENT '冻结的客户报送资料ID', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '冻结覆盖入仓单ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '冻结覆盖客户ID', + order_id BIGINT UNSIGNED NOT NULL COMMENT '冻结覆盖订单ID', + inbound_code VARCHAR(40) NOT NULL COMMENT '冻结覆盖入仓码快照', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '冻结关联创建时间', + PRIMARY KEY(document_id,inbound_id), + CONSTRAINT fk_customs_frozen_document FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id) +) ENGINE=InnoDB COMMENT='开始报关时冻结的客户资料覆盖范围'; + +CREATE TABLE IF NOT EXISTS fl_customs_completion_document ( + id BIGINT UNSIGNED NOT NULL COMMENT '报关完成文件ID', + source_document_id BIGINT UNSIGNED NOT NULL COMMENT '一份冻结客户资料严格对应一份完成文件逻辑根', + file_id BIGINT UNSIGNED NOT NULL COMMENT 'File服务文件ID', + file_name VARCHAR(255) NOT NULL COMMENT '完成文件名称快照', + file_hash CHAR(64) NOT NULL COMMENT '完成文件SHA-256摘要', + content_type VARCHAR(128) NULL COMMENT '完成文件媒体类型', + size_bytes BIGINT UNSIGNED NOT NULL COMMENT '完成文件大小(字节)', + uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传操作人ID', + uploaded_by_name VARCHAR(64) NULL COMMENT '上传操作人名称快照', + uploaded_at DATETIME(3) NOT NULL COMMENT '上传时间', + version INT UNSIGNED NOT NULL DEFAULT 1 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_customs_completion_source(source_document_id), + CONSTRAINT fk_customs_completion_source FOREIGN KEY(source_document_id) REFERENCES fl_customs_customer_document(id) +) ENGINE=InnoDB COMMENT='报关完成文件当前版本'; + +CREATE TABLE IF NOT EXISTS fl_customs_completion_document_version ( + id BIGINT UNSIGNED NOT NULL COMMENT '完成文件版本记录ID', + completion_document_id BIGINT UNSIGNED NOT NULL COMMENT '报关完成文件ID', + document_version INT UNSIGNED NOT NULL COMMENT '完成文件版本号', + file_id BIGINT UNSIGNED NOT NULL COMMENT '本版本File服务文件ID', + file_name VARCHAR(255) NOT NULL COMMENT '本版本文件名称快照', + file_hash CHAR(64) NOT NULL COMMENT '本版本文件SHA-256摘要', + content_type VARCHAR(128) NULL COMMENT '本版本文件媒体类型', + size_bytes BIGINT UNSIGNED NOT NULL COMMENT '本版本文件大小(字节)', + operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', + operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '版本创建时间', + PRIMARY KEY(id), + UNIQUE KEY uk_customs_completion_version(completion_document_id,document_version), + CONSTRAINT fk_customs_completion_version FOREIGN KEY(completion_document_id) REFERENCES fl_customs_completion_document(id) +) ENGINE=InnoDB COMMENT='报关完成文件不可变覆盖版本'; + +CREATE TABLE IF NOT EXISTS fl_customs_container_history ( + id BIGINT UNSIGNED NOT NULL COMMENT '报关历史记录ID', + customs_container_id BIGINT UNSIGNED NOT NULL COMMENT '所属整柜报关聚合ID', + action VARCHAR(40) NOT NULL COMMENT '报关操作类型', + from_status VARCHAR(40) NULL COMMENT '变更前报关状态', + to_status VARCHAR(40) NULL COMMENT '变更后报关状态', + remark VARCHAR(500) NULL COMMENT '操作备注', + operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', + operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '历史创建时间', + PRIMARY KEY(id), + KEY idx_customs_container_history(customs_container_id,created_at,id), + CONSTRAINT fk_customs_container_history FOREIGN KEY(customs_container_id) REFERENCES fl_customs_container(id) +) ENGINE=InnoDB COMMENT='整柜报关状态与系统触发历史'; + +CREATE TABLE IF NOT EXISTS fl_customs_command ( + id BIGINT UNSIGNED NOT NULL COMMENT '报关幂等命令ID', + actor_id BIGINT UNSIGNED NOT NULL COMMENT '命令操作人ID', + action VARCHAR(80) NOT NULL COMMENT '命令动作类型', + idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键', + request_hash CHAR(64) NOT NULL COMMENT '规范化请求SHA-256摘要', + status VARCHAR(16) NOT NULL COMMENT '命令状态:PROCESSING处理中、SUCCESS成功', + result_id BIGINT UNSIGNED NULL COMMENT '命令结果业务记录ID', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '命令创建时间', + completed_at DATETIME(3) NULL COMMENT '命令完成时间', + PRIMARY KEY(id), + UNIQUE KEY uk_customs_command(actor_id,action,idempotency_key), + CONSTRAINT chk_customs_command_status CHECK(status IN('PROCESSING','SUCCESS')) +) ENGINE=InnoDB COMMENT='整柜报关写命令幂等事实'; + +USE baiyue_iam; +DELETE rp FROM iam_role_permission rp WHERE rp.permission_id IN(5102171,5102173,5102174,5102175); +DELETE FROM iam_permission WHERE id IN(5102171,5102173,5102174,5102175) + AND permission_code IN('platform:firstleg:customs:view','platform:firstleg:customs:review','platform:firstleg:customs:submit','platform:firstleg:customs:receipt'); +INSERT INTO iam_permission(id,tenant_id,app_code,permission_type,parent_id,permission_code,permission_name, + route_path,http_method,sort_no,status,built_in,deleted) VALUES + (5102170,0,'PLATFORM','MENU',5102000,'platform:firstleg:customs:list','整柜报关','/first-leg/customs','GET',100,'ACTIVE',1,0), + (5102172,0,'PLATFORM','BUTTON',5102170,'platform:firstleg:customs:manage','维护整柜报关',NULL,'POST',20,'ACTIVE',1,0) +ON DUPLICATE KEY UPDATE permission_code=VALUES(permission_code),permission_name=VALUES(permission_name), + parent_id=VALUES(parent_id),route_path=VALUES(route_path),http_method=VALUES(http_method),status='ACTIVE',deleted=0; +INSERT IGNORE INTO iam_role_permission(role_id,permission_id,tenant_id) +SELECT r.id,p.id,0 FROM iam_role r JOIN iam_permission p ON p.tenant_id=0 AND p.app_code='PLATFORM' + AND p.permission_code IN('platform:firstleg:customs:list','platform:firstleg:customs:manage') +WHERE r.tenant_id=0 AND r.role_code IN('PLATFORM_ADMIN','ORDER_OPERATOR'); + /* Phase 3: link inbound preload plans to one or more container loading plans. */ CREATE TABLE IF NOT EXISTS fl_preload_loading_plan_link ( id BIGINT UNSIGNED NOT NULL COMMENT '关联ID', @@ -11877,6 +12128,7 @@ END$$ DELIMITER ; CALL finance_fee_source_assert_schema(); DROP PROCEDURE IF EXISTS finance_fee_source_assert_schema; + -- END FINANCE FEE SOURCE MODULE MIGRATIONS -- 九库中文注释存量升级。 @@ -12237,6 +12489,7 @@ CALL queue_table_comment('baiyue_iam', 'iam_user', 'IAM用户资料表:连接 CALL queue_table_comment('baiyue_iam', 'sys_audit_outbox', '可靠审计事件本地发送箱'); CALL queue_table_comment('baiyue_order', 'ord_idempotency_record', '订单写接口持久化幂等记录'); CALL queue_table_comment('baiyue_order', 'ord_order', '头程订单主表:保存商户委托、目的仓、运输方式和订单当前状态'); +CALL queue_table_comment('baiyue_order', 'ord_customer_address', '客户自有下单地址簿;不承载平台仓库主档'); CALL queue_table_comment('baiyue_order', 'ord_order_cargo', '订单货物明细表:记录件数、重量、体积、申报价值和危险品属性'); CALL queue_table_comment('baiyue_order', 'ord_order_fulfillment_split', '父订单→子订单→柜次数量台账'); CALL queue_table_comment('baiyue_order', 'ord_order_internal_note', '订单内部备注表:保存平台运营或履约人员的内部协作记录,不向商户客户展示'); @@ -13264,6 +13517,7 @@ CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'created_at', ' CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'created_by', '创建人ID'); CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'created_by_name', '创建人名称快照'); CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'current_hold_reason', '当前扣货理由快照'); +CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'last_overseas_hold_version', '海外暂扣事件最新聚合版本,用于阻止乱序覆盖'); CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'customer_id', '客户逻辑ID'); CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'customer_name', '客户名称快照'); CALL queue_column_comment('baiyue_firstleg', 'fl_inbound_order', 'customs_inspection', '是否商检'); @@ -14636,9 +14890,12 @@ CALL queue_column_comment('baiyue_warehouse', 'wh_warehouse_address', 'version', CALL queue_column_comment('baiyue_warehouse', 'wh_warehouse_address', 'warehouse_id', '所属仓库ID'); -- END GENERATED NINE-SCHEMA COMMENT UPGRADE CALLS CALL apply_queued_comments(); --- 后续还会创建整柜报关和同柜组最新基线,保留本会话内的结构保真注释升级器并清空首批队列。 -TRUNCATE TABLE tmp_column_comment_target; -TRUNCATE TABLE tmp_table_comment_target; +DROP PROCEDURE IF EXISTS apply_queued_comments; +DROP PROCEDURE IF EXISTS apply_one_table_comments; +DROP PROCEDURE IF EXISTS queue_column_comment; +DROP PROCEDURE IF EXISTS queue_table_comment; +DROP TEMPORARY TABLE IF EXISTS tmp_column_comment_target; +DROP TEMPORARY TABLE IF EXISTS tmp_table_comment_target; -- 三期统一最终总断言:稳定箱号、单箱测量、墨家收件箱、客户尺寸和装柜权限。 USE baiyue_firstleg; @@ -16070,12 +16327,35 @@ DROP PROCEDURE IF EXISTS add_container_empty_report_fields; CREATE TABLE IF NOT EXISTS fl_container_event_inbox ( event_id VARCHAR(64) NOT NULL COMMENT '跨区事件全局唯一ID', event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - event_version INT UNSIGNED NOT NULL COMMENT '事件契约版本', aggregate_id VARCHAR(64) NOT NULL COMMENT '货柜聚合ID', - aggregate_version BIGINT UNSIGNED NOT NULL COMMENT '货柜聚合版本', payload_hash VARCHAR(80) NOT NULL COMMENT '规范化负载SHA-256摘要', + event_version INT UNSIGNED NOT NULL COMMENT '事件契约版本', aggregate_id VARCHAR(64) NOT NULL COMMENT '跨区业务聚合ID', + aggregate_version BIGINT UNSIGNED NOT NULL COMMENT '跨区业务聚合版本', payload_hash VARCHAR(80) NOT NULL COMMENT '规范化负载SHA-256摘要', payload_json JSON NOT NULL COMMENT '原始事件负载', status VARCHAR(16) NOT NULL COMMENT 'RECEIVED或PROCESSED', received_at DATETIME(3) NOT NULL COMMENT '接收时间(UTC)', processed_at DATETIME(3) NULL COMMENT '处理完成时间(UTC)', PRIMARY KEY (event_id), KEY idx_container_event_aggregate (aggregate_id,aggregate_version) -) ENGINE=InnoDB COMMENT='海外货柜事件消费Inbox'; +) ENGINE=InnoDB COMMENT='海外到国内业务事件消费Inbox'; + +DROP PROCEDURE IF EXISTS add_inbound_overseas_hold_version; +DELIMITER $$ +CREATE PROCEDURE add_inbound_overseas_hold_version() +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema=DATABASE() AND table_name='fl_inbound_order' + AND column_name='last_overseas_hold_version' + ) THEN + ALTER TABLE fl_inbound_order + ADD COLUMN last_overseas_hold_version BIGINT UNSIGNED NULL + COMMENT '海外暂扣事件最新聚合版本,用于阻止乱序覆盖' + AFTER current_hold_reason; + END IF; + ALTER TABLE fl_container_event_inbox + MODIFY COLUMN aggregate_id VARCHAR(64) NOT NULL COMMENT '跨区业务聚合ID', + MODIFY COLUMN aggregate_version BIGINT UNSIGNED NOT NULL COMMENT '跨区业务聚合版本', + COMMENT='海外到国内业务事件消费Inbox'; +END$$ +DELIMITER ; +CALL add_inbound_overseas_hold_version(); +DROP PROCEDURE IF EXISTS add_inbound_overseas_hold_version; -- 标准跨区事件摘要包含 sha256: 前缀,共 71 字符;兼容既有 Finance 64 位摘要。 ALTER TABLE fl_inbound_outbox @@ -16122,6 +16402,9 @@ 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), + (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), (5107100,0,'PLATFORM','MENU',0,'platform:overseas-business:purchase:list','海外采购订单','/overseas-business/purchases','GET',800,'ACTIVE',1,0), (5107101,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:edit','编辑海外采购订单',NULL,'PATCH',801,'ACTIVE',1,0), (5107102,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:review','审核海外采购订单',NULL,'POST',802,'ACTIVE',1,0), @@ -16296,6 +16579,314 @@ WHERE role.tenant_id=0 AND role.app_code='PLATFORM' AND UPPER(role.role_code) IN ('PLATFORM_ADMIN','PLATFORM_CUSTOM_ADMIN') AND role.status='ACTIVE' AND role.deleted=0 AND permission.status='ACTIVE' AND permission.deleted=0; +-- PLATFORM_CUSTOM_ADMIN needs access to the overseas outbound and delivery lists shown in the admin navigation. +INSERT IGNORE INTO baiyue_iam.iam_role_permission (tenant_id, role_id, permission_id, created_at) +SELECT 0, role.id, permission.id, NOW(3) +FROM baiyue_iam.iam_role role +JOIN baiyue_iam.iam_permission permission ON permission.tenant_id=0 AND permission.app_code='PLATFORM' + AND permission.permission_code IN ( + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:delivery:list' + ) +WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN' + AND role.status='ACTIVE' AND role.deleted=0 AND permission.status='ACTIVE' AND permission.deleted=0; + +-- 五期海外排车、出库与派送权限(来源:iam/db/phase5-delivery-permissions.sql) +USE baiyue_iam; +SET NAMES utf8mb4; + +-- 五期海外排车、出库与派送权限。列表权限同时覆盖列表和详情只读,写操作保持独立授权。 +DROP PROCEDURE IF EXISTS guard_phase5_delivery_permission_ids; +DELIMITER $$ +CREATE PROCEDURE guard_phase5_delivery_permission_ids() +BEGIN + IF EXISTS ( + SELECT 1 FROM iam_permission + WHERE (id = 5107064 AND permission_code <> 'platform:overseas-warehouse:dispatch:list') + OR (id = 5107016 AND permission_code <> 'platform:overseas-warehouse:dispatch:edit') + OR (id = 5107017 AND permission_code <> 'platform:overseas-warehouse:dispatch:cancel') + OR (id = 5107018 AND permission_code <> 'platform:overseas-warehouse:dispatch:transfer-delivery') + OR (id = 5107090 AND permission_code <> 'platform:overseas-warehouse:outbound:list') + OR (id = 5107091 AND permission_code <> 'platform:overseas-warehouse:outbound:create') + OR (id = 5107092 AND permission_code <> 'platform:overseas-warehouse:delivery:list') + OR (id = 5107093 AND permission_code <> 'platform:overseas-warehouse:outbound:cancel') + OR (id = 5107070 AND permission_code <> 'platform:overseas-warehouse:exception-order:list') + OR (id = 5107071 AND permission_code <> 'platform:overseas-warehouse:exception-order:create') + OR (id = 5107072 AND permission_code <> 'platform:overseas-warehouse:delivery:return') + OR (id = 5107080 AND permission_code <> 'platform:overseas-warehouse:customer-visit:list') + OR (id = 5107081 AND permission_code <> 'platform:overseas-warehouse:customer-visit:edit') + OR (id = 5107082 AND permission_code <> 'platform:overseas-warehouse:delivery:status') + OR (id = 5306000 AND permission_code <> 'merchant:warehouse:delivery:list') + OR (id = 5306001 AND permission_code <> 'merchant:warehouse:delivery:create') + ) OR EXISTS ( + SELECT 1 FROM iam_permission + WHERE (permission_code = 'platform:overseas-warehouse:dispatch:list' AND id <> 5107064) + OR (permission_code = 'platform:overseas-warehouse:dispatch:edit' AND id <> 5107016) + OR (permission_code = 'platform:overseas-warehouse:dispatch:cancel' AND id <> 5107017) + OR (permission_code = 'platform:overseas-warehouse:dispatch:transfer-delivery' AND id <> 5107018) + OR (permission_code = 'platform:overseas-warehouse:outbound:list' AND id <> 5107090) + OR (permission_code = 'platform:overseas-warehouse:outbound:create' AND id <> 5107091) + OR (permission_code = 'platform:overseas-warehouse:delivery:list' AND id <> 5107092) + OR (permission_code = 'platform:overseas-warehouse:outbound:cancel' AND id <> 5107093) + OR (permission_code = 'platform:overseas-warehouse:exception-order:list' AND id <> 5107070) + OR (permission_code = 'platform:overseas-warehouse:exception-order:create' AND id <> 5107071) + OR (permission_code = 'platform:overseas-warehouse:delivery:return' AND id <> 5107072) + OR (permission_code = 'platform:overseas-warehouse:customer-visit:list' AND id <> 5107080) + OR (permission_code = 'platform:overseas-warehouse:customer-visit:edit' AND id <> 5107081) + OR (permission_code = 'platform:overseas-warehouse:delivery:status' AND id <> 5107082) + OR (permission_code = 'merchant:warehouse:delivery:list' AND id <> 5306000) + OR (permission_code = 'merchant:warehouse:delivery:create' AND id <> 5306001) + ) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:权限ID或编码冲突'; + END IF; +END$$ +DELIMITER ; +CALL guard_phase5_delivery_permission_ids(); +DROP PROCEDURE guard_phase5_delivery_permission_ids; + +INSERT INTO iam_permission + (id, tenant_id, app_code, permission_type, parent_id, permission_code, + permission_name, route_path, http_method, sort_no, status, built_in, deleted) +VALUES + (5107064,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:dispatch:list','海外排车单','/overseas-warehouse/dispatches','GET',764,'ACTIVE',1,0), + (5107016,0,'PLATFORM','BUTTON',5107064,'platform:overseas-warehouse:dispatch:edit','编辑海外排车',NULL,'PUT',716,'ACTIVE',1,0), + (5107017,0,'PLATFORM','BUTTON',5107064,'platform:overseas-warehouse:dispatch:cancel','取消海外排车',NULL,'DELETE',717,'ACTIVE',1,0), + (5107018,0,'PLATFORM','BUTTON',5107064,'platform:overseas-warehouse:dispatch:transfer-delivery','排车转派送',NULL,'POST',718,'ACTIVE',1,0), + (5107070,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:exception-order:list','海外异常订单','/overseas-warehouse/exception-orders','GET',770,'ACTIVE',1,0), + (5107071,0,'PLATFORM','BUTTON',5107070,'platform:overseas-warehouse:exception-order:create','新增海外异常订单',NULL,'POST',771,'ACTIVE',1,0), + (5107072,0,'PLATFORM','BUTTON',5107092,'platform:overseas-warehouse:delivery:return','派送单标记退货',NULL,'POST',772,'ACTIVE',1,0), + (5107080,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:customer-visit:list','客户回访','/overseas-warehouse/customer-visits','GET',780,'ACTIVE',1,0), + (5107081,0,'PLATFORM','BUTTON',5107080,'platform:overseas-warehouse:customer-visit:edit','保存客户回访',NULL,'PUT',781,'ACTIVE',1,0), + (5107082,0,'PLATFORM','BUTTON',5107092,'platform:overseas-warehouse:delivery:status','编辑派送单状态',NULL,'PUT',782,'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), + (5107093,0,'PLATFORM','BUTTON',5107090,'platform:overseas-warehouse:outbound:cancel','取消海外出库单',NULL,'POST',768,'ACTIVE',1,0), + (5306000,0,'MERCHANT','MENU',0,'merchant:warehouse:delivery:list','海外仓派送单','/orders/delivery','GET',60,'ACTIVE',1,0), + (5306001,0,'MERCHANT','BUTTON',5306000,'merchant:warehouse:delivery:create','创建海外仓派送单',NULL,'POST',10,'ACTIVE',1,0) +ON DUPLICATE KEY UPDATE + permission_type=VALUES(permission_type), parent_id=VALUES(parent_id), + permission_name=VALUES(permission_name), route_path=VALUES(route_path), + http_method=VALUES(http_method), sort_no=VALUES(sort_no), status='ACTIVE', + built_in=1, deleted=0; + +-- 平台管理员默认拥有五期全部后台动作;已有的平台自定义管理员保持同等五期操作能力。 +INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) +SELECT 0, role.id, permission.id, CURRENT_TIMESTAMP(3) + FROM iam_role role + JOIN iam_permission permission ON permission.tenant_id=0 AND permission.app_code='PLATFORM' + WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND UPPER(role.role_code) IN ('PLATFORM_ADMIN','PLATFORM_CUSTOM_ADMIN') + AND role.status='ACTIVE' AND role.deleted=0 + AND permission.permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit') + AND permission.status='ACTIVE' AND permission.deleted=0; + +-- 仓库后台岗位按最小职责授权;PDA 岗位不得获得后台排车、出库或派送权限。 +DROP TEMPORARY TABLE IF EXISTS tmp_phase5_delivery_role_permission; +CREATE TEMPORARY TABLE tmp_phase5_delivery_role_permission ( + role_code VARCHAR(64) NOT NULL, + permission_code VARCHAR(160) NOT NULL, + PRIMARY KEY (role_code, permission_code) +) ENGINE=MEMORY; +INSERT INTO tmp_phase5_delivery_role_permission (role_code, permission_code) VALUES + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:dispatch:list'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:dispatch:edit'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:dispatch:cancel'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:dispatch:transfer-delivery'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:outbound:list'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:outbound:create'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:outbound:cancel'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:delivery:list'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:exception-order:list'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:exception-order:create'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:delivery:return'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:delivery:status'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:customer-visit:list'), + ('WAREHOUSE_OPERATOR','platform:overseas-warehouse:customer-visit:edit'), + ('WAREHOUSE_TALLY','platform:overseas-warehouse:dispatch:list'), + ('WAREHOUSE_TALLY','platform:overseas-warehouse:outbound:list'), + ('WAREHOUSE_TALLY','platform:overseas-warehouse:delivery:list'), + ('WAREHOUSE_TALLY','platform:overseas-warehouse:exception-order:list'), + ('WAREHOUSE_TALLY','platform:overseas-warehouse:customer-visit:list'); + +DELETE grant_row FROM iam_role_permission grant_row +JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id +JOIN iam_permission permission ON permission.id=grant_row.permission_id AND permission.tenant_id=grant_row.tenant_id +LEFT JOIN tmp_phase5_delivery_role_permission expected + ON expected.role_code=role.role_code AND expected.permission_code=permission.permission_code +WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND role.role_code IN ('WAREHOUSE_OPERATOR','WAREHOUSE_TALLY','OVERSEAS_WAREHOUSE_PDA_OPERATOR','CN_FIRSTLEG_PDA_OPERATOR') + AND permission.permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit') + AND expected.permission_code IS NULL; + +INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) +SELECT 0, role.id, permission.id, CURRENT_TIMESTAMP(3) + FROM tmp_phase5_delivery_role_permission expected + JOIN iam_role role ON role.tenant_id=0 AND role.app_code='PLATFORM' + AND role.role_code=expected.role_code AND role.status='ACTIVE' AND role.deleted=0 + JOIN iam_permission permission ON permission.tenant_id=0 AND permission.app_code='PLATFORM' + AND permission.permission_code=expected.permission_code + AND permission.status='ACTIVE' AND permission.deleted=0; + +-- 客户默认管理员获得派送列表/详情只读及独立创建;其他客户角色不自动扩权。 +INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) +SELECT 0, role.id, permission.id, CURRENT_TIMESTAMP(3) + FROM iam_role role + JOIN iam_permission permission ON permission.tenant_id=0 AND permission.app_code='MERCHANT' + WHERE role.tenant_id=0 AND role.app_code='MERCHANT' AND role.role_code='MERCHANT_OWNER' + AND role.status='ACTIVE' AND role.deleted=0 + AND permission.permission_code IN ( + 'merchant:warehouse:delivery:list', + 'merchant:warehouse:delivery:create') + AND permission.status='ACTIVE' AND permission.deleted=0; + +DROP PROCEDURE IF EXISTS assert_phase5_delivery_permissions; +DELIMITER $$ +CREATE PROCEDURE assert_phase5_delivery_permissions() +BEGIN + DECLARE v_warehouse_operator_permission_count INT DEFAULT 0; + DECLARE v_warehouse_tally_permission_count INT DEFAULT 0; + + IF (SELECT COUNT(*) FROM iam_permission + WHERE tenant_id=0 AND status='ACTIVE' AND deleted=0 + AND permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit', + 'merchant:warehouse:delivery:list', + 'merchant:warehouse:delivery:create')) <> 16 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:权限目录不完整'; + END IF; + IF (SELECT COUNT(*) FROM iam_role_permission grant_row + JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id + JOIN iam_permission permission ON permission.id=grant_row.permission_id + WHERE role.role_code='PLATFORM_ADMIN' + AND permission.permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit')) <> 14 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台管理员授权不完整'; + END IF; + IF EXISTS (SELECT 1 FROM iam_role role + WHERE role.tenant_id=0 AND role.app_code='PLATFORM' + AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN' + AND role.status='ACTIVE' AND role.deleted=0 + AND (SELECT COUNT(*) FROM iam_role_permission grant_row + JOIN iam_permission permission ON permission.id=grant_row.permission_id + WHERE grant_row.role_id=role.id AND grant_row.tenant_id=role.tenant_id + AND permission.permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit')) <> 14) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:平台自定义管理员授权不完整'; + END IF; + SELECT COALESCE(SUM(role_code='WAREHOUSE_OPERATOR'),0), + COALESCE(SUM(role_code='WAREHOUSE_TALLY'),0) + INTO v_warehouse_operator_permission_count, v_warehouse_tally_permission_count + FROM tmp_phase5_delivery_role_permission; + IF v_warehouse_operator_permission_count <> 14 + OR v_warehouse_tally_permission_count <> 5 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:仓库岗位最小权限矩阵异常'; + END IF; + IF EXISTS (SELECT 1 FROM iam_role_permission grant_row + JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id + JOIN iam_permission permission ON permission.id=grant_row.permission_id + WHERE role.role_code IN ('OVERSEAS_WAREHOUSE_PDA_OPERATOR','CN_FIRSTLEG_PDA_OPERATOR') + AND permission.permission_code IN ( + 'platform:overseas-warehouse:dispatch:list', + 'platform:overseas-warehouse:dispatch:edit', + 'platform:overseas-warehouse:dispatch:cancel', + 'platform:overseas-warehouse:dispatch:transfer-delivery', + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:outbound:create', + 'platform:overseas-warehouse:outbound:cancel', + 'platform:overseas-warehouse:delivery:list', + 'platform:overseas-warehouse:exception-order:list', + 'platform:overseas-warehouse:exception-order:create', + 'platform:overseas-warehouse:delivery:return', + 'platform:overseas-warehouse:delivery:status', + 'platform:overseas-warehouse:customer-visit:list', + 'platform:overseas-warehouse:customer-visit:edit')) THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:PDA岗位错误获得后台权限'; + END IF; + IF (SELECT COUNT(*) FROM iam_role_permission grant_row + JOIN iam_role role ON role.id=grant_row.role_id AND role.tenant_id=grant_row.tenant_id + JOIN iam_permission permission ON permission.id=grant_row.permission_id + WHERE role.role_code='MERCHANT_OWNER' AND role.app_code='MERCHANT' + AND permission.permission_code IN ( + 'merchant:warehouse:delivery:list', + 'merchant:warehouse:delivery:create')) <> 2 THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='五期海外派送权限初始化失败:客户默认管理员授权不完整'; + END IF; +END$$ +DELIMITER ; +CALL assert_phase5_delivery_permissions(); +DROP PROCEDURE assert_phase5_delivery_permissions; +DROP TEMPORARY TABLE tmp_phase5_delivery_role_permission; + + -- IAM 客户提交即成功,默认尺寸通过持久化任务后台初始化;已有客户按历史事实标记 READY。 USE baiyue_iam; SET @customer_dimension_status_ddl = (SELECT IF( @@ -16328,6 +16919,16 @@ CREATE TABLE IF NOT EXISTS iam_customer_dimension_initialization_task ( KEY idx_customer_dimension_task_diagnosis (status,updated_at) ) ENGINE=InnoDB COMMENT='IAM客户默认尺寸可靠后台初始化任务及诊断状态'; +-- 兼容已存在的旧表:CREATE TABLE IF NOT EXISTS 不会为旧表补充新字段。 +SET @customer_dimension_lease_ddl = (SELECT IF( + EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() + AND table_name='iam_customer_dimension_initialization_task' AND column_name='lease_until'), + 'SELECT 1', + 'ALTER TABLE iam_customer_dimension_initialization_task ADD COLUMN lease_until DATETIME(3) NULL COMMENT ''当前任务租约截止时间'' AFTER lease_owner')); +PREPARE customer_dimension_lease_stmt FROM @customer_dimension_lease_ddl; +EXECUTE customer_dimension_lease_stmt; +DEALLOCATE PREPARE customer_dimension_lease_stmt; + USE baiyue_firstleg; ALTER TABLE fl_loading_pick_task MODIFY COLUMN task_status VARCHAR(24) NOT NULL DEFAULT 'LOADING' COMMENT 'PDA任务状态:LOADING、COMPLETING、COMPLETION_FAILED、COMPLETED'; @@ -16391,77 +16992,6 @@ BEGIN END$$ DELIMITER ; --- 最新整柜报关基线:装柜完成后收集退税资料,按柜冻结、回传并自动收敛离仓。 -USE baiyue_firstleg; -CREATE TABLE IF NOT EXISTS fl_customs_container( - id BIGINT UNSIGNED NOT NULL,loading_plan_id BIGINT UNSIGNED NOT NULL,container_booking_id BIGINT UNSIGNED NOT NULL, - status VARCHAR(40) NOT NULL,started_by BIGINT UNSIGNED NULL,started_by_name VARCHAR(64) NULL,started_at DATETIME(3) NULL, - completed_by BIGINT UNSIGNED NULL,completed_by_name VARCHAR(64) 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), - version INT UNSIGNED NOT NULL DEFAULT 0,PRIMARY KEY(id),UNIQUE KEY uk_customs_container_plan(loading_plan_id), - UNIQUE KEY uk_customs_container_booking(container_booking_id),KEY idx_customs_container_status(status,updated_at), - CONSTRAINT chk_customs_container_status CHECK(status IN('WAITING_CUSTOMER_DOCUMENTS','READY_TO_START','DECLARING','COMPLETED')) -)ENGINE=InnoDB COMMENT='装柜完成后的整柜出口报关聚合'; -CREATE TABLE IF NOT EXISTS fl_customs_customer_document( - id BIGINT UNSIGNED NOT NULL,customs_container_id BIGINT UNSIGNED NOT NULL,tenant_id BIGINT UNSIGNED NOT NULL, - file_id BIGINT UNSIGNED NOT NULL,file_name VARCHAR(255) NOT NULL,file_hash CHAR(64) NOT NULL,content_type VARCHAR(128) NULL, - size_bytes BIGINT UNSIGNED NOT NULL,status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',uploaded_by BIGINT UNSIGNED NOT NULL, - uploaded_at DATETIME(3) NOT NULL,frozen_version INT UNSIGNED NULL,frozen_at DATETIME(3) NULL,deleted_by BIGINT UNSIGNED NULL, - deleted_at DATETIME(3) NULL,version INT UNSIGNED NOT NULL DEFAULT 1,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), - KEY idx_customs_customer_document_container(customs_container_id,status,tenant_id), - CONSTRAINT fk_customs_customer_document_container FOREIGN KEY(customs_container_id) REFERENCES fl_customs_container(id), - CONSTRAINT chk_customs_customer_document_status CHECK(status IN('ACTIVE','DELETED')), - CONSTRAINT chk_customs_customer_document_freeze CHECK((frozen_at IS NULL AND frozen_version IS NULL)OR(frozen_at IS NOT NULL AND frozen_version IS NOT NULL)) -)ENGINE=InnoDB COMMENT='客户整份退税报送资料逻辑根'; -CREATE TABLE IF NOT EXISTS fl_customs_customer_document_inbound( - document_id BIGINT UNSIGNED NOT NULL,inbound_id BIGINT UNSIGNED NOT NULL,tenant_id BIGINT UNSIGNED NOT NULL, - order_id BIGINT UNSIGNED NOT NULL,inbound_code VARCHAR(40) NOT NULL,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - PRIMARY KEY(document_id,inbound_id),KEY idx_customs_document_inbound(inbound_id,tenant_id), - CONSTRAINT fk_customs_document_inbound_document FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id) -)ENGINE=InnoDB COMMENT='客户报送资料与当前柜退税入仓码多对多关系'; -CREATE TABLE IF NOT EXISTS fl_customs_customer_document_version( - id BIGINT UNSIGNED NOT NULL,document_id BIGINT UNSIGNED NOT NULL,document_version INT UNSIGNED NOT NULL,file_id BIGINT UNSIGNED NOT NULL, - file_name VARCHAR(255) NOT NULL,file_hash CHAR(64) NOT NULL,content_type VARCHAR(128) NULL,size_bytes BIGINT UNSIGNED NOT NULL, - scope_snapshot_json JSON NOT NULL,action VARCHAR(24) NOT NULL,operator_id BIGINT UNSIGNED NOT NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),PRIMARY KEY(id),UNIQUE KEY uk_customs_customer_document_version(document_id,document_version), - CONSTRAINT fk_customs_customer_document_version FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id), - CONSTRAINT chk_customs_customer_document_version_action CHECK(action IN('UPLOAD','REPLACE','SCOPE_CHANGE','DELETE')) -)ENGINE=InnoDB COMMENT='客户报送资料文件与覆盖范围不可变版本'; -CREATE TABLE IF NOT EXISTS fl_customs_frozen_document_inbound( - document_id BIGINT UNSIGNED NOT NULL,inbound_id BIGINT UNSIGNED NOT NULL,tenant_id BIGINT UNSIGNED NOT NULL, - order_id BIGINT UNSIGNED NOT NULL,inbound_code VARCHAR(40) NOT NULL,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - PRIMARY KEY(document_id,inbound_id),CONSTRAINT fk_customs_frozen_document FOREIGN KEY(document_id) REFERENCES fl_customs_customer_document(id) -)ENGINE=InnoDB COMMENT='开始报关时冻结的客户资料覆盖范围'; -CREATE TABLE IF NOT EXISTS fl_customs_completion_document( - id BIGINT UNSIGNED NOT NULL,source_document_id BIGINT UNSIGNED NOT NULL,file_id BIGINT UNSIGNED NOT NULL, - file_name VARCHAR(255) NOT NULL,file_hash CHAR(64) NOT NULL,content_type VARCHAR(128) NULL,size_bytes BIGINT UNSIGNED NOT NULL, - uploaded_by BIGINT UNSIGNED NOT NULL,uploaded_by_name VARCHAR(64) NULL,uploaded_at DATETIME(3) NOT NULL,version INT UNSIGNED NOT NULL DEFAULT 1, - 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_customs_completion_source(source_document_id), - CONSTRAINT fk_customs_completion_source FOREIGN KEY(source_document_id) REFERENCES fl_customs_customer_document(id) -)ENGINE=InnoDB COMMENT='报关完成文件当前版本'; -CREATE TABLE IF NOT EXISTS fl_customs_completion_document_version( - id BIGINT UNSIGNED NOT NULL,completion_document_id BIGINT UNSIGNED NOT NULL,document_version INT UNSIGNED NOT NULL, - file_id BIGINT UNSIGNED NOT NULL,file_name VARCHAR(255) NOT NULL,file_hash CHAR(64) NOT NULL,content_type VARCHAR(128) NULL, - size_bytes BIGINT UNSIGNED NOT NULL,operator_id BIGINT UNSIGNED NOT NULL,operator_name VARCHAR(64) NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),PRIMARY KEY(id), - UNIQUE KEY uk_customs_completion_version(completion_document_id,document_version), - CONSTRAINT fk_customs_completion_version FOREIGN KEY(completion_document_id) REFERENCES fl_customs_completion_document(id) -)ENGINE=InnoDB COMMENT='报关完成文件不可变覆盖版本'; -CREATE TABLE IF NOT EXISTS fl_customs_container_history( - id BIGINT UNSIGNED NOT NULL,customs_container_id BIGINT UNSIGNED NOT NULL,action VARCHAR(40) NOT NULL, - from_status VARCHAR(40) NULL,to_status VARCHAR(40) NULL,remark VARCHAR(500) NULL,operator_id BIGINT UNSIGNED NOT NULL, - operator_name VARCHAR(64) NULL,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),PRIMARY KEY(id), - KEY idx_customs_container_history(customs_container_id,created_at,id), - CONSTRAINT fk_customs_container_history FOREIGN KEY(customs_container_id) REFERENCES fl_customs_container(id) -)ENGINE=InnoDB COMMENT='整柜报关状态与系统触发历史'; -CREATE TABLE IF NOT EXISTS fl_customs_command( - id BIGINT UNSIGNED NOT NULL,actor_id BIGINT UNSIGNED NOT NULL,action VARCHAR(80) NOT NULL,idempotency_key VARCHAR(128) NOT NULL, - request_hash CHAR(64) NOT NULL,status VARCHAR(16) NOT NULL,result_id BIGINT UNSIGNED NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),completed_at DATETIME(3) NULL,PRIMARY KEY(id), - UNIQUE KEY uk_customs_command(actor_id,action,idempotency_key),CONSTRAINT chk_customs_command_status CHECK(status IN('PROCESSING','SUCCESS')) -)ENGINE=InnoDB COMMENT='整柜报关写命令幂等事实'; -- 同柜且不可拆组:跨客户但同国内仓、渠道和目的仓港,整组锁定/解锁/消费。 USE baiyue_firstleg; CREATE TABLE IF NOT EXISTS fl_coload_group ( @@ -16511,167 +17041,130 @@ CREATE TABLE IF NOT EXISTS fl_coload_command ( CONSTRAINT chk_coload_command_status CHECK(command_status IN('PROCESSING','SUCCESS')) )ENGINE=InnoDB COMMENT='同柜不可拆组幂等写命令'; --- 最新追加基线在首轮注释升级之后创建;统一在最终断言前使用同一结构保真升级器收敛存量库注释。 -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','action_type','命令动作类型'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','idempotency_key','幂等键'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','request_hash','请求摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','command_status','命令状态:PROCESSING处理中、SUCCESS成功'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','result_group_id','命令结果组ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','created_at','命令创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_command','completed_at','命令完成时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','group_status','组状态:ACTIVE有效、LOCKED锁定、CONSUMED已消费、CANCELLED已取消'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','created_at','创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','updated_at','更新时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','locked_by','锁定操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','locked_by_name','锁定操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','locked_at','锁定时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','consumed_by','消费操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','consumed_by_name','消费操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','consumed_at','消费完成时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','cancelled_by','取消操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','cancelled_by_name','取消操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group','cancelled_at','取消时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','group_id','同柜不可拆组ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','action_type','操作类型:CREATE创建、CANCEL取消、LOCK锁定、UNLOCK解锁、CONSUME消费'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','from_status','变更前组状态'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','to_status','变更后组状态'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','plan_id','关联装柜计划ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','remark','操作原因或备注'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','operator_id','操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','operator_name','操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_history','created_at','历史记录时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_member','created_at','成员创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_coload_group_member','closed_at','成员约束关闭时间'); +-- 一件代发测量完成后的独立 PDA 合托;不代表国内仓库存入库。 +USE baiyue_firstleg; -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','id','报关幂等命令ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','actor_id','命令操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','action','命令动作类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','idempotency_key','客户端幂等键'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','request_hash','规范化请求SHA-256摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','status','命令状态:PROCESSING处理中、SUCCESS成功'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','result_id','命令结果业务记录ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','created_at','命令创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_command','completed_at','命令完成时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','id','报关完成文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','file_id','File服务文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','file_name','完成文件名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','file_hash','完成文件SHA-256摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','content_type','完成文件媒体类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','size_bytes','完成文件大小(字节)'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','uploaded_by','上传操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','uploaded_by_name','上传操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','uploaded_at','上传时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','version','完成文件版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','created_at','完成文件创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document','updated_at','完成文件更新时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','id','完成文件版本记录ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','completion_document_id','报关完成文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','document_version','完成文件版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','file_id','本版本File服务文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','file_name','本版本文件名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','file_hash','本版本文件SHA-256摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','content_type','本版本文件媒体类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','size_bytes','本版本文件大小(字节)'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','operator_id','操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','operator_name','操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_completion_document_version','created_at','版本创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','id','整柜报关聚合ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','status','报关状态:WAITING_CUSTOMER_DOCUMENTS待资料、READY_TO_START可开始、DECLARING申报中、COMPLETED已完成'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','started_by','开始报关操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','started_by_name','开始报关操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','started_at','开始报关时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','completed_by','完成报关操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','completed_by_name','完成报关操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','completed_at','报关完成时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','created_at','聚合创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','updated_at','聚合更新时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container','version','乐观锁版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','id','报关历史记录ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','customs_container_id','所属整柜报关聚合ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','action','报关操作类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','from_status','变更前报关状态'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','to_status','变更后报关状态'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','remark','操作备注'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','operator_id','操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','operator_name','操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_container_history','created_at','历史创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','id','客户报送资料ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','customs_container_id','所属整柜报关聚合ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','file_id','File服务文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','file_name','文件名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','file_hash','文件SHA-256摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','content_type','文件媒体类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','size_bytes','文件大小(字节)'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','status','资料状态:ACTIVE有效、DELETED已删除'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','uploaded_by','上传操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','uploaded_at','上传时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','frozen_version','开始报关时冻结的资料版本'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','frozen_at','资料冻结时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','deleted_by','删除操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','deleted_at','删除时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','version','资料版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','created_at','资料创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document','updated_at','资料更新时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','document_id','客户报送资料ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','inbound_id','覆盖入仓单ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','tenant_id','覆盖入仓单客户ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','order_id','覆盖订单ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','inbound_code','覆盖入仓码快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_inbound','created_at','关联创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','id','资料版本记录ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','document_id','客户报送资料ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','document_version','资料版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','file_id','本版本File服务文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','file_name','本版本文件名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','file_hash','本版本文件SHA-256摘要'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','content_type','本版本文件媒体类型'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','size_bytes','本版本文件大小(字节)'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','scope_snapshot_json','本版本覆盖入仓码范围快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','action','版本动作:UPLOAD上传、REPLACE替换、SCOPE_CHANGE范围变化、DELETE删除'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','operator_id','操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_customer_document_version','created_at','版本创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','document_id','冻结的客户报送资料ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','inbound_id','冻结覆盖入仓单ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','tenant_id','冻结覆盖客户ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','order_id','冻结覆盖订单ID'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','inbound_code','冻结覆盖入仓码快照'); -CALL queue_column_comment('baiyue_firstleg','fl_customs_frozen_document_inbound','created_at','冻结关联创建时间'); +CREATE TABLE IF NOT EXISTS fl_dropship_pallet_task ( + id BIGINT UNSIGNED NOT NULL COMMENT '合托任务ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '一件代发入仓单ID', + warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '作业仓库ID', + task_status VARCHAR(24) NOT NULL COMMENT '任务状态:PENDING待领取、CLAIMED已领取、COMPLETED已完成', + total_cartons INT UNSIGNED NOT NULL COMMENT '测量确认总箱数', + allocated_cartons INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已上托箱数', + assignee_id BIGINT UNSIGNED NULL COMMENT '任务领取人ID', + assignee_name VARCHAR(64) NULL COMMENT '任务领取人姓名快照', + claimed_at DATETIME(3) NULL COMMENT '任务领取时间', + completed_at DATETIME(3) NULL COMMENT '任务完成时间', + version INT NOT NULL DEFAULT 1 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_dropship_task_inbound (tenant_id,inbound_id), + KEY idx_dropship_task_operator (task_status,assignee_id,warehouse_id,created_at), + CONSTRAINT fk_dropship_task_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order(id), + CONSTRAINT chk_dropship_task_status CHECK (task_status IN ('PENDING','CLAIMED','COMPLETED')), + CONSTRAINT chk_dropship_task_cartons CHECK (allocated_cartons<=total_cartons) +) ENGINE=InnoDB COMMENT='一件代发测量后PDA合托任务'; -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','id','柜次证据记录ID'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','file_id','File服务文件ID'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','file_name','文件名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','seal_no','带锁码照对应锁码'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','remark','证据备注'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','status','证据状态:ACTIVE有效、VOID作废'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','void_reason','作废原因'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','voided_by','作废操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','voided_by_name','作废操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','voided_at','作废时间'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','version','乐观锁版本号'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','created_by','创建操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','created_by_name','创建操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','updated_by','最后修改操作人ID'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','updated_by_name','最后修改操作人名称快照'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','created_at','创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_loading_cabinet_evidence','updated_at','最后更新时间'); -CALL queue_column_comment('baiyue_firstleg','fl_order_declaration_event','consumed_at','事件消费完成时间'); -CALL queue_column_comment('baiyue_firstleg','fl_order_declaration_snapshot','created_at','快照创建时间'); -CALL queue_column_comment('baiyue_firstleg','fl_order_declaration_snapshot','updated_at','快照更新时间'); -CALL queue_column_comment('baiyue_order','ord_customer_address','created_by','创建人ID'); -CALL queue_column_comment('baiyue_order','ord_customer_address','created_at','创建时间'); -CALL queue_column_comment('baiyue_order','ord_customer_address','updated_by','最后修改人ID'); -CALL queue_column_comment('baiyue_order','ord_customer_address','updated_at','更新时间'); -CALL queue_column_comment('baiyue_order','ord_customer_address','deleted','逻辑删除标记:0未删除、1已删除'); -CALL queue_column_comment('baiyue_order','ord_customer_address','version','乐观锁版本号'); +CREATE TABLE IF NOT EXISTS fl_dropship_pallet ( + id BIGINT UNSIGNED NOT NULL COMMENT '合托托盘ID', + task_id BIGINT UNSIGNED NOT NULL COMMENT '所属合托任务ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '一件代发入仓单ID', + warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '作业仓库ID', + pallet_no VARCHAR(32) NULL COMMENT '封托时生成的DP托盘号', + pallet_status VARCHAR(16) NOT NULL COMMENT '托盘状态:OPEN合托中、COMPLETED已封托', + open_operation_id VARCHAR(128) NOT NULL COMMENT '创建托盘幂等操作ID', + seal_operation_id VARCHAR(128) NULL COMMENT '封托幂等操作ID', + created_by BIGINT UNSIGNED NOT NULL COMMENT '托盘创建人ID', + created_by_name VARCHAR(64) NULL COMMENT '托盘创建人姓名快照', + completed_by BIGINT UNSIGNED NULL COMMENT '封托操作人ID', + completed_by_name VARCHAR(64) NULL COMMENT '封托操作人姓名快照', + completed_at DATETIME(3) NULL COMMENT '封托完成时间', + version INT NOT NULL DEFAULT 1 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_dropship_pallet_no (pallet_no), + UNIQUE KEY uk_dropship_pallet_open_op (open_operation_id), + UNIQUE KEY uk_dropship_pallet_seal_op (seal_operation_id), + KEY idx_dropship_pallet_inbound (tenant_id,inbound_id,pallet_status), + CONSTRAINT fk_dropship_pallet_task FOREIGN KEY (task_id) REFERENCES fl_dropship_pallet_task(id), + CONSTRAINT chk_dropship_pallet_status CHECK (pallet_status IN ('OPEN','COMPLETED')) +) ENGINE=InnoDB COMMENT='一件代发合托形成的可打印托盘'; -CALL apply_queued_comments(); -DROP PROCEDURE IF EXISTS apply_queued_comments; -DROP PROCEDURE IF EXISTS apply_one_table_comments; -DROP PROCEDURE IF EXISTS queue_column_comment; -DROP PROCEDURE IF EXISTS queue_table_comment; -DROP TEMPORARY TABLE IF EXISTS tmp_column_comment_target; -DROP TEMPORARY TABLE IF EXISTS tmp_table_comment_target; +CREATE TABLE IF NOT EXISTS fl_dropship_pallet_carton ( + id BIGINT UNSIGNED NOT NULL COMMENT '托盘箱明细ID', + task_id BIGINT UNSIGNED NOT NULL COMMENT '所属合托任务ID', + pallet_id BIGINT UNSIGNED NOT NULL COMMENT '所属合托托盘ID', + tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键', + inbound_id BIGINT UNSIGNED NOT NULL COMMENT '一件代发入仓单ID', + inbound_detail_id BIGINT UNSIGNED NOT NULL COMMENT '入仓货物明细ID', + carton_label_id BIGINT UNSIGNED NOT NULL COMMENT '稳定箱唛记录ID', + sku_code VARCHAR(128) NOT NULL COMMENT '箱唛冻结SKU编码', + cargo_name VARCHAR(255) NULL COMMENT '货物名称快照', + box_code VARCHAR(64) NOT NULL COMMENT '稳定箱码', + operation_id VARCHAR(128) NOT NULL COMMENT '上托幂等操作ID', + bound_by BIGINT UNSIGNED NOT NULL COMMENT '上托操作人ID', + bound_by_name VARCHAR(64) NULL COMMENT '上托操作人姓名快照', + bound_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上托时间', + PRIMARY KEY (id), + UNIQUE KEY uk_dropship_carton_task_label (task_id,carton_label_id), + KEY idx_dropship_carton_pallet_sku (pallet_id,sku_code,id), + KEY idx_dropship_carton_inbound (tenant_id,inbound_id,pallet_id), + KEY idx_dropship_carton_operation (operation_id), + CONSTRAINT fk_dropship_carton_task FOREIGN KEY (task_id) REFERENCES fl_dropship_pallet_task(id), + CONSTRAINT fk_dropship_carton_pallet FOREIGN KEY (pallet_id) REFERENCES fl_dropship_pallet(id), + CONSTRAINT fk_dropship_carton_label FOREIGN KEY (carton_label_id) REFERENCES fl_inbound_carton_label(id) +) ENGINE=InnoDB COMMENT='一件代发托盘内逐箱SKU和入仓单明细'; +-- Auth 登录手机号只从 IAM 中唯一归属的中国大陆手机号回填;存量重复号保持 NULL。 +USE baiyue_auth; +DROP PROCEDURE IF EXISTS auth_add_login_phone; +DELIMITER $$ +CREATE PROCEDURE auth_add_login_phone() +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_schema = 'baiyue_auth' AND table_name = 'auth_account' AND column_name = 'phone') THEN + ALTER TABLE auth_account ADD COLUMN phone VARCHAR(32) NULL COMMENT '全局唯一中国大陆登录手机号' AFTER username; + END IF; +END$$ +DELIMITER ; +CALL auth_add_login_phone(); +DROP PROCEDURE auth_add_login_phone; + +DROP PROCEDURE IF EXISTS auth_backfill_login_phone; +DELIMITER $$ +CREATE PROCEDURE auth_backfill_login_phone() +BEGIN + UPDATE auth_account + SET phone = NULL + WHERE phone IS NOT NULL AND phone NOT REGEXP '^1[3-9][0-9]{9}$'; + UPDATE auth_account account + JOIN baiyue_iam.iam_user user ON user.auth_user_id = account.id AND user.deleted = 0 + JOIN ( + SELECT phone + FROM baiyue_iam.iam_user + WHERE deleted = 0 AND phone REGEXP '^1[3-9][0-9]{9}$' + GROUP BY phone + HAVING COUNT(DISTINCT auth_user_id) = 1 + ) unique_phone ON unique_phone.phone = user.phone + SET account.phone = user.phone + WHERE account.phone IS NULL AND user.phone REGEXP '^1[3-9][0-9]{9}$'; + IF NOT EXISTS ( + SELECT 1 FROM information_schema.statistics + WHERE table_schema = 'baiyue_auth' AND table_name = 'auth_account' + AND index_name = 'uk_auth_account_phone') THEN + ALTER TABLE auth_account ADD UNIQUE KEY uk_auth_account_phone (phone); + END IF; +END$$ +DELIMITER ; +CALL auth_backfill_login_phone(); +DROP PROCEDURE auth_backfill_login_phone; + +USE baiyue_firstleg; CALL baiyue_firstleg.assert_unified_final_schema(); DROP PROCEDURE IF EXISTS baiyue_firstleg.assert_unified_final_schema; SELECT 'PASS' AS migration_status,