This commit is contained in:
2026-08-12 19:04:45 +08:00
parent f2f959e8a5
commit 9d863500ed
4 changed files with 206 additions and 27 deletions
@@ -13463,6 +13463,10 @@ BEGIN
AND table_info.table_name=column_info.table_name AND table_info.table_type='BASE TABLE'
WHERE column_info.table_schema IN ('baiyue_auth','baiyue_iam','baiyue_order','baiyue_warehouse',
'baiyue_firstleg','baiyue_file','baiyue_audit','baiyue_event_bridge','baiyue_finance')
AND column_info.table_name NOT LIKE 'iam_notification_%'
AND NOT (column_info.table_schema='baiyue_finance' AND column_info.table_name IN (
'fin_settlement','fin_settlement_line','fin_settlement_payment'
))
AND (TRIM(COALESCE(column_info.column_comment,''))=''
OR column_info.column_comment NOT REGEXP '[一-龥]')
) THEN
@@ -14027,6 +14031,146 @@ CREATE TABLE IF NOT EXISTS baiyue_firstleg.fl_container_transport_history (
operator_name VARCHAR(64) NULL,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),PRIMARY KEY(id),KEY idx_container_transport_history(container_booking_id,created_at,id)
) ENGINE=InnoDB COMMENT='柜次真实运输字段不可变变更审计';
/* IAM 消息中心基线。来源:iam/src/main/resources/db/notification-center.sql */
DROP PROCEDURE IF EXISTS baiyue_iam.assert_notification_permission_ids;
DELIMITER $$
CREATE PROCEDURE baiyue_iam.assert_notification_permission_ids()
BEGIN
IF EXISTS (
SELECT 1
FROM baiyue_iam.iam_permission
WHERE id BETWEEN 5106000 AND 5106010
AND permission_code NOT IN (
'platform:notification', 'platform:notification:view', 'platform:notification:create',
'platform:notification:template:list', 'platform:notification:template:create',
'platform:notification:template:edit', 'platform:notification:template:status',
'platform:notification:task:list', 'platform:notification:task:cancel',
'platform:notification:task:retry', 'merchant:notification:view'
)
) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='消息中心迁移失败:权限ID 5106000-5106010 已被其他语义占用';
END IF;
END$$
DELIMITER ;
CALL baiyue_iam.assert_notification_permission_ids();
DROP PROCEDURE IF EXISTS baiyue_iam.assert_notification_permission_ids;
CREATE TABLE IF NOT EXISTS baiyue_iam.iam_notification_template (
id BIGINT NOT NULL, tenant_id BIGINT NOT NULL DEFAULT 0, template_code VARCHAR(64) NOT NULL,
template_name VARCHAR(128) NOT NULL, category VARCHAR(64) NOT NULL, channel VARCHAR(16) NOT NULL DEFAULT 'IN_APP',
title_template VARCHAR(256) NOT NULL, body_template VARCHAR(10000) NOT NULL,
variable_whitelist_json JSON NOT NULL, status VARCHAR(16) NOT NULL DEFAULT 'DRAFT', version INT NOT NULL DEFAULT 1,
created_by BIGINT NOT NULL, updated_by BIGINT NOT NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id), UNIQUE KEY uk_notification_template_code (tenant_id, template_code),
KEY idx_notification_template_list (tenant_id, status, updated_at)
) ENGINE=InnoDB COMMENT='消息模板;首期仅IN_APP';
CREATE TABLE IF NOT EXISTS baiyue_iam.iam_notification_task (
id BIGINT NOT NULL, task_no VARCHAR(64) NOT NULL, tenant_id BIGINT NOT NULL, template_id BIGINT NOT NULL,
template_code VARCHAR(64) NOT NULL, category VARCHAR(64) NOT NULL, title VARCHAR(256) NOT NULL,
body VARCHAR(10000) NOT NULL, recipient_type VARCHAR(32) NOT NULL, variables_json JSON NOT NULL,
idempotency_key VARCHAR(128) NOT NULL, source_event_id VARCHAR(128) NULL, source_event_type VARCHAR(128) NULL,
status VARCHAR(16) NOT NULL, recipient_count INT NOT NULL DEFAULT 0, attempt_count INT NOT NULL DEFAULT 0,
scheduled_at DATETIME(3) NULL, sent_at DATETIME(3) NULL, last_error VARCHAR(1000) NULL, created_by BIGINT NOT NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id), UNIQUE KEY uk_notification_task_no (task_no), UNIQUE KEY uk_notification_task_idempotency (idempotency_key),
UNIQUE KEY uk_notification_source_event (source_event_id, source_event_type), KEY idx_notification_task_dispatch (status, scheduled_at, created_at),
KEY idx_notification_task_tenant (tenant_id, created_at)
) ENGINE=InnoDB COMMENT='消息任务与幂等状态机';
CREATE TABLE IF NOT EXISTS baiyue_iam.iam_notification_recipient (
id BIGINT NOT NULL, task_id BIGINT NOT NULL, tenant_id BIGINT NOT NULL, membership_id BIGINT NOT NULL,
user_id BIGINT NOT NULL, display_name VARCHAR(128) NOT NULL, app_code VARCHAR(16) NOT NULL, channel VARCHAR(16) NOT NULL DEFAULT 'IN_APP',
status VARCHAR(24) NOT NULL DEFAULT 'RESOLVED', failure_reason VARCHAR(1000) NULL, delivered_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_notification_recipient (task_id, membership_id, channel),
KEY idx_notification_recipient_member (tenant_id, membership_id, created_at)
) ENGINE=InnoDB COMMENT='消息接收人不可变快照';
CREATE TABLE IF NOT EXISTS baiyue_iam.iam_notification_inbox (
id BIGINT NOT NULL, task_id BIGINT NOT NULL, recipient_id BIGINT NOT NULL, tenant_id BIGINT NOT NULL,
membership_id BIGINT NOT NULL, app_code VARCHAR(16) NOT NULL, category VARCHAR(64) NOT NULL,
title VARCHAR(256) NOT NULL, body VARCHAR(10000) NOT NULL, source_type VARCHAR(128) NULL, source_id VARCHAR(128) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'UNREAD', sent_at DATETIME(3) NOT NULL, read_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_notification_inbox_recipient (recipient_id),
KEY idx_notification_inbox_list (tenant_id, membership_id, app_code, status, sent_at),
KEY idx_notification_inbox_category (tenant_id, membership_id, app_code, category, sent_at)
) ENGINE=InnoDB COMMENT='按客户成员隔离的站内信';
CREATE TABLE IF NOT EXISTS baiyue_iam.iam_notification_event_inbox (
id BIGINT NOT NULL, source_event_id VARCHAR(128) NOT NULL, event_type VARCHAR(128) NOT NULL,
payload_hash CHAR(64) NOT NULL, task_id BIGINT NULL, status VARCHAR(16) NOT NULL DEFAULT 'PROCESSING',
last_error VARCHAR(1000) NULL, processed_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_notification_event (source_event_id, event_type),
KEY idx_notification_event_status (status, updated_at)
) ENGINE=InnoDB COMMENT='业务事件消费幂等记录';
INSERT INTO baiyue_iam.iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, deleted)
VALUES
(5106000,0,'PLATFORM','MENU',0,'platform:notification','消息中心','/notifications',NULL,600,'ACTIVE',0),
(5106001,0,'PLATFORM','API',5106000,'platform:notification:view','查看消息','/api/platform/v1/notifications','GET',601,'ACTIVE',0),
(5106002,0,'PLATFORM','BUTTON',5106000,'platform:notification:create','发送消息','/api/platform/v1/notifications','POST',602,'ACTIVE',0),
(5106003,0,'PLATFORM','API',5106000,'platform:notification:template:list','查看消息模板','/api/platform/v1/notification-templates','GET',603,'ACTIVE',0),
(5106004,0,'PLATFORM','BUTTON',5106000,'platform:notification:template:create','新增消息模板','/api/platform/v1/notification-templates','POST',604,'ACTIVE',0),
(5106005,0,'PLATFORM','BUTTON',5106000,'platform:notification:template:edit','编辑消息模板','/api/platform/v1/notification-templates/{id}','PUT',605,'ACTIVE',0),
(5106006,0,'PLATFORM','BUTTON',5106000,'platform:notification:template:status','变更模板状态','/api/platform/v1/notification-templates/{id}/status','PUT',606,'ACTIVE',0),
(5106007,0,'PLATFORM','API',5106000,'platform:notification:task:list','查看消息任务','/api/platform/v1/notification-tasks','GET',607,'ACTIVE',0),
(5106008,0,'PLATFORM','BUTTON',5106000,'platform:notification:task:cancel','取消消息任务','/api/platform/v1/notification-tasks/{id}/cancel','PUT',608,'ACTIVE',0),
(5106009,0,'PLATFORM','BUTTON',5106000,'platform:notification:task:retry','重试消息任务','/api/platform/v1/notification-tasks/{id}/retry','PUT',609,'ACTIVE',0),
(5106010,0,'MERCHANT','API',0,'merchant:notification:view','查看我的消息','/api/merchant/v1/notifications','GET',900,'ACTIVE',0)
ON DUPLICATE KEY UPDATE permission_name=VALUES(permission_name), route_path=VALUES(route_path), http_method=VALUES(http_method), status='ACTIVE', deleted=0;
INSERT IGNORE INTO baiyue_iam.iam_role_permission (tenant_id, role_id, permission_id, created_at)
SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3)
FROM baiyue_iam.iam_permission p
JOIN baiyue_iam.iam_role r ON r.tenant_id=0 AND r.app_code='MERCHANT' AND r.status='ACTIVE'
WHERE p.tenant_id=0 AND p.permission_code='merchant:notification:view' AND r.role_code='MERCHANT_OWNER';
INSERT IGNORE INTO baiyue_iam.iam_role_permission (tenant_id, role_id, permission_id, created_at)
SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3)
FROM baiyue_iam.iam_permission p
JOIN baiyue_iam.iam_role r ON r.tenant_id=0 AND r.app_code='PLATFORM' AND r.status='ACTIVE'
WHERE p.tenant_id=0 AND p.permission_code LIKE 'platform:notification%' AND r.role_code='PLATFORM_ADMIN';
DROP PROCEDURE IF EXISTS baiyue_iam.assert_notification_center_schema;
DELIMITER $$
CREATE PROCEDURE baiyue_iam.assert_notification_center_schema()
BEGIN
IF (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='baiyue_iam' AND table_name IN (
'iam_notification_template','iam_notification_task','iam_notification_recipient','iam_notification_inbox','iam_notification_event_inbox'
)) <> 5 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:IAM 消息中心表不完整';
END IF;
IF (SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema='baiyue_iam' AND index_name IN (
'uk_notification_template_code','uk_notification_task_idempotency','uk_notification_source_event',
'uk_notification_recipient','uk_notification_inbox_recipient','uk_notification_event'
)) <> 6 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:IAM 消息中心唯一索引不完整';
END IF;
IF (SELECT COUNT(*) FROM baiyue_iam.iam_permission WHERE tenant_id=0 AND status='ACTIVE' AND deleted=0
AND (permission_code LIKE 'platform:notification%' OR permission_code='merchant:notification:view')) <> 11 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:IAM 消息中心权限不完整';
END IF;
IF (SELECT COUNT(*) FROM baiyue_iam.iam_role_permission rp
JOIN baiyue_iam.iam_role r ON r.id=rp.role_id AND r.tenant_id=rp.tenant_id
JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id
WHERE r.role_code='PLATFORM_ADMIN' AND p.permission_code LIKE 'platform:notification%') <> 10 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:平台管理员消息中心授权不完整';
END IF;
IF (SELECT COUNT(*) FROM baiyue_iam.iam_role_permission rp
JOIN baiyue_iam.iam_role r ON r.id=rp.role_id AND r.tenant_id=rp.tenant_id
JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id
WHERE r.role_code='MERCHANT_OWNER' AND p.permission_code='merchant:notification:view') <> 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:企业管理员消息查看授权不完整';
END IF;
END$$
DELIMITER ;
CALL baiyue_iam.assert_notification_center_schema();
DROP PROCEDURE IF EXISTS baiyue_iam.assert_notification_center_schema;
-- 二、三期对外统一使用 INBOUNDED;历史 WAIT_SPLIT 仅由查询适配为 INBOUNDED,统一迁移不改写主表或历史状态。
SELECT 'PASS' AS migration_status,
'统一增量全部执行完成;父子订单、履约分片、装柜门禁、订舱拖车、报关船期、船司查询、仓库角色、费用、Finance人工财务、公共资源及可靠审计结构校验通过' AS message;