Files
biz-api-cloud-zax/db/20260814_add_hard_auto_refund.sql
dzc 6e1af7c84d fix:修改用户管理样式,能展示用户身份信息。
fix:修改树状查询让他更紧凑。
fix:修改app微信登录,先检测用户手机上没有有装微信,没有就隐藏微信登录。
fix:修改商户管理"商户功能"样式
feat:增加自动退款模块
2026-08-14 15:03:58 +08:00

149 lines
9.9 KiB
SQL

-- 每日菜谱预约订单自动退款。
-- 本脚本只新增自动退款所需表、订单快照字段、钱包幂等索引和技术重试权限点,
-- 不回填历史订单,不创建跨库外键,也不自动向已有角色授予技术重试权限。
-- 执行唯一索引变更前应确认本查询返回 0 行;发现重复时必须先人工核对资金记录,禁止自动清理。
SELECT pay_refund_order_id, COUNT(*) AS duplicate_count
FROM pjcloudx_wallet.wallet_recharge
WHERE pay_refund_order_id IS NOT NULL
GROUP BY pay_refund_order_id
HAVING COUNT(*) > 1;
-- Wallet按售后单ID保证退款到账幂等;MySQL唯一索引允许保留多条NULL历史记录。
-- 将该变更放在其他DDL之前,重复检测不通过时由唯一索引直接阻止脚本继续执行。
ALTER TABLE `pjcloudx_wallet`.`wallet_recharge`
ADD UNIQUE KEY `uk_wallet_recharge_refund_order` (`pay_refund_order_id`);
-- 商户自动退款配置。父店和分店按各自 mch_id 独立配置,每个订单类型只保留一条配置记录。
CREATE TABLE `pjcloudx_wallet`.`mch_auto_refund_config`
(
`id` bigint(20) NOT NULL COMMENT '配置主键,由应用使用雪花算法生成',
`mch_id` bigint(20) NOT NULL COMMENT '商户ID,父店和分店互不继承配置',
`order_type` char(10) NOT NULL COMMENT '硬件订单类型编码,首期仅支持2预约订单',
`enabled` char(1) NOT NULL DEFAULT '0' COMMENT '自动退款开关,0关闭,1开启',
`rule_type` varchar(32) NOT NULL COMMENT '自动退款规则,PAY_TIME_LIMIT支付后限时,APPT_CYCLE_CLOSE周期预约截止',
`pay_time_limit_hours` int(11) DEFAULT NULL COMMENT '支付后可自动退款小时数,仅PAY_TIME_LIMIT使用,业务允许1至168',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) DEFAULT '0' COMMENT '逻辑删除标记,0有效,1删除;本功能不提供删除接口',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_mch_auto_refund_config` (`tenant_id`, `mch_id`, `order_type`),
KEY `idx_mch_auto_refund_config_mch` (`tenant_id`, `mch_id`, `del_flag`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '商户自动退款配置';
-- 订单保存下单时的配置与规则快照;三个关键字段任一为空均不具备免审资格,历史订单保持为空。
ALTER TABLE `pjcloudx_hardware`.`hard_order`
ADD COLUMN `auto_refund_config_id` bigint(20) DEFAULT NULL
COMMENT '下单时命中的Wallet自动退款配置ID,为空表示不具备免审资格' AFTER `appt_rule_id`,
ADD COLUMN `auto_refund_rule_type` varchar(32) DEFAULT NULL
COMMENT '下单时自动退款规则快照,PAY_TIME_LIMIT或APPT_CYCLE_CLOSE' AFTER `auto_refund_config_id`,
ADD COLUMN `auto_refund_deadline` datetime DEFAULT NULL
COMMENT '免审退款申请截止时间,闭区间判断为申请时间小于等于该值' AFTER `auto_refund_rule_type`;
-- 自动退款持久化任务。一个售后单最多一条任务,失败后由该记录驱动定时恢复。
CREATE TABLE `pjcloudx_hardware`.`hard_auto_refund_task`
(
`id` bigint(20) NOT NULL COMMENT '任务主键,由应用使用雪花算法生成',
`after_sale_id` bigint(20) NOT NULL COMMENT '售后单ID,同时作为钱包退款幂等键',
`order_id` bigint(20) NOT NULL COMMENT '原硬件订单ID,用于订单级加锁和退款状态汇总',
`mch_id` bigint(20) NOT NULL COMMENT '订单所属商户ID,用于数据范围和配置复核',
`config_id` bigint(20) NOT NULL COMMENT '下单时命中的Wallet自动退款配置ID',
`rule_type` varchar(32) NOT NULL COMMENT '自动退款规则快照,任务重试期间不随配置规则变化',
`eligibility_deadline` datetime NOT NULL COMMENT '申请免审资格截止时间,任务受理后跨过该时间仍继续重试',
`status` char(10) NOT NULL COMMENT '任务状态,10待执行,20等待重试,30开关关闭暂停,31配置不可用暂停,40重试耗尽,50成功',
`auto_attempt_count` int(11) NOT NULL DEFAULT 0 COMMENT '已消耗自动尝试次数,含首次执行,最大8次',
`total_attempt_count` int(11) NOT NULL DEFAULT 0 COMMENT '全部尝试序号计数,包含自动、人工和开关关闭跳过',
`next_retry_time` datetime DEFAULT NULL COMMENT '下次自动重试时间,暂停、耗尽和成功状态为空',
`last_attempt_time` datetime DEFAULT NULL COMMENT '最近一次实际尝试或开关关闭跳过的开始时间',
`success_time` datetime DEFAULT NULL COMMENT '钱包到账且售后与订单状态提交成功的时间',
`last_error` varchar(2000) DEFAULT NULL COMMENT '最近一次失败诊断信息,不保存资金凭证等敏感数据',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) DEFAULT '0' COMMENT '逻辑删除标记,0有效,1删除;任务不提供删除接口',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hard_auto_refund_task_after_sale` (`after_sale_id`),
KEY `idx_hard_auto_refund_task_scan` (`tenant_id`, `status`, `next_retry_time`, `del_flag`),
KEY `idx_hard_auto_refund_task_order` (`tenant_id`, `order_id`, `del_flag`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '硬件订单自动退款任务';
-- 自动退款单次尝试日志。日志只在一次尝试内从执行中更新为最终结果,完成后只读。
CREATE TABLE `pjcloudx_hardware`.`hard_auto_refund_attempt_log`
(
`id` bigint(20) NOT NULL COMMENT '日志主键,由应用使用雪花算法生成',
`task_id` bigint(20) NOT NULL COMMENT '自动退款任务ID',
`after_sale_id` bigint(20) NOT NULL COMMENT '售后单ID,用于直接查询完整尝试历史',
`attempt_no` int(11) NOT NULL COMMENT '任务内递增尝试序号,包含开关关闭跳过记录',
`trigger_type` char(10) NOT NULL COMMENT '触发来源,10首次同步执行,20定时重试,30人工技术重试',
`result_status` char(10) NOT NULL COMMENT '尝试结果,10执行中,20成功,30失败,40因开关关闭跳过',
`refund_code` varchar(128) NOT NULL COMMENT '稳定钱包退款业务号,格式hard_{orderId}_{afterSaleId}',
`operator_user_id` bigint(20) DEFAULT NULL COMMENT '人工技术重试操作用户ID,自动触发为空',
`started_time` datetime NOT NULL COMMENT '本次尝试开始时间',
`finished_time` datetime DEFAULT NULL COMMENT '本次尝试完成时间,执行中记录为空',
`error_message` varchar(2000) DEFAULT NULL COMMENT '失败诊断信息,成功或开关关闭跳过时为空',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` char(1) DEFAULT '0' COMMENT '逻辑删除标记,0有效,1删除;日志不提供删除接口',
`tenant_id` bigint(20) NOT NULL COMMENT '租户ID',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_hard_auto_refund_attempt` (`task_id`, `attempt_no`),
KEY `idx_hard_auto_refund_attempt_after_sale` (`tenant_id`, `after_sale_id`, `create_time`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci
COMMENT = '硬件订单自动退款尝试日志';
-- 为每个已有“售后订单-查看”权限所在租户注册技术重试按钮。
-- 菜单ID从迁移日期种子或现有最大ID之后分配;脚本不写sys_role_menu,需由角色管理显式授权。
SET @hard_auto_refund_menu_id_base = (
SELECT GREATEST(COALESCE(MAX(menu_id), 0), 2026081400000000000)
FROM pjcloudx.sys_menu
);
INSERT INTO `pjcloudx`.`sys_menu`
(`menu_id`, `name`, `permission`, `path`, `component`, `parent_id`, `icon`, `visible`, `sort_order`,
`keep_alive`, `embedded`, `menu_type`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `tenant_id`)
SELECT @hard_auto_refund_menu_id_base + ROW_NUMBER() OVER (ORDER BY source_menu.tenant_id, source_menu.menu_id),
'自动退款重试',
'hard_autoRefundTask_retry',
NULL,
NULL,
source_menu.parent_id,
'1',
'1',
COALESCE(source_menu.sort_order, 0) + 1,
'0',
NULL,
source_menu.menu_type,
'system',
NOW(),
'system',
NOW(),
'0',
source_menu.tenant_id
FROM pjcloudx.sys_menu source_menu
WHERE source_menu.permission = 'hard_hardAfterSale_view'
AND source_menu.del_flag = '0'
AND NOT EXISTS (
SELECT 1
FROM pjcloudx.sys_menu existing_menu
WHERE existing_menu.permission = 'hard_autoRefundTask_retry'
AND existing_menu.tenant_id <=> source_menu.tenant_id
AND existing_menu.del_flag = '0'
);
SET @hard_auto_refund_menu_id_base = NULL;