194 lines
12 KiB
SQL
194 lines
12 KiB
SQL
-- 每日菜谱预约订单过期未核销自动核销。
|
||
-- 幂等迁移脚本:可反复执行。每个字段/索引先查 information_schema,已存在则跳过(执行 SELECT 1 占位),
|
||
-- 不存在才执行 DDL;部分应用过的库重跑不会报 Duplicate column / Duplicate key。
|
||
-- 前置条件:20260822(wallet 配置列、订单列)与 20260823(订单核销时间列)的锚点列需已存在,
|
||
-- 否则对应语句会因 AFTER 锚点缺失报错——这是有意的失败提示,请先补齐前置迁移。
|
||
-- 任务表部分兼容 20260822 任务表语句未成功落库(scene_biz_id 缺失)的环境,会自动补齐。
|
||
-- 权限复用 wallet_mchManage_setting、hard_hardAfterSale_view、hard_hardAfterSale_adminRefund,无需新增 sys_menu 记录。
|
||
|
||
-- 【可选诊断】任务表当前列与索引,执行后可对照确认脚本将补齐的内容。
|
||
SELECT COLUMN_NAME, COLUMN_TYPE, IFNULL(GENERATION_EXPRESSION, '') AS generation
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware'
|
||
AND TABLE_NAME = 'hard_auto_refund_task'
|
||
AND COLUMN_NAME IN ('task_type', 'trigger_time', 'restore_inventory', 'scene_biz_id')
|
||
ORDER BY ORDINAL_POSITION;
|
||
|
||
SELECT INDEX_NAME, GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX SEPARATOR ',') AS index_columns
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware'
|
||
AND TABLE_NAME = 'hard_auto_refund_task'
|
||
GROUP BY INDEX_NAME
|
||
ORDER BY INDEX_NAME;
|
||
|
||
-- 一、Wallet 配置列(三列各自独立判断)。
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_wallet`.`mch_auto_refund_config` ADD COLUMN `auto_verify_enabled` char(1) NOT NULL DEFAULT ''0'' COMMENT ''过期未核销自动核销开关,0关闭,1开启'' AFTER `expired_reserve_refund_restore_inventory`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_wallet' AND TABLE_NAME = 'mch_auto_refund_config' AND COLUMN_NAME = 'auto_verify_enabled');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_wallet`.`mch_auto_refund_config` ADD COLUMN `auto_verify_days` int(11) DEFAULT NULL COMMENT ''支付后自动核销天数,允许1至365,开关开启时必填'' AFTER `auto_verify_enabled`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_wallet' AND TABLE_NAME = 'mch_auto_refund_config' AND COLUMN_NAME = 'auto_verify_days');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_wallet`.`mch_auto_refund_config` ADD COLUMN `auto_verify_restore_inventory` char(1) NOT NULL DEFAULT ''1'' COMMENT ''自动核销是否恢复线上池库存,0不恢复,1恢复'' AFTER `auto_verify_days`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_wallet' AND TABLE_NAME = 'mch_auto_refund_config' AND COLUMN_NAME = 'auto_verify_restore_inventory');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 二、订单快照与核销方式列(四列各自独立判断)。
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_order` ADD COLUMN `auto_verify_config_id` bigint(20) DEFAULT NULL COMMENT ''支付成功时命中的自动核销配置ID快照,为空表示不参与自动核销'' AFTER `expired_refund_restore_inventory`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND COLUMN_NAME = 'auto_verify_config_id');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_order` ADD COLUMN `auto_verify_deadline` datetime DEFAULT NULL COMMENT ''支付时间加配置天数后的自动核销触发时间'' AFTER `auto_verify_config_id`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND COLUMN_NAME = 'auto_verify_deadline');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_order` ADD COLUMN `auto_verify_restore_inventory` char(1) DEFAULT NULL COMMENT ''自动核销退库存快照,0不恢复,1恢复线上池库存'' AFTER `auto_verify_deadline`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND COLUMN_NAME = 'auto_verify_restore_inventory');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_order` ADD COLUMN `verification_type` char(1) DEFAULT NULL COMMENT ''核销方式,1人工核销,2自动核销;历史已核销订单为空视为人工'' AFTER `verification_time`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND COLUMN_NAME = 'verification_type');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 三、任务表:兼容 20260822 任务表语句未落库的环境,先确保任务场景列存在(幂等 MODIFY 注释与空值语义)。
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD COLUMN `task_type` char(10) NOT NULL DEFAULT ''10'' COMMENT ''任务场景,10用户免审售后,20过期预约退款,30过期未核销自动核销'' AFTER `after_sale_id`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND COLUMN_NAME = 'task_type');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD COLUMN `trigger_time` datetime DEFAULT NULL COMMENT ''过期退款和自动核销任务按订单快照触发时间,旧售后任务为空'' AFTER `eligibility_deadline`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND COLUMN_NAME = 'trigger_time');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD COLUMN `restore_inventory` char(1) DEFAULT NULL COMMENT ''任务退库存快照,0不恢复,1恢复'' AFTER `trigger_time`',
|
||
'SELECT 1')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND COLUMN_NAME = 'restore_inventory');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 幂等注释与空值语义修正(重复执行无副作用,兼为 20260822 未落库环境补齐)。
|
||
ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task`
|
||
MODIFY COLUMN `after_sale_id` bigint(20) DEFAULT NULL COMMENT '售后单ID,过期退款和自动核销任务为空',
|
||
MODIFY COLUMN `rule_type` varchar(32) DEFAULT NULL COMMENT '普通售后任务规则快照,过期预约任务为空',
|
||
MODIFY COLUMN `eligibility_deadline` datetime DEFAULT NULL COMMENT '普通售后免审资格截止时间,过期预约任务为空',
|
||
MODIFY COLUMN `task_type` char(10) NOT NULL DEFAULT '10'
|
||
COMMENT '任务场景,10用户免审售后,20过期预约退款,30过期未核销自动核销',
|
||
MODIFY COLUMN `status` char(10) NOT NULL
|
||
COMMENT '任务状态,10待执行,20等待重试,30开关关闭暂停,31配置不可用暂停,40重试耗尽,50成功,60订单已终态跳过';
|
||
|
||
-- scene_biz_id 生成列:缺失则新增(表达式含自动核销场景 30),已存在则 MODIFY 刷新表达式。
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD COLUMN `scene_biz_id` bigint(20) GENERATED ALWAYS AS (CASE WHEN `task_type` IN (''20'', ''30'') THEN `order_id` ELSE `after_sale_id` END) STORED COMMENT ''任务场景业务唯一值,系统生成,禁止业务代码写入'' AFTER `restore_inventory`',
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` MODIFY COLUMN `scene_biz_id` bigint(20) GENERATED ALWAYS AS (CASE WHEN `task_type` IN (''20'', ''30'') THEN `order_id` ELSE `after_sale_id` END) STORED COMMENT ''任务场景业务唯一值,系统生成,禁止业务代码写入''')
|
||
FROM information_schema.COLUMNS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND COLUMN_NAME = 'scene_biz_id');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 新建场景唯一键前应确认本查询返回 0 行;存在重复说明历史任务数据冲突,必须先人工核对,禁止自动清理。
|
||
SELECT tenant_id, task_type, del_flag,
|
||
CASE WHEN task_type = '20' THEN order_id ELSE after_sale_id END AS scene_biz_id,
|
||
COUNT(*) AS duplicate_count
|
||
FROM pjcloudx_hardware.hard_auto_refund_task
|
||
GROUP BY tenant_id, task_type, del_flag,
|
||
CASE WHEN task_type = '20' THEN order_id ELSE after_sale_id END
|
||
HAVING COUNT(*) > 1;
|
||
|
||
-- 旧售后单唯一键:存在才删除,给场景唯一键让位。
|
||
SET @ddl = (SELECT IF(COUNT(*) > 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` DROP INDEX `uk_hard_auto_refund_task_after_sale`',
|
||
'SELECT 1')
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND INDEX_NAME = 'uk_hard_auto_refund_task_after_sale');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 场景唯一键:缺失才创建(存在重复数据时本语句会失败,先处理上方诊断结果)。
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD UNIQUE KEY `uk_hard_auto_refund_task_scene_biz` (`tenant_id`, `task_type`, `scene_biz_id`, `del_flag`)',
|
||
'SELECT 1')
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND INDEX_NAME = 'uk_hard_auto_refund_task_scene_biz');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 扫描索引:缺失才创建。
|
||
SET @ddl = (SELECT IF(COUNT(*) = 0,
|
||
'ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_task` ADD KEY `idx_hard_auto_refund_task_scan_type` (`tenant_id`, `task_type`, `status`, `next_retry_time`, `del_flag`)',
|
||
'SELECT 1')
|
||
FROM information_schema.STATISTICS
|
||
WHERE TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND INDEX_NAME = 'idx_hard_auto_refund_task_scan_type');
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 四、尝试日志注释更新。幂等,任何状态都可执行。
|
||
ALTER TABLE `pjcloudx_hardware`.`hard_auto_refund_attempt_log`
|
||
MODIFY COLUMN `result_status` char(10) NOT NULL
|
||
COMMENT '尝试结果,10执行中,20成功,30失败,40因开关关闭跳过,50订单已终态跳过',
|
||
MODIFY COLUMN `after_sale_id` bigint(20) DEFAULT NULL
|
||
COMMENT '售后单ID,过期退款和自动核销任务为空';
|
||
|
||
-- 【验收】生成列表达式应包含 '20' 和 '30',且三张表的新列均已存在。
|
||
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, IFNULL(GENERATION_EXPRESSION, '') AS generation
|
||
FROM information_schema.COLUMNS
|
||
WHERE (TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_auto_refund_task' AND COLUMN_NAME = 'scene_biz_id')
|
||
OR (TABLE_SCHEMA = 'pjcloudx_wallet' AND TABLE_NAME = 'mch_auto_refund_config' AND COLUMN_NAME LIKE 'auto_verify_%')
|
||
OR (TABLE_SCHEMA = 'pjcloudx_hardware' AND TABLE_NAME = 'hard_order' AND COLUMN_NAME = 'verification_type');
|
||
|
||
SET @ddl = NULL;
|