-- ====================================================
-- v20: 资金关键表唯一索引（幂等兜底）
-- 目的：为支付回调 / 退款回调 / 订单结算提供数据库层幂等兜底，
--       防止并发回调、消息重投导致重复入账 / 重复扣减 / 重复分账。
-- 涉及表：t_pay_log、t_wallet_detail、t_split_record
--
-- 执行前提（重要）：
--   1. 生产执行前先运行下方"查重"SQL，确认无重复数据；
--      若存在重复，需先人工清理后再执行本脚本（否则建索引会失败）。
--   2. 建议在业务低峰期执行（大表加唯一索引会锁表/耗时）。
-- ====================================================

-- ----------------------------
-- 0. 查重检查（执行前先跑，以下 3 条应全部返回 0 行或空集）
-- ----------------------------
-- SELECT out_trade_no, COUNT(*) FROM t_pay_log GROUP BY out_trade_no HAVING COUNT(*) > 1;
-- SELECT order_no, type, COUNT(*) FROM t_wallet_detail GROUP BY order_no, type HAVING COUNT(*) > 1;
-- SELECT trade_no, type, from_station_id, to_station_id, COUNT(*) FROM t_split_record
--     GROUP BY trade_no, type, from_station_id, to_station_id HAVING COUNT(*) > 1;

-- ----------------------------
-- 1. 幂等建唯一索引
-- ----------------------------
DROP PROCEDURE IF EXISTS add_finance_idempotency_indexes;
DELIMITER //
CREATE PROCEDURE add_finance_idempotency_indexes()
BEGIN
    -- t_pay_log.out_trade_no：微信商户订单号唯一，同一笔支付只允许处理一次
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.STATISTICS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = 't_pay_log'
          AND INDEX_NAME = 'uk_out_trade_no'
    ) THEN
        ALTER TABLE `t_pay_log` ADD UNIQUE KEY `uk_out_trade_no` (`out_trade_no`);
    END IF;

    -- t_wallet_detail(order_no, type)：同一订单号同类型的钱包流水唯一
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.STATISTICS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = 't_wallet_detail'
          AND INDEX_NAME = 'uk_order_no_type'
    ) THEN
        ALTER TABLE `t_wallet_detail` ADD UNIQUE KEY `uk_order_no_type` (`order_no`, `type`);
    END IF;

    -- t_split_record(trade_no, type, from_station_id, to_station_id)：
    -- 同一交易同类型同流向的分账记录唯一（跨店 EXPEND/INCOME 两条 type 不同，互不冲突）
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.STATISTICS
        WHERE TABLE_SCHEMA = DATABASE()
          AND TABLE_NAME = 't_split_record'
          AND INDEX_NAME = 'uk_trade_no_type_from_to'
    ) THEN
        ALTER TABLE `t_split_record`
            ADD UNIQUE KEY `uk_trade_no_type_from_to` (`trade_no`, `type`, `from_station_id`, `to_station_id`);
    END IF;
END //
DELIMITER ;
CALL add_finance_idempotency_indexes();
DROP PROCEDURE IF EXISTS add_finance_idempotency_indexes;

-- ====================================================
-- 验证：
--   SHOW INDEX FROM t_pay_log WHERE Key_name = 'uk_out_trade_no';
--   SHOW INDEX FROM t_wallet_detail WHERE Key_name = 'uk_order_no_type';
--   SHOW INDEX FROM t_split_record WHERE Key_name = 'uk_trade_no_type_from_to';
-- ====================================================
