diff --git a/deploy/sql/2026-07-31一期回归测试环境增量迁移.sql b/deploy/sql/2026-07-31一期回归测试环境增量迁移.sql deleted file mode 100644 index f33a89241..000000000 --- a/deploy/sql/2026-07-31一期回归测试环境增量迁移.sql +++ /dev/null @@ -1,930 +0,0 @@ --- 一期回归测试环境增量迁移汇总 --- 适用版本: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'); -CALL regression_assert_table('iam_tenant_review'); -CALL regression_assert_table('iam_tenant_qualification'); -CALL regression_assert_table('iam_membership'); -DROP PROCEDURE regression_assert_table; - -ALTER TABLE iam_tenant - MODIFY COLUMN status VARCHAR(20) NOT NULL DEFAULT 'PROFILE_REQUIRED' - COMMENT '租户状态:PROFILE_REQUIRED、PENDING、ACTIVE、REJECTED、DISABLED'; - -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; - --- 审核通过自动开户依赖全局企业管理员模板。通过自然键幂等补齐,避免存量环境 --- 已存在同编码但 ID 不同的角色时,把权限错误授予固定 ID。 -INSERT INTO iam_role ( - id, tenant_id, app_code, role_code, role_name, role_type, status, - description, created_by, updated_by, deleted, version -) VALUES ( - 4000100, 0, 'MERCHANT', 'MERCHANT_OWNER', '企业管理员', 'SYSTEM', 'ACTIVE', - '企业审核通过后自动创建的管理员角色模板', 1000001, 1000001, 0, 0 -) -ON DUPLICATE KEY UPDATE - role_name = VALUES(role_name), role_type = 'SYSTEM', status = 'ACTIVE', - description = VALUES(description), 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 -) -SELECT permission.id + 100000, 0, permission.app_code, permission.permission_type, - CASE WHEN permission.parent_id = 0 THEN 0 ELSE permission.parent_id + 100000 END, - permission.permission_code, permission.permission_name, permission.route_path, - permission.http_method, permission.sort_no, 'ACTIVE', 1, 0 -FROM iam_permission permission -WHERE permission.tenant_id = 10001 AND permission.app_code = 'MERCHANT' - AND permission.permission_type IN ('MENU', 'BUTTON') - AND permission.deleted = 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_role_permission (role_id, permission_id, tenant_id) -SELECT owner_role.id, permission.id, 0 -FROM iam_role owner_role -JOIN iam_permission permission - ON permission.tenant_id = 0 AND permission.app_code = 'MERCHANT' - AND permission.permission_type IN ('MENU', 'BUTTON') - AND permission.status = 'ACTIVE' AND permission.deleted = 0 -WHERE owner_role.tenant_id = 0 AND owner_role.app_code = 'MERCHANT' - AND owner_role.role_code = 'MERCHANT_OWNER' - AND owner_role.status = 'ACTIVE' AND owner_role.deleted = 0 -ON DUPLICATE KEY UPDATE tenant_id = VALUES(tenant_id); - --- 一期客户档案字段;与 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('legal_representative', 'VARCHAR(64) NULL COMMENT ''法定代表人'' AFTER legal_name'); -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'); -CALL regression_add_iam_column('approved_at', 'DATETIME(3) NULL COMMENT ''审核通过时间'' AFTER internal_remark'); -CALL regression_add_iam_column('approved_by', 'BIGINT NULL COMMENT ''审核人ID'' AFTER approved_at'); -CALL regression_add_iam_column('reject_reason', 'VARCHAR(500) NULL COMMENT ''驳回原因'' AFTER approved_by'); -DROP PROCEDURE regression_add_iam_column; - --- 注册审核和资质替换依赖的辅助字段;存量测试库也必须具备同一契约。 -DROP PROCEDURE IF EXISTS regression_add_iam_related_column; -DELIMITER $$ -CREATE PROCEDURE regression_add_iam_related_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_iam_related_sql = CONCAT( - 'ALTER TABLE `', p_table_name, '` ADD COLUMN `', p_column_name, '` ', p_definition - ); - PREPARE regression_iam_related_stmt FROM @regression_iam_related_sql; - EXECUTE regression_iam_related_stmt; - DEALLOCATE PREPARE regression_iam_related_stmt; - END IF; -END$$ -DELIMITER ; -CALL regression_add_iam_related_column('iam_tenant_qualification', 'review_comment', 'VARCHAR(500) NULL COMMENT ''审核意见'''); -CALL regression_add_iam_related_column('iam_membership', 'created_by', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''创建人ID'''); -CALL regression_add_iam_related_column('iam_membership', 'updated_by', 'BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''最后修改人ID'''); -DROP PROCEDURE regression_add_iam_related_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), - (5100020, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:review', '客户审核', NULL, NULL, 50, 'ACTIVE', 1, 0), - (5100021, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:approve', '审核通过', NULL, NULL, 60, 'ACTIVE', 1, 0), - (5100022, 0, 'PLATFORM', 'BUTTON', 5100010, 'platform:customer:reject', '审核驳回', NULL, NULL, 70, '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:customer:review', 'platform:customer:approve', 'platform:customer:reject', - '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:customer:review', 'platform:customer:approve', 'platform:customer:reject', - '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, - 10 AS expected_count, - IF(COUNT(*) = 10, '通过', '请检查客户档案字段迁移') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_tenant' - AND column_name IN ( - 'legal_representative', 'contact_wechat', 'sales_owner_name', 'payment_term_days', 'enterprise_type', - 'established_date', 'registered_capital', 'registered_capital_currency', - 'registered_address', 'internal_remark' - ); - -SELECT - 'IAM注册审核字段' AS check_item, - COUNT(*) AS actual_count, - 4 AS expected_count, - IF(COUNT(*) = 4, '通过', '请检查租户审核状态和结果字段') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_tenant' - AND column_name IN ('status', 'approved_at', 'approved_by', 'reject_reason'); - -SELECT - 'IAM资质与成员审计字段' AS check_item, - ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_tenant_qualification' - AND column_name = 'review_comment' - ) + ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_membership' - AND column_name IN ('created_by', 'updated_by') - ) AS actual_count, - 3 AS expected_count, - IF( - ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_tenant_qualification' - AND column_name = 'review_comment' - ) + ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = 'baiyue_iam' - AND table_name = 'iam_membership' - AND column_name IN ('created_by', 'updated_by') - ) = 3, - '通过', '请检查资质审核备注和成员审计字段' - ) AS check_result; - -SELECT - 'IAM全局企业管理员模板' AS check_item, - COUNT(DISTINCT owner_role.id) AS role_count, - COUNT(DISTINCT role_permission.permission_id) AS actual_permission_count, - (SELECT COUNT(*) FROM baiyue_iam.iam_permission permission - WHERE permission.tenant_id = 0 AND permission.app_code = 'MERCHANT' - AND permission.permission_type IN ('MENU', 'BUTTON') - AND permission.status = 'ACTIVE' AND permission.deleted = 0) AS expected_permission_count, - IF( - COUNT(DISTINCT owner_role.id) = 1 - AND COUNT(DISTINCT role_permission.permission_id) = ( - SELECT COUNT(*) FROM baiyue_iam.iam_permission permission - WHERE permission.tenant_id = 0 AND permission.app_code = 'MERCHANT' - AND permission.permission_type IN ('MENU', 'BUTTON') - AND permission.status = 'ACTIVE' AND permission.deleted = 0 - ) - AND COUNT(DISTINCT role_permission.permission_id) > 0, - '通过', '请检查全局MERCHANT_OWNER角色及授权' - ) AS check_result -FROM baiyue_iam.iam_role owner_role -LEFT JOIN baiyue_iam.iam_role_permission role_permission - ON role_permission.role_id = owner_role.id AND role_permission.tenant_id = 0 -WHERE owner_role.tenant_id = 0 AND owner_role.app_code = 'MERCHANT' - AND owner_role.role_code = 'MERCHANT_OWNER' - AND owner_role.role_type = 'SYSTEM' AND owner_role.status = 'ACTIVE' AND owner_role.deleted = 0; - -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; diff --git a/deploy/sql/2026-08-03-一期头程下单前置增量迁移.sql b/deploy/sql/2026-08-03-一期头程下单前置增量迁移.sql deleted file mode 100644 index 28c4efd71..000000000 --- a/deploy/sql/2026-08-03-一期头程下单前置增量迁移.sql +++ /dev/null @@ -1,202 +0,0 @@ --- 一期头程下单前置增量迁移。 --- 适用:旧版测试库已存在基础表,但缺少客户档案、往来单位或订单一期字段。 --- 特性:仅新增缺失字段/表,可重复执行;不删除数据,不写入订单业务数据。 -SET NAMES utf8mb4; - --- 1. IAM:下单资格校验会查询以下租户档案字段。 -USE baiyue_iam; -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'service_package'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN service_package VARCHAR(64) NOT NULL DEFAULT ''基础版'' COMMENT ''客户服务套餐'' AFTER contact_email'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'contact_wechat'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN contact_wechat VARCHAR(64) NULL COMMENT ''联系微信'' AFTER contact_email'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'sales_owner_name'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN sales_owner_name VARCHAR(64) NULL COMMENT ''销售负责人姓名'' AFTER contact_wechat'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'payment_term_days'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN payment_term_days SMALLINT UNSIGNED NULL COMMENT ''账期天数'' AFTER sales_owner_name'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'enterprise_type'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN enterprise_type VARCHAR(64) NULL COMMENT ''企业类型'' AFTER payment_term_days'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'established_date'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN established_date DATE NULL COMMENT ''成立日期'' AFTER enterprise_type'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'registered_capital'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN registered_capital DECIMAL(18,2) NULL COMMENT ''注册资本'' AFTER established_date'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'registered_capital_currency'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN registered_capital_currency CHAR(3) NULL COMMENT ''注册资本币种'' AFTER registered_capital'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'registered_address'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN registered_address VARCHAR(500) NULL COMMENT ''注册地址'' AFTER registered_capital_currency'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'iam_tenant' AND column_name = 'internal_remark'), - 'SELECT 1', 'ALTER TABLE iam_tenant ADD COLUMN internal_remark VARCHAR(1000) NULL COMMENT ''平台内部备注'' AFTER registered_address'); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - --- 2. Warehouse:订单主数据校验依赖往来单位及其 SHIPPER 类型。 -USE baiyue_warehouse; -DROP PROCEDURE IF EXISTS order_prerequisite_add_partner_column; -DELIMITER $$ -CREATE PROCEDURE order_prerequisite_add_partner_column( - IN p_column VARCHAR(64), - IN p_definition TEXT -) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = 'wh_partner' AND column_name = p_column - ) THEN - SET @sql = CONCAT('ALTER TABLE wh_partner ADD COLUMN `', p_column, '` ', p_definition); - PREPARE add_column_stmt FROM @sql; - EXECUTE add_column_stmt; - DEALLOCATE PREPARE add_column_stmt; - END IF; -END$$ -DELIMITER ; - -CALL order_prerequisite_add_partner_column('tenant_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0'); -CALL order_prerequisite_add_partner_column('data_scope_id', 'BIGINT UNSIGNED NOT NULL DEFAULT 0'); -CALL order_prerequisite_add_partner_column('partner_code', 'VARCHAR(50) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('partner_name', 'VARCHAR(128) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('partner_type', 'VARCHAR(20) NOT NULL DEFAULT ''CUSTOMER'''); -CALL order_prerequisite_add_partner_column('contact_name', 'VARCHAR(64) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('contact_phone', 'VARCHAR(32) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('contact_email', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_partner_column('country_code', 'CHAR(2) NOT NULL DEFAULT ''CN'''); -CALL order_prerequisite_add_partner_column('province', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_partner_column('city', 'VARCHAR(64) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('district', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_partner_column('address_line', 'VARCHAR(255) NOT NULL DEFAULT '''''); -CALL order_prerequisite_add_partner_column('postal_code', 'VARCHAR(20) NULL'); -CALL order_prerequisite_add_partner_column('status', 'VARCHAR(20) NOT NULL DEFAULT ''ACTIVE'''); -CALL order_prerequisite_add_partner_column('remark', 'VARCHAR(500) NULL'); -CALL order_prerequisite_add_partner_column('created_by', 'BIGINT UNSIGNED NULL'); -CALL order_prerequisite_add_partner_column('created_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)'); -CALL order_prerequisite_add_partner_column('updated_by', 'BIGINT UNSIGNED NULL'); -CALL order_prerequisite_add_partner_column('updated_at', 'DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)'); -CALL order_prerequisite_add_partner_column('deleted', 'TINYINT(1) NOT NULL DEFAULT 0'); -CALL order_prerequisite_add_partner_column('version', 'INT NOT NULL DEFAULT 0'); -DROP PROCEDURE IF EXISTS order_prerequisite_add_partner_column; - -UPDATE wh_partner SET data_scope_id = tenant_id WHERE data_scope_id = 0; -CREATE TABLE IF NOT EXISTS wh_partner_type ( - partner_id BIGINT UNSIGNED NOT NULL, - tenant_id BIGINT UNSIGNED NOT NULL, - data_scope_id BIGINT UNSIGNED NOT NULL, - partner_type VARCHAR(32) NOT NULL, - PRIMARY KEY (partner_id, partner_type), - KEY idx_wh_partner_type_scope (tenant_id, data_scope_id, partner_type, partner_id) -) ENGINE=InnoDB COMMENT='往来单位业务类型'; - --- 将既有有效往来单位的兼容单值类型回填到类型关联表。 -INSERT IGNORE INTO wh_partner_type(partner_id, tenant_id, data_scope_id, partner_type) -SELECT id, tenant_id, data_scope_id, partner_type -FROM wh_partner -WHERE deleted = 0 AND partner_type <> 'BOTH'; -INSERT IGNORE INTO wh_partner_type(partner_id, tenant_id, data_scope_id, partner_type) -SELECT id, tenant_id, data_scope_id, 'CUSTOMER' -FROM wh_partner -WHERE deleted = 0 AND partner_type = 'BOTH'; -INSERT IGNORE INTO wh_partner_type(partner_id, tenant_id, data_scope_id, partner_type) -SELECT id, tenant_id, data_scope_id, 'SUPPLIER' -FROM wh_partner -WHERE deleted = 0 AND partner_type = 'BOTH'; - --- 一期演示商户的既有客户同时作为发货单位,供头程订单 customerId=191000000000000001 使用。 -INSERT IGNORE INTO wh_partner_type(partner_id, tenant_id, data_scope_id, partner_type) -SELECT id, tenant_id, data_scope_id, 'SHIPPER' -FROM wh_partner -WHERE id = 191000000000000001 AND tenant_id = 10001 AND status = 'ACTIVE' AND deleted = 0; - --- 3. Order:草稿创建、货物快照和 Idempotency-Key 持久化。 -USE baiyue_order; -DROP PROCEDURE IF EXISTS order_prerequisite_add_order_column; -DELIMITER $$ -CREATE PROCEDURE order_prerequisite_add_order_column( - IN p_table VARCHAR(64), - IN p_column VARCHAR(64), - IN p_definition TEXT -) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = p_table AND column_name = p_column - ) THEN - SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); - PREPARE add_column_stmt FROM @sql; - EXECUTE add_column_stmt; - DEALLOCATE PREPARE add_column_stmt; - END IF; -END$$ -DELIMITER ; - -CALL order_prerequisite_add_order_column('ord_order', 'pickup_method', 'VARCHAR(24) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'receiving_warehouse_id', 'BIGINT UNSIGNED NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'receiving_warehouse_name', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'receiving_warehouse_address', 'VARCHAR(600) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'receiving_time', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'channel_code', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'channel_name', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'tax_mode', 'VARCHAR(24) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'container_mode', 'VARCHAR(24) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'customs_inspection', 'TINYINT(1) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'destination_type', 'VARCHAR(24) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'amazon_warehouse_code', 'VARCHAR(32) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'shipment_id', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'reference_id', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'express_company', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order', 'express_tracking_no', 'VARCHAR(128) NULL'); - -CALL order_prerequisite_add_order_column('ord_order_cargo', 'sku_no', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'upc_no', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'cargo_name_en', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'customs_hs_code', 'VARCHAR(20) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'units_per_package', 'INT UNSIGNED NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'total_quantity', 'INT UNSIGNED NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'net_weight_kg', 'DECIMAL(18,3) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'unit_declared_value', 'DECIMAL(18,2) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'material', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'product_usage', 'VARCHAR(128) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'model', 'VARCHAR(64) NULL'); -CALL order_prerequisite_add_order_column('ord_order_cargo', 'brand', 'VARCHAR(64) NULL'); -DROP PROCEDURE IF EXISTS order_prerequisite_add_order_column; - -CREATE TABLE IF NOT EXISTS ord_idempotency_record ( - id BIGINT UNSIGNED NOT NULL, - tenant_id BIGINT UNSIGNED NOT NULL, - operator_id BIGINT UNSIGNED NOT NULL, - operation VARCHAR(32) NOT NULL, - resource_id BIGINT UNSIGNED NOT NULL DEFAULT 0, - idempotency_key VARCHAR(128) NOT NULL, - request_hash CHAR(64) NOT NULL, - status VARCHAR(16) NOT NULL, - result_order_id BIGINT UNSIGNED NULL, - completed_at DATETIME(3) NULL, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (id), - UNIQUE KEY uk_order_idempotency_scope (tenant_id, operator_id, operation, idempotency_key), - KEY idx_order_idempotency_created (created_at) -) ENGINE=InnoDB COMMENT='订单幂等记录'; diff --git a/deploy/sql/2026-08-03-二期入库表结构-TEST环境一键执行.sql b/deploy/sql/2026-08-03-二期入库表结构-TEST环境一键执行.sql deleted file mode 100644 index 8ed4b5c61..000000000 --- a/deploy/sql/2026-08-03-二期入库表结构-TEST环境一键执行.sql +++ /dev/null @@ -1,699 +0,0 @@ --- 柏悦头程二期入库表结构:TEST环境一键执行脚本 --- 生成日期:2026-08-03 --- 适用版本:MySQL 8.0及以上 --- 执行范围:只新增二期表、字段、索引和约束,不插入、更新或删除业务数据 --- 目标数据库:baiyue_firstleg、baiyue_warehouse --- 前置条件:一期基线表 fl_fulfillment_task、wh_warehouse 已存在 --- 注意:MySQL DDL会自动提交,请使用具有目标库建表权限的测试环境账号执行 - -SET NAMES utf8mb4; -SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; - -SELECT VERSION() AS mysql_version, - '开始执行二期入库表结构' AS execution_message; - - -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_firstleg - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_firstleg; - -CREATE TABLE IF NOT EXISTS fl_inbound_order ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - task_id BIGINT UNSIGNED NULL COMMENT '头程履约任务ID', - order_id BIGINT UNSIGNED NOT NULL COMMENT '订单服务订单ID,不建立跨库外键', - order_no VARCHAR(32) NOT NULL COMMENT '订单号快照', - inbound_code VARCHAR(40) NOT NULL COMMENT '租户内唯一入仓码', - process_status VARCHAR(24) NOT NULL DEFAULT 'WAIT_MEASURE' COMMENT '入库流程状态', - order_status_snapshot VARCHAR(24) NOT NULL COMMENT '订单状态快照', - measure_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '测量数据审核状态', - fee_status VARCHAR(24) NOT NULL DEFAULT 'UNPRICED' COMMENT '费用业务状态', - fee_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - notification_status VARCHAR(24) NOT NULL DEFAULT 'NOT_CREATED' COMMENT '客户通知状态', - expected_arrival_at DATETIME(3) NULL COMMENT '预计到达时间', - customer_id BIGINT UNSIGNED NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - company_id BIGINT UNSIGNED NULL COMMENT '运营公司逻辑ID', - company_name VARCHAR(128) NULL COMMENT '运营公司名称快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '实际作业仓库ID', - warehouse_name VARCHAR(128) NOT NULL COMMENT '实际作业仓库名称快照', - delivery_warehouse_id BIGINT UNSIGNED NULL COMMENT '交货仓逻辑ID', - delivery_warehouse_name VARCHAR(128) NULL COMMENT '交货仓名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - channel_name VARCHAR(128) NULL COMMENT '渠道名称快照', - tax_mode VARCHAR(24) NULL COMMENT '买单或退税模式', - container_mode VARCHAR(24) NULL COMMENT '整柜或散货模式', - customs_inspection TINYINT(1) NULL COMMENT '是否商检', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_warehouse_id BIGINT UNSIGNED NULL COMMENT '目的仓逻辑ID', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码,例如FBA仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称快照', - hold_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '当前是否扣货', - current_hold_reason VARCHAR(500) 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', - actual_volume_cbm DECIMAL(18,4) NULL COMMENT '确认后的实际总体积m3', - chargeable_volume_cbm DECIMAL(18,4) NULL COMMENT '当前费用快照的计费体积m3', - pallet_count INT UNSIGNED NULL COMMENT '已分配总托盘数快照', - volume_weight_kg DECIMAL(18,3) NULL COMMENT '总材积重kg', - actual_net_weight_kg DECIMAL(18,3) NULL COMMENT '总净重kg', - measure_completed_at DATETIME(3) NULL COMMENT '测量完成时间', - inbounded_at DATETIME(3) NULL COMMENT '入库完成时间', - express_company_code VARCHAR(64) NULL COMMENT '快递公司编码快照', - express_company_name VARCHAR(128) NULL COMMENT '快递公司名称快照', - express_tracking_no VARCHAR(128) NULL COMMENT '快递单号快照', - public_remark VARCHAR(1000) NULL COMMENT '客户可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - 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), - UNIQUE KEY uk_inbound_tenant_code (tenant_id, inbound_code), - UNIQUE KEY uk_inbound_tenant_order (tenant_id, order_id), - KEY idx_inbound_process_time (tenant_id, process_status, created_at, id), - KEY idx_inbound_measure_time (tenant_id, measure_review_status, created_at, id), - KEY idx_inbound_fee_time (tenant_id, fee_review_status, created_at, id), - KEY idx_inbound_warehouse_status (tenant_id, warehouse_id, process_status, created_at), - KEY idx_inbound_customer_time (tenant_id, customer_id, created_at), - KEY idx_inbound_company_time (tenant_id, company_id, created_at), - KEY idx_inbound_arrival (tenant_id, expected_arrival_at), - KEY idx_inbound_destination (tenant_id, destination_code, created_at), - KEY idx_inbound_channel (tenant_id, channel_code, created_at), - CONSTRAINT fk_inbound_task FOREIGN KEY (task_id) REFERENCES fl_fulfillment_task (id) -) ENGINE=InnoDB COMMENT='二期头程入库单聚合根和列表查询快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pickup_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '提货信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - pickup_method VARCHAR(24) NULL COMMENT '提货方式', - pickup_at DATETIME(3) NULL COMMENT '提货时间', - contact_name VARCHAR(64) NULL COMMENT '提货联系人', - contact_phone VARCHAR(32) NULL COMMENT '提货联系人电话', - contact_email VARCHAR(128) NULL COMMENT '提货联系人邮箱', - country_code CHAR(2) NULL COMMENT '国家二字码', - province VARCHAR(64) NULL COMMENT '省或州', - city VARCHAR(64) NULL COMMENT '城市', - district VARCHAR(64) NULL COMMENT '区县', - address_line VARCHAR(512) NULL COMMENT '提货详细地址', - postal_code VARCHAR(20) NULL COMMENT '提货邮编', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_pickup_inbound (tenant_id, inbound_id), - CONSTRAINT fk_pickup_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单提货信息不可变快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_destination_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '目的仓地址快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称', - country_code CHAR(2) NULL COMMENT '国家二字码', - state_province VARCHAR(100) NULL COMMENT '省或州', - city VARCHAR(100) NULL COMMENT '城市', - address_line VARCHAR(512) NULL COMMENT '详细地址', - postal_code VARCHAR(20) NULL COMMENT '邮编', - contact_name VARCHAR(64) NULL COMMENT '联系人', - contact_phone VARCHAR(32) NULL COMMENT '联系人电话', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_destination_inbound (tenant_id, inbound_id), - CONSTRAINT fk_destination_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单目的仓地址和联系人快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_transport_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '运输信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - loading_status VARCHAR(24) NULL COMMENT '配载状态快照', - container_no VARCHAR(64) NULL COMMENT '集装箱号', - cabinet_no VARCHAR(64) NULL COMMENT '柜号或内部柜单号', - vessel_name VARCHAR(128) NULL COMMENT '船名', - voyage_no VARCHAR(64) NULL COMMENT '航次', - sailing_at DATETIME(3) NULL COMMENT '开船时间', - port_arrival_at DATETIME(3) NULL COMMENT '到港时间', - source_updated_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_transport_inbound (tenant_id, inbound_id), - KEY idx_transport_container (tenant_id, container_no), - KEY idx_transport_cabinet (tenant_id, cabinet_no), - KEY idx_transport_loading (tenant_id, loading_status, sailing_at), - CONSTRAINT fk_transport_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单关联运输信息只读快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - source_type VARCHAR(24) NOT NULL COMMENT '数据来源:THIRD_PARTY或MANUAL', - source_code VARCHAR(64) NULL COMMENT '第三方应用或来源编码', - external_event_no VARCHAR(128) NULL COMMENT '第三方事件号', - device_code VARCHAR(64) NULL COMMENT '测量设备编码', - warehouse_code VARCHAR(50) NULL COMMENT '第三方回传仓库编码', - measured_at DATETIME(3) NULL COMMENT '设备测量时间', - status VARCHAR(24) NOT NULL DEFAULT 'RECEIVED' COMMENT '测量批次状态', - raw_payload_json JSON NULL COMMENT '第三方原始报文', - total_package_count INT UNSIGNED NULL COMMENT '本批次总箱数', - total_volume_raw_cbm DECIMAL(18,6) NULL COMMENT '本批次原始总体积m3', - total_volume_cbm DECIMAL(18,4) NULL COMMENT '本批次业务总体积m3', - created_by BIGINT UNSIGNED NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_external_event (tenant_id, source_code, external_event_no), - KEY idx_measure_inbound_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_measure_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库长宽高测量批次和第三方原始数据'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - measurement_id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - item_no VARCHAR(32) NOT NULL COMMENT '批次内明细号', - package_count INT UNSIGNED NOT NULL COMMENT '相同箱规箱数', - length_cm DECIMAL(12,3) NOT NULL COMMENT '原始长度cm', - width_cm DECIMAL(12,3) NOT NULL COMMENT '原始宽度cm', - height_cm DECIMAL(12,3) NOT NULL COMMENT '原始高度cm', - volume_raw_cbm DECIMAL(18,6) NOT NULL COMMENT '原始体积m3', - volume_cbm DECIMAL(18,4) NOT NULL COMMENT '业务体积m3', - calculation_rule_version VARCHAR(32) NOT NULL COMMENT '体积计算和舍入规则版本', - source_image_file_id BIGINT UNSIGNED NULL COMMENT '测量设备图片文件ID', - remark VARCHAR(500) NULL COMMENT '测量明细备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_item_no (tenant_id, measurement_id, item_no), - CONSTRAINT fk_measure_item_batch FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='入库长宽高和箱数测量明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_result ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '称重图片文件ID', - ocr_provider VARCHAR(64) NULL COMMENT 'OCR服务商编码', - ocr_raw_text VARCHAR(1000) NULL COMMENT 'OCR原始文本', - ocr_weight_value DECIMAL(18,3) NULL COMMENT 'OCR识别原始重量值', - ocr_weight_unit VARCHAR(8) NULL COMMENT 'OCR识别原始单位', - confidence DECIMAL(6,5) NULL COMMENT '识别置信度', - adjusted_weight_value DECIMAL(18,3) NULL COMMENT '人工修正后的原单位重量', - adjusted_weight_unit VARCHAR(8) NULL COMMENT '人工修正后的单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认并统一换算后的重量kg', - recognition_status VARCHAR(24) NOT NULL DEFAULT 'PENDING' COMMENT '识别和确认状态', - adjustment_reason VARCHAR(500) NULL COMMENT '人工修正原因', - adjusted_by BIGINT UNSIGNED NULL COMMENT '修正人ID', - adjusted_at DATETIME(3) NULL COMMENT '修正时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_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 '更新时间', - deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - PRIMARY KEY (id), - UNIQUE KEY uk_weight_inbound_file (tenant_id, inbound_id, file_id), - KEY idx_weight_inbound_status (tenant_id, inbound_id, recognition_status), - CONSTRAINT fk_weight_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='称重图片OCR原值、人工修正值和确认重量'; - -CREATE TABLE IF NOT EXISTS fl_measure_review_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量审核记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - measurement_id BIGINT UNSIGNED NULL COMMENT '被审核的测量批次ID', - review_result VARCHAR(24) NOT NULL COMMENT '审核结果', - review_reason VARCHAR(1000) NULL COMMENT '审核或驳回原因', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否异常放行', - release_reason VARCHAR(1000) NULL COMMENT '异常放行原因', - allow_rejected_config TINYINT(1) NOT NULL DEFAULT 0 COMMENT '操作时Nacos异常放行开关值', - reviewer_id BIGINT UNSIGNED NOT NULL COMMENT '审核人ID', - reviewer_name VARCHAR(64) NULL COMMENT '审核人名称快照', - reviewed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '审核时间', - PRIMARY KEY (id), - KEY idx_review_inbound_time (tenant_id, inbound_id, reviewed_at), - CONSTRAINT fk_review_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_review_measurement FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='测量审核、驳回和异常放行不可变记录'; - -CREATE TABLE IF NOT EXISTS fl_customer_charge_rule ( - id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rule_code VARCHAR(50) NOT NULL COMMENT '租户内规则编码', - rule_version INT UNSIGNED NOT NULL COMMENT '规则版本号', - customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - tax_mode VARCHAR(24) NULL COMMENT '包税或不包税类型', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '重量体积换算系数', - rounding_scale TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '结果保留小数位数', - rounding_mode VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式', - currency CHAR(3) NOT NULL COMMENT '默认币种', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '规则状态', - remark VARCHAR(500) NULL 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 '逻辑删除标记', - PRIMARY KEY (id), - UNIQUE KEY uk_charge_rule_version (tenant_id, rule_code, rule_version), - KEY idx_charge_rule_match (tenant_id, customer_id, business_type, status, effective_from, effective_to) -) ENGINE=InnoDB COMMENT='客户头程计费规则版本'; - -CREATE TABLE IF NOT EXISTS fl_carrier_fba_rate ( - id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rate_code VARCHAR(50) NOT NULL COMMENT '租户内价格编码', - rate_version INT UNSIGNED NOT NULL COMMENT '价格版本号', - origin_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '起运仓逻辑ID', - origin_warehouse_name VARCHAR(128) NOT NULL COMMENT '起运仓名称快照', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - carrier_id BIGINT UNSIGNED NULL COMMENT '船司逻辑ID', - carrier_name VARCHAR(128) NOT NULL COMMENT '船司名称快照', - destination_code VARCHAR(32) NOT NULL COMMENT 'FBA目的仓编码', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位:KG或CBM', - unit_price DECIMAL(18,6) NOT NULL COMMENT '基础单价', - currency CHAR(3) NOT NULL COMMENT '币种', - additional_fee DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '固定附加费', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '价格状态', - remark VARCHAR(500) NULL 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 '逻辑删除标记', - PRIMARY KEY (id), - UNIQUE KEY uk_fba_rate_version (tenant_id, rate_code, rate_version), - KEY idx_fba_rate_match (tenant_id, origin_warehouse_id, channel_code, destination_code, charge_unit, status, effective_from) -) ENGINE=InnoDB COMMENT='船司FBA目的仓价格版本'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库费用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - fee_no VARCHAR(40) NOT NULL COMMENT '租户内唯一费用单号', - fee_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '费用快照版本', - charge_rule_id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - charge_rule_version INT UNSIGNED NOT NULL COMMENT '客户规则版本快照', - carrier_rate_id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - carrier_rate_version INT UNSIGNED NOT NULL COMMENT '船司价格版本快照', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '使用的换算系数快照', - actual_weight_kg DECIMAL(18,3) NOT NULL COMMENT '试算时实际重量kg', - actual_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '试算时实际体积m3', - converted_quantity DECIMAL(18,4) NOT NULL COMMENT '换算后的重量或体积', - chargeable_quantity DECIMAL(18,4) NOT NULL COMMENT '最终计费量', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位', - currency CHAR(3) NOT NULL COMMENT '币种', - subtotal_amount DECIMAL(18,2) NOT NULL COMMENT '基础费用金额', - additional_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '附加费金额', - total_amount DECIMAL(18,2) NOT NULL COMMENT '总金额', - fee_status VARCHAR(24) NOT NULL DEFAULT 'CALCULATED' COMMENT '费用状态', - review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否基于测量异常放行生成', - calculated_by BIGINT UNSIGNED NOT NULL COMMENT '试算人ID', - calculated_at DATETIME(3) NOT NULL COMMENT '试算时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_at DATETIME(3) NULL COMMENT '确认时间', - sent_by BIGINT UNSIGNED NULL COMMENT '发送人ID', - sent_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_inbound_fee_no (tenant_id, fee_no), - UNIQUE KEY uk_inbound_fee_version (tenant_id, inbound_id, fee_version), - KEY idx_inbound_fee_status (tenant_id, inbound_id, fee_status, review_status), - CONSTRAINT fk_fee_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_fee_charge_rule FOREIGN KEY (charge_rule_id) REFERENCES fl_customer_charge_rule (id), - CONSTRAINT fk_fee_carrier_rate FOREIGN KEY (carrier_rate_id) REFERENCES fl_carrier_fba_rate (id) -) ENGINE=InnoDB COMMENT='入库头程费用计算和确认快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '费用明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - fee_id BIGINT UNSIGNED NOT NULL COMMENT '费用头ID', - item_no INT UNSIGNED NOT NULL COMMENT '费用单内序号', - fee_code VARCHAR(50) NOT NULL COMMENT '费用项目编码', - fee_name VARCHAR(128) NOT NULL COMMENT '费用项目名称快照', - quantity DECIMAL(18,4) NOT NULL COMMENT '计费数量', - unit VARCHAR(16) NOT NULL COMMENT '计费单位', - unit_price DECIMAL(18,6) NOT NULL COMMENT '单价', - amount DECIMAL(18,2) NOT NULL COMMENT '金额', - currency CHAR(3) NOT NULL COMMENT '币种', - automatic_flag TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否自动计算', - remark VARCHAR(500) NULL COMMENT '费用备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_fee_item_no (tenant_id, fee_id, item_no), - CONSTRAINT fk_fee_item_header FOREIGN KEY (fee_id) REFERENCES fl_inbound_fee (id) -) ENGINE=InnoDB COMMENT='入库头程费用项目明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pallet_allocation ( - id BIGINT UNSIGNED NOT NULL COMMENT '头程托盘分配引用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - allocation_no INT UNSIGNED NOT NULL COMMENT '入库单内分配序号', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - pallet_capacity_cbm DECIMAL(18,4) NOT NULL COMMENT '托盘可用容积快照', - allocated_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '本托盘分配体积', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - location_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - reservation_no VARCHAR(64) NOT NULL COMMENT '仓库库位预占单号', - allocation_status VARCHAR(24) NOT NULL DEFAULT 'RESERVED' 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_pallet_allocation_no (tenant_id, inbound_id, allocation_no), - UNIQUE KEY uk_pallet_allocation_pallet (tenant_id, inbound_id, pallet_id), - KEY idx_allocation_location (tenant_id, warehouse_id, location_id, allocation_status), - CONSTRAINT fk_allocation_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='头程侧托盘、库位和仓库预占结果引用'; - -CREATE TABLE IF NOT EXISTS fl_inbound_file ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单文件关系ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件服务文件ID', - file_type VARCHAR(24) NOT NULL COMMENT '文件类型:RELATED、MARK、PC_ORDER、MEASURE或WEIGHT', - file_name_snapshot VARCHAR(255) NOT NULL COMMENT '文件名快照', - visibility VARCHAR(16) NOT NULL DEFAULT 'INTERNAL' COMMENT '可见范围', - file_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '业务文件版本', - uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传人ID', - uploaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上传时间', - deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', - PRIMARY KEY (id), - UNIQUE KEY uk_inbound_file_relation (tenant_id, inbound_id, file_id, file_type), - KEY idx_inbound_file_type (tenant_id, inbound_id, file_type, deleted), - CONSTRAINT fk_file_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单与文件中心对象的分类关系'; - -CREATE TABLE IF NOT EXISTS fl_inbound_hold_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '扣货记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - hold_action VARCHAR(16) NOT NULL COMMENT '动作:HOLD或RELEASE', - reason VARCHAR(1000) NOT NULL COMMENT '扣货或解除原因', - evidence_file_id BIGINT UNSIGNED NULL COMMENT '证据文件ID', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - KEY idx_hold_inbound_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_hold_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单扣货和解除扣货不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_internal_note ( - id BIGINT UNSIGNED NOT NULL COMMENT '客服内部备注ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - content VARCHAR(2000) NOT NULL COMMENT '仅内部可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_internal_note_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_internal_note_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单客服内部备注历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_status_history ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库状态历史ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - from_status VARCHAR(24) NULL COMMENT '变更前状态', - to_status VARCHAR(24) NOT NULL COMMENT '变更后状态', - action VARCHAR(32) NOT NULL COMMENT '触发动作', - reason VARCHAR(1000) NULL COMMENT '变更原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '发生时间', - PRIMARY KEY (id), - KEY idx_inbound_history_time (tenant_id, inbound_id, occurred_at), - CONSTRAINT fk_history_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单流程状态不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_outbox ( - id BIGINT UNSIGNED NOT NULL COMMENT '领域事件全局ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '事件所属租户ID', - aggregate_type VARCHAR(32) NOT NULL DEFAULT 'INBOUND' COMMENT '聚合类型', - aggregate_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - payload_json JSON NOT NULL COMMENT '事件负载快照', - publish_status VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '发布状态', - retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数', - next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', - published_at DATETIME(3) NULL COMMENT '发布时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_inbound_outbox_publish (publish_status, next_retry_at, created_at) -) ENGINE=InnoDB COMMENT='入库事务Outbox事件表'; - -CREATE TABLE IF NOT EXISTS fl_inbound_idempotency ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库写操作幂等记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '租户ID', - operation VARCHAR(40) NOT NULL COMMENT '操作类型', - operator_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作者或外部应用ID', - inbound_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '入库单ID,创建前可为0', - idempotency_key VARCHAR(128) NOT NULL COMMENT '幂等键', - request_hash CHAR(64) NOT NULL COMMENT '请求内容摘要', - status VARCHAR(16) NOT NULL COMMENT '处理状态', - result_json JSON NULL COMMENT '成功结果摘要', - completed_at DATETIME(3) NULL COMMENT '完成时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - PRIMARY KEY (id), - UNIQUE KEY uk_inbound_idempotency (tenant_id, operation, operator_id, idempotency_key), - KEY idx_inbound_idempotency_created (created_at) -) ENGINE=InnoDB COMMENT='第三方测量、审核、费用发送和入库写操作幂等记录'; - --- 二期托盘、库位、预占与占用表结构。 --- 本脚本只新增表、字段、索引和约束,不包含业务数据及流程实现。 --- 可在 warehouse.sql 和一期增量脚本之后执行;所有建表均可重复执行。 -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_warehouse - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_warehouse; - -CREATE TABLE IF NOT EXISTS wh_pallet ( - id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一托盘编码', - pallet_type VARCHAR(32) NOT NULL COMMENT '托盘类型', - pallet_name VARCHAR(100) NULL COMMENT '托盘名称', - capacity_cbm DECIMAL(18,6) NOT NULL COMMENT '托盘可用容积CBM', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT 'AVAILABLE、RESERVED、OCCUPIED或DISABLED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_pallet_tenant_warehouse_code (tenant_id, warehouse_id, pallet_code), - KEY idx_pallet_available (tenant_id, warehouse_id, status, deleted), - KEY idx_pallet_type (tenant_id, warehouse_id, pallet_type, status, deleted), - CONSTRAINT fk_pallet_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_pallet_capacity CHECK (capacity_cbm > 0) -) ENGINE=InnoDB COMMENT='二期托盘基础资料和物理托盘实例'; - -CREATE TABLE IF NOT EXISTS wh_location ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - zone_code VARCHAR(50) NULL COMMENT '库区编码', - zone_name VARCHAR(100) NULL COMMENT '库区名称', - location_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一库位编码', - location_name VARCHAR(100) NULL COMMENT '库位名称', - location_type VARCHAR(32) NOT NULL DEFAULT 'PALLET' COMMENT '库位类型,二期为PALLET', - max_weight_kg DECIMAL(18,3) NULL COMMENT '最大承重展示值,二期不作容量拦截', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT 'AVAILABLE、RESERVED、OCCUPIED或DISABLED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_location_tenant_warehouse_code (tenant_id, warehouse_id, location_code), - KEY idx_location_available (tenant_id, warehouse_id, status, deleted), - KEY idx_location_zone (tenant_id, warehouse_id, zone_code, status, deleted), - CONSTRAINT fk_location_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_location_max_weight CHECK (max_weight_kg IS NULL OR max_weight_kg > 0) -) ENGINE=InnoDB COMMENT='二期库位基础资料,默认一托盘对应一个库位且不作容量校验'; - -CREATE TABLE IF NOT EXISTS wh_location_reservation ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位预占ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - reservation_no VARCHAR(40) NOT NULL COMMENT '租户内唯一预占业务号', - idempotency_key VARCHAR(128) NOT NULL COMMENT '调用方幂等键', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - reservation_status VARCHAR(20) NOT NULL DEFAULT 'RESERVED' COMMENT 'RESERVED、CONFIRMED、RELEASED或EXPIRED', - expires_at DATETIME(3) NOT NULL COMMENT '预占过期时间', - confirmed_at DATETIME(3) NULL COMMENT '确认占用时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放或过期原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_reservation TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' THEN 1 ELSE NULL END) STORED COMMENT '活动预占唯一标记', - PRIMARY KEY (id), - UNIQUE KEY uk_location_reservation_no (tenant_id, reservation_no), - UNIQUE KEY uk_location_reservation_idempotency (tenant_id, source_service, idempotency_key), - UNIQUE KEY uk_location_active_reservation (tenant_id, location_id, active_reservation), - KEY idx_location_reservation_business (tenant_id, source_service, business_id, reservation_status), - KEY idx_location_reservation_expire (reservation_status, expires_at), - KEY idx_location_reservation_target (tenant_id, warehouse_id, location_id, reservation_status), - CONSTRAINT fk_reservation_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_reservation_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_reservation_location FOREIGN KEY (location_id) REFERENCES wh_location (id) -) ENGINE=InnoDB COMMENT='跨服务入库Saga的托盘和库位临时预占'; - -CREATE TABLE IF NOT EXISTS wh_location_occupancy ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位占用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - occupancy_no VARCHAR(40) NOT NULL COMMENT '租户内唯一占用业务号', - reservation_id BIGINT UNSIGNED NOT NULL COMMENT '来源预占ID', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - allocated_volume_cbm DECIMAL(18,6) NOT NULL COMMENT '本托盘分配体积CBM', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - occupancy_status VARCHAR(20) NOT NULL DEFAULT 'OCCUPIED' COMMENT 'OCCUPIED或RELEASED', - occupied_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '占用开始时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_occupancy TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = 'OCCUPIED' THEN 1 ELSE NULL END) STORED COMMENT '活动占用唯一标记', - PRIMARY KEY (id), - UNIQUE KEY uk_location_occupancy_no (tenant_id, occupancy_no), - UNIQUE KEY uk_occupancy_reservation (tenant_id, reservation_id), - UNIQUE KEY uk_location_active_occupancy (tenant_id, location_id, active_occupancy), - UNIQUE KEY uk_pallet_active_occupancy (tenant_id, pallet_id, active_occupancy), - KEY idx_occupancy_business (tenant_id, source_service, business_id, occupancy_status), - KEY idx_occupancy_warehouse (tenant_id, warehouse_id, occupancy_status, occupied_at), - CONSTRAINT fk_occupancy_reservation FOREIGN KEY (reservation_id) REFERENCES wh_location_reservation (id), - CONSTRAINT fk_occupancy_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_occupancy_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_occupancy_location FOREIGN KEY (location_id) REFERENCES wh_location (id), - CONSTRAINT ck_occupancy_volume CHECK (allocated_volume_cbm > 0) -) ENGINE=InnoDB COMMENT='已确认的一托一库位占用事实记录'; - --- 头程入库单属于其他数据库,不建立跨库外键。 - - --- 执行后结构核对:只输出检查结果,不写入业务数据。 -SELECT '头程二期表数量' AS check_item, - COUNT(*) AS actual_value, - 19 AS expected_value, - IF(COUNT(*) = 19, 'PASS', 'FAIL') AS check_result -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'baiyue_firstleg' - AND TABLE_NAME IN ( - 'fl_inbound_order', - 'fl_inbound_pickup_snapshot', - 'fl_inbound_destination_snapshot', - 'fl_inbound_transport_snapshot', - 'fl_inbound_measurement', - 'fl_inbound_measurement_item', - 'fl_inbound_weight_result', - 'fl_measure_review_record', - 'fl_customer_charge_rule', - 'fl_carrier_fba_rate', - 'fl_inbound_fee', - 'fl_inbound_fee_item', - 'fl_inbound_pallet_allocation', - 'fl_inbound_file', - 'fl_inbound_hold_record', - 'fl_inbound_internal_note', - 'fl_inbound_status_history', - 'fl_inbound_outbox', - 'fl_inbound_idempotency' - ) -UNION ALL -SELECT '仓库二期表数量' AS check_item, - COUNT(*) AS actual_value, - 4 AS expected_value, - IF(COUNT(*) = 4, 'PASS', 'FAIL') AS check_result -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = 'baiyue_warehouse' - AND TABLE_NAME IN ( - 'wh_pallet', - 'wh_location', - 'wh_location_reservation', - 'wh_location_occupancy' - ); - -SELECT '关键唯一索引数量' AS check_item, - COUNT(DISTINCT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME, '.', INDEX_NAME)) AS actual_value, - 5 AS expected_value, - IF(COUNT(DISTINCT CONCAT(TABLE_SCHEMA, '.', TABLE_NAME, '.', INDEX_NAME)) = 5, 'PASS', 'FAIL') AS check_result -FROM information_schema.STATISTICS -WHERE (TABLE_SCHEMA = 'baiyue_firstleg' - AND TABLE_NAME = 'fl_inbound_order' - AND INDEX_NAME IN ('uk_inbound_tenant_code', 'uk_inbound_tenant_order')) - OR (TABLE_SCHEMA = 'baiyue_warehouse' - AND TABLE_NAME = 'wh_location_reservation' - AND INDEX_NAME = 'uk_location_active_reservation') - OR (TABLE_SCHEMA = 'baiyue_warehouse' - AND TABLE_NAME = 'wh_location_occupancy' - AND INDEX_NAME IN ('uk_location_active_occupancy', 'uk_pallet_active_occupancy')); - -SELECT '关键字段数量' AS check_item, - COUNT(*) AS actual_value, - 8 AS expected_value, - IF(COUNT(*) = 8, 'PASS', 'FAIL') AS check_result -FROM information_schema.COLUMNS -WHERE (TABLE_SCHEMA = 'baiyue_firstleg' - AND TABLE_NAME = 'fl_inbound_order' - AND COLUMN_NAME IN ( - 'inbound_code', - 'measure_review_status', - 'fee_review_status', - 'expected_arrival_at', - 'chargeable_weight_kg', - 'chargeable_volume_cbm' - )) - OR (TABLE_SCHEMA = 'baiyue_warehouse' - AND TABLE_NAME = 'wh_location_reservation' - AND COLUMN_NAME = 'active_reservation') - OR (TABLE_SCHEMA = 'baiyue_warehouse' - AND TABLE_NAME = 'wh_location_occupancy' - AND COLUMN_NAME = 'active_occupancy'); - -SELECT '二期入库表结构执行完成,请确认以上检查全部为PASS' AS execution_message; diff --git a/deploy/sql/2026-08-04-二期TEST环境增量-MySQL8直接执行.sql b/deploy/sql/2026-08-04-二期TEST环境增量-MySQL8直接执行.sql deleted file mode 100644 index c8c674ecd..000000000 --- a/deploy/sql/2026-08-04-二期TEST环境增量-MySQL8直接执行.sql +++ /dev/null @@ -1,1341 +0,0 @@ --- 柏悦头程二期 TEST 环境增量:MySQL 8 直接执行脚本 --- 生成日期:2026-08-04 --- 适用版本:MySQL 8.0+(需要 GENERATED COLUMN、JSON、CHECK 约束支持) --- 环境边界:仅用于 TEST 联调环境,不包含生产环境连接信息。 --- 数据库名:baiyue_file、baiyue_firstleg、baiyue_warehouse。 --- 执行方式:在 TEST MySQL 连接中完整运行本文件,不要拆分执行。 --- 适用场景: --- 1. 新环境:在一期基线完成后直接执行,创建二期最终表结构。 --- 2. 存量二期环境:可重复执行,自动补齐新字段、索引和 A0 共享溢出约束。 --- 执行范围:仅 CREATE / ALTER 表、字段、索引、约束;不插入权限、不写业务单据。 --- 目标数据库:baiyue_file、baiyue_firstleg、baiyue_warehouse。 --- 前置条件:一期的 baiyue_firstleg.fl_fulfillment_task 与 baiyue_warehouse.wh_warehouse 已存在。 --- 注意: --- - MySQL DDL 自动提交,执行前必须完成备份并在临时/预发布库演练。 --- - 既有数据若已违反即将建立的唯一约束,脚本会停止,需要先治理数据。 --- - 本脚本由 MySQL Client / MySQL Workbench 直接执行;包含 DELIMITER 的存储过程定义。 --- - 不连接、不修改正式库;请在明确指定的目标库连接中执行。 - -SET NAMES utf8mb4; -SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; -SET @deployment_environment := 'TEST'; - -SELECT @deployment_environment AS deployment_environment, - VERSION() AS mysql_version, - '开始执行二期入库新增表与字段脚本' AS execution_message; - -SELECT - EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'baiyue_firstleg' AND table_name = 'fl_fulfillment_task') AS has_phase1_fulfillment_task, - EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'baiyue_warehouse' AND table_name = 'wh_warehouse') AS has_phase1_warehouse; - --- ============================================================================ --- 文件中心基线(测量图片依赖) --- 来源:file/src/main/resources/db/file.sql --- ============================================================================ --- 文件中心独占数据库,其他服务只保存文件逻辑ID。 -CREATE DATABASE IF NOT EXISTS baiyue_file - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_file; - -CREATE TABLE IF NOT EXISTS file_object ( - id BIGINT UNSIGNED NOT NULL COMMENT '文件ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - business_type VARCHAR(32) NULL COMMENT '关联业务类型', - business_id VARCHAR(64) NULL COMMENT '关联业务逻辑ID', - original_name VARCHAR(255) NOT NULL COMMENT '原始文件名', - object_key VARCHAR(512) NOT NULL COMMENT '对象存储键', - storage_provider VARCHAR(32) NOT NULL COMMENT '存储提供方', - bucket_name VARCHAR(128) NOT NULL COMMENT '存储桶名称', - content_type VARCHAR(128) NOT NULL COMMENT '文件内容类型', - size_bytes BIGINT UNSIGNED NOT NULL COMMENT '文件字节数', - sha256 CHAR(64) NULL COMMENT '文件SHA-256摘要', - status VARCHAR(24) NOT NULL DEFAULT 'ACTIVE' 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), - UNIQUE KEY uk_file_tenant_object (tenant_id, object_key), - KEY idx_file_tenant_business (tenant_id, business_type, business_id), - KEY idx_file_tenant_created (tenant_id, created_at) -) ENGINE=InnoDB COMMENT='文件元数据表'; - -CREATE TABLE IF NOT EXISTS file_download_token ( - id BIGINT UNSIGNED NOT NULL COMMENT '下载令牌ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件逻辑ID', - token_hash CHAR(64) NOT NULL COMMENT '下载令牌SHA-256摘要', - expires_at DATETIME(3) NOT NULL COMMENT '过期时间', - max_downloads INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '最大下载次数', - download_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已下载次数', - revoked_at DATETIME(3) NULL COMMENT '撤销时间', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_download_token_hash (token_hash), - KEY idx_download_file (tenant_id, file_id), - KEY idx_download_expiry (expires_at) -) ENGINE=InnoDB COMMENT='临时下载授权令牌表'; - -CREATE TABLE IF NOT EXISTS file_download_log ( - id BIGINT UNSIGNED NOT NULL COMMENT '下载日志ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件逻辑ID', - user_id BIGINT UNSIGNED NULL COMMENT '下载用户ID', - request_id VARCHAR(64) NULL COMMENT '请求ID', - client_ip VARCHAR(64) NULL COMMENT '客户端IP', - result VARCHAR(16) NOT NULL COMMENT '下载结果', - failure_reason VARCHAR(500) NULL COMMENT '失败原因', - downloaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '下载时间', - PRIMARY KEY (id), - KEY idx_download_log_file (tenant_id, file_id, downloaded_at), - KEY idx_download_log_user (tenant_id, user_id, downloaded_at) -) ENGINE=InnoDB COMMENT='文件下载审计日志表'; - - --- ============================================================================ --- Firstleg 二期最终基线表 --- 来源:firstleg/src/main/resources/db/phase2-inbound-schema.sql --- ============================================================================ -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_firstleg - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_firstleg; - -CREATE TABLE IF NOT EXISTS fl_inbound_order ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - task_id BIGINT UNSIGNED NULL COMMENT '头程履约任务ID', - order_id BIGINT UNSIGNED NOT NULL COMMENT '订单服务订单ID,不建立跨库外键', - order_no VARCHAR(32) NOT NULL COMMENT '订单号快照', - inbound_code VARCHAR(40) NOT NULL COMMENT '租户内唯一入仓码', - process_status VARCHAR(24) NOT NULL DEFAULT 'WAIT_MEASURE' COMMENT '入库流程状态', - order_status_snapshot VARCHAR(24) NOT NULL COMMENT '订单状态快照', - measure_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '测量数据审核状态', - fee_status VARCHAR(24) NOT NULL DEFAULT 'UNPRICED' COMMENT '费用业务状态', - fee_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - notification_status VARCHAR(24) NOT NULL DEFAULT 'NOT_CREATED' COMMENT '客户通知状态', - expected_arrival_at DATETIME(3) NULL COMMENT '预计到达时间', - customer_id BIGINT UNSIGNED NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - company_id BIGINT UNSIGNED NULL COMMENT '运营公司逻辑ID', - company_name VARCHAR(128) NULL COMMENT '运营公司名称快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '实际作业仓库ID', - warehouse_name VARCHAR(128) NOT NULL COMMENT '实际作业仓库名称快照', - delivery_warehouse_id BIGINT UNSIGNED NULL COMMENT '交货仓逻辑ID', - delivery_warehouse_name VARCHAR(128) NULL COMMENT '交货仓名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - channel_name VARCHAR(128) NULL COMMENT '渠道名称快照', - carrier_id BIGINT UNSIGNED NULL COMMENT '计费船司逻辑ID', - carrier_name VARCHAR(128) NULL COMMENT '计费船司名称快照', - tax_mode VARCHAR(24) NULL COMMENT '买单或退税模式', - container_mode VARCHAR(24) NULL COMMENT '整柜或散货模式', - customs_inspection TINYINT(1) NULL COMMENT '是否商检', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_warehouse_id BIGINT UNSIGNED NULL COMMENT '目的仓逻辑ID', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码,例如FBA仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称快照', - hold_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '当前是否扣货', - current_hold_reason VARCHAR(500) 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', - actual_volume_cbm DECIMAL(18,4) NULL COMMENT '确认后的实际总体积m3', - chargeable_volume_cbm DECIMAL(18,4) NULL COMMENT '当前费用快照的计费体积m3', - pallet_count INT UNSIGNED NULL COMMENT '已分配总托盘数快照', - volume_weight_kg DECIMAL(18,3) NULL COMMENT '总材积重kg', - actual_net_weight_kg DECIMAL(18,3) NULL COMMENT '总净重kg', - measure_completed_at DATETIME(3) NULL COMMENT '测量完成时间', - inbounded_at DATETIME(3) NULL COMMENT '入库完成时间', - express_company_code VARCHAR(64) NULL COMMENT '快递公司编码快照', - express_company_name VARCHAR(128) NULL COMMENT '快递公司名称快照', - express_tracking_no VARCHAR(128) NULL COMMENT '快递单号快照', - public_remark VARCHAR(1000) NULL COMMENT '客户可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - 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), - UNIQUE KEY uk_inbound_tenant_code (tenant_id, inbound_code), - UNIQUE KEY uk_inbound_tenant_order (tenant_id, order_id), - KEY idx_inbound_process_time (tenant_id, process_status, created_at, id), - KEY idx_inbound_measure_time (tenant_id, measure_review_status, created_at, id), - KEY idx_inbound_fee_time (tenant_id, fee_review_status, created_at, id), - KEY idx_inbound_warehouse_status (tenant_id, warehouse_id, process_status, created_at), - KEY idx_inbound_customer_time (tenant_id, customer_id, created_at), - KEY idx_inbound_company_time (tenant_id, company_id, created_at), - KEY idx_inbound_arrival (tenant_id, expected_arrival_at), - KEY idx_inbound_destination (tenant_id, destination_code, created_at), - KEY idx_inbound_channel (tenant_id, channel_code, created_at), - CONSTRAINT fk_inbound_task FOREIGN KEY (task_id) REFERENCES fl_fulfillment_task (id) -) ENGINE=InnoDB COMMENT='二期头程入库单聚合根和列表查询快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pickup_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '提货信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - pickup_method VARCHAR(24) NULL COMMENT '提货方式', - pickup_at DATETIME(3) NULL COMMENT '提货时间', - contact_name VARCHAR(64) NULL COMMENT '提货联系人', - contact_phone VARCHAR(32) NULL COMMENT '提货联系人电话', - contact_email VARCHAR(128) NULL COMMENT '提货联系人邮箱', - country_code CHAR(2) NULL COMMENT '国家二字码', - province VARCHAR(64) NULL COMMENT '省或州', - city VARCHAR(64) NULL COMMENT '城市', - district VARCHAR(64) NULL COMMENT '区县', - address_line VARCHAR(512) NULL COMMENT '提货详细地址', - postal_code VARCHAR(20) NULL COMMENT '提货邮编', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_pickup_inbound (tenant_id, inbound_id), - CONSTRAINT fk_pickup_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单提货信息不可变快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_destination_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '目的仓地址快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称', - country_code CHAR(2) NULL COMMENT '国家二字码', - state_province VARCHAR(100) NULL COMMENT '省或州', - city VARCHAR(100) NULL COMMENT '城市', - address_line VARCHAR(512) NULL COMMENT '详细地址', - postal_code VARCHAR(20) NULL COMMENT '邮编', - contact_name VARCHAR(64) NULL COMMENT '联系人', - contact_phone VARCHAR(32) NULL COMMENT '联系人电话', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_destination_inbound (tenant_id, inbound_id), - CONSTRAINT fk_destination_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单目的仓地址和联系人快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_transport_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '运输信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - loading_status VARCHAR(24) NULL COMMENT '配载状态快照', - container_no VARCHAR(64) NULL COMMENT '集装箱号', - cabinet_no VARCHAR(64) NULL COMMENT '柜号或内部柜单号', - vessel_name VARCHAR(128) NULL COMMENT '船名', - voyage_no VARCHAR(64) NULL COMMENT '航次', - sailing_at DATETIME(3) NULL COMMENT '开船时间', - port_arrival_at DATETIME(3) NULL COMMENT '到港时间', - source_updated_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_transport_inbound (tenant_id, inbound_id), - KEY idx_transport_container (tenant_id, container_no), - KEY idx_transport_cabinet (tenant_id, cabinet_no), - KEY idx_transport_loading (tenant_id, loading_status, sailing_at), - CONSTRAINT fk_transport_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单关联运输信息只读快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - source_type VARCHAR(24) NOT NULL COMMENT '数据来源:THIRD_PARTY或MANUAL', - source_code VARCHAR(64) NULL COMMENT '第三方应用或来源编码', - external_event_no VARCHAR(128) NULL COMMENT '第三方事件号', - device_code VARCHAR(64) NULL COMMENT '测量设备编码', - warehouse_code VARCHAR(50) NULL COMMENT '第三方回传仓库编码', - measured_at DATETIME(3) NULL COMMENT '设备测量时间', - status VARCHAR(24) NOT NULL DEFAULT 'RECEIVED' COMMENT '测量批次状态', - raw_payload_json JSON NULL COMMENT '第三方原始报文', - original_document_no VARCHAR(64) NULL COMMENT '原单据号码快照', - original_gross_weight_kg DECIMAL(18,3) NULL COMMENT '原单据毛重kg', - original_volume_cbm DECIMAL(18,4) NULL COMMENT '原单据体积或材积m3', - actual_goods_name VARCHAR(255) NULL COMMENT '实际品名', - total_package_count INT UNSIGNED NULL COMMENT '本批次总箱数', - total_volume_raw_cbm DECIMAL(18,6) NULL COMMENT '本批次原始总体积m3', - total_volume_cbm DECIMAL(18,4) NULL COMMENT '本批次业务总体积m3', - volume_weight_kg DECIMAL(18,3) NULL COMMENT '本批次总材积重kg', - created_by BIGINT UNSIGNED NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_external_event (tenant_id, source_code, external_event_no), - KEY idx_measure_inbound_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_measure_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库长宽高测量批次和第三方原始数据'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - measurement_id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - item_no VARCHAR(32) NOT NULL COMMENT '批次内明细号', - box_specification VARCHAR(64) NOT NULL COMMENT '箱规标识', - package_count INT UNSIGNED NOT NULL COMMENT '相同箱规箱数', - length_cm DECIMAL(12,3) NOT NULL COMMENT '原始长度cm', - width_cm DECIMAL(12,3) NOT NULL COMMENT '原始宽度cm', - height_cm DECIMAL(12,3) NOT NULL COMMENT '原始高度cm', - girth_cm DECIMAL(12,3) NOT NULL COMMENT '周长cm,规则为长+2*(宽+高)', - unit_weight_kg DECIMAL(18,3) NULL COMMENT '单箱重量kg,第三方仅回传尺寸时可为空', - unit_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '单箱业务体积m3', - volume_raw_cbm DECIMAL(18,6) NOT NULL COMMENT '原始体积m3', - volume_cbm DECIMAL(18,4) NOT NULL COMMENT '业务体积m3', - total_weight_kg DECIMAL(18,3) NULL COMMENT '本箱规总重量kg', - total_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '本箱规总体积m3', - volume_weight_kg DECIMAL(18,3) NOT NULL COMMENT '本箱规材积重kg', - calculation_rule_version VARCHAR(32) NOT NULL COMMENT '体积计算和舍入规则版本', - source_image_file_id BIGINT UNSIGNED NULL COMMENT '测量设备图片文件ID', - over_limit_warning VARCHAR(500) NULL COMMENT '超线提醒快照', - outer_length_cm DECIMAL(12,3) NULL COMMENT '外箱规长度cm', - outer_width_cm DECIMAL(12,3) NULL COMMENT '外箱规宽度cm', - outer_height_cm DECIMAL(12,3) NULL COMMENT '外箱规高度cm', - remark VARCHAR(500) NULL COMMENT '测量明细备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_item_no (tenant_id, measurement_id, item_no), - CONSTRAINT fk_measure_item_batch FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='入库长宽高和箱数测量明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_result ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '称重图片文件ID', - ocr_provider VARCHAR(64) NULL COMMENT 'OCR服务商编码', - ocr_raw_text VARCHAR(1000) NULL COMMENT 'OCR原始文本', - ocr_weight_value DECIMAL(18,3) NULL COMMENT 'OCR识别原始重量值', - ocr_weight_unit VARCHAR(8) NULL COMMENT 'OCR识别原始单位', - confidence DECIMAL(6,5) NULL COMMENT '识别置信度', - adjusted_weight_value DECIMAL(18,3) NULL COMMENT '人工修正后的原单位重量', - adjusted_weight_unit VARCHAR(8) NULL COMMENT '人工修正后的单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认并统一换算后的重量kg', - recognition_status VARCHAR(24) NOT NULL DEFAULT 'PENDING' COMMENT '识别和确认状态', - adjustment_reason VARCHAR(500) NULL COMMENT '人工修正原因', - adjusted_by BIGINT UNSIGNED NULL COMMENT '修正人ID', - adjusted_at DATETIME(3) NULL COMMENT '修正时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_at DATETIME(3) NULL COMMENT '确认时间', - created_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0 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_weight_inbound_file (tenant_id, inbound_id, file_id), - KEY idx_weight_inbound_status (tenant_id, inbound_id, recognition_status), - CONSTRAINT fk_weight_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='称重图片OCR原值、人工修正值和确认重量'; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_revision ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量修订记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - weight_result_id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - revision_no INT UNSIGNED NOT NULL COMMENT '结果版本号,与乐观锁版本一致', - action VARCHAR(24) NOT NULL COMMENT '动作:CORRECT或CONFIRM', - before_weight_value DECIMAL(18,3) NULL COMMENT '变更前原单位重量', - before_weight_unit VARCHAR(8) NULL COMMENT '变更前单位', - after_weight_value DECIMAL(18,3) NULL COMMENT '变更后原单位重量', - after_weight_unit VARCHAR(8) NULL COMMENT '变更后单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认时统一换算后的重量kg', - reason VARCHAR(500) NULL COMMENT '人工修正原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - UNIQUE KEY uk_weight_revision_no (tenant_id, weight_result_id, revision_no), - KEY idx_weight_revision_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_weight_revision_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_weight_revision_result FOREIGN KEY (weight_result_id) REFERENCES fl_inbound_weight_result (id) -) ENGINE=InnoDB COMMENT='OCR重量人工修正和确认的不可变版本历史'; - -CREATE TABLE IF NOT EXISTS fl_measure_review_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量审核记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - measurement_id BIGINT UNSIGNED NULL COMMENT '被审核的测量批次ID', - review_result VARCHAR(24) NOT NULL COMMENT '审核结果', - review_reason VARCHAR(1000) NULL COMMENT '审核或驳回原因', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否异常放行', - release_reason VARCHAR(1000) NULL COMMENT '异常放行原因', - allow_rejected_config TINYINT(1) NOT NULL DEFAULT 0 COMMENT '操作时Nacos异常放行开关值', - reviewer_id BIGINT UNSIGNED NOT NULL COMMENT '审核人ID', - reviewer_name VARCHAR(64) NULL COMMENT '审核人名称快照', - reviewed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '审核时间', - PRIMARY KEY (id), - KEY idx_review_inbound_time (tenant_id, inbound_id, reviewed_at), - KEY idx_review_exception_release (tenant_id, inbound_id, exception_release, reviewed_at), - CONSTRAINT fk_review_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_review_measurement FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='测量审核、驳回和异常放行不可变记录'; - -CREATE TABLE IF NOT EXISTS fl_customer_charge_rule ( - id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rule_code VARCHAR(50) NOT NULL COMMENT '租户内规则编码', - rule_version INT UNSIGNED NOT NULL COMMENT '规则版本号', - customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - tax_mode VARCHAR(24) NULL COMMENT '包税或不包税类型', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '重量体积换算系数', - rounding_scale TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '结果保留小数位数', - rounding_mode VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式', - currency CHAR(3) NOT NULL COMMENT '默认币种', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '规则状态', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_charge_rule_version (tenant_id, rule_code, rule_version), - KEY idx_charge_rule_match (tenant_id, customer_id, business_type, status, effective_from, effective_to) -) ENGINE=InnoDB COMMENT='客户头程计费规则版本'; - -CREATE TABLE IF NOT EXISTS fl_carrier_fba_rate ( - id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rate_code VARCHAR(50) NOT NULL COMMENT '租户内价格编码', - rate_version INT UNSIGNED NOT NULL COMMENT '价格版本号', - origin_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '起运仓逻辑ID', - origin_warehouse_name VARCHAR(128) NOT NULL COMMENT '起运仓名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务或计费类型', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - carrier_id BIGINT UNSIGNED NULL COMMENT '船司逻辑ID', - carrier_name VARCHAR(128) NOT NULL COMMENT '船司名称快照', - destination_code VARCHAR(32) NOT NULL COMMENT 'FBA目的仓编码', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位:KG或CBM', - unit_price DECIMAL(18,6) NOT NULL COMMENT '基础单价', - currency CHAR(3) NOT NULL COMMENT '币种', - additional_fee DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '固定附加费', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '价格状态', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_fba_rate_version (tenant_id, rate_code, rate_version), - KEY idx_fba_rate_match (tenant_id, origin_warehouse_id, business_type, channel_code, carrier_id, destination_code, charge_unit, status, effective_from, effective_to) -) ENGINE=InnoDB COMMENT='船司FBA目的仓价格版本'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库费用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - fee_no VARCHAR(40) NOT NULL COMMENT '租户内唯一费用单号', - fee_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '费用快照版本', - charge_rule_id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - charge_rule_version INT UNSIGNED NOT NULL COMMENT '客户规则版本快照', - carrier_rate_id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - carrier_rate_version INT UNSIGNED NOT NULL COMMENT '船司价格版本快照', - rule_code VARCHAR(50) NOT NULL COMMENT '客户规则编码快照', - customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID快照', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型快照', - tax_mode VARCHAR(24) NULL COMMENT '包税模式快照', - rounding_scale TINYINT UNSIGNED NOT NULL COMMENT '计费量保留位数快照', - rounding_mode VARCHAR(24) NOT NULL COMMENT '舍入方式快照', - rule_effective_from DATETIME(3) NOT NULL COMMENT '客户规则生效开始快照', - rule_effective_to DATETIME(3) NULL COMMENT '客户规则生效结束快照', - rate_code VARCHAR(50) NOT NULL COMMENT '船司价格编码快照', - origin_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '起运仓ID快照', - origin_warehouse_name VARCHAR(128) NOT NULL COMMENT '起运仓名称快照', - channel_code VARCHAR(64) NOT NULL COMMENT '渠道编码快照', - carrier_id BIGINT UNSIGNED NOT NULL COMMENT '船司ID快照', - carrier_name VARCHAR(128) NOT NULL COMMENT '船司名称快照', - destination_code VARCHAR(32) NOT NULL COMMENT 'FBA仓编码快照', - rate_effective_from DATETIME(3) NOT NULL COMMENT '价格生效开始快照', - rate_effective_to DATETIME(3) NULL COMMENT '价格生效结束快照', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '使用的换算系数快照', - actual_weight_kg DECIMAL(18,3) NOT NULL COMMENT '试算时实际重量kg', - actual_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '试算时实际体积m3', - converted_quantity DECIMAL(18,4) NOT NULL COMMENT '换算后的重量或体积', - chargeable_quantity DECIMAL(18,4) NOT NULL COMMENT '最终计费量', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位', - currency CHAR(3) NOT NULL COMMENT '币种', - subtotal_amount DECIMAL(18,2) NOT NULL COMMENT '基础费用金额', - additional_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '附加费金额', - total_amount DECIMAL(18,2) NOT NULL COMMENT '总金额', - fee_status VARCHAR(24) NOT NULL DEFAULT 'CALCULATED' COMMENT '费用状态', - review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否基于测量异常放行生成', - calculated_by BIGINT UNSIGNED NOT NULL COMMENT '试算人ID', - calculated_at DATETIME(3) NOT NULL COMMENT '试算时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_at DATETIME(3) NULL COMMENT '确认时间', - sent_by BIGINT UNSIGNED NULL COMMENT '发送人ID', - sent_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_inbound_fee_no (tenant_id, fee_no), - UNIQUE KEY uk_inbound_fee_version (tenant_id, inbound_id, fee_version), - KEY idx_inbound_fee_status (tenant_id, inbound_id, fee_status, review_status), - CONSTRAINT fk_fee_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_fee_charge_rule FOREIGN KEY (charge_rule_id) REFERENCES fl_customer_charge_rule (id), - CONSTRAINT fk_fee_carrier_rate FOREIGN KEY (carrier_rate_id) REFERENCES fl_carrier_fba_rate (id) -) ENGINE=InnoDB COMMENT='入库头程费用计算和确认快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '费用明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - fee_id BIGINT UNSIGNED NOT NULL COMMENT '费用头ID', - item_no INT UNSIGNED NOT NULL COMMENT '费用单内序号', - fee_code VARCHAR(50) NOT NULL COMMENT '费用项目编码', - fee_name VARCHAR(128) NOT NULL COMMENT '费用项目名称快照', - quantity DECIMAL(18,4) NOT NULL COMMENT '计费数量', - unit VARCHAR(16) NOT NULL COMMENT '计费单位', - unit_price DECIMAL(18,6) NOT NULL COMMENT '单价', - amount DECIMAL(18,2) NOT NULL COMMENT '金额', - currency CHAR(3) NOT NULL COMMENT '币种', - automatic_flag TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否自动计算', - remark VARCHAR(500) NULL COMMENT '费用备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_fee_item_no (tenant_id, fee_id, item_no), - CONSTRAINT fk_fee_item_header FOREIGN KEY (fee_id) REFERENCES fl_inbound_fee (id) -) ENGINE=InnoDB COMMENT='入库头程费用项目明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pallet_allocation ( - id BIGINT UNSIGNED NOT NULL COMMENT '头程托盘分配引用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - allocation_no INT UNSIGNED NOT NULL COMMENT '入库单内分配序号', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务仓库ID', - warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓储资源所属租户ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - pallet_capacity_cbm DECIMAL(18,4) NOT NULL COMMENT '托盘可用容积快照', - allocated_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '本托盘分配体积', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - location_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - reservation_no VARCHAR(64) NOT NULL COMMENT '仓库库位预占单号', - allocation_status VARCHAR(24) NOT NULL DEFAULT 'RESERVED' 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_pallet_allocation_no (tenant_id, inbound_id, allocation_no), - UNIQUE KEY uk_pallet_allocation_pallet (tenant_id, inbound_id, pallet_id), - KEY idx_allocation_location (tenant_id, warehouse_id, location_id, allocation_status), - CONSTRAINT fk_allocation_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='头程侧托盘、库位和仓库预占结果引用'; - -CREATE TABLE IF NOT EXISTS fl_inbound_file ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单文件关系ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件服务文件ID', - file_type VARCHAR(24) NOT NULL COMMENT '文件类型:RELATED、MARK、PC_ORDER、MEASURE或WEIGHT', - file_name_snapshot VARCHAR(255) NOT NULL COMMENT '文件名快照', - visibility VARCHAR(16) NOT NULL DEFAULT 'INTERNAL' COMMENT '可见范围', - file_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '业务文件版本', - uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传人ID', - uploaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上传时间', - deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', - PRIMARY KEY (id), - UNIQUE KEY uk_inbound_file_relation (tenant_id, inbound_id, file_id, file_type), - KEY idx_inbound_file_type (tenant_id, inbound_id, file_type, deleted), - CONSTRAINT fk_file_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单与文件中心对象的分类关系'; - -CREATE TABLE IF NOT EXISTS fl_inbound_hold_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '扣货记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - hold_action VARCHAR(16) NOT NULL COMMENT '动作:HOLD或RELEASE', - reason VARCHAR(1000) NOT NULL COMMENT '扣货或解除原因', - evidence_file_id BIGINT UNSIGNED NULL COMMENT '证据文件ID', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - KEY idx_hold_inbound_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_hold_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单扣货和解除扣货不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_internal_note ( - id BIGINT UNSIGNED NOT NULL COMMENT '客服内部备注ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - content VARCHAR(2000) NOT NULL COMMENT '仅内部可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_internal_note_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_internal_note_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单客服内部备注历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_status_history ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库状态历史ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - from_status VARCHAR(24) NULL COMMENT '变更前状态', - to_status VARCHAR(24) NOT NULL COMMENT '变更后状态', - action VARCHAR(32) NOT NULL COMMENT '触发动作', - reason VARCHAR(1000) NULL COMMENT '变更原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '发生时间', - PRIMARY KEY (id), - KEY idx_inbound_history_time (tenant_id, inbound_id, occurred_at), - CONSTRAINT fk_history_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单流程状态不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_outbox ( - id BIGINT UNSIGNED NOT NULL COMMENT '领域事件全局ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '事件所属租户ID', - aggregate_type VARCHAR(32) NOT NULL DEFAULT 'INBOUND' COMMENT '聚合类型', - aggregate_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - payload_json JSON NOT NULL COMMENT '事件负载快照', - publish_status VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '发布状态', - retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数', - next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', - published_at DATETIME(3) NULL COMMENT '发布时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_inbound_outbox_publish (publish_status, next_retry_at, created_at) -) ENGINE=InnoDB COMMENT='入库事务Outbox事件表'; - -CREATE TABLE IF NOT EXISTS fl_inbound_idempotency ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库写操作幂等记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '租户ID', - operation VARCHAR(40) NOT NULL COMMENT '操作类型', - operator_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作者或外部应用ID', - inbound_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '入库单ID,创建前可为0', - idempotency_key VARCHAR(128) NOT NULL COMMENT '幂等键', - request_hash CHAR(64) NOT NULL COMMENT '请求内容摘要', - status VARCHAR(16) NOT NULL COMMENT '处理状态', - result_json JSON NULL COMMENT '成功结果摘要', - result_resource_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_inbound_idempotency (tenant_id, operation, operator_id, idempotency_key), - KEY idx_inbound_idempotency_created (created_at) -) ENGINE=InnoDB COMMENT='第三方测量、审核、费用发送和入库写操作幂等记录'; - - --- ============================================================================ --- Firstleg 称重结果审计字段存量补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-weight-audit-migration.sql --- ============================================================================ -USE baiyue_firstleg; - -SET @has_created_by := ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_weight_result' AND column_name = 'created_by' -); -SET @created_by_sql := IF(@has_created_by = 0, - 'ALTER TABLE fl_inbound_weight_result ADD COLUMN created_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''创建人ID'' AFTER confirmed_at', - 'SELECT 1'); -PREPARE created_by_stmt FROM @created_by_sql; -EXECUTE created_by_stmt; -DEALLOCATE PREPARE created_by_stmt; - -SET @has_updated_by := ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_weight_result' AND column_name = 'updated_by' -); -SET @updated_by_sql := IF(@has_updated_by = 0, - 'ALTER TABLE fl_inbound_weight_result ADD COLUMN updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''最后修改人ID'' AFTER created_at', - 'SELECT 1'); -PREPARE updated_by_stmt FROM @updated_by_sql; -EXECUTE updated_by_stmt; -DEALLOCATE PREPARE updated_by_stmt; - - --- ============================================================================ --- Firstleg 测量与 OCR 存量字段补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-measurement-maintenance.sql --- ============================================================================ --- 二期入库测量与 OCR 维护增量(只增不删,可重复执行)。 --- 执行顺序:phase2-inbound-schema.sql 后执行本文件;已有二期库只需执行本文件。 -SET NAMES utf8mb4; -USE baiyue_firstleg; - -DROP PROCEDURE IF EXISTS phase2_measure_add_column; -DELIMITER $$ -CREATE PROCEDURE phase2_measure_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 @phase2_measure_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE phase2_measure_statement FROM @phase2_measure_sql; - EXECUTE phase2_measure_statement; - DEALLOCATE PREPARE phase2_measure_statement; - END IF; -END$$ -DELIMITER ; - -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_document_no', - 'VARCHAR(64) NULL COMMENT ''原单据号码快照'' AFTER raw_payload_json'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_gross_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''原单据毛重kg'' AFTER original_document_no'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_volume_cbm', - 'DECIMAL(18,4) NULL COMMENT ''原单据体积或材积m3'' AFTER original_gross_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'actual_goods_name', - 'VARCHAR(255) NULL COMMENT ''实际品名'' AFTER original_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'volume_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''本批次总材积重kg'' AFTER total_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'version', - 'INT NOT NULL DEFAULT 0 COMMENT ''乐观锁版本号'' AFTER updated_at'); - -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'box_specification', - 'VARCHAR(64) NOT NULL DEFAULT '''' COMMENT ''箱规标识'' AFTER item_no'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'girth_cm', - 'DECIMAL(12,3) NOT NULL DEFAULT 0 COMMENT ''周长cm,规则为长+2*(宽+高)'' AFTER height_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'unit_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''单箱重量kg'' AFTER girth_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'unit_volume_cbm', - 'DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''单箱业务体积m3'' AFTER unit_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'total_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''本箱规总重量kg'' AFTER volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'total_volume_cbm', - 'DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''本箱规总体积m3'' AFTER total_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'volume_weight_kg', - 'DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT ''本箱规材积重kg'' AFTER total_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'over_limit_warning', - 'VARCHAR(500) NULL COMMENT ''超线提醒快照'' AFTER source_image_file_id'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_length_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规长度cm'' AFTER over_limit_warning'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_width_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规宽度cm'' AFTER outer_length_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_height_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规高度cm'' AFTER outer_width_cm'); - -DROP PROCEDURE IF EXISTS phase2_measure_add_column; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_revision ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量修订记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - weight_result_id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - revision_no INT UNSIGNED NOT NULL COMMENT '结果版本号,与乐观锁版本一致', - action VARCHAR(24) NOT NULL COMMENT '动作:CORRECT或CONFIRM', - before_weight_value DECIMAL(18,3) NULL COMMENT '变更前原单位重量', - before_weight_unit VARCHAR(8) NULL COMMENT '变更前单位', - after_weight_value DECIMAL(18,3) NULL COMMENT '变更后原单位重量', - after_weight_unit VARCHAR(8) NULL COMMENT '变更后单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认时统一换算后的重量kg', - reason VARCHAR(500) NULL COMMENT '人工修正原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - UNIQUE KEY uk_weight_revision_no (tenant_id, weight_result_id, revision_no), - KEY idx_weight_revision_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_weight_revision_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_weight_revision_result FOREIGN KEY (weight_result_id) REFERENCES fl_inbound_weight_result (id) -) ENGINE=InnoDB COMMENT='OCR重量人工修正和确认的不可变版本历史'; - - --- ============================================================================ --- Firstleg 审核工作流索引补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-workflow-migration.sql --- ============================================================================ --- 业务块4增量迁移:既有二期库补齐异常放行关口查询索引。 --- 可重复执行;新库仍先执行 phase2-inbound-schema.sql。 -USE baiyue_firstleg; -SET NAMES utf8mb4; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.statistics - WHERE table_schema = DATABASE() AND table_name = 'fl_measure_review_record' - AND index_name = 'idx_review_exception_release'), - 'SELECT 1', - 'ALTER TABLE fl_measure_review_record ADD INDEX idx_review_exception_release (tenant_id, inbound_id, exception_release, reviewed_at)' -); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - - --- ============================================================================ --- Firstleg 第三方测量调用日志 --- 来源:firstleg/src/main/resources/db/phase2-measurement-openapi.sql --- ============================================================================ -SET NAMES utf8mb4; -USE baiyue_firstleg; - --- 既有二期数据库增量:先确保 phase2-inbound-schema.sql 中的测量和幂等表已存在。 -CREATE TABLE IF NOT EXISTS fl_third_party_call_log ( - id BIGINT UNSIGNED NOT NULL COMMENT '第三方调用日志ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '识别出的租户ID,未知应用为0', - app_key VARCHAR(128) NULL COMMENT '第三方应用标识', - signature_subject VARCHAR(128) NULL COMMENT '签名主体快照', - request_method VARCHAR(8) NOT NULL COMMENT 'HTTP方法', - request_path VARCHAR(255) NOT NULL COMMENT '签名使用的规范路径', - request_timestamp VARCHAR(32) NULL COMMENT '请求头Unix毫秒时间戳原值', - nonce VARCHAR(128) NULL COMMENT '请求Nonce', - idempotency_key VARCHAR(128) NULL COMMENT 'HTTP幂等键,查询接口为空', - idempotency_anchor TINYINT UNSIGNED NULL COMMENT '签名通过后首个请求为1,重复调用为空', - signature_value VARCHAR(128) NULL COMMENT '第三方签名原值', - request_hash CHAR(64) NOT NULL COMMENT '原始请求体SHA-256小写十六进制', - raw_payload LONGTEXT NOT NULL COMMENT '未经重新序列化的UTF-8原始请求体', - processing_status VARCHAR(16) NOT NULL COMMENT 'PROCESSING、ACCEPTED或REJECTED', - result_code VARCHAR(32) NULL COMMENT '统一响应业务码', - result_message VARCHAR(1000) NULL COMMENT '处理结果或失败原因', - result_json JSON NULL COMMENT '首次成功结果快照', - requested_at DATETIME(3) NOT NULL COMMENT '服务端接收时间', - processed_at DATETIME(3) NULL COMMENT '处理完成时间', - PRIMARY KEY (id), - KEY idx_third_call_app_time (tenant_id, app_key, requested_at), - KEY idx_third_call_idempotency (tenant_id, app_key, idempotency_key), - KEY idx_third_call_nonce (tenant_id, app_key, nonce), - UNIQUE KEY uk_third_call_idempotency_owner (tenant_id, app_key, idempotency_key, idempotency_anchor) -) ENGINE=InnoDB COMMENT='第三方测量开放接口原始请求、签名主体和处理结果留档'; - - --- ============================================================================ --- Firstleg FBA 计费字段与索引补齐 --- 来源:firstleg/src/main/resources/db/phase2-fba-pricing-migration.sql --- ============================================================================ -SET NAMES utf8mb4; -USE baiyue_firstleg; - --- 二期 FBA 计费增量迁移。通过 information_schema 判断,允许重复部署。 -DROP PROCEDURE IF EXISTS phase2_fba_add_column; -DELIMITER $$ -CREATE PROCEDURE phase2_fba_add_column(IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_definition TEXT) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND COLUMN_NAME = p_column - ) THEN - SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); - PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - END IF; -END$$ -DELIMITER ; - -CALL phase2_fba_add_column('fl_inbound_order', 'carrier_id', "BIGINT UNSIGNED NULL COMMENT '计费船司逻辑ID' AFTER channel_name"); -CALL phase2_fba_add_column('fl_inbound_order', 'carrier_name', "VARCHAR(128) NULL COMMENT '计费船司名称快照' AFTER carrier_id"); -CALL phase2_fba_add_column('fl_carrier_fba_rate', 'business_type', "VARCHAR(32) NOT NULL DEFAULT 'FBA' COMMENT '业务或计费类型' AFTER origin_warehouse_name"); -CALL phase2_fba_add_column('fl_customer_charge_rule', 'version', "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted"); -CALL phase2_fba_add_column('fl_carrier_fba_rate', 'version', "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_code', "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '客户规则编码快照' AFTER carrier_rate_version"); -CALL phase2_fba_add_column('fl_inbound_fee', 'customer_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID快照' AFTER rule_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'customer_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '客户名称快照' AFTER customer_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'business_type', "VARCHAR(32) NOT NULL DEFAULT '' COMMENT '业务类型快照' AFTER customer_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'tax_mode', "VARCHAR(24) NULL COMMENT '包税模式快照' AFTER business_type"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rounding_scale', "TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '计费量保留位数快照' AFTER tax_mode"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rounding_mode', "VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式快照' AFTER rounding_scale"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_effective_from', "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '客户规则生效开始快照' AFTER rounding_mode"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_effective_to', "DATETIME(3) NULL COMMENT '客户规则生效结束快照' AFTER rule_effective_from"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_code', "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '船司价格编码快照' AFTER rule_effective_to"); -CALL phase2_fba_add_column('fl_inbound_fee', 'origin_warehouse_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '起运仓ID快照' AFTER rate_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'origin_warehouse_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '起运仓名称快照' AFTER origin_warehouse_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'channel_code', "VARCHAR(64) NOT NULL DEFAULT '' COMMENT '渠道编码快照' AFTER origin_warehouse_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'carrier_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '船司ID快照' AFTER channel_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'carrier_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '船司名称快照' AFTER carrier_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'destination_code', "VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'FBA仓编码快照' AFTER carrier_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_effective_from', "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '价格生效开始快照' AFTER destination_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_effective_to', "DATETIME(3) NULL COMMENT '价格生效结束快照' AFTER rate_effective_from"); -CALL phase2_fba_add_column('fl_inbound_idempotency', 'result_resource_id', "BIGINT UNSIGNED NULL COMMENT '成功结果资源ID' AFTER result_json"); -CALL phase2_fba_add_column('fl_inbound_pallet_allocation', 'warehouse_resource_tenant_id', - "BIGINT UNSIGNED NULL COMMENT '仓储资源所属租户ID' AFTER warehouse_id"); - -UPDATE fl_inbound_pallet_allocation -SET warehouse_resource_tenant_id = tenant_id -WHERE warehouse_resource_tenant_id IS NULL OR warehouse_resource_tenant_id = 0; -SET @resource_tenant_nullable = (SELECT IS_NULLABLE FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_inbound_pallet_allocation' - AND COLUMN_NAME = 'warehouse_resource_tenant_id'); -SET @sql = IF(@resource_tenant_nullable = 'YES', - "ALTER TABLE fl_inbound_pallet_allocation MODIFY COLUMN warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓储资源所属租户ID'", - 'SELECT 1'); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -DROP PROCEDURE IF EXISTS phase2_fba_add_column; - --- 旧索引可能缺少业务类型、船司和结束时间;用新索引名并存,避免破坏线上依赖。 -SET @idx_exists = (SELECT COUNT(*) FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_carrier_fba_rate' AND INDEX_NAME = 'idx_fba_rate_unique_match'); -SET @sql = IF(@idx_exists = 0, - 'ALTER TABLE fl_carrier_fba_rate ADD INDEX idx_fba_rate_unique_match (tenant_id, origin_warehouse_id, business_type, channel_code, carrier_id, destination_code, charge_unit, status, effective_from, effective_to)', - 'SELECT 1'); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - - --- ============================================================================ --- Warehouse 二期托盘库位最终基线表 --- 来源:warehouse/src/main/resources/db/phase2-pallet-location-schema.sql --- ============================================================================ --- 二期托盘、库位、预占与占用表结构。 --- 本脚本只新增表、字段、索引和约束,不包含业务数据及流程实现。 --- 可在 warehouse.sql 和一期增量脚本之后执行;所有建表均可重复执行。 -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_warehouse - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_warehouse; - -CREATE TABLE IF NOT EXISTS wh_pallet ( - id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一托盘编码', - pallet_type VARCHAR(32) NOT NULL COMMENT '托盘类型', - pallet_name VARCHAR(100) NULL COMMENT '托盘名称', - capacity_cbm DECIMAL(18,6) NOT NULL COMMENT '托盘可用容积CBM', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT '内部状态:AVAILABLE、RESERVED或OCCUPIED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_pallet_tenant_warehouse_code (tenant_id, warehouse_id, pallet_code), - KEY idx_pallet_available (tenant_id, warehouse_id, status, deleted), - KEY idx_pallet_type (tenant_id, warehouse_id, pallet_type, status, deleted), - CONSTRAINT fk_pallet_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_pallet_capacity CHECK (capacity_cbm > 0) -) ENGINE=InnoDB COMMENT='二期托盘基础资料和物理托盘实例'; - -CREATE TABLE IF NOT EXISTS wh_location ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - zone_code VARCHAR(50) NULL COMMENT '库区编码', - zone_name VARCHAR(100) NULL COMMENT '库区名称', - location_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一库位编码', - location_name VARCHAR(100) NULL COMMENT '库位名称', - location_type VARCHAR(32) NOT NULL DEFAULT 'PALLET' COMMENT '库位类型,二期为PALLET', - max_weight_kg DECIMAL(18,3) NULL COMMENT '最大承重展示值,二期不作容量拦截', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否为系统共享溢出位A0', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT 'AVAILABLE、RESERVED、OCCUPIED或DISABLED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_location_tenant_warehouse_code (tenant_id, warehouse_id, location_code), - KEY idx_location_available (tenant_id, warehouse_id, status, deleted), - KEY idx_location_zone (tenant_id, warehouse_id, zone_code, status, deleted), - CONSTRAINT fk_location_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_location_max_weight CHECK (max_weight_kg IS NULL OR max_weight_kg > 0) -) ENGINE=InnoDB COMMENT='二期库位基础资料,默认一托盘对应一个库位且不作容量校验'; - -CREATE TABLE IF NOT EXISTS wh_location_reservation ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位预占ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - reservation_no VARCHAR(40) NOT NULL COMMENT '租户内唯一预占业务号', - idempotency_key VARCHAR(128) NOT NULL COMMENT '调用方幂等键', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否使用共享溢出位A0', - reservation_status VARCHAR(20) NOT NULL DEFAULT 'RESERVED' COMMENT 'RESERVED、CONFIRMED、RELEASED或EXPIRED', - expires_at DATETIME(3) NOT NULL COMMENT '预占过期时间', - confirmed_at DATETIME(3) NULL COMMENT '确认占用时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放或过期原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_reservation TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT '普通库位活动预占唯一标记', - active_pallet_reservation TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' THEN 1 ELSE NULL END) STORED COMMENT '托盘活动预占唯一标记(包含A0)', - PRIMARY KEY (id), - UNIQUE KEY uk_location_reservation_no (tenant_id, reservation_no), - UNIQUE KEY uk_location_reservation_idempotency (tenant_id, source_service, idempotency_key), - UNIQUE KEY uk_location_active_reservation (tenant_id, location_id, active_reservation), - UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation), - KEY idx_location_reservation_business (tenant_id, source_service, business_id, reservation_status), - KEY idx_location_reservation_expire (reservation_status, expires_at), - KEY idx_location_reservation_target (tenant_id, warehouse_id, location_id, reservation_status), - CONSTRAINT fk_reservation_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_reservation_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_reservation_location FOREIGN KEY (location_id) REFERENCES wh_location (id) -) ENGINE=InnoDB COMMENT='跨服务入库Saga的托盘和库位临时预占'; - -CREATE TABLE IF NOT EXISTS wh_location_occupancy ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位占用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - occupancy_no VARCHAR(40) NOT NULL COMMENT '租户内唯一占用业务号', - reservation_id BIGINT UNSIGNED NOT NULL COMMENT '来源预占ID', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否使用共享溢出位A0', - allocated_volume_cbm DECIMAL(18,6) NOT NULL COMMENT '本托盘分配体积CBM', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - occupancy_status VARCHAR(20) NOT NULL DEFAULT 'OCCUPIED' COMMENT 'OCCUPIED或RELEASED', - occupied_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '占用开始时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_location_occupancy TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = 'OCCUPIED' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT '普通库位活动占用唯一标记', - active_pallet_occupancy TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = 'OCCUPIED' THEN 1 ELSE NULL END) STORED COMMENT '托盘活动占用唯一标记(包含A0)', - PRIMARY KEY (id), - UNIQUE KEY uk_location_occupancy_no (tenant_id, occupancy_no), - UNIQUE KEY uk_occupancy_reservation (tenant_id, reservation_id), - UNIQUE KEY uk_location_active_occupancy (tenant_id, location_id, active_location_occupancy), - UNIQUE KEY uk_pallet_active_occupancy (tenant_id, pallet_id, active_pallet_occupancy), - KEY idx_occupancy_business (tenant_id, source_service, business_id, occupancy_status), - KEY idx_occupancy_warehouse (tenant_id, warehouse_id, occupancy_status, occupied_at), - CONSTRAINT fk_occupancy_reservation FOREIGN KEY (reservation_id) REFERENCES wh_location_reservation (id), - CONSTRAINT fk_occupancy_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_occupancy_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_occupancy_location FOREIGN KEY (location_id) REFERENCES wh_location (id), - CONSTRAINT ck_occupancy_volume CHECK (allocated_volume_cbm > 0) -) ENGINE=InnoDB COMMENT='已确认的一托一库位占用事实记录'; - --- 头程入库单属于其他数据库,不建立跨库外键。 - - --- ============================================================================ --- Warehouse 托盘活动预占唯一约束补齐 --- 来源:warehouse/src/main/resources/db/phase2-pallet-location-schema-migration.sql --- ============================================================================ --- 二期托盘、库位表的可重复执行增量迁移。 --- 执行顺序:phase2-pallet-location-schema.sql 之后。 -SET NAMES utf8mb4; -USE baiyue_warehouse; - --- 活动预占必须同时保证“一托一位”;A0 共享只放宽库位,不放宽托盘唯一性。 -SET @schema_name = DATABASE(); -DROP PROCEDURE IF EXISTS add_pallet_reservation_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_pallet_reservation_column_if_missing() -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = DATABASE() - AND table_name = 'wh_location_reservation' - AND column_name = 'active_pallet_reservation' - ) THEN - ALTER TABLE wh_location_reservation - ADD COLUMN active_pallet_reservation TINYINT - GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' THEN 1 ELSE NULL END) - STORED COMMENT '托盘活动预占唯一标记(包含A0)'; - END IF; -END$$ -DELIMITER ; -CALL add_pallet_reservation_column_if_missing(); -DROP PROCEDURE IF EXISTS add_pallet_reservation_column_if_missing; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics - WHERE table_schema = @schema_name - AND table_name = 'wh_location_reservation' - AND index_name = 'uk_pallet_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_pallet_active_reservation', - 'SELECT 1'); -PREPARE statement FROM @sql; -EXECUTE statement; -DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics - WHERE table_schema = @schema_name - AND table_name = 'wh_location_reservation' - AND index_name = 'uk_pallet_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation)', - 'SELECT 1'); -PREPARE statement FROM @sql; -EXECUTE statement; -DEALLOCATE PREPARE statement; - - --- ============================================================================ --- Warehouse A0 共享溢出位与最终并发约束 --- 来源:warehouse/src/main/resources/db/phase2-location-overflow-migration.sql --- ============================================================================ --- 二期库位共享溢出位 A0 增量迁移。 --- 执行顺序:phase2-pallet-location-schema.sql、本文件。 --- 普通库位仍保持一托一位;同一租户仓库只有一个 A0,且 A0 可承载多个活动资源。 -SET NAMES utf8mb4; -USE baiyue_warehouse; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_location_overflow_column_if_missing( - 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 @column_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE column_statement FROM @column_sql; - EXECUTE column_statement; - DEALLOCATE PREPARE column_statement; - END IF; -END$$ -DELIMITER ; - -CALL add_location_overflow_column_if_missing( - 'wh_location', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否为系统共享溢出位 A0'' AFTER max_weight_kg' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_reservation', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否使用共享溢出位 A0'' AFTER location_code' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否使用共享溢出位 A0'' AFTER location_code' -); - --- 兼容迁移前人工或旧流程已创建的 A0,并将资源快照回填一致。 -UPDATE wh_location - SET shared_overflow = 1, - status = 'AVAILABLE' - WHERE location_code = 'A0' AND deleted = 0; - -UPDATE wh_location_reservation r -JOIN wh_location l - ON l.tenant_id = r.tenant_id AND l.id = r.location_id - SET r.shared_overflow = l.shared_overflow; - -UPDATE wh_location_occupancy o -JOIN wh_location l - ON l.tenant_id = o.tenant_id AND l.id = o.location_id - SET o.shared_overflow = l.shared_overflow; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; - --- 先移除依赖旧生成列的唯一索引,再按普通库位/A0 的不同语义重建。 -SET @schema_name = DATABASE(); -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_location_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_location_active_reservation', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_pallet_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_pallet_active_reservation', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -ALTER TABLE wh_location_reservation - MODIFY COLUMN active_reservation TINYINT - GENERATED ALWAYS AS ( - CASE WHEN reservation_status = 'RESERVED' AND shared_overflow = 0 THEN 1 ELSE NULL END - ) STORED COMMENT '普通库位活动预占唯一标记,A0 返回 NULL'; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_location_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_location_active_reservation (tenant_id, location_id, active_reservation)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_location_active_occupancy') > 0, - 'ALTER TABLE wh_location_occupancy DROP INDEX uk_location_active_occupancy', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_pallet_active_occupancy') > 0, - 'ALTER TABLE wh_location_occupancy DROP INDEX uk_pallet_active_occupancy', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_location_overflow_column_if_missing( - 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 @column_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE column_statement FROM @column_sql; - EXECUTE column_statement; - DEALLOCATE PREPARE column_statement; - END IF; -END$$ -DELIMITER ; - -CALL add_location_overflow_column_if_missing( - 'wh_location_reservation', 'active_pallet_reservation', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = ''RESERVED'' THEN 1 ELSE NULL END) STORED COMMENT ''托盘活动预占唯一标记(包含 A0)''' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'active_location_occupancy', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = ''OCCUPIED'' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT ''普通库位活动占用唯一标记''' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'active_pallet_occupancy', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = ''OCCUPIED'' THEN 1 ELSE NULL END) STORED COMMENT ''托盘活动占用唯一标记(包含 A0)''' -); -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_pallet_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_location_active_occupancy') = 0, - 'ALTER TABLE wh_location_occupancy ADD UNIQUE KEY uk_location_active_occupancy (tenant_id, location_id, active_location_occupancy)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_pallet_active_occupancy') = 0, - 'ALTER TABLE wh_location_occupancy ADD UNIQUE KEY uk_pallet_active_occupancy (tenant_id, pallet_id, active_pallet_occupancy)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - - --- 第三方单条箱规 + 单张图片绑定增量。 -USE baiyue_firstleg; -DROP PROCEDURE IF EXISTS phase2_add_measurement_column; -DELIMITER $$ -CREATE PROCEDURE phase2_add_measurement_column( - IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_definition TEXT) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND COLUMN_NAME = p_column - ) THEN - SET @ddl = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); - PREPARE statement FROM @ddl; - EXECUTE statement; - DEALLOCATE PREPARE statement; - END IF; -END$$ -DELIMITER ; -CALL phase2_add_measurement_column('fl_inbound_measurement', 'external_request_hash', - 'CHAR(64) NULL COMMENT ''第三方data原文和图片内容联合请求哈希'' AFTER external_event_no'); -CALL phase2_add_measurement_column('fl_inbound_measurement_item', 'inbound_detail_id', - 'BIGINT UNSIGNED NULL COMMENT ''绑定的订单货物明细ID,平台手工明细可为空'' AFTER measurement_id'); -CALL phase2_add_measurement_column('fl_inbound_measurement_item', 'external_detail_no', - 'VARCHAR(128) NULL COMMENT ''第三方测量明细唯一号,平台手工明细可为空'' AFTER inbound_detail_id'); -DROP PROCEDURE IF EXISTS phase2_add_measurement_column; -SET @has_index = (SELECT COUNT(*) FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_inbound_measurement_item' - AND INDEX_NAME = 'uk_measure_external_detail'); -SET @ddl = IF(@has_index = 0, - 'ALTER TABLE fl_inbound_measurement_item ADD UNIQUE KEY uk_measure_external_detail (tenant_id, inbound_detail_id, external_detail_no)', - 'SELECT 1'); -PREPARE statement FROM @ddl; EXECUTE statement; DEALLOCATE PREPARE statement; - --- 结构核对:只读输出,不写业务数据。 -SELECT 'firstleg 二期核心表数量' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 21, 'PASS', 'FAIL') AS check_result -FROM information_schema.tables -WHERE table_schema = 'baiyue_firstleg' - AND table_name IN ( - 'fl_inbound_order', 'fl_inbound_pickup_snapshot', 'fl_inbound_destination_snapshot', - 'fl_inbound_transport_snapshot', 'fl_inbound_measurement', 'fl_inbound_measurement_item', - 'fl_inbound_weight_result', 'fl_inbound_weight_revision', 'fl_measure_review_record', - 'fl_customer_charge_rule', 'fl_carrier_fba_rate', 'fl_inbound_fee', 'fl_inbound_fee_item', - 'fl_inbound_pallet_allocation', 'fl_inbound_file', 'fl_inbound_hold_record', - 'fl_inbound_internal_note', 'fl_inbound_status_history', 'fl_inbound_outbox', - 'fl_inbound_idempotency', 'fl_third_party_call_log' - ) -UNION ALL -SELECT 'warehouse 二期核心表数量', - COUNT(*), - IF(COUNT(*) = 4, 'PASS', 'FAIL') -FROM information_schema.tables -WHERE table_schema = 'baiyue_warehouse' - AND table_name IN ('wh_pallet', 'wh_location', 'wh_location_reservation', 'wh_location_occupancy') -UNION ALL -SELECT 'file 图片依赖表数量', - COUNT(*), - IF(COUNT(*) = 3, 'PASS', 'FAIL') -FROM information_schema.tables -WHERE table_schema = 'baiyue_file' - AND table_name IN ('file_object', 'file_download_token', 'file_download_log'); - -SELECT 'A0 共享溢出与活动占用关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 6, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location' AND column_name = 'shared_overflow') - OR (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location_reservation' - AND column_name IN ('shared_overflow', 'active_reservation', 'active_pallet_reservation')) - OR (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location_occupancy' - AND column_name IN ('shared_overflow', 'active_location_occupancy', 'active_pallet_occupancy')); - -SELECT 'A0 共享溢出与活动占用关键唯一索引' AS check_item, - COUNT(DISTINCT CONCAT(table_schema, '.', table_name, '.', index_name)) AS actual_value, - IF(COUNT(DISTINCT CONCAT(table_schema, '.', table_name, '.', index_name)) = 4, 'PASS', 'FAIL') AS check_result -FROM information_schema.statistics -WHERE table_schema = 'baiyue_warehouse' - AND ( - (table_name = 'wh_location_reservation' AND index_name IN ('uk_location_active_reservation', 'uk_pallet_active_reservation')) - OR (table_name = 'wh_location_occupancy' AND index_name IN ('uk_location_active_occupancy', 'uk_pallet_active_occupancy')) - ); - -SELECT '第三方单条测量绑定关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 3, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_firstleg' - AND ((table_name = 'fl_inbound_measurement' AND column_name = 'external_request_hash') - OR (table_name = 'fl_inbound_measurement_item' - AND column_name IN ('inbound_detail_id', 'external_detail_no'))); - -SELECT '第三方单条测量绑定唯一索引' AS check_item, - COUNT(DISTINCT index_name) AS actual_value, - IF(COUNT(DISTINCT index_name) = 1, 'PASS', 'FAIL') AS check_result -FROM information_schema.statistics -WHERE table_schema = 'baiyue_firstleg' - AND table_name = 'fl_inbound_measurement_item' - AND index_name = 'uk_measure_external_detail'; - -SELECT '称重结果审计关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 2, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_firstleg' - AND table_name = 'fl_inbound_weight_result' - AND column_name IN ('created_by', 'updated_by'); - -SELECT @deployment_environment AS deployment_environment, - 'PHASE2_TEST_MIGRATION_COMPLETED' AS execution_code, - '二期 TEST 环境增量脚本执行完成,请确认以上检查全部为 PASS' AS execution_message; diff --git a/deploy/sql/2026-08-04-二期入库新增表字段-MySQL8一键执行.sql b/deploy/sql/2026-08-04-二期入库新增表字段-MySQL8一键执行.sql deleted file mode 100644 index 6478d11e8..000000000 --- a/deploy/sql/2026-08-04-二期入库新增表字段-MySQL8一键执行.sql +++ /dev/null @@ -1,1334 +0,0 @@ --- 柏悦头程二期入库新增表与字段:MySQL 8 一键执行脚本 --- 生成日期:2026-08-04 --- 适用版本:MySQL 8.0+(需要 GENERATED COLUMN、JSON、CHECK 约束支持) --- 适用场景: --- 1. 新环境:在一期基线完成后直接执行,创建二期最终表结构。 --- 2. 存量二期环境:可重复执行,自动补齐新字段、索引和 A0 共享溢出约束。 --- 执行范围:仅 CREATE / ALTER 表、字段、索引、约束;不插入权限、不写业务单据。 --- 目标数据库:baiyue_file、baiyue_firstleg、baiyue_warehouse。 --- 前置条件:一期的 baiyue_firstleg.fl_fulfillment_task 与 baiyue_warehouse.wh_warehouse 已存在。 --- 注意: --- - MySQL DDL 自动提交,执行前必须完成备份并在临时/预发布库演练。 --- - 既有数据若已违反即将建立的唯一约束,脚本会停止,需要先治理数据。 --- - 本脚本由 MySQL Client / MySQL Workbench 直接执行;包含 DELIMITER 的存储过程定义。 --- - 不连接、不修改正式库;请在明确指定的目标库连接中执行。 - -SET NAMES utf8mb4; -SET SESSION sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; - -SELECT VERSION() AS mysql_version, - '开始执行二期入库新增表与字段脚本' AS execution_message; - -SELECT - EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'baiyue_firstleg' AND table_name = 'fl_fulfillment_task') AS has_phase1_fulfillment_task, - EXISTS(SELECT 1 FROM information_schema.tables WHERE table_schema = 'baiyue_warehouse' AND table_name = 'wh_warehouse') AS has_phase1_warehouse; - --- ============================================================================ --- 文件中心基线(测量图片依赖) --- 来源:file/src/main/resources/db/file.sql --- ============================================================================ --- 文件中心独占数据库,其他服务只保存文件逻辑ID。 -CREATE DATABASE IF NOT EXISTS baiyue_file - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_file; - -CREATE TABLE IF NOT EXISTS file_object ( - id BIGINT UNSIGNED NOT NULL COMMENT '文件ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - business_type VARCHAR(32) NULL COMMENT '关联业务类型', - business_id VARCHAR(64) NULL COMMENT '关联业务逻辑ID', - original_name VARCHAR(255) NOT NULL COMMENT '原始文件名', - object_key VARCHAR(512) NOT NULL COMMENT '对象存储键', - storage_provider VARCHAR(32) NOT NULL COMMENT '存储提供方', - bucket_name VARCHAR(128) NOT NULL COMMENT '存储桶名称', - content_type VARCHAR(128) NOT NULL COMMENT '文件内容类型', - size_bytes BIGINT UNSIGNED NOT NULL COMMENT '文件字节数', - sha256 CHAR(64) NULL COMMENT '文件SHA-256摘要', - status VARCHAR(24) NOT NULL DEFAULT 'ACTIVE' 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), - UNIQUE KEY uk_file_tenant_object (tenant_id, object_key), - KEY idx_file_tenant_business (tenant_id, business_type, business_id), - KEY idx_file_tenant_created (tenant_id, created_at) -) ENGINE=InnoDB COMMENT='文件元数据表'; - -CREATE TABLE IF NOT EXISTS file_download_token ( - id BIGINT UNSIGNED NOT NULL COMMENT '下载令牌ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件逻辑ID', - token_hash CHAR(64) NOT NULL COMMENT '下载令牌SHA-256摘要', - expires_at DATETIME(3) NOT NULL COMMENT '过期时间', - max_downloads INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '最大下载次数', - download_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '已下载次数', - revoked_at DATETIME(3) NULL COMMENT '撤销时间', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_download_token_hash (token_hash), - KEY idx_download_file (tenant_id, file_id), - KEY idx_download_expiry (expires_at) -) ENGINE=InnoDB COMMENT='临时下载授权令牌表'; - -CREATE TABLE IF NOT EXISTS file_download_log ( - id BIGINT UNSIGNED NOT NULL COMMENT '下载日志ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件逻辑ID', - user_id BIGINT UNSIGNED NULL COMMENT '下载用户ID', - request_id VARCHAR(64) NULL COMMENT '请求ID', - client_ip VARCHAR(64) NULL COMMENT '客户端IP', - result VARCHAR(16) NOT NULL COMMENT '下载结果', - failure_reason VARCHAR(500) NULL COMMENT '失败原因', - downloaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '下载时间', - PRIMARY KEY (id), - KEY idx_download_log_file (tenant_id, file_id, downloaded_at), - KEY idx_download_log_user (tenant_id, user_id, downloaded_at) -) ENGINE=InnoDB COMMENT='文件下载审计日志表'; - - --- ============================================================================ --- Firstleg 二期最终基线表 --- 来源:firstleg/src/main/resources/db/phase2-inbound-schema.sql --- ============================================================================ -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_firstleg - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_firstleg; - -CREATE TABLE IF NOT EXISTS fl_inbound_order ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - task_id BIGINT UNSIGNED NULL COMMENT '头程履约任务ID', - order_id BIGINT UNSIGNED NOT NULL COMMENT '订单服务订单ID,不建立跨库外键', - order_no VARCHAR(32) NOT NULL COMMENT '订单号快照', - inbound_code VARCHAR(40) NOT NULL COMMENT '租户内唯一入仓码', - process_status VARCHAR(24) NOT NULL DEFAULT 'WAIT_MEASURE' COMMENT '入库流程状态', - order_status_snapshot VARCHAR(24) NOT NULL COMMENT '订单状态快照', - measure_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '测量数据审核状态', - fee_status VARCHAR(24) NOT NULL DEFAULT 'UNPRICED' COMMENT '费用业务状态', - fee_review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - notification_status VARCHAR(24) NOT NULL DEFAULT 'NOT_CREATED' COMMENT '客户通知状态', - expected_arrival_at DATETIME(3) NULL COMMENT '预计到达时间', - customer_id BIGINT UNSIGNED NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - company_id BIGINT UNSIGNED NULL COMMENT '运营公司逻辑ID', - company_name VARCHAR(128) NULL COMMENT '运营公司名称快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '实际作业仓库ID', - warehouse_name VARCHAR(128) NOT NULL COMMENT '实际作业仓库名称快照', - delivery_warehouse_id BIGINT UNSIGNED NULL COMMENT '交货仓逻辑ID', - delivery_warehouse_name VARCHAR(128) NULL COMMENT '交货仓名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - channel_name VARCHAR(128) NULL COMMENT '渠道名称快照', - carrier_id BIGINT UNSIGNED NULL COMMENT '计费船司逻辑ID', - carrier_name VARCHAR(128) NULL COMMENT '计费船司名称快照', - tax_mode VARCHAR(24) NULL COMMENT '买单或退税模式', - container_mode VARCHAR(24) NULL COMMENT '整柜或散货模式', - customs_inspection TINYINT(1) NULL COMMENT '是否商检', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_warehouse_id BIGINT UNSIGNED NULL COMMENT '目的仓逻辑ID', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码,例如FBA仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称快照', - hold_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '当前是否扣货', - current_hold_reason VARCHAR(500) 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', - actual_volume_cbm DECIMAL(18,4) NULL COMMENT '确认后的实际总体积m3', - chargeable_volume_cbm DECIMAL(18,4) NULL COMMENT '当前费用快照的计费体积m3', - pallet_count INT UNSIGNED NULL COMMENT '已分配总托盘数快照', - volume_weight_kg DECIMAL(18,3) NULL COMMENT '总材积重kg', - actual_net_weight_kg DECIMAL(18,3) NULL COMMENT '总净重kg', - measure_completed_at DATETIME(3) NULL COMMENT '测量完成时间', - inbounded_at DATETIME(3) NULL COMMENT '入库完成时间', - express_company_code VARCHAR(64) NULL COMMENT '快递公司编码快照', - express_company_name VARCHAR(128) NULL COMMENT '快递公司名称快照', - express_tracking_no VARCHAR(128) NULL COMMENT '快递单号快照', - public_remark VARCHAR(1000) NULL COMMENT '客户可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - 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), - UNIQUE KEY uk_inbound_tenant_code (tenant_id, inbound_code), - UNIQUE KEY uk_inbound_tenant_order (tenant_id, order_id), - KEY idx_inbound_process_time (tenant_id, process_status, created_at, id), - KEY idx_inbound_measure_time (tenant_id, measure_review_status, created_at, id), - KEY idx_inbound_fee_time (tenant_id, fee_review_status, created_at, id), - KEY idx_inbound_warehouse_status (tenant_id, warehouse_id, process_status, created_at), - KEY idx_inbound_customer_time (tenant_id, customer_id, created_at), - KEY idx_inbound_company_time (tenant_id, company_id, created_at), - KEY idx_inbound_arrival (tenant_id, expected_arrival_at), - KEY idx_inbound_destination (tenant_id, destination_code, created_at), - KEY idx_inbound_channel (tenant_id, channel_code, created_at), - CONSTRAINT fk_inbound_task FOREIGN KEY (task_id) REFERENCES fl_fulfillment_task (id) -) ENGINE=InnoDB COMMENT='二期头程入库单聚合根和列表查询快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pickup_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '提货信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - pickup_method VARCHAR(24) NULL COMMENT '提货方式', - pickup_at DATETIME(3) NULL COMMENT '提货时间', - contact_name VARCHAR(64) NULL COMMENT '提货联系人', - contact_phone VARCHAR(32) NULL COMMENT '提货联系人电话', - contact_email VARCHAR(128) NULL COMMENT '提货联系人邮箱', - country_code CHAR(2) NULL COMMENT '国家二字码', - province VARCHAR(64) NULL COMMENT '省或州', - city VARCHAR(64) NULL COMMENT '城市', - district VARCHAR(64) NULL COMMENT '区县', - address_line VARCHAR(512) NULL COMMENT '提货详细地址', - postal_code VARCHAR(20) NULL COMMENT '提货邮编', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_pickup_inbound (tenant_id, inbound_id), - CONSTRAINT fk_pickup_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单提货信息不可变快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_destination_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '目的仓地址快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - destination_type VARCHAR(24) NULL COMMENT '目的仓类型', - destination_code VARCHAR(32) NULL COMMENT '目的仓编码', - destination_name VARCHAR(128) NULL COMMENT '目的仓名称', - country_code CHAR(2) NULL COMMENT '国家二字码', - state_province VARCHAR(100) NULL COMMENT '省或州', - city VARCHAR(100) NULL COMMENT '城市', - address_line VARCHAR(512) NULL COMMENT '详细地址', - postal_code VARCHAR(20) NULL COMMENT '邮编', - contact_name VARCHAR(64) NULL COMMENT '联系人', - contact_phone VARCHAR(32) NULL COMMENT '联系人电话', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_destination_inbound (tenant_id, inbound_id), - CONSTRAINT fk_destination_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单目的仓地址和联系人快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_transport_snapshot ( - id BIGINT UNSIGNED NOT NULL COMMENT '运输信息快照ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - loading_status VARCHAR(24) NULL COMMENT '配载状态快照', - container_no VARCHAR(64) NULL COMMENT '集装箱号', - cabinet_no VARCHAR(64) NULL COMMENT '柜号或内部柜单号', - vessel_name VARCHAR(128) NULL COMMENT '船名', - voyage_no VARCHAR(64) NULL COMMENT '航次', - sailing_at DATETIME(3) NULL COMMENT '开船时间', - port_arrival_at DATETIME(3) NULL COMMENT '到港时间', - source_updated_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_transport_inbound (tenant_id, inbound_id), - KEY idx_transport_container (tenant_id, container_no), - KEY idx_transport_cabinet (tenant_id, cabinet_no), - KEY idx_transport_loading (tenant_id, loading_status, sailing_at), - CONSTRAINT fk_transport_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单关联运输信息只读快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - source_type VARCHAR(24) NOT NULL COMMENT '数据来源:THIRD_PARTY或MANUAL', - source_code VARCHAR(64) NULL COMMENT '第三方应用或来源编码', - external_event_no VARCHAR(128) NULL COMMENT '第三方事件号', - device_code VARCHAR(64) NULL COMMENT '测量设备编码', - warehouse_code VARCHAR(50) NULL COMMENT '第三方回传仓库编码', - measured_at DATETIME(3) NULL COMMENT '设备测量时间', - status VARCHAR(24) NOT NULL DEFAULT 'RECEIVED' COMMENT '测量批次状态', - raw_payload_json JSON NULL COMMENT '第三方原始报文', - original_document_no VARCHAR(64) NULL COMMENT '原单据号码快照', - original_gross_weight_kg DECIMAL(18,3) NULL COMMENT '原单据毛重kg', - original_volume_cbm DECIMAL(18,4) NULL COMMENT '原单据体积或材积m3', - actual_goods_name VARCHAR(255) NULL COMMENT '实际品名', - total_package_count INT UNSIGNED NULL COMMENT '本批次总箱数', - total_volume_raw_cbm DECIMAL(18,6) NULL COMMENT '本批次原始总体积m3', - total_volume_cbm DECIMAL(18,4) NULL COMMENT '本批次业务总体积m3', - volume_weight_kg DECIMAL(18,3) NULL COMMENT '本批次总材积重kg', - created_by BIGINT UNSIGNED NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_external_event (tenant_id, source_code, external_event_no), - KEY idx_measure_inbound_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_measure_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库长宽高测量批次和第三方原始数据'; - -CREATE TABLE IF NOT EXISTS fl_inbound_measurement_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - measurement_id BIGINT UNSIGNED NOT NULL COMMENT '测量批次ID', - item_no VARCHAR(32) NOT NULL COMMENT '批次内明细号', - box_specification VARCHAR(64) NOT NULL COMMENT '箱规标识', - package_count INT UNSIGNED NOT NULL COMMENT '相同箱规箱数', - length_cm DECIMAL(12,3) NOT NULL COMMENT '原始长度cm', - width_cm DECIMAL(12,3) NOT NULL COMMENT '原始宽度cm', - height_cm DECIMAL(12,3) NOT NULL COMMENT '原始高度cm', - girth_cm DECIMAL(12,3) NOT NULL COMMENT '周长cm,规则为长+2*(宽+高)', - unit_weight_kg DECIMAL(18,3) NULL COMMENT '单箱重量kg,第三方仅回传尺寸时可为空', - unit_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '单箱业务体积m3', - volume_raw_cbm DECIMAL(18,6) NOT NULL COMMENT '原始体积m3', - volume_cbm DECIMAL(18,4) NOT NULL COMMENT '业务体积m3', - total_weight_kg DECIMAL(18,3) NULL COMMENT '本箱规总重量kg', - total_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '本箱规总体积m3', - volume_weight_kg DECIMAL(18,3) NOT NULL COMMENT '本箱规材积重kg', - calculation_rule_version VARCHAR(32) NOT NULL COMMENT '体积计算和舍入规则版本', - source_image_file_id BIGINT UNSIGNED NULL COMMENT '测量设备图片文件ID', - over_limit_warning VARCHAR(500) NULL COMMENT '超线提醒快照', - outer_length_cm DECIMAL(12,3) NULL COMMENT '外箱规长度cm', - outer_width_cm DECIMAL(12,3) NULL COMMENT '外箱规宽度cm', - outer_height_cm DECIMAL(12,3) NULL COMMENT '外箱规高度cm', - remark VARCHAR(500) NULL COMMENT '测量明细备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_measure_item_no (tenant_id, measurement_id, item_no), - CONSTRAINT fk_measure_item_batch FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='入库长宽高和箱数测量明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_result ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '称重图片文件ID', - ocr_provider VARCHAR(64) NULL COMMENT 'OCR服务商编码', - ocr_raw_text VARCHAR(1000) NULL COMMENT 'OCR原始文本', - ocr_weight_value DECIMAL(18,3) NULL COMMENT 'OCR识别原始重量值', - ocr_weight_unit VARCHAR(8) NULL COMMENT 'OCR识别原始单位', - confidence DECIMAL(6,5) NULL COMMENT '识别置信度', - adjusted_weight_value DECIMAL(18,3) NULL COMMENT '人工修正后的原单位重量', - adjusted_weight_unit VARCHAR(8) NULL COMMENT '人工修正后的单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认并统一换算后的重量kg', - recognition_status VARCHAR(24) NOT NULL DEFAULT 'PENDING' COMMENT '识别和确认状态', - adjustment_reason VARCHAR(500) NULL COMMENT '人工修正原因', - adjusted_by BIGINT UNSIGNED NULL COMMENT '修正人ID', - adjusted_at DATETIME(3) NULL COMMENT '修正时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_at DATETIME(3) NULL COMMENT '确认时间', - created_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0 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_weight_inbound_file (tenant_id, inbound_id, file_id), - KEY idx_weight_inbound_status (tenant_id, inbound_id, recognition_status), - CONSTRAINT fk_weight_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='称重图片OCR原值、人工修正值和确认重量'; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_revision ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量修订记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - weight_result_id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - revision_no INT UNSIGNED NOT NULL COMMENT '结果版本号,与乐观锁版本一致', - action VARCHAR(24) NOT NULL COMMENT '动作:CORRECT或CONFIRM', - before_weight_value DECIMAL(18,3) NULL COMMENT '变更前原单位重量', - before_weight_unit VARCHAR(8) NULL COMMENT '变更前单位', - after_weight_value DECIMAL(18,3) NULL COMMENT '变更后原单位重量', - after_weight_unit VARCHAR(8) NULL COMMENT '变更后单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认时统一换算后的重量kg', - reason VARCHAR(500) NULL COMMENT '人工修正原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - UNIQUE KEY uk_weight_revision_no (tenant_id, weight_result_id, revision_no), - KEY idx_weight_revision_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_weight_revision_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_weight_revision_result FOREIGN KEY (weight_result_id) REFERENCES fl_inbound_weight_result (id) -) ENGINE=InnoDB COMMENT='OCR重量人工修正和确认的不可变版本历史'; - -CREATE TABLE IF NOT EXISTS fl_measure_review_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '测量审核记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - measurement_id BIGINT UNSIGNED NULL COMMENT '被审核的测量批次ID', - review_result VARCHAR(24) NOT NULL COMMENT '审核结果', - review_reason VARCHAR(1000) NULL COMMENT '审核或驳回原因', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否异常放行', - release_reason VARCHAR(1000) NULL COMMENT '异常放行原因', - allow_rejected_config TINYINT(1) NOT NULL DEFAULT 0 COMMENT '操作时Nacos异常放行开关值', - reviewer_id BIGINT UNSIGNED NOT NULL COMMENT '审核人ID', - reviewer_name VARCHAR(64) NULL COMMENT '审核人名称快照', - reviewed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '审核时间', - PRIMARY KEY (id), - KEY idx_review_inbound_time (tenant_id, inbound_id, reviewed_at), - KEY idx_review_exception_release (tenant_id, inbound_id, exception_release, reviewed_at), - CONSTRAINT fk_review_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_review_measurement FOREIGN KEY (measurement_id) REFERENCES fl_inbound_measurement (id) -) ENGINE=InnoDB COMMENT='测量审核、驳回和异常放行不可变记录'; - -CREATE TABLE IF NOT EXISTS fl_customer_charge_rule ( - id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rule_code VARCHAR(50) NOT NULL COMMENT '租户内规则编码', - rule_version INT UNSIGNED NOT NULL COMMENT '规则版本号', - customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户逻辑ID', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - tax_mode VARCHAR(24) NULL COMMENT '包税或不包税类型', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '重量体积换算系数', - rounding_scale TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '结果保留小数位数', - rounding_mode VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式', - currency CHAR(3) NOT NULL COMMENT '默认币种', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '规则状态', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_charge_rule_version (tenant_id, rule_code, rule_version), - KEY idx_charge_rule_match (tenant_id, customer_id, business_type, status, effective_from, effective_to) -) ENGINE=InnoDB COMMENT='客户头程计费规则版本'; - -CREATE TABLE IF NOT EXISTS fl_carrier_fba_rate ( - id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - rate_code VARCHAR(50) NOT NULL COMMENT '租户内价格编码', - rate_version INT UNSIGNED NOT NULL COMMENT '价格版本号', - origin_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '起运仓逻辑ID', - origin_warehouse_name VARCHAR(128) NOT NULL COMMENT '起运仓名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务或计费类型', - channel_code VARCHAR(64) NULL COMMENT '渠道编码', - carrier_id BIGINT UNSIGNED NULL COMMENT '船司逻辑ID', - carrier_name VARCHAR(128) NOT NULL COMMENT '船司名称快照', - destination_code VARCHAR(32) NOT NULL COMMENT 'FBA目的仓编码', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位:KG或CBM', - unit_price DECIMAL(18,6) NOT NULL COMMENT '基础单价', - currency CHAR(3) NOT NULL COMMENT '币种', - additional_fee DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '固定附加费', - effective_from DATETIME(3) NOT NULL COMMENT '生效开始时间', - effective_to DATETIME(3) NULL COMMENT '生效结束时间', - status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '价格状态', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_fba_rate_version (tenant_id, rate_code, rate_version), - KEY idx_fba_rate_match (tenant_id, origin_warehouse_id, business_type, channel_code, carrier_id, destination_code, charge_unit, status, effective_from, effective_to) -) ENGINE=InnoDB COMMENT='船司FBA目的仓价格版本'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库费用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - fee_no VARCHAR(40) NOT NULL COMMENT '租户内唯一费用单号', - fee_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '费用快照版本', - charge_rule_id BIGINT UNSIGNED NOT NULL COMMENT '客户计费规则ID', - charge_rule_version INT UNSIGNED NOT NULL COMMENT '客户规则版本快照', - carrier_rate_id BIGINT UNSIGNED NOT NULL COMMENT '船司FBA价格ID', - carrier_rate_version INT UNSIGNED NOT NULL COMMENT '船司价格版本快照', - rule_code VARCHAR(50) NOT NULL COMMENT '客户规则编码快照', - customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID快照', - customer_name VARCHAR(128) NOT NULL COMMENT '客户名称快照', - business_type VARCHAR(32) NOT NULL COMMENT '业务类型快照', - tax_mode VARCHAR(24) NULL COMMENT '包税模式快照', - rounding_scale TINYINT UNSIGNED NOT NULL COMMENT '计费量保留位数快照', - rounding_mode VARCHAR(24) NOT NULL COMMENT '舍入方式快照', - rule_effective_from DATETIME(3) NOT NULL COMMENT '客户规则生效开始快照', - rule_effective_to DATETIME(3) NULL COMMENT '客户规则生效结束快照', - rate_code VARCHAR(50) NOT NULL COMMENT '船司价格编码快照', - origin_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '起运仓ID快照', - origin_warehouse_name VARCHAR(128) NOT NULL COMMENT '起运仓名称快照', - channel_code VARCHAR(64) NOT NULL COMMENT '渠道编码快照', - carrier_id BIGINT UNSIGNED NOT NULL COMMENT '船司ID快照', - carrier_name VARCHAR(128) NOT NULL COMMENT '船司名称快照', - destination_code VARCHAR(32) NOT NULL COMMENT 'FBA仓编码快照', - rate_effective_from DATETIME(3) NOT NULL COMMENT '价格生效开始快照', - rate_effective_to DATETIME(3) NULL COMMENT '价格生效结束快照', - charge_mode VARCHAR(16) NOT NULL COMMENT '计费口径:KG或CBM', - conversion_factor DECIMAL(18,6) NOT NULL COMMENT '使用的换算系数快照', - actual_weight_kg DECIMAL(18,3) NOT NULL COMMENT '试算时实际重量kg', - actual_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '试算时实际体积m3', - converted_quantity DECIMAL(18,4) NOT NULL COMMENT '换算后的重量或体积', - chargeable_quantity DECIMAL(18,4) NOT NULL COMMENT '最终计费量', - charge_unit VARCHAR(16) NOT NULL COMMENT '计费单位', - currency CHAR(3) NOT NULL COMMENT '币种', - subtotal_amount DECIMAL(18,2) NOT NULL COMMENT '基础费用金额', - additional_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '附加费金额', - total_amount DECIMAL(18,2) NOT NULL COMMENT '总金额', - fee_status VARCHAR(24) NOT NULL DEFAULT 'CALCULATED' COMMENT '费用状态', - review_status VARCHAR(24) NOT NULL DEFAULT 'NOT_SUBMITTED' COMMENT '费用审核状态', - exception_release TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否基于测量异常放行生成', - calculated_by BIGINT UNSIGNED NOT NULL COMMENT '试算人ID', - calculated_at DATETIME(3) NOT NULL COMMENT '试算时间', - confirmed_by BIGINT UNSIGNED NULL COMMENT '确认人ID', - confirmed_at DATETIME(3) NULL COMMENT '确认时间', - sent_by BIGINT UNSIGNED NULL COMMENT '发送人ID', - sent_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_inbound_fee_no (tenant_id, fee_no), - UNIQUE KEY uk_inbound_fee_version (tenant_id, inbound_id, fee_version), - KEY idx_inbound_fee_status (tenant_id, inbound_id, fee_status, review_status), - CONSTRAINT fk_fee_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_fee_charge_rule FOREIGN KEY (charge_rule_id) REFERENCES fl_customer_charge_rule (id), - CONSTRAINT fk_fee_carrier_rate FOREIGN KEY (carrier_rate_id) REFERENCES fl_carrier_fba_rate (id) -) ENGINE=InnoDB COMMENT='入库头程费用计算和确认快照'; - -CREATE TABLE IF NOT EXISTS fl_inbound_fee_item ( - id BIGINT UNSIGNED NOT NULL COMMENT '费用明细ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - fee_id BIGINT UNSIGNED NOT NULL COMMENT '费用头ID', - item_no INT UNSIGNED NOT NULL COMMENT '费用单内序号', - fee_code VARCHAR(50) NOT NULL COMMENT '费用项目编码', - fee_name VARCHAR(128) NOT NULL COMMENT '费用项目名称快照', - quantity DECIMAL(18,4) NOT NULL COMMENT '计费数量', - unit VARCHAR(16) NOT NULL COMMENT '计费单位', - unit_price DECIMAL(18,6) NOT NULL COMMENT '单价', - amount DECIMAL(18,2) NOT NULL COMMENT '金额', - currency CHAR(3) NOT NULL COMMENT '币种', - automatic_flag TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否自动计算', - remark VARCHAR(500) NULL COMMENT '费用备注', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - UNIQUE KEY uk_fee_item_no (tenant_id, fee_id, item_no), - CONSTRAINT fk_fee_item_header FOREIGN KEY (fee_id) REFERENCES fl_inbound_fee (id) -) ENGINE=InnoDB COMMENT='入库头程费用项目明细'; - -CREATE TABLE IF NOT EXISTS fl_inbound_pallet_allocation ( - id BIGINT UNSIGNED NOT NULL COMMENT '头程托盘分配引用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - allocation_no INT UNSIGNED NOT NULL COMMENT '入库单内分配序号', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务仓库ID', - warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓储资源所属租户ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - pallet_capacity_cbm DECIMAL(18,4) NOT NULL COMMENT '托盘可用容积快照', - allocated_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '本托盘分配体积', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - location_id BIGINT UNSIGNED NOT NULL COMMENT '仓库服务库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - reservation_no VARCHAR(64) NOT NULL COMMENT '仓库库位预占单号', - allocation_status VARCHAR(24) NOT NULL DEFAULT 'RESERVED' 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_pallet_allocation_no (tenant_id, inbound_id, allocation_no), - UNIQUE KEY uk_pallet_allocation_pallet (tenant_id, inbound_id, pallet_id), - KEY idx_allocation_location (tenant_id, warehouse_id, location_id, allocation_status), - CONSTRAINT fk_allocation_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='头程侧托盘、库位和仓库预占结果引用'; - -CREATE TABLE IF NOT EXISTS fl_inbound_file ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库单文件关系ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - file_id BIGINT UNSIGNED NOT NULL COMMENT '文件服务文件ID', - file_type VARCHAR(24) NOT NULL COMMENT '文件类型:RELATED、MARK、PC_ORDER、MEASURE或WEIGHT', - file_name_snapshot VARCHAR(255) NOT NULL COMMENT '文件名快照', - visibility VARCHAR(16) NOT NULL DEFAULT 'INTERNAL' COMMENT '可见范围', - file_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '业务文件版本', - uploaded_by BIGINT UNSIGNED NOT NULL COMMENT '上传人ID', - uploaded_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上传时间', - deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', - PRIMARY KEY (id), - UNIQUE KEY uk_inbound_file_relation (tenant_id, inbound_id, file_id, file_type), - KEY idx_inbound_file_type (tenant_id, inbound_id, file_type, deleted), - CONSTRAINT fk_file_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单与文件中心对象的分类关系'; - -CREATE TABLE IF NOT EXISTS fl_inbound_hold_record ( - id BIGINT UNSIGNED NOT NULL COMMENT '扣货记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - hold_action VARCHAR(16) NOT NULL COMMENT '动作:HOLD或RELEASE', - reason VARCHAR(1000) NOT NULL COMMENT '扣货或解除原因', - evidence_file_id BIGINT UNSIGNED NULL COMMENT '证据文件ID', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - KEY idx_hold_inbound_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_hold_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单扣货和解除扣货不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_internal_note ( - id BIGINT UNSIGNED NOT NULL COMMENT '客服内部备注ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - content VARCHAR(2000) NOT NULL COMMENT '仅内部可见备注', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID', - created_by_name VARCHAR(64) NULL COMMENT '创建人名称快照', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_internal_note_time (tenant_id, inbound_id, created_at), - CONSTRAINT fk_internal_note_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单客服内部备注历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_status_history ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库状态历史ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - from_status VARCHAR(24) NULL COMMENT '变更前状态', - to_status VARCHAR(24) NOT NULL COMMENT '变更后状态', - action VARCHAR(32) NOT NULL COMMENT '触发动作', - reason VARCHAR(1000) NULL COMMENT '变更原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - occurred_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '发生时间', - PRIMARY KEY (id), - KEY idx_inbound_history_time (tenant_id, inbound_id, occurred_at), - CONSTRAINT fk_history_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id) -) ENGINE=InnoDB COMMENT='入库单流程状态不可变历史'; - -CREATE TABLE IF NOT EXISTS fl_inbound_outbox ( - id BIGINT UNSIGNED NOT NULL COMMENT '领域事件全局ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '事件所属租户ID', - aggregate_type VARCHAR(32) NOT NULL DEFAULT 'INBOUND' COMMENT '聚合类型', - aggregate_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - event_type VARCHAR(64) NOT NULL COMMENT '事件类型', - payload_json JSON NOT NULL COMMENT '事件负载快照', - publish_status VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '发布状态', - retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数', - next_retry_at DATETIME(3) NULL COMMENT '下次重试时间', - published_at DATETIME(3) NULL COMMENT '发布时间', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - PRIMARY KEY (id), - KEY idx_inbound_outbox_publish (publish_status, next_retry_at, created_at) -) ENGINE=InnoDB COMMENT='入库事务Outbox事件表'; - -CREATE TABLE IF NOT EXISTS fl_inbound_idempotency ( - id BIGINT UNSIGNED NOT NULL COMMENT '入库写操作幂等记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '租户ID', - operation VARCHAR(40) NOT NULL COMMENT '操作类型', - operator_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作者或外部应用ID', - inbound_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '入库单ID,创建前可为0', - idempotency_key VARCHAR(128) NOT NULL COMMENT '幂等键', - request_hash CHAR(64) NOT NULL COMMENT '请求内容摘要', - status VARCHAR(16) NOT NULL COMMENT '处理状态', - result_json JSON NULL COMMENT '成功结果摘要', - result_resource_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_inbound_idempotency (tenant_id, operation, operator_id, idempotency_key), - KEY idx_inbound_idempotency_created (created_at) -) ENGINE=InnoDB COMMENT='第三方测量、审核、费用发送和入库写操作幂等记录'; - - --- ============================================================================ --- Firstleg 称重结果审计字段存量补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-weight-audit-migration.sql --- ============================================================================ -USE baiyue_firstleg; - -SET @has_created_by := ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_weight_result' AND column_name = 'created_by' -); -SET @created_by_sql := IF(@has_created_by = 0, - 'ALTER TABLE fl_inbound_weight_result ADD COLUMN created_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''创建人ID'' AFTER confirmed_at', - 'SELECT 1'); -PREPARE created_by_stmt FROM @created_by_sql; -EXECUTE created_by_stmt; -DEALLOCATE PREPARE created_by_stmt; - -SET @has_updated_by := ( - SELECT COUNT(*) FROM information_schema.columns - WHERE table_schema = DATABASE() AND table_name = 'fl_inbound_weight_result' AND column_name = 'updated_by' -); -SET @updated_by_sql := IF(@has_updated_by = 0, - 'ALTER TABLE fl_inbound_weight_result ADD COLUMN updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT ''最后修改人ID'' AFTER created_at', - 'SELECT 1'); -PREPARE updated_by_stmt FROM @updated_by_sql; -EXECUTE updated_by_stmt; -DEALLOCATE PREPARE updated_by_stmt; - - --- ============================================================================ --- Firstleg 测量与 OCR 存量字段补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-measurement-maintenance.sql --- ============================================================================ --- 二期入库测量与 OCR 维护增量(只增不删,可重复执行)。 --- 执行顺序:phase2-inbound-schema.sql 后执行本文件;已有二期库只需执行本文件。 -SET NAMES utf8mb4; -USE baiyue_firstleg; - -DROP PROCEDURE IF EXISTS phase2_measure_add_column; -DELIMITER $$ -CREATE PROCEDURE phase2_measure_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 @phase2_measure_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE phase2_measure_statement FROM @phase2_measure_sql; - EXECUTE phase2_measure_statement; - DEALLOCATE PREPARE phase2_measure_statement; - END IF; -END$$ -DELIMITER ; - -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_document_no', - 'VARCHAR(64) NULL COMMENT ''原单据号码快照'' AFTER raw_payload_json'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_gross_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''原单据毛重kg'' AFTER original_document_no'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'original_volume_cbm', - 'DECIMAL(18,4) NULL COMMENT ''原单据体积或材积m3'' AFTER original_gross_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'actual_goods_name', - 'VARCHAR(255) NULL COMMENT ''实际品名'' AFTER original_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'volume_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''本批次总材积重kg'' AFTER total_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement', 'version', - 'INT NOT NULL DEFAULT 0 COMMENT ''乐观锁版本号'' AFTER updated_at'); - -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'box_specification', - 'VARCHAR(64) NOT NULL DEFAULT '''' COMMENT ''箱规标识'' AFTER item_no'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'girth_cm', - 'DECIMAL(12,3) NOT NULL DEFAULT 0 COMMENT ''周长cm,规则为长+2*(宽+高)'' AFTER height_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'unit_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''单箱重量kg'' AFTER girth_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'unit_volume_cbm', - 'DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''单箱业务体积m3'' AFTER unit_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'total_weight_kg', - 'DECIMAL(18,3) NULL COMMENT ''本箱规总重量kg'' AFTER volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'total_volume_cbm', - 'DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT ''本箱规总体积m3'' AFTER total_weight_kg'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'volume_weight_kg', - 'DECIMAL(18,3) NOT NULL DEFAULT 0 COMMENT ''本箱规材积重kg'' AFTER total_volume_cbm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'over_limit_warning', - 'VARCHAR(500) NULL COMMENT ''超线提醒快照'' AFTER source_image_file_id'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_length_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规长度cm'' AFTER over_limit_warning'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_width_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规宽度cm'' AFTER outer_length_cm'); -CALL phase2_measure_add_column('fl_inbound_measurement_item', 'outer_height_cm', - 'DECIMAL(12,3) NULL COMMENT ''外箱规高度cm'' AFTER outer_width_cm'); - -DROP PROCEDURE IF EXISTS phase2_measure_add_column; - -CREATE TABLE IF NOT EXISTS fl_inbound_weight_revision ( - id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量修订记录ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', - weight_result_id BIGINT UNSIGNED NOT NULL COMMENT 'OCR重量结果ID', - revision_no INT UNSIGNED NOT NULL COMMENT '结果版本号,与乐观锁版本一致', - action VARCHAR(24) NOT NULL COMMENT '动作:CORRECT或CONFIRM', - before_weight_value DECIMAL(18,3) NULL COMMENT '变更前原单位重量', - before_weight_unit VARCHAR(8) NULL COMMENT '变更前单位', - after_weight_value DECIMAL(18,3) NULL COMMENT '变更后原单位重量', - after_weight_unit VARCHAR(8) NULL COMMENT '变更后单位', - final_weight_kg DECIMAL(18,3) NULL COMMENT '确认时统一换算后的重量kg', - reason VARCHAR(500) NULL COMMENT '人工修正原因', - operator_id BIGINT UNSIGNED NOT NULL COMMENT '操作人ID', - operator_name VARCHAR(64) NULL COMMENT '操作人名称快照', - operated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '操作时间', - PRIMARY KEY (id), - UNIQUE KEY uk_weight_revision_no (tenant_id, weight_result_id, revision_no), - KEY idx_weight_revision_time (tenant_id, inbound_id, operated_at), - CONSTRAINT fk_weight_revision_inbound FOREIGN KEY (inbound_id) REFERENCES fl_inbound_order (id), - CONSTRAINT fk_weight_revision_result FOREIGN KEY (weight_result_id) REFERENCES fl_inbound_weight_result (id) -) ENGINE=InnoDB COMMENT='OCR重量人工修正和确认的不可变版本历史'; - - --- ============================================================================ --- Firstleg 审核工作流索引补齐 --- 来源:firstleg/src/main/resources/db/phase2-inbound-workflow-migration.sql --- ============================================================================ --- 业务块4增量迁移:既有二期库补齐异常放行关口查询索引。 --- 可重复执行;新库仍先执行 phase2-inbound-schema.sql。 -USE baiyue_firstleg; -SET NAMES utf8mb4; - -SET @ddl = IF( - EXISTS(SELECT 1 FROM information_schema.statistics - WHERE table_schema = DATABASE() AND table_name = 'fl_measure_review_record' - AND index_name = 'idx_review_exception_release'), - 'SELECT 1', - 'ALTER TABLE fl_measure_review_record ADD INDEX idx_review_exception_release (tenant_id, inbound_id, exception_release, reviewed_at)' -); -PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; - - --- ============================================================================ --- Firstleg 第三方测量调用日志 --- 来源:firstleg/src/main/resources/db/phase2-measurement-openapi.sql --- ============================================================================ -SET NAMES utf8mb4; -USE baiyue_firstleg; - --- 既有二期数据库增量:先确保 phase2-inbound-schema.sql 中的测量和幂等表已存在。 -CREATE TABLE IF NOT EXISTS fl_third_party_call_log ( - id BIGINT UNSIGNED NOT NULL COMMENT '第三方调用日志ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '识别出的租户ID,未知应用为0', - app_key VARCHAR(128) NULL COMMENT '第三方应用标识', - signature_subject VARCHAR(128) NULL COMMENT '签名主体快照', - request_method VARCHAR(8) NOT NULL COMMENT 'HTTP方法', - request_path VARCHAR(255) NOT NULL COMMENT '签名使用的规范路径', - request_timestamp VARCHAR(32) NULL COMMENT '请求头Unix毫秒时间戳原值', - nonce VARCHAR(128) NULL COMMENT '请求Nonce', - idempotency_key VARCHAR(128) NULL COMMENT 'HTTP幂等键,查询接口为空', - idempotency_anchor TINYINT UNSIGNED NULL COMMENT '签名通过后首个请求为1,重复调用为空', - signature_value VARCHAR(128) NULL COMMENT '第三方签名原值', - request_hash CHAR(64) NOT NULL COMMENT '原始请求体SHA-256小写十六进制', - raw_payload LONGTEXT NOT NULL COMMENT '未经重新序列化的UTF-8原始请求体', - processing_status VARCHAR(16) NOT NULL COMMENT 'PROCESSING、ACCEPTED或REJECTED', - result_code VARCHAR(32) NULL COMMENT '统一响应业务码', - result_message VARCHAR(1000) NULL COMMENT '处理结果或失败原因', - result_json JSON NULL COMMENT '首次成功结果快照', - requested_at DATETIME(3) NOT NULL COMMENT '服务端接收时间', - processed_at DATETIME(3) NULL COMMENT '处理完成时间', - PRIMARY KEY (id), - KEY idx_third_call_app_time (tenant_id, app_key, requested_at), - KEY idx_third_call_idempotency (tenant_id, app_key, idempotency_key), - KEY idx_third_call_nonce (tenant_id, app_key, nonce), - UNIQUE KEY uk_third_call_idempotency_owner (tenant_id, app_key, idempotency_key, idempotency_anchor) -) ENGINE=InnoDB COMMENT='第三方测量开放接口原始请求、签名主体和处理结果留档'; - - --- ============================================================================ --- Firstleg FBA 计费字段与索引补齐 --- 来源:firstleg/src/main/resources/db/phase2-fba-pricing-migration.sql --- ============================================================================ -SET NAMES utf8mb4; -USE baiyue_firstleg; - --- 二期 FBA 计费增量迁移。通过 information_schema 判断,允许重复部署。 -DROP PROCEDURE IF EXISTS phase2_fba_add_column; -DELIMITER $$ -CREATE PROCEDURE phase2_fba_add_column(IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_definition TEXT) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND COLUMN_NAME = p_column - ) THEN - SET @sql = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); - PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - END IF; -END$$ -DELIMITER ; - -CALL phase2_fba_add_column('fl_inbound_order', 'carrier_id', "BIGINT UNSIGNED NULL COMMENT '计费船司逻辑ID' AFTER channel_name"); -CALL phase2_fba_add_column('fl_inbound_order', 'carrier_name', "VARCHAR(128) NULL COMMENT '计费船司名称快照' AFTER carrier_id"); -CALL phase2_fba_add_column('fl_carrier_fba_rate', 'business_type', "VARCHAR(32) NOT NULL DEFAULT 'FBA' COMMENT '业务或计费类型' AFTER origin_warehouse_name"); -CALL phase2_fba_add_column('fl_customer_charge_rule', 'version', "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted"); -CALL phase2_fba_add_column('fl_carrier_fba_rate', 'version', "INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号' AFTER deleted"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_code', "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '客户规则编码快照' AFTER carrier_rate_version"); -CALL phase2_fba_add_column('fl_inbound_fee', 'customer_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID快照' AFTER rule_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'customer_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '客户名称快照' AFTER customer_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'business_type', "VARCHAR(32) NOT NULL DEFAULT '' COMMENT '业务类型快照' AFTER customer_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'tax_mode', "VARCHAR(24) NULL COMMENT '包税模式快照' AFTER business_type"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rounding_scale', "TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT '计费量保留位数快照' AFTER tax_mode"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rounding_mode', "VARCHAR(24) NOT NULL DEFAULT 'CEILING' COMMENT '舍入方式快照' AFTER rounding_scale"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_effective_from', "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '客户规则生效开始快照' AFTER rounding_mode"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rule_effective_to', "DATETIME(3) NULL COMMENT '客户规则生效结束快照' AFTER rule_effective_from"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_code', "VARCHAR(50) NOT NULL DEFAULT '' COMMENT '船司价格编码快照' AFTER rule_effective_to"); -CALL phase2_fba_add_column('fl_inbound_fee', 'origin_warehouse_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '起运仓ID快照' AFTER rate_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'origin_warehouse_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '起运仓名称快照' AFTER origin_warehouse_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'channel_code', "VARCHAR(64) NOT NULL DEFAULT '' COMMENT '渠道编码快照' AFTER origin_warehouse_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'carrier_id', "BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '船司ID快照' AFTER channel_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'carrier_name', "VARCHAR(128) NOT NULL DEFAULT '' COMMENT '船司名称快照' AFTER carrier_id"); -CALL phase2_fba_add_column('fl_inbound_fee', 'destination_code', "VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'FBA仓编码快照' AFTER carrier_name"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_effective_from', "DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '价格生效开始快照' AFTER destination_code"); -CALL phase2_fba_add_column('fl_inbound_fee', 'rate_effective_to', "DATETIME(3) NULL COMMENT '价格生效结束快照' AFTER rate_effective_from"); -CALL phase2_fba_add_column('fl_inbound_idempotency', 'result_resource_id', "BIGINT UNSIGNED NULL COMMENT '成功结果资源ID' AFTER result_json"); -CALL phase2_fba_add_column('fl_inbound_pallet_allocation', 'warehouse_resource_tenant_id', - "BIGINT UNSIGNED NULL COMMENT '仓储资源所属租户ID' AFTER warehouse_id"); - -UPDATE fl_inbound_pallet_allocation -SET warehouse_resource_tenant_id = tenant_id -WHERE warehouse_resource_tenant_id IS NULL OR warehouse_resource_tenant_id = 0; -SET @resource_tenant_nullable = (SELECT IS_NULLABLE FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_inbound_pallet_allocation' - AND COLUMN_NAME = 'warehouse_resource_tenant_id'); -SET @sql = IF(@resource_tenant_nullable = 'YES', - "ALTER TABLE fl_inbound_pallet_allocation MODIFY COLUMN warehouse_resource_tenant_id BIGINT UNSIGNED NOT NULL COMMENT '仓储资源所属租户ID'", - 'SELECT 1'); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -DROP PROCEDURE IF EXISTS phase2_fba_add_column; - --- 旧索引可能缺少业务类型、船司和结束时间;用新索引名并存,避免破坏线上依赖。 -SET @idx_exists = (SELECT COUNT(*) FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_carrier_fba_rate' AND INDEX_NAME = 'idx_fba_rate_unique_match'); -SET @sql = IF(@idx_exists = 0, - 'ALTER TABLE fl_carrier_fba_rate ADD INDEX idx_fba_rate_unique_match (tenant_id, origin_warehouse_id, business_type, channel_code, carrier_id, destination_code, charge_unit, status, effective_from, effective_to)', - 'SELECT 1'); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - - --- ============================================================================ --- Warehouse 二期托盘库位最终基线表 --- 来源:warehouse/src/main/resources/db/phase2-pallet-location-schema.sql --- ============================================================================ --- 二期托盘、库位、预占与占用表结构。 --- 本脚本只新增表、字段、索引和约束,不包含业务数据及流程实现。 --- 可在 warehouse.sql 和一期增量脚本之后执行;所有建表均可重复执行。 -SET NAMES utf8mb4; - -CREATE DATABASE IF NOT EXISTS baiyue_warehouse - DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -USE baiyue_warehouse; - -CREATE TABLE IF NOT EXISTS wh_pallet ( - id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一托盘编码', - pallet_type VARCHAR(32) NOT NULL COMMENT '托盘类型', - pallet_name VARCHAR(100) NULL COMMENT '托盘名称', - capacity_cbm DECIMAL(18,6) NOT NULL COMMENT '托盘可用容积CBM', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT '内部状态:AVAILABLE、RESERVED或OCCUPIED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_pallet_tenant_warehouse_code (tenant_id, warehouse_id, pallet_code), - KEY idx_pallet_available (tenant_id, warehouse_id, status, deleted), - KEY idx_pallet_type (tenant_id, warehouse_id, pallet_type, status, deleted), - CONSTRAINT fk_pallet_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_pallet_capacity CHECK (capacity_cbm > 0) -) ENGINE=InnoDB COMMENT='二期托盘基础资料和物理托盘实例'; - -CREATE TABLE IF NOT EXISTS wh_location ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位ID(雪花ID)', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '所属仓库ID', - zone_code VARCHAR(50) NULL COMMENT '库区编码', - zone_name VARCHAR(100) NULL COMMENT '库区名称', - location_code VARCHAR(50) NOT NULL COMMENT '租户仓库内唯一库位编码', - location_name VARCHAR(100) NULL COMMENT '库位名称', - location_type VARCHAR(32) NOT NULL DEFAULT 'PALLET' COMMENT '库位类型,二期为PALLET', - max_weight_kg DECIMAL(18,3) NULL COMMENT '最大承重展示值,二期不作容量拦截', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否为系统共享溢出位A0', - status VARCHAR(20) NOT NULL DEFAULT 'AVAILABLE' COMMENT 'AVAILABLE、RESERVED、OCCUPIED或DISABLED', - remark VARCHAR(500) NULL 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), - UNIQUE KEY uk_location_tenant_warehouse_code (tenant_id, warehouse_id, location_code), - KEY idx_location_available (tenant_id, warehouse_id, status, deleted), - KEY idx_location_zone (tenant_id, warehouse_id, zone_code, status, deleted), - CONSTRAINT fk_location_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT ck_location_max_weight CHECK (max_weight_kg IS NULL OR max_weight_kg > 0) -) ENGINE=InnoDB COMMENT='二期库位基础资料,默认一托盘对应一个库位且不作容量校验'; - -CREATE TABLE IF NOT EXISTS wh_location_reservation ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位预占ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - reservation_no VARCHAR(40) NOT NULL COMMENT '租户内唯一预占业务号', - idempotency_key VARCHAR(128) NOT NULL COMMENT '调用方幂等键', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否使用共享溢出位A0', - reservation_status VARCHAR(20) NOT NULL DEFAULT 'RESERVED' COMMENT 'RESERVED、CONFIRMED、RELEASED或EXPIRED', - expires_at DATETIME(3) NOT NULL COMMENT '预占过期时间', - confirmed_at DATETIME(3) NULL COMMENT '确认占用时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放或过期原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_reservation TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT '普通库位活动预占唯一标记', - active_pallet_reservation TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' THEN 1 ELSE NULL END) STORED COMMENT '托盘活动预占唯一标记(包含A0)', - PRIMARY KEY (id), - UNIQUE KEY uk_location_reservation_no (tenant_id, reservation_no), - UNIQUE KEY uk_location_reservation_idempotency (tenant_id, source_service, idempotency_key), - UNIQUE KEY uk_location_active_reservation (tenant_id, location_id, active_reservation), - UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation), - KEY idx_location_reservation_business (tenant_id, source_service, business_id, reservation_status), - KEY idx_location_reservation_expire (reservation_status, expires_at), - KEY idx_location_reservation_target (tenant_id, warehouse_id, location_id, reservation_status), - CONSTRAINT fk_reservation_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_reservation_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_reservation_location FOREIGN KEY (location_id) REFERENCES wh_location (id) -) ENGINE=InnoDB COMMENT='跨服务入库Saga的托盘和库位临时预占'; - -CREATE TABLE IF NOT EXISTS wh_location_occupancy ( - id BIGINT UNSIGNED NOT NULL COMMENT '库位占用ID', - tenant_id BIGINT UNSIGNED NOT NULL COMMENT '数据所属租户ID', - occupancy_no VARCHAR(40) NOT NULL COMMENT '租户内唯一占用业务号', - reservation_id BIGINT UNSIGNED NOT NULL COMMENT '来源预占ID', - source_service VARCHAR(40) NOT NULL DEFAULT 'FIRSTLEG' COMMENT '来源服务', - business_id BIGINT UNSIGNED NOT NULL COMMENT '来源服务入库单ID', - inbound_code VARCHAR(40) NOT NULL COMMENT '入仓码快照', - warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID', - pallet_id BIGINT UNSIGNED NOT NULL COMMENT '托盘ID', - pallet_code VARCHAR(50) NOT NULL COMMENT '托盘编码快照', - location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID', - location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照', - shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否使用共享溢出位A0', - allocated_volume_cbm DECIMAL(18,6) NOT NULL COMMENT '本托盘分配体积CBM', - allocated_package_count INT UNSIGNED NULL COMMENT '本托盘分配箱数', - occupancy_status VARCHAR(20) NOT NULL DEFAULT 'OCCUPIED' COMMENT 'OCCUPIED或RELEASED', - occupied_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '占用开始时间', - released_at DATETIME(3) NULL COMMENT '释放时间', - release_reason VARCHAR(500) NULL COMMENT '释放原因', - created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', - version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', - active_location_occupancy TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = 'OCCUPIED' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT '普通库位活动占用唯一标记', - active_pallet_occupancy TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = 'OCCUPIED' THEN 1 ELSE NULL END) STORED COMMENT '托盘活动占用唯一标记(包含A0)', - PRIMARY KEY (id), - UNIQUE KEY uk_location_occupancy_no (tenant_id, occupancy_no), - UNIQUE KEY uk_occupancy_reservation (tenant_id, reservation_id), - UNIQUE KEY uk_location_active_occupancy (tenant_id, location_id, active_location_occupancy), - UNIQUE KEY uk_pallet_active_occupancy (tenant_id, pallet_id, active_pallet_occupancy), - KEY idx_occupancy_business (tenant_id, source_service, business_id, occupancy_status), - KEY idx_occupancy_warehouse (tenant_id, warehouse_id, occupancy_status, occupied_at), - CONSTRAINT fk_occupancy_reservation FOREIGN KEY (reservation_id) REFERENCES wh_location_reservation (id), - CONSTRAINT fk_occupancy_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id), - CONSTRAINT fk_occupancy_pallet FOREIGN KEY (pallet_id) REFERENCES wh_pallet (id), - CONSTRAINT fk_occupancy_location FOREIGN KEY (location_id) REFERENCES wh_location (id), - CONSTRAINT ck_occupancy_volume CHECK (allocated_volume_cbm > 0) -) ENGINE=InnoDB COMMENT='已确认的一托一库位占用事实记录'; - --- 头程入库单属于其他数据库,不建立跨库外键。 - - --- ============================================================================ --- Warehouse 托盘活动预占唯一约束补齐 --- 来源:warehouse/src/main/resources/db/phase2-pallet-location-schema-migration.sql --- ============================================================================ --- 二期托盘、库位表的可重复执行增量迁移。 --- 执行顺序:phase2-pallet-location-schema.sql 之后。 -SET NAMES utf8mb4; -USE baiyue_warehouse; - --- 活动预占必须同时保证“一托一位”;A0 共享只放宽库位,不放宽托盘唯一性。 -SET @schema_name = DATABASE(); -DROP PROCEDURE IF EXISTS add_pallet_reservation_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_pallet_reservation_column_if_missing() -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.columns - WHERE table_schema = DATABASE() - AND table_name = 'wh_location_reservation' - AND column_name = 'active_pallet_reservation' - ) THEN - ALTER TABLE wh_location_reservation - ADD COLUMN active_pallet_reservation TINYINT - GENERATED ALWAYS AS (CASE WHEN reservation_status = 'RESERVED' THEN 1 ELSE NULL END) - STORED COMMENT '托盘活动预占唯一标记(包含A0)'; - END IF; -END$$ -DELIMITER ; -CALL add_pallet_reservation_column_if_missing(); -DROP PROCEDURE IF EXISTS add_pallet_reservation_column_if_missing; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics - WHERE table_schema = @schema_name - AND table_name = 'wh_location_reservation' - AND index_name = 'uk_pallet_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_pallet_active_reservation', - 'SELECT 1'); -PREPARE statement FROM @sql; -EXECUTE statement; -DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics - WHERE table_schema = @schema_name - AND table_name = 'wh_location_reservation' - AND index_name = 'uk_pallet_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation)', - 'SELECT 1'); -PREPARE statement FROM @sql; -EXECUTE statement; -DEALLOCATE PREPARE statement; - - --- ============================================================================ --- Warehouse A0 共享溢出位与最终并发约束 --- 来源:warehouse/src/main/resources/db/phase2-location-overflow-migration.sql --- ============================================================================ --- 二期库位共享溢出位 A0 增量迁移。 --- 执行顺序:phase2-pallet-location-schema.sql、本文件。 --- 普通库位仍保持一托一位;同一租户仓库只有一个 A0,且 A0 可承载多个活动资源。 -SET NAMES utf8mb4; -USE baiyue_warehouse; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_location_overflow_column_if_missing( - 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 @column_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE column_statement FROM @column_sql; - EXECUTE column_statement; - DEALLOCATE PREPARE column_statement; - END IF; -END$$ -DELIMITER ; - -CALL add_location_overflow_column_if_missing( - 'wh_location', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否为系统共享溢出位 A0'' AFTER max_weight_kg' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_reservation', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否使用共享溢出位 A0'' AFTER location_code' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'shared_overflow', - 'TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否使用共享溢出位 A0'' AFTER location_code' -); - --- 兼容迁移前人工或旧流程已创建的 A0,并将资源快照回填一致。 -UPDATE wh_location - SET shared_overflow = 1, - status = 'AVAILABLE' - WHERE location_code = 'A0' AND deleted = 0; - -UPDATE wh_location_reservation r -JOIN wh_location l - ON l.tenant_id = r.tenant_id AND l.id = r.location_id - SET r.shared_overflow = l.shared_overflow; - -UPDATE wh_location_occupancy o -JOIN wh_location l - ON l.tenant_id = o.tenant_id AND l.id = o.location_id - SET o.shared_overflow = l.shared_overflow; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; - --- 先移除依赖旧生成列的唯一索引,再按普通库位/A0 的不同语义重建。 -SET @schema_name = DATABASE(); -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_location_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_location_active_reservation', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_pallet_active_reservation') > 0, - 'ALTER TABLE wh_location_reservation DROP INDEX uk_pallet_active_reservation', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -ALTER TABLE wh_location_reservation - MODIFY COLUMN active_reservation TINYINT - GENERATED ALWAYS AS ( - CASE WHEN reservation_status = 'RESERVED' AND shared_overflow = 0 THEN 1 ELSE NULL END - ) STORED COMMENT '普通库位活动预占唯一标记,A0 返回 NULL'; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_location_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_location_active_reservation (tenant_id, location_id, active_reservation)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_location_active_occupancy') > 0, - 'ALTER TABLE wh_location_occupancy DROP INDEX uk_location_active_occupancy', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_pallet_active_occupancy') > 0, - 'ALTER TABLE wh_location_occupancy DROP INDEX uk_pallet_active_occupancy', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; -DELIMITER $$ -CREATE PROCEDURE add_location_overflow_column_if_missing( - 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 @column_sql = CONCAT( - 'ALTER TABLE `', REPLACE(p_table_name, '`', '``'), - '` ADD COLUMN `', REPLACE(p_column_name, '`', '``'), '` ', p_column_definition - ); - PREPARE column_statement FROM @column_sql; - EXECUTE column_statement; - DEALLOCATE PREPARE column_statement; - END IF; -END$$ -DELIMITER ; - -CALL add_location_overflow_column_if_missing( - 'wh_location_reservation', 'active_pallet_reservation', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN reservation_status = ''RESERVED'' THEN 1 ELSE NULL END) STORED COMMENT ''托盘活动预占唯一标记(包含 A0)''' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'active_location_occupancy', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = ''OCCUPIED'' AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED COMMENT ''普通库位活动占用唯一标记''' -); -CALL add_location_overflow_column_if_missing( - 'wh_location_occupancy', 'active_pallet_occupancy', - 'TINYINT GENERATED ALWAYS AS (CASE WHEN occupancy_status = ''OCCUPIED'' THEN 1 ELSE NULL END) STORED COMMENT ''托盘活动占用唯一标记(包含 A0)''' -); -DROP PROCEDURE IF EXISTS add_location_overflow_column_if_missing; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_reservation' AND index_name = 'uk_pallet_active_reservation') = 0, - 'ALTER TABLE wh_location_reservation ADD UNIQUE KEY uk_pallet_active_reservation (tenant_id, pallet_id, active_pallet_reservation)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_location_active_occupancy') = 0, - 'ALTER TABLE wh_location_occupancy ADD UNIQUE KEY uk_location_active_occupancy (tenant_id, location_id, active_location_occupancy)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; -SET @sql = IF((SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = @schema_name AND table_name = 'wh_location_occupancy' AND index_name = 'uk_pallet_active_occupancy') = 0, - 'ALTER TABLE wh_location_occupancy ADD UNIQUE KEY uk_pallet_active_occupancy (tenant_id, pallet_id, active_pallet_occupancy)', 'SELECT 1'); -PREPARE statement FROM @sql; EXECUTE statement; DEALLOCATE PREPARE statement; - - --- 第三方单条箱规 + 单张图片绑定增量。 -USE baiyue_firstleg; -DROP PROCEDURE IF EXISTS phase2_add_measurement_column; -DELIMITER $$ -CREATE PROCEDURE phase2_add_measurement_column( - IN p_table VARCHAR(64), IN p_column VARCHAR(64), IN p_definition TEXT) -BEGIN - IF NOT EXISTS ( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table AND COLUMN_NAME = p_column - ) THEN - SET @ddl = CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_definition); - PREPARE statement FROM @ddl; - EXECUTE statement; - DEALLOCATE PREPARE statement; - END IF; -END$$ -DELIMITER ; -CALL phase2_add_measurement_column('fl_inbound_measurement', 'external_request_hash', - 'CHAR(64) NULL COMMENT ''第三方data原文和图片内容联合请求哈希'' AFTER external_event_no'); -CALL phase2_add_measurement_column('fl_inbound_measurement_item', 'inbound_detail_id', - 'BIGINT UNSIGNED NULL COMMENT ''绑定的订单货物明细ID,平台手工明细可为空'' AFTER measurement_id'); -CALL phase2_add_measurement_column('fl_inbound_measurement_item', 'external_detail_no', - 'VARCHAR(128) NULL COMMENT ''第三方测量明细唯一号,平台手工明细可为空'' AFTER inbound_detail_id'); -DROP PROCEDURE IF EXISTS phase2_add_measurement_column; -SET @has_index = (SELECT COUNT(*) FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'fl_inbound_measurement_item' - AND INDEX_NAME = 'uk_measure_external_detail'); -SET @ddl = IF(@has_index = 0, - 'ALTER TABLE fl_inbound_measurement_item ADD UNIQUE KEY uk_measure_external_detail (tenant_id, inbound_detail_id, external_detail_no)', - 'SELECT 1'); -PREPARE statement FROM @ddl; EXECUTE statement; DEALLOCATE PREPARE statement; - --- 结构核对:只读输出,不写业务数据。 -SELECT 'firstleg 二期核心表数量' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 21, 'PASS', 'FAIL') AS check_result -FROM information_schema.tables -WHERE table_schema = 'baiyue_firstleg' - AND table_name IN ( - 'fl_inbound_order', 'fl_inbound_pickup_snapshot', 'fl_inbound_destination_snapshot', - 'fl_inbound_transport_snapshot', 'fl_inbound_measurement', 'fl_inbound_measurement_item', - 'fl_inbound_weight_result', 'fl_inbound_weight_revision', 'fl_measure_review_record', - 'fl_customer_charge_rule', 'fl_carrier_fba_rate', 'fl_inbound_fee', 'fl_inbound_fee_item', - 'fl_inbound_pallet_allocation', 'fl_inbound_file', 'fl_inbound_hold_record', - 'fl_inbound_internal_note', 'fl_inbound_status_history', 'fl_inbound_outbox', - 'fl_inbound_idempotency', 'fl_third_party_call_log' - ) -UNION ALL -SELECT 'warehouse 二期核心表数量', - COUNT(*), - IF(COUNT(*) = 4, 'PASS', 'FAIL') -FROM information_schema.tables -WHERE table_schema = 'baiyue_warehouse' - AND table_name IN ('wh_pallet', 'wh_location', 'wh_location_reservation', 'wh_location_occupancy') -UNION ALL -SELECT 'file 图片依赖表数量', - COUNT(*), - IF(COUNT(*) = 3, 'PASS', 'FAIL') -FROM information_schema.tables -WHERE table_schema = 'baiyue_file' - AND table_name IN ('file_object', 'file_download_token', 'file_download_log'); - -SELECT 'A0 共享溢出与活动占用关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 6, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location' AND column_name = 'shared_overflow') - OR (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location_reservation' - AND column_name IN ('shared_overflow', 'active_reservation', 'active_pallet_reservation')) - OR (table_schema = 'baiyue_warehouse' AND table_name = 'wh_location_occupancy' - AND column_name IN ('shared_overflow', 'active_location_occupancy', 'active_pallet_occupancy')); - -SELECT 'A0 共享溢出与活动占用关键唯一索引' AS check_item, - COUNT(DISTINCT CONCAT(table_schema, '.', table_name, '.', index_name)) AS actual_value, - IF(COUNT(DISTINCT CONCAT(table_schema, '.', table_name, '.', index_name)) = 4, 'PASS', 'FAIL') AS check_result -FROM information_schema.statistics -WHERE table_schema = 'baiyue_warehouse' - AND ( - (table_name = 'wh_location_reservation' AND index_name IN ('uk_location_active_reservation', 'uk_pallet_active_reservation')) - OR (table_name = 'wh_location_occupancy' AND index_name IN ('uk_location_active_occupancy', 'uk_pallet_active_occupancy')) - ); - -SELECT '第三方单条测量绑定关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 3, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_firstleg' - AND ((table_name = 'fl_inbound_measurement' AND column_name = 'external_request_hash') - OR (table_name = 'fl_inbound_measurement_item' - AND column_name IN ('inbound_detail_id', 'external_detail_no'))); - -SELECT '第三方单条测量绑定唯一索引' AS check_item, - COUNT(DISTINCT index_name) AS actual_value, - IF(COUNT(DISTINCT index_name) = 1, 'PASS', 'FAIL') AS check_result -FROM information_schema.statistics -WHERE table_schema = 'baiyue_firstleg' - AND table_name = 'fl_inbound_measurement_item' - AND index_name = 'uk_measure_external_detail'; - -SELECT '称重结果审计关键列' AS check_item, - COUNT(*) AS actual_value, - IF(COUNT(*) = 2, 'PASS', 'FAIL') AS check_result -FROM information_schema.columns -WHERE table_schema = 'baiyue_firstleg' - AND table_name = 'fl_inbound_weight_result' - AND column_name IN ('created_by', 'updated_by'); - -SELECT '二期入库新增表与字段脚本执行完成,请确认以上检查全部为 PASS' AS execution_message;