Files
baiyue-firstleg/deploy/sql/2026-07-31一期回归测试环境增量迁移.sql
T
2026-08-03 18:28:35 +08:00

777 lines
44 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 一期回归测试环境增量迁移汇总
-- 适用版本:MySQL 8.0
-- 涉及数据库:baiyue_iam、baiyue_warehouse、baiyue_order、baiyue_firstleg、baiyue_file
-- 安全边界:不创建数据库、不清表、不删除业务数据、不写入演示租户及演示业务数据。
-- 可重复执行:所有新增字段、表、索引和权限均带存在性判断或幂等写入。
-- 重要说明:MySQL DDL 会隐式提交,本脚本不能作为一个跨库事务整体回滚。
SET NAMES utf8mb4;
-- ============================================================================
-- 1. IAM:权限资源结构、平台/商户按钮权限及管理员授权
-- ============================================================================
USE baiyue_iam;
DROP PROCEDURE IF EXISTS regression_assert_table;
DELIMITER $$
CREATE PROCEDURE regression_assert_table(IN p_table_name VARCHAR(64))
BEGIN
IF NOT EXISTS (
SELECT 1
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name = p_table_name
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'baiyue_iam 缺少基础表,请先执行 IAM 基线建表脚本';
END IF;
END$$
DELIMITER ;
CALL regression_assert_table('iam_permission');
CALL regression_assert_table('iam_role');
CALL regression_assert_table('iam_role_permission');
CALL regression_assert_table('iam_tenant');
DROP PROCEDURE regression_assert_table;
SET @iam_permission_built_in_sql = IF(
EXISTS(
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'iam_permission'
AND column_name = 'built_in'
),
'SELECT 1',
'ALTER TABLE iam_permission ADD COLUMN built_in TINYINT NOT NULL DEFAULT 0 COMMENT ''是否为系统预置权限;预置资源不可通过管理接口修改'' AFTER status'
);
PREPARE iam_permission_built_in_stmt FROM @iam_permission_built_in_sql;
EXECUTE iam_permission_built_in_stmt;
DEALLOCATE PREPARE iam_permission_built_in_stmt;
-- 一期客户档案字段;与 iam/db/phase1-customer-profile.sql 保持一致。
DROP PROCEDURE IF EXISTS regression_add_iam_column;
DELIMITER $$
CREATE PROCEDURE regression_add_iam_column(
IN p_column_name VARCHAR(64),
IN p_definition VARCHAR(1000)
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = 'iam_tenant'
AND column_name = p_column_name
) THEN
SET @regression_iam_sql = CONCAT(
'ALTER TABLE iam_tenant ADD COLUMN `', p_column_name, '` ', p_definition
);
PREPARE regression_iam_stmt FROM @regression_iam_sql;
EXECUTE regression_iam_stmt;
DEALLOCATE PREPARE regression_iam_stmt;
END IF;
END$$
DELIMITER ;
CALL regression_add_iam_column('contact_wechat', 'VARCHAR(64) NULL COMMENT ''联系微信'' AFTER contact_email');
CALL regression_add_iam_column('sales_owner_name', 'VARCHAR(64) NULL COMMENT ''销售负责人姓名'' AFTER contact_wechat');
CALL regression_add_iam_column('payment_term_days', 'SMALLINT UNSIGNED NULL COMMENT ''账期天数'' AFTER sales_owner_name');
CALL regression_add_iam_column('enterprise_type', 'VARCHAR(64) NULL COMMENT ''企业类型'' AFTER payment_term_days');
CALL regression_add_iam_column('established_date', 'DATE NULL COMMENT ''成立日期'' AFTER enterprise_type');
CALL regression_add_iam_column('registered_capital', 'DECIMAL(18,2) NULL COMMENT ''注册资本'' AFTER established_date');
CALL regression_add_iam_column('registered_capital_currency', 'CHAR(3) NULL COMMENT ''注册资本币种 ISO 4217'' AFTER registered_capital');
CALL regression_add_iam_column('registered_address', 'VARCHAR(500) NULL COMMENT ''注册地址文本'' AFTER registered_capital_currency');
CALL regression_add_iam_column('internal_remark', 'VARCHAR(1000) NULL COMMENT ''平台内部备注'' AFTER registered_address');
DROP PROCEDURE regression_add_iam_column;
-- 先写入父菜单,再写入按钮,避免新增环境出现悬空父节点。
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
(5100000, 0, 'PLATFORM', 'MENU', 0, 'platform:customer', '客户管理', '/customers', NULL, 10, 'ACTIVE', 1, 0),
(5101000, 0, 'PLATFORM', 'MENU', 0, 'platform:system', '系统管理', '/system', NULL, 20, 'ACTIVE', 1, 0),
(5102000, 0, 'PLATFORM', 'MENU', 0, 'platform:order', '头程订单', '/first-leg-orders', NULL, 30, 'ACTIVE', 1, 0),
(5103000, 0, 'PLATFORM', 'MENU', 0, 'platform:master-data', '基础资料', '/master-data', NULL, 40, 'ACTIVE', 1, 0),
(5100010, 0, 'PLATFORM', 'MENU', 5100000, 'platform:customer:list', '企业客户', '/customers/list', NULL, 10, 'ACTIVE', 1, 0),
(5101010, 0, 'PLATFORM', 'MENU', 5101000, 'platform:user:list', '内部用户', '/system/users', NULL, 10, 'ACTIVE', 1, 0),
(5101020, 0, 'PLATFORM', 'MENU', 5101000, 'platform:role:list', '角色管理', '/system/roles', NULL, 20, 'ACTIVE', 1, 0),
(5101030, 0, 'PLATFORM', 'MENU', 5101000, 'platform:permission:list', '菜单按钮', '/system/permissions', NULL, 30, 'ACTIVE', 1, 0),
(5101040, 0, 'PLATFORM', 'MENU', 5101000, 'platform:member:list', '平台成员', '/system/members', NULL, 40, 'ACTIVE', 1, 0),
(5102010, 0, 'PLATFORM', 'MENU', 5102000, 'platform:order:list', '订单列表', '/first-leg-orders/list', NULL, 10, 'ACTIVE', 1, 0),
(5102020, 0, 'PLATFORM', 'MENU', 5102000, 'platform:firstleg:task:list', '履约任务', '/first-leg-tasks/list', NULL, 20, 'ACTIVE', 1, 0),
(5103020, 0, 'PLATFORM', 'MENU', 5103000, 'platform:express:list', '快递公司', '/master-data/express', NULL, 20, 'ACTIVE', 1, 0),
(5103030, 0, 'PLATFORM', 'MENU', 5103000, 'platform:counterparty:list', '往来单位', '/master-data/counterparties', NULL, 30, 'ACTIVE', 1, 0),
(5103040, 0, 'PLATFORM', 'MENU', 5103000, 'platform:download:list', '下载中心', '/downloads', NULL, 40, '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 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
(5100011, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:create', '新增企业客户', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5100014, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:view', '查看企业客户档案', NULL, NULL, 15, 'ACTIVE', 1, 0),
(5100012, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:edit', '编辑企业客户', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5100013, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:status', '启停企业客户', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5100015, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:export', '导出企业客户', NULL, NULL, 40, 'ACTIVE', 1, 0),
(5101011, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:create', '新增内部用户', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5101012, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:edit', '编辑内部用户', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5101013, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:status', '启停内部用户', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5101014, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:reset-password', '重置内部用户密码', NULL, NULL, 40, 'ACTIVE', 1, 0),
(5101015, 0, 'PLATFORM', 'BUTTON', 5101010, 'platform:user:grant-role', '分配内部用户角色', NULL, NULL, 50, 'ACTIVE', 1, 0),
(5101021, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:create', '新增角色', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5101022, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:grant', '角色授权', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5101023, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:edit', '编辑角色', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5101024, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:status', '启停角色', NULL, NULL, 40, 'ACTIVE', 1, 0),
(5101025, 0, 'PLATFORM', 'BUTTON', 5101020, 'platform:role:delete', '删除角色', NULL, NULL, 50, 'ACTIVE', 1, 0),
(5101031, 0, 'PLATFORM', 'BUTTON', 5101030, 'platform:permission:create', '新增菜单按钮', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5101032, 0, 'PLATFORM', 'BUTTON', 5101030, 'platform:permission:edit', '编辑权限资源', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5101033, 0, 'PLATFORM', 'BUTTON', 5101030, 'platform:permission:status', '启停权限资源', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5101034, 0, 'PLATFORM', 'BUTTON', 5101030, 'platform:permission:delete', '删除权限资源', NULL, NULL, 40, 'ACTIVE', 1, 0),
(5101041, 0, 'PLATFORM', 'BUTTON', 5101040, 'platform:member:grant-role', '分配平台成员角色', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5102019, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:create', '平台代客创建订单', NULL, NULL, 90, 'ACTIVE', 1, 0),
(5102024, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:edit', '平台编辑订单草稿', NULL, NULL, 100, 'ACTIVE', 1, 0),
(5102025, 0, 'PLATFORM', 'BUTTON', 5102010, 'platform:order:submit', '平台代客提交订单', NULL, NULL, 110, 'ACTIVE', 1, 0),
(5102021, 0, 'PLATFORM', 'BUTTON', 5102020, 'platform:firstleg:task:view', '查看履约任务', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5102022, 0, 'PLATFORM', 'BUTTON', 5102020, 'platform:firstleg:assignment:history', '查看分配历史', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5102023, 0, 'PLATFORM', 'BUTTON', 5102020, 'platform:firstleg:assignment:assign', '分配履约任务', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5103021, 0, 'PLATFORM', 'BUTTON', 5103020, 'platform:express:create', '新增快递公司', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5103022, 0, 'PLATFORM', 'BUTTON', 5103020, 'platform:express:edit', '编辑快递公司', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5103023, 0, 'PLATFORM', 'BUTTON', 5103020, 'platform:express:status', '启停快递公司', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5103031, 0, 'PLATFORM', 'BUTTON', 5103030, 'platform:counterparty:create', '新增往来单位', NULL, NULL, 10, 'ACTIVE', 1, 0),
(5103032, 0, 'PLATFORM', 'BUTTON', 5103030, 'platform:counterparty:edit', '编辑往来单位', NULL, NULL, 20, 'ACTIVE', 1, 0),
(5103033, 0, 'PLATFORM', 'BUTTON', 5103030, 'platform:counterparty:status', '启停往来单位', NULL, NULL, 30, 'ACTIVE', 1, 0),
(5103041, 0, 'PLATFORM', 'BUTTON', 5103040, 'platform:download:all', '查看全部下载任务', NULL, NULL, 10, 'ACTIVE', 1, 0)
ON DUPLICATE KEY UPDATE
permission_type = VALUES(permission_type),
parent_id = VALUES(parent_id),
permission_name = VALUES(permission_name),
sort_no = VALUES(sort_no),
status = 'ACTIVE',
built_in = 1,
deleted = 0;
-- 商户角色维护权限仅在对应父菜单已存在时补齐,不创建演示租户或角色。
INSERT INTO iam_permission
(id, tenant_id, app_code, permission_type, parent_id, permission_code,
permission_name, sort_no, status, built_in, deleted)
SELECT 5200033, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:edit', '编辑角色', 30, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5200030 AND tenant_id = 10001)
UNION ALL
SELECT 5200034, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:status', '启停角色', 40, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5200030 AND tenant_id = 10001)
UNION ALL
SELECT 5200035, 10001, 'MERCHANT', 'BUTTON', 5200030, 'merchant:role:delete', '删除角色', 50, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5200030 AND tenant_id = 10001)
UNION ALL
SELECT 5300033, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:edit', '编辑角色', 30, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5300030 AND tenant_id = 0)
UNION ALL
SELECT 5300034, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:status', '启停角色', 40, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5300030 AND tenant_id = 0)
UNION ALL
SELECT 5300035, 0, 'MERCHANT', 'BUTTON', 5300030, 'merchant:role:delete', '删除角色', 50, 'ACTIVE', 1, 0
WHERE EXISTS (SELECT 1 FROM iam_permission WHERE id = 5300030 AND tenant_id = 0)
ON DUPLICATE KEY UPDATE
permission_name = VALUES(permission_name),
parent_id = VALUES(parent_id),
sort_no = VALUES(sort_no),
status = 'ACTIVE',
built_in = 1,
deleted = 0;
UPDATE iam_permission
SET built_in = 1
WHERE id BETWEEN 5000000 AND 5399999
AND built_in = 0;
-- 平台超级管理员自动获得本轮新增权限;不存在该角色时不插入任何授权记录。
INSERT 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'
WHERE r.tenant_id = 0
AND r.app_code = 'PLATFORM'
AND r.role_code = 'PLATFORM_ADMIN'
AND r.deleted = 0
AND p.permission_code IN (
'platform:customer', 'platform:customer:list', 'platform:customer:create',
'platform:customer:view', 'platform:customer:edit', 'platform:customer:status', 'platform:customer:export',
'platform:system', 'platform:user:list', 'platform:user:create', 'platform:user:edit',
'platform:user:status', 'platform:user:reset-password', 'platform:user:grant-role',
'platform:role:list', 'platform:role:create', 'platform:role:grant',
'platform:role:edit', 'platform:role:status', 'platform:role:delete',
'platform:member:list', 'platform:member:grant-role',
'platform:permission:list', 'platform:permission:create', 'platform:permission:edit',
'platform:permission:status', 'platform:permission:delete',
'platform:order', 'platform:order:list', 'platform:order:create',
'platform:order:edit', 'platform:order:submit',
'platform:firstleg:task:list', 'platform:firstleg:task:view',
'platform:firstleg:assignment:history', 'platform:firstleg:assignment:assign',
'platform:master-data', 'platform:express:list', 'platform:express:create',
'platform:express:edit', 'platform:express:status',
'platform:counterparty:list', 'platform:counterparty:create',
'platform:counterparty:edit', 'platform:counterparty:status',
'platform:download:list', 'platform:download:all'
)
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- 既有客户列表或审核角色继承详情查看权限,避免升级后丢失原查询能力。
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT DISTINCT existing_grant.role_id, view_permission.id, existing_grant.tenant_id
FROM iam_role_permission existing_grant
JOIN iam_permission existing_permission
ON existing_permission.id = existing_grant.permission_id
JOIN iam_permission view_permission
ON view_permission.tenant_id = 0
AND view_permission.app_code = 'PLATFORM'
AND view_permission.permission_code = 'platform:customer:view'
WHERE existing_permission.tenant_id = 0
AND existing_permission.app_code = 'PLATFORM'
AND existing_permission.permission_code IN ('platform:customer:list', 'platform:customer:review')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- 已有客户列表或审核角色获得客户导出及本人下载任务查询,不继承查看全部任务权限。
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT DISTINCT existing_grant.role_id, added_permission.id, existing_grant.tenant_id
FROM iam_role_permission existing_grant
JOIN iam_permission existing_permission ON existing_permission.id = existing_grant.permission_id
JOIN iam_permission added_permission
ON added_permission.tenant_id = 0
AND added_permission.app_code = 'PLATFORM'
AND added_permission.permission_code IN ('platform:customer:export', 'platform:download:list')
WHERE existing_permission.tenant_id = 0
AND existing_permission.app_code = 'PLATFORM'
AND existing_permission.permission_code IN ('platform:customer:list', 'platform:customer:review')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- 已存在的商户超级管理员/企业管理员获得对应租户的角色维护权限。
INSERT INTO iam_role_permission (role_id, permission_id, tenant_id)
SELECT r.id, p.id, r.tenant_id
FROM iam_role r
JOIN iam_permission p
ON p.tenant_id = r.tenant_id
AND p.app_code = 'MERCHANT'
WHERE r.app_code = 'MERCHANT'
AND r.role_code IN ('MERCHANT_OWNER', 'MERCHANT_ADMIN')
AND r.deleted = 0
AND p.permission_code IN ('merchant:role:edit', 'merchant:role:status', 'merchant:role:delete')
ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id);
-- ============================================================================
-- 2. Warehouse:仓库、地址、能力、往来单位、快递公司结构兼容迁移
-- ============================================================================
USE baiyue_warehouse;
CREATE TABLE IF NOT EXISTS wh_partner (
id BIGINT UNSIGNED NOT NULL,
tenant_id BIGINT UNSIGNED NOT NULL,
partner_code VARCHAR(50) NOT NULL,
partner_name VARCHAR(128) NOT NULL,
partner_type VARCHAR(20) NOT NULL COMMENT 'CUSTOMER、SUPPLIER或BOTH',
contact_name VARCHAR(64) NOT NULL,
contact_phone VARCHAR(32) NOT NULL,
contact_email VARCHAR(128) NULL,
country_code CHAR(2) NOT NULL,
province VARCHAR(64) NULL,
city VARCHAR(64) NOT NULL,
district VARCHAR(64) NULL,
address_line VARCHAR(255) NOT NULL,
postal_code VARCHAR(20) NULL,
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
created_by BIGINT UNSIGNED NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT UNSIGNED NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
deleted TINYINT(1) NOT NULL DEFAULT 0,
version INT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uk_wh_partner_tenant_code (tenant_id, partner_code, deleted),
KEY idx_wh_partner_tenant_status (tenant_id, status, deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='仓储域内的租户往来单位配置';
CREATE TABLE IF NOT EXISTS wh_express_company (
id BIGINT UNSIGNED NOT NULL COMMENT '快递公司记录ID',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '所属租户ID',
company_code VARCHAR(50) NOT NULL COMMENT '租户内唯一快递公司编码',
company_name VARCHAR(128) NOT NULL COMMENT '快递公司名称',
service_phone VARCHAR(32) NULL COMMENT '客服电话',
website VARCHAR(255) NULL COMMENT '官方网站',
tracking_url_template VARCHAR(500) NULL COMMENT '轨迹查询地址模板,可包含{trackingNo}',
status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态',
remark VARCHAR(500) NULL COMMENT '备注',
created_by BIGINT UNSIGNED NULL COMMENT '创建人ID',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
updated_by BIGINT UNSIGNED NULL COMMENT '最后修改人ID',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_wh_express_tenant_code (tenant_id, company_code, deleted),
KEY idx_wh_express_tenant_status (tenant_id, status, deleted)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户维度快递公司主数据';
DROP PROCEDURE IF EXISTS regression_assert_warehouse_table;
DELIMITER $$
CREATE PROCEDURE regression_assert_warehouse_table(IN p_table_name VARCHAR(64))
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_name = p_table_name
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'baiyue_warehouse 缺少仓库基础表,请先执行 warehouse.sql';
END IF;
END$$
DELIMITER ;
CALL regression_assert_warehouse_table('wh_warehouse');
CALL regression_assert_warehouse_table('wh_warehouse_address');
CALL regression_assert_warehouse_table('wh_service_capability');
DROP PROCEDURE regression_assert_warehouse_table;
DROP PROCEDURE IF EXISTS regression_add_column;
DELIMITER $$
CREATE PROCEDURE regression_add_column(
IN p_table_name VARCHAR(64),
IN p_column_name VARCHAR(64),
IN p_column_definition TEXT
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = p_table_name
AND column_name = p_column_name
) THEN
SET @regression_column_sql = CONCAT(
'ALTER TABLE `', REPLACE(p_table_name, '`', '``'),
'` ADD COLUMN `', REPLACE(p_column_name, '`', '``'),
'` ', p_column_definition
);
PREPARE regression_column_stmt FROM @regression_column_sql;
EXECUTE regression_column_stmt;
DEALLOCATE PREPARE regression_column_stmt;
END IF;
END$$
DELIMITER ;
CALL regression_add_column('wh_warehouse', 'warehouse_type', 'VARCHAR(32) NOT NULL DEFAULT ''DOMESTIC'' COMMENT ''仓库类型'' AFTER warehouse_name');
CALL regression_add_column('wh_warehouse', 'country_code', 'CHAR(2) NOT NULL DEFAULT ''CN'' COMMENT ''所在国家二字码'' AFTER warehouse_type');
CALL regression_add_column('wh_warehouse', 'timezone', 'VARCHAR(64) NOT NULL DEFAULT ''Asia/Shanghai'' COMMENT ''IANA时区'' AFTER country_code');
CALL regression_add_column('wh_warehouse', 'contact_name', 'VARCHAR(64) NULL AFTER timezone');
CALL regression_add_column('wh_warehouse', 'contact_phone', 'VARCHAR(32) NULL AFTER contact_name');
CALL regression_add_column('wh_warehouse', 'contact_email', 'VARCHAR(128) NULL AFTER contact_phone');
CALL regression_add_column('wh_warehouse', 'status', 'VARCHAR(20) NOT NULL DEFAULT ''ACTIVE'' AFTER contact_email');
CALL regression_add_column('wh_warehouse', 'remark', 'VARCHAR(500) NULL AFTER status');
CALL regression_add_column('wh_warehouse', 'created_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_warehouse', 'created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_warehouse', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_warehouse', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_warehouse', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL regression_add_column('wh_warehouse', 'version', 'INT NOT NULL DEFAULT 0');
CALL regression_add_column('wh_warehouse_address', 'tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER id');
CALL regression_add_column('wh_warehouse_address', 'warehouse_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER tenant_id');
CALL regression_add_column('wh_warehouse_address', 'address_type', 'VARCHAR(20) NOT NULL DEFAULT ''OPERATING'' AFTER warehouse_id');
CALL regression_add_column('wh_warehouse_address', 'country_code', 'CHAR(2) NOT NULL DEFAULT ''CN'' AFTER address_type');
CALL regression_add_column('wh_warehouse_address', 'state_province', 'VARCHAR(100) NULL');
CALL regression_add_column('wh_warehouse_address', 'city', 'VARCHAR(100) NOT NULL DEFAULT '''' AFTER state_province');
CALL regression_add_column('wh_warehouse_address', 'district', 'VARCHAR(100) NULL');
CALL regression_add_column('wh_warehouse_address', 'postal_code', 'VARCHAR(20) NULL');
CALL regression_add_column('wh_warehouse_address', 'address_line1', 'VARCHAR(255) NOT NULL DEFAULT '''' AFTER postal_code');
CALL regression_add_column('wh_warehouse_address', 'address_line2', 'VARCHAR(255) NULL');
CALL regression_add_column('wh_warehouse_address', 'latitude', 'DECIMAL(10,7) NULL');
CALL regression_add_column('wh_warehouse_address', 'longitude', 'DECIMAL(10,7) NULL');
CALL regression_add_column('wh_warehouse_address', 'created_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_warehouse_address', 'created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_warehouse_address', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_warehouse_address', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_warehouse_address', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL regression_add_column('wh_warehouse_address', 'version', 'INT NOT NULL DEFAULT 0');
CALL regression_add_column('wh_service_capability', 'tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER id');
CALL regression_add_column('wh_service_capability', 'warehouse_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER tenant_id');
CALL regression_add_column('wh_service_capability', 'capability_code', 'VARCHAR(50) NOT NULL DEFAULT '''' AFTER warehouse_id');
CALL regression_add_column('wh_service_capability', 'capability_name', 'VARCHAR(100) NOT NULL DEFAULT '''' AFTER capability_code');
CALL regression_add_column('wh_service_capability', 'enabled', 'TINYINT(1) NOT NULL DEFAULT 1');
CALL regression_add_column('wh_service_capability', 'cutoff_time', 'TIME NULL');
CALL regression_add_column('wh_service_capability', 'description', 'VARCHAR(500) NULL');
CALL regression_add_column('wh_service_capability', 'created_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_service_capability', 'created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_service_capability', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_service_capability', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_service_capability', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL regression_add_column('wh_service_capability', 'version', 'INT NOT NULL DEFAULT 0');
CALL regression_add_column('wh_partner', 'tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER id');
CALL regression_add_column('wh_partner', 'partner_code', 'VARCHAR(50) NOT NULL DEFAULT '''' AFTER tenant_id');
CALL regression_add_column('wh_partner', 'partner_name', 'VARCHAR(128) NOT NULL DEFAULT '''' AFTER partner_code');
CALL regression_add_column('wh_partner', 'partner_type', 'VARCHAR(20) NOT NULL DEFAULT ''CUSTOMER'' AFTER partner_name');
CALL regression_add_column('wh_partner', 'contact_name', 'VARCHAR(64) NOT NULL DEFAULT '''' AFTER partner_type');
CALL regression_add_column('wh_partner', 'contact_phone', 'VARCHAR(32) NOT NULL DEFAULT '''' AFTER contact_name');
CALL regression_add_column('wh_partner', 'contact_email', 'VARCHAR(128) NULL');
CALL regression_add_column('wh_partner', 'country_code', 'CHAR(2) NOT NULL DEFAULT ''CN'' AFTER contact_email');
CALL regression_add_column('wh_partner', 'province', 'VARCHAR(64) NULL');
CALL regression_add_column('wh_partner', 'city', 'VARCHAR(64) NOT NULL DEFAULT '''' AFTER province');
CALL regression_add_column('wh_partner', 'district', 'VARCHAR(64) NULL');
CALL regression_add_column('wh_partner', 'address_line', 'VARCHAR(255) NOT NULL DEFAULT '''' AFTER district');
CALL regression_add_column('wh_partner', 'postal_code', 'VARCHAR(20) NULL');
CALL regression_add_column('wh_partner', 'status', 'VARCHAR(20) NOT NULL DEFAULT ''ACTIVE'' AFTER postal_code');
CALL regression_add_column('wh_partner', 'created_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_partner', 'created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_partner', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_partner', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_partner', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL regression_add_column('wh_partner', 'version', 'INT NOT NULL DEFAULT 0');
CALL regression_add_column('wh_express_company', 'tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 AFTER id');
CALL regression_add_column('wh_express_company', 'company_code', 'VARCHAR(50) NOT NULL DEFAULT '''' AFTER tenant_id');
CALL regression_add_column('wh_express_company', 'company_name', 'VARCHAR(128) NOT NULL DEFAULT '''' AFTER company_code');
CALL regression_add_column('wh_express_company', 'service_phone', 'VARCHAR(32) NULL');
CALL regression_add_column('wh_express_company', 'website', 'VARCHAR(255) NULL');
CALL regression_add_column('wh_express_company', 'tracking_url_template', 'VARCHAR(500) NULL');
CALL regression_add_column('wh_express_company', 'status', 'VARCHAR(20) NOT NULL DEFAULT ''ACTIVE'' AFTER tracking_url_template');
CALL regression_add_column('wh_express_company', 'remark', 'VARCHAR(500) NULL');
CALL regression_add_column('wh_express_company', 'created_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_express_company', 'created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_express_company', 'updated_by', 'BIGINT UNSIGNED NULL');
CALL regression_add_column('wh_express_company', 'updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)');
CALL regression_add_column('wh_express_company', 'deleted', 'TINYINT(1) NOT NULL DEFAULT 0');
CALL regression_add_column('wh_express_company', 'version', 'INT NOT NULL DEFAULT 0');
DROP PROCEDURE regression_add_column;
DROP PROCEDURE IF EXISTS regression_add_index;
DELIMITER $$
CREATE PROCEDURE regression_add_index(
IN p_table_name VARCHAR(64),
IN p_index_name VARCHAR(64),
IN p_index_definition TEXT
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = p_table_name
AND index_name = p_index_name
) THEN
SET @regression_index_sql = CONCAT(
'ALTER TABLE `', REPLACE(p_table_name, '`', '``'),
'` ADD ', p_index_definition
);
PREPARE regression_index_stmt FROM @regression_index_sql;
EXECUTE regression_index_stmt;
DEALLOCATE PREPARE regression_index_stmt;
END IF;
END$$
DELIMITER ;
CALL regression_add_index('wh_warehouse', 'idx_wh_tenant_status', 'KEY idx_wh_tenant_status (tenant_id, status, deleted)');
CALL regression_add_index('wh_warehouse_address', 'idx_address_warehouse', 'KEY idx_address_warehouse (tenant_id, warehouse_id, deleted)');
CALL regression_add_index('wh_service_capability', 'idx_capability_query', 'KEY idx_capability_query (tenant_id, warehouse_id, enabled, deleted)');
CALL regression_add_index('wh_partner', 'idx_wh_partner_tenant_status', 'KEY idx_wh_partner_tenant_status (tenant_id, status, deleted)');
CALL regression_add_index('wh_partner', 'uk_wh_partner_tenant_code', 'UNIQUE KEY uk_wh_partner_tenant_code (tenant_id, partner_code, deleted)');
CALL regression_add_index('wh_express_company', 'idx_wh_express_tenant_status', 'KEY idx_wh_express_tenant_status (tenant_id, status, deleted)');
CALL regression_add_index('wh_express_company', 'uk_wh_express_tenant_code', 'UNIQUE KEY uk_wh_express_tenant_code (tenant_id, company_code, deleted)');
DROP PROCEDURE regression_add_index;
-- ============================================================================
-- 3. Order:一期订单快照字段、货物字段和持久化幂等记录
-- ============================================================================
USE baiyue_order;
DROP PROCEDURE IF EXISTS regression_assert_order_table;
DELIMITER $$
CREATE PROCEDURE regression_assert_order_table(IN p_table_name VARCHAR(64))
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_name = p_table_name
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'baiyue_order 缺少订单基础表,请先执行 order.sql';
END IF;
END$$
DELIMITER ;
CALL regression_assert_order_table('ord_order');
CALL regression_assert_order_table('ord_order_cargo');
DROP PROCEDURE regression_assert_order_table;
DROP PROCEDURE IF EXISTS regression_add_order_column;
DELIMITER $$
CREATE PROCEDURE regression_add_order_column(
IN p_table_name VARCHAR(64),
IN p_column_name VARCHAR(64),
IN p_definition VARCHAR(1000)
)
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = p_table_name
AND column_name = p_column_name
) THEN
SET @regression_order_sql = CONCAT(
'ALTER TABLE `', p_table_name, '` ADD COLUMN `', p_column_name, '` ', p_definition
);
PREPARE regression_order_stmt FROM @regression_order_sql;
EXECUTE regression_order_stmt;
DEALLOCATE PREPARE regression_order_stmt;
END IF;
END$$
DELIMITER ;
CALL regression_add_order_column('ord_order', 'pickup_method', 'VARCHAR(24) NULL COMMENT ''提货方式''');
CALL regression_add_order_column('ord_order', 'receiving_warehouse_id', 'BIGINT UNSIGNED NULL COMMENT ''国内收货仓ID''');
CALL regression_add_order_column('ord_order', 'receiving_warehouse_name', 'VARCHAR(128) NULL COMMENT ''国内收货仓名称快照''');
CALL regression_add_order_column('ord_order', 'receiving_warehouse_address', 'VARCHAR(512) NULL COMMENT ''国内收货仓完整地址快照''');
CALL regression_add_order_column('ord_order', 'receiving_time', 'VARCHAR(128) NULL COMMENT ''国内收货仓收货时间快照''');
CALL regression_add_order_column('ord_order', 'channel_code', 'VARCHAR(64) NULL COMMENT ''运输渠道编码''');
CALL regression_add_order_column('ord_order', 'channel_name', 'VARCHAR(128) NULL COMMENT ''运输渠道名称快照''');
CALL regression_add_order_column('ord_order', 'tax_mode', 'VARCHAR(24) NULL COMMENT ''报关买单或退税模式''');
CALL regression_add_order_column('ord_order', 'container_mode', 'VARCHAR(24) NULL COMMENT ''整柜或散货模式''');
CALL regression_add_order_column('ord_order', 'customs_inspection', 'TINYINT(1) NULL COMMENT ''是否需要海关查验''');
CALL regression_add_order_column('ord_order', 'destination_type', 'VARCHAR(24) NULL COMMENT ''FBA、海外仓或私人地址''');
CALL regression_add_order_column('ord_order', 'amazon_warehouse_code', 'VARCHAR(32) NULL COMMENT ''亚马逊仓库编码''');
CALL regression_add_order_column('ord_order', 'shipment_id', 'VARCHAR(64) NULL COMMENT ''亚马逊Shipment ID''');
CALL regression_add_order_column('ord_order', 'reference_id', 'VARCHAR(64) NULL COMMENT ''亚马逊Reference ID''');
CALL regression_add_order_column('ord_order', 'express_company', 'VARCHAR(64) NULL COMMENT ''履约快递公司名称快照''');
CALL regression_add_order_column('ord_order', 'express_tracking_no', 'VARCHAR(128) NULL COMMENT ''履约快递单号''');
CALL regression_add_order_column('ord_order_cargo', 'sku_no', 'VARCHAR(64) NULL COMMENT ''SKU编号''');
CALL regression_add_order_column('ord_order_cargo', 'upc_no', 'VARCHAR(64) NULL COMMENT ''UPC编号''');
CALL regression_add_order_column('ord_order_cargo', 'cargo_name_en', 'VARCHAR(128) NULL COMMENT ''货物英文名称''');
CALL regression_add_order_column('ord_order_cargo', 'customs_hs_code', 'VARCHAR(20) NULL COMMENT ''目的国海关HS编码''');
CALL regression_add_order_column('ord_order_cargo', 'units_per_package', 'INT UNSIGNED NULL COMMENT ''每箱件数''');
CALL regression_add_order_column('ord_order_cargo', 'total_quantity', 'INT UNSIGNED NULL COMMENT ''总件数''');
CALL regression_add_order_column('ord_order_cargo', 'net_weight_kg', 'DECIMAL(18,3) NULL COMMENT ''净重千克''');
CALL regression_add_order_column('ord_order_cargo', 'unit_declared_value', 'DECIMAL(18,2) NULL COMMENT ''单件申报价值''');
CALL regression_add_order_column('ord_order_cargo', 'material', 'VARCHAR(128) NULL COMMENT ''材质''');
CALL regression_add_order_column('ord_order_cargo', 'product_usage', 'VARCHAR(128) NULL COMMENT ''用途''');
CALL regression_add_order_column('ord_order_cargo', 'model', 'VARCHAR(64) NULL COMMENT ''型号''');
CALL regression_add_order_column('ord_order_cargo', 'brand', 'VARCHAR(64) NULL COMMENT ''品牌''');
DROP PROCEDURE regression_add_order_column;
CREATE TABLE IF NOT EXISTS ord_idempotency_record (
id BIGINT UNSIGNED NOT NULL COMMENT '幂等记录ID',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '租户ID',
operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID',
operation VARCHAR(32) NOT NULL COMMENT '操作类型',
resource_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '资源ID',
idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键',
request_hash CHAR(64) NOT NULL COMMENT '请求内容摘要',
status VARCHAR(16) NOT NULL COMMENT '处理状态',
result_order_id BIGINT UNSIGNED NULL COMMENT '重放结果订单ID',
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_order_idempotency_scope (tenant_id, operator_id, operation, idempotency_key),
KEY idx_order_idempotency_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单写接口持久化幂等记录';
-- 兼容曾经只建表但未建立完整索引的测试库。
SET @order_idempotency_unique_sql = IF(
EXISTS(
SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'ord_idempotency_record'
AND index_name = 'uk_order_idempotency_scope'
),
'SELECT 1',
'ALTER TABLE ord_idempotency_record ADD UNIQUE KEY uk_order_idempotency_scope (tenant_id, operator_id, operation, idempotency_key)'
);
PREPARE order_idempotency_unique_stmt FROM @order_idempotency_unique_sql;
EXECUTE order_idempotency_unique_stmt;
DEALLOCATE PREPARE order_idempotency_unique_stmt;
SET @order_idempotency_created_sql = IF(
EXISTS(
SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'ord_idempotency_record'
AND index_name = 'idx_order_idempotency_created'
),
'SELECT 1',
'ALTER TABLE ord_idempotency_record ADD KEY idx_order_idempotency_created (created_at)'
);
PREPARE order_idempotency_created_stmt FROM @order_idempotency_created_sql;
EXECUTE order_idempotency_created_stmt;
DEALLOCATE PREPARE order_idempotency_created_stmt;
-- ============================================================================
-- 4. Firstleg:履约任务分页索引
-- ============================================================================
USE baiyue_firstleg;
DROP PROCEDURE IF EXISTS regression_assert_firstleg_table;
DELIMITER $$
CREATE PROCEDURE regression_assert_firstleg_table()
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_name = 'fl_fulfillment_task'
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'baiyue_firstleg 缺少履约任务基础表,请先执行 firstleg.sql';
END IF;
END$$
DELIMITER ;
CALL regression_assert_firstleg_table();
DROP PROCEDURE regression_assert_firstleg_table;
SET @firstleg_task_list_index_sql = IF(
EXISTS(
SELECT 1 FROM information_schema.statistics
WHERE table_schema = DATABASE()
AND table_name = 'fl_fulfillment_task'
AND index_name = 'idx_task_tenant_created'
),
'SELECT 1',
'CREATE INDEX idx_task_tenant_created ON fl_fulfillment_task (tenant_id, created_at)'
);
PREPARE firstleg_task_list_index_stmt FROM @firstleg_task_list_index_sql;
EXECUTE firstleg_task_list_index_stmt;
DEALLOCATE PREPARE firstleg_task_list_index_stmt;
-- ============================================================================
-- 5. File:公共导出与下载中心任务表
-- ============================================================================
USE baiyue_file;
CREATE TABLE IF NOT EXISTS file_export_task (
id BIGINT UNSIGNED NOT NULL COMMENT '导出任务ID(雪花ID)',
tenant_id BIGINT UNSIGNED NOT NULL COMMENT '申请人所属租户ID,平台任务为0',
app_code VARCHAR(24) NOT NULL COMMENT '申请端',
task_no VARCHAR(40) NOT NULL COMMENT '导出任务编号',
export_type VARCHAR(64) NOT NULL COMMENT '导出类型',
format VARCHAR(16) NOT NULL DEFAULT 'XLSX' COMMENT '导出格式',
task_name VARCHAR(128) NOT NULL COMMENT '任务名称',
parameters_json JSON NOT NULL COMMENT '筛选条件快照',
status VARCHAR(24) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态',
total_rows BIGINT UNSIGNED NULL,
processed_rows BIGINT UNSIGNED NOT NULL DEFAULT 0,
file_name VARCHAR(255) NULL,
object_key VARCHAR(512) NULL,
content_type VARCHAR(128) NULL,
size_bytes BIGINT UNSIGNED NULL,
failure_message VARCHAR(1000) NULL,
requested_by BIGINT UNSIGNED NOT NULL,
requested_username VARCHAR(128) NULL,
requested_at DATETIME(3) NOT NULL,
started_at DATETIME(3) NULL,
completed_at DATETIME(3) NULL,
expires_at DATETIME(3) NULL,
created_by BIGINT UNSIGNED NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT UNSIGNED NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
deleted TINYINT(1) NOT NULL DEFAULT 0,
version INT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uk_file_export_task_no (task_no),
KEY idx_file_export_owner (tenant_id, app_code, requested_by, requested_at),
KEY idx_file_export_status (status, requested_at),
KEY idx_file_export_expiry (status, expires_at)
) ENGINE=InnoDB COMMENT='公共异步导出任务表';
-- ============================================================================
-- 6. 执行后只读核验
-- ============================================================================
SELECT
'IAM权限资源' AS check_item,
COUNT(*) AS actual_count,
47 AS expected_count,
IF(COUNT(*) = 47, '通过', '请检查缺失权限') AS check_result
FROM baiyue_iam.iam_permission
WHERE deleted = 0
AND permission_code IN (
'platform:customer', 'platform:customer:list', 'platform:customer:create',
'platform:customer:view', 'platform:customer:edit', 'platform:customer:status', 'platform:customer:export',
'platform:system', 'platform:user:list', 'platform:user:create', 'platform:user:edit',
'platform:user:status', 'platform:user:reset-password', 'platform:user:grant-role',
'platform:role:list', 'platform:role:create', 'platform:role:grant',
'platform:role:edit', 'platform:role:status', 'platform:role:delete',
'platform:member:list', 'platform:member:grant-role',
'platform:permission:list', 'platform:permission:create', 'platform:permission:edit',
'platform:permission:status', 'platform:permission:delete',
'platform:order', 'platform:order:list', 'platform:order:create',
'platform:order:edit', 'platform:order:submit',
'platform:firstleg:task:list', 'platform:firstleg:task:view',
'platform:firstleg:assignment:history', 'platform:firstleg:assignment:assign',
'platform:master-data', 'platform:express:list', 'platform:express:create',
'platform:express:edit', 'platform:express:status',
'platform:counterparty:list', 'platform:counterparty:create',
'platform:counterparty:edit', 'platform:counterparty:status',
'platform:download:list', 'platform:download:all'
);
SELECT
'IAM客户档案字段' AS check_item,
COUNT(*) AS actual_count,
9 AS expected_count,
IF(COUNT(*) = 9, '通过', '请检查客户档案字段迁移') AS check_result
FROM information_schema.columns
WHERE table_schema = 'baiyue_iam'
AND table_name = 'iam_tenant'
AND column_name IN (
'contact_wechat', 'sales_owner_name', 'payment_term_days', 'enterprise_type',
'established_date', 'registered_capital', 'registered_capital_currency',
'registered_address', 'internal_remark'
);
SELECT
table_name,
COUNT(*) AS column_count
FROM information_schema.columns
WHERE table_schema = 'baiyue_warehouse'
AND table_name IN (
'wh_warehouse', 'wh_warehouse_address', 'wh_service_capability',
'wh_partner', 'wh_express_company'
)
GROUP BY table_name
ORDER BY table_name;
SELECT
IF(COUNT(*) = 1, '通过', '缺失') AS idempotency_table,
'baiyue_order.ord_idempotency_record' AS object_name
FROM information_schema.tables
WHERE table_schema = 'baiyue_order'
AND table_name = 'ord_idempotency_record';
SELECT
IF(COUNT(*) > 0, '通过', '缺失') AS idempotency_unique_index,
'uk_order_idempotency_scope' AS object_name
FROM information_schema.statistics
WHERE table_schema = 'baiyue_order'
AND table_name = 'ord_idempotency_record'
AND index_name = 'uk_order_idempotency_scope';
SELECT
IF(COUNT(*) > 0, '通过', '缺失') AS firstleg_task_index,
'idx_task_tenant_created' AS object_name
FROM information_schema.statistics
WHERE table_schema = 'baiyue_firstleg'
AND table_name = 'fl_fulfillment_task'
AND index_name = 'idx_task_tenant_created';
SELECT
IF(COUNT(*) = 1, '通过', '缺失') AS export_task_table,
'baiyue_file.file_export_task' AS object_name
FROM information_schema.tables
WHERE table_schema = 'baiyue_file'
AND table_name = 'file_export_task';
SELECT 'MIGRATION_COMPLETED' AS migration_status,
'请确认上方所有核验结果均为通过后再启动服务回归' AS message;