-- ============================================================================
-- 矫正在线支付「保险订单」的 pay_amount
-- 背景：提交 f11b781c2 上线到本次回退期间，在线支付回调把 order_basic_info.pay_amount
--       写成了「完整实付(充电+保险)」。规则应为：
--         order_basic_info.pay_amount = 充电金额(不含保险)
--         order_pay_record 汇总        = 完整实付(充电 + 保险)
--       故需把这批订单的 pay_amount 从「完整金额」矫正为「pay_amount - insurance_amount」。
-- 适用：MySQL 5.7+（未用 CTE，5.7 可直接跑）
-- 日期：2026-07-25
--
-- 识别口径：在线支付(微信'4'/支付宝'5') + 已支付 + insurance>0 + pay_amount≈明细汇总。
--   · 正确订单：pay_amount = 明细 - 保险  <  明细
--   · 错误订单：pay_amount = 明细(含保险)  => 命中本脚本
--
-- ⚠️ 关于「已完成(order_status='6')」订单：结算时已用错误的 pay_amount 计算过
--    退款(residue = pay_amount - 消费)，即保险已被多退，本脚本无法追回那笔钱；
--    对已完成订单矫正 pay_amount 只是让「记录」变正确，且会与已落库的 refund_amount
--    不再自洽。是否处理已完成订单请按业务决定（见第 3 步的两种 WHERE）。
-- ============================================================================


-- ---------------------------------------------------------------------------
-- 第 1 步：DRY-RUN 预览（务必先只跑这个，核对数量与金额）
-- ---------------------------------------------------------------------------
SELECT
    o.order_code,
    o.order_status,
    CASE o.order_status WHEN '6' THEN '已完成' WHEN '4' THEN '异常' ELSE '未完成' END AS status_desc,
    o.pay_mode,
    o.pay_amount                          AS cur_pay_amount,        -- 当前(错误,含保险)
    o.insurance_amount                    AS insurance_amount,
    pr.pay_record_sum                     AS pay_record_sum,        -- 明细汇总(完整实付)
    (o.pay_amount - o.insurance_amount)   AS corrected_pay_amount   -- 矫正后(充电金额)
FROM order_basic_info o
JOIN (
    SELECT order_code, SUM(pay_amount) AS pay_record_sum
    FROM order_pay_record
    WHERE del_flag = '0'
    GROUP BY order_code
) pr ON pr.order_code = o.order_code
WHERE o.pay_mode IN ('4','5')                        -- 在线支付(微信/支付宝)
  AND o.pay_status = '1'                              -- 已支付
  AND o.insurance_amount > 0                          -- 有保险
  AND ABS(o.pay_amount - pr.pay_record_sum) < 0.005   -- pay_amount == 明细汇总 => 含了保险(错误)
ORDER BY o.order_status, o.order_code;


-- ---------------------------------------------------------------------------
-- 第 2 步：备份受影响行（建议执行，便于回滚）
-- ---------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS bak_order_pay_amount_fix_20260725 (
    order_code       VARCHAR(64) PRIMARY KEY,
    old_pay_amount   DECIMAL(10,2),
    insurance_amount DECIMAL(10,2),
    new_pay_amount   DECIMAL(10,2),
    order_status     VARCHAR(4),
    backup_time      DATETIME
);

INSERT INTO bak_order_pay_amount_fix_20260725
    (order_code, old_pay_amount, insurance_amount, new_pay_amount, order_status, backup_time)
SELECT o.order_code, o.pay_amount, o.insurance_amount,
       (o.pay_amount - o.insurance_amount), o.order_status, NOW()
FROM order_basic_info o
JOIN (
    SELECT order_code, SUM(pay_amount) AS pay_record_sum
    FROM order_pay_record WHERE del_flag = '0' GROUP BY order_code
) pr ON pr.order_code = o.order_code
WHERE o.pay_mode IN ('4','5')
  AND o.pay_status = '1'
  AND o.insurance_amount > 0
  AND ABS(o.pay_amount - pr.pay_record_sum) < 0.005
ON DUPLICATE KEY UPDATE backup_time = NOW();


-- ---------------------------------------------------------------------------
-- 第 3 步：正式矫正（确认第 1 步无误后执行）
--   pay_amount = pay_amount - insurance_amount = 充电金额
--
--   ▸ 方案 A（推荐）：只矫正「未完成」订单，避免动已结算/已退款的历史账
--     —— 防止这些单将来结算时多退保险。把下面这条的注释去掉执行：
-- ---------------------------------------------------------------------------
-- UPDATE order_basic_info o
-- JOIN (
--     SELECT order_code, SUM(pay_amount) AS pay_record_sum
--     FROM order_pay_record WHERE del_flag = '0' GROUP BY order_code
-- ) pr ON pr.order_code = o.order_code
-- SET o.pay_amount = o.pay_amount - o.insurance_amount
-- WHERE o.pay_mode IN ('4','5')
--   AND o.pay_status = '1'
--   AND o.insurance_amount > 0
--   AND ABS(o.pay_amount - pr.pay_record_sum) < 0.005
--   AND o.order_status NOT IN ('6','7');            -- 排除已完成/已关闭

--   ▸ 方案 B：矫正「全部」受影响订单（含已完成，仅让记录口径一致；已多退的保险无法追回）
--     如需按此执行，去掉下面这条的注释：
-- UPDATE order_basic_info o
-- JOIN (
--     SELECT order_code, SUM(pay_amount) AS pay_record_sum
--     FROM order_pay_record WHERE del_flag = '0' GROUP BY order_code
-- ) pr ON pr.order_code = o.order_code
-- SET o.pay_amount = o.pay_amount - o.insurance_amount
-- WHERE o.pay_mode IN ('4','5')
--   AND o.pay_status = '1'
--   AND o.insurance_amount > 0
--   AND ABS(o.pay_amount - pr.pay_record_sum) < 0.005;


-- ---------------------------------------------------------------------------
-- 第 4 步：矫正后复核（应为 0 行）
-- ---------------------------------------------------------------------------
-- 复核逻辑：矫正后 正确订单应满足 pay_amount + insurance = 明细汇总；
--           若仍有 pay_amount == 明细汇总 且 insurance>0，说明还有漏网的。
SELECT COUNT(*) AS still_wrong
FROM order_basic_info o
JOIN (
    SELECT order_code, SUM(pay_amount) AS pay_record_sum
    FROM order_pay_record WHERE del_flag = '0' GROUP BY order_code
) pr ON pr.order_code = o.order_code
WHERE o.pay_mode IN ('4','5')
  AND o.pay_status = '1'
  AND o.insurance_amount > 0
  AND ABS(o.pay_amount - pr.pay_record_sum) < 0.005;


-- ---------------------------------------------------------------------------
-- 回滚（如需）：从备份表还原
-- ---------------------------------------------------------------------------
-- UPDATE order_basic_info o
-- JOIN bak_order_pay_amount_fix_20260725 b ON b.order_code = o.order_code
-- SET o.pay_amount = b.old_pay_amount;
