Files
tyc-server-v2/deploy/sql/repair_order_refund_q176967208700018143d9f6.sql
2026-02-12 15:16:54 +08:00

285 lines
8.9 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =============================================================================
-- 修复订单 Q_176967208700018143d9f6支付宝已退款成功但库内未完成
-- =============================================================================
--
-- 【原因简述】
-- 后台发起支付宝退款后,支付宝侧已退款成功,但创建退款记录时因 unique_refund_no
-- 冲突Duplicate entry 'refund-Q_176967208700018143d9f6')导致 createRefundRecordAndUpdateOrder
-- 失败,后续流程未执行:订单未置为 refunded、未写退款记录、未扣代理佣金与钱包。
--
-- 【本单实际退款金额】支付宝已退 99.5 元(非整单金额)
--
-- 【与 adminrefundorderlogic 退款链路对照】
-- 代码路径AdminRefundOrder -> handleAlipayRefund -> createRefundRecordAndUpdateOrder + HandleCommissionAndWalletDeduction
--
-- handleAlipayRefund 成功分支:
-- 1) createRefundRecordAndUpdateOrder(order, req, refundNo, refundResp.TradeNo, ...)
-- -> 事务内Insert order_refundrefund_no, platform_refund_id=TradeNo, order_id, user_id, product_id, refund_amount, status=success, refund_time=NOW()
-- -> 事务内Update order仅 code 中赋了 status=refunded未显式设 refund_time/version
-- 2) HandleCommissionAndWalletDeduction(ctx, svcCtx, nil, order, req.RefundAmount)
-- -> 该订单下 agent_commission按 refundAmount 比例冲减refunded_amount 增加,满额则 status=2UpdateWithVersion
-- -> 按代理汇总扣减额agent_wallet 先扣冻结再扣可用UpdateWithVersion
-- -> agent_wallet_transaction 插入 type=refund、金额为负的流水
--
-- 本 SQL 对应关系:
-- Step 2 = createRefundRecordAndUpdateOrder 的 Insert order_refundplatform_refund_id 修复时无支付宝 TradeNo 填 NULL可从支付宝补
-- Step 3 = createRefundRecordAndUpdateOrder 的 Update order并显式补全 refund_time、version+1
-- Step 4 = HandleCommissionAndWalletDeduction 对 agent_commission 的冲减(按 99.5 比例)
-- Step 5 = HandleCommissionAndWalletDeduction 对 agent_wallet 扣减 + agent_wallet_transaction 插入
--
-- 【执行前请确认】
-- 1该订单在支付宝侧已退款成功2已备份相关表或先在测试环境执行。
-- Step 25 已包在事务中:任一步报错请执行 ROLLBACK若 step 1 未查到订单_order_not_found=1勿执行后续。
-- =============================================================================
-- 与表字段 collation 一致,避免 #1267 Illegal mix of collations若表为 utf8mb4_general_ci 则改为 COLLATE utf8mb4_general_ci
SET
@order_no = CONVERT(
'Q_176967208700018143d9f6' USING utf8mb4
) COLLATE utf8mb4_general_ci;
-- 本单实际退款金额(元)
SET @repair_refund_amount = 99.5;
-- 1) 取订单信息
SELECT
id,
user_id,
product_id,
amount,
version INTO @order_id,
@user_id,
@product_id,
@order_amount,
@order_version
FROM `order`
WHERE
order_no = @order_no
AND del_state = 0
LIMIT 1;
SET @refund_amount = @repair_refund_amount;
-- 若无记录则说明订单号错误,终止
SELECT IF(@order_id IS NULL, 1, 0) AS _order_not_found;
-- 若 _order_not_found=1 请勿继续执行后续语句
-- ---------- 以下为事务:任一步报错请执行 ROLLBACK ----------
START TRANSACTION;
-- 2) 补写退款记录(若该订单尚无成功状态的退款记录)
-- 代码中 platform_refund_id 来自支付宝 refundResp.TradeNo修复时无则填 NULL如有支付宝退款单号可事后 UPDATE 补上
INSERT INTO
order_refund (
refund_no,
order_id,
user_id,
product_id,
platform_refund_id,
refund_amount,
refund_reason,
status,
del_state,
version,
refund_time,
close_time,
delete_time
)
SELECT
CONCAT(
'refund-',
@order_no,
'-repair'
),
@order_id,
@user_id,
@product_id,
NULL,
@refund_amount,
NULL,
'success',
0,
0,
NOW(),
NULL,
NULL
FROM (
SELECT 1
) _one
WHERE
NOT EXISTS (
SELECT 1
FROM order_refund
WHERE
order_id = @order_id
AND status = 'success'
AND del_state = 0
);
-- 3) 订单状态改为已退款
UPDATE `order`
SET
status = 'refunded',
refund_time = NOW(),
version = version + 1,
update_time = NOW()
WHERE
id = @order_id
AND del_state = 0
AND status = 'paid';
-- 4) 代理佣金:按本次退款 99.5 元在该订单的佣金上比例冲减refunded_amount 增加,满额则 status=2
SET
@total_available = (
SELECT COALESCE(
SUM(amount - refunded_amount), 0
)
FROM agent_commission
WHERE
order_id = @order_id
AND del_state = 0
);
UPDATE agent_commission
SET
refunded_amount = LEAST(
amount,
refunded_amount + @repair_refund_amount * (amount - refunded_amount) / NULLIF(@total_available, 0)
),
status = CASE
WHEN LEAST(
amount,
refunded_amount + @repair_refund_amount * (amount - refunded_amount) / NULLIF(@total_available, 0)
) >= amount THEN 2
ELSE status
END,
version = version + 1,
update_time = NOW()
WHERE
order_id = @order_id
AND del_state = 0
AND @total_available > 0;
-- 5) 代理钱包扣减 + 流水(仅对尚未存在本单退款流水的代理扣减,避免重复执行导致重复扣款)
DROP TEMPORARY TABLE IF EXISTS _repair_wallet_snapshot;
CREATE TEMPORARY TABLE _repair_wallet_snapshot (
agent_id BIGINT NOT NULL,
balance_before DECIMAL(20, 4) NOT NULL,
frozen_before DECIMAL(20, 4) NOT NULL,
total_deduct DECIMAL(20, 4) NOT NULL,
PRIMARY KEY (agent_id)
);
-- 按 99.5 元在该订单各代理间按“可退佣金”比例分配扣减额(与 step 4 一致),仅扣减额>0 的代理
INSERT INTO
_repair_wallet_snapshot (
agent_id,
balance_before,
frozen_before,
total_deduct
)
SELECT
agent_id,
balance_before,
frozen_before,
total_deduct
FROM (
SELECT
c.agent_id, w.balance AS balance_before, w.frozen_balance AS frozen_before, @repair_refund_amount * COALESCE(
SUM(c.amount - c.refunded_amount), 0
) / NULLIF(@total_available, 0) AS total_deduct
FROM
agent_commission c
JOIN agent_wallet w ON w.agent_id = c.agent_id
AND w.del_state = 0
WHERE
c.order_id = @order_id
AND c.del_state = 0
AND @total_available > 0
AND NOT EXISTS (
SELECT 1
FROM agent_wallet_transaction t
WHERE
t.agent_id = c.agent_id
AND t.transaction_id = @order_no
AND t.transaction_type = 'refund'
AND t.del_state = 0
)
GROUP BY
c.agent_id, w.balance, w.frozen_balance
) _agent_deduct
WHERE
total_deduct > 0;
-- 从钱包扣减:优先扣冻结余额,不足再扣可用余额
UPDATE agent_wallet w
INNER JOIN _repair_wallet_snapshot r ON w.agent_id = r.agent_id
SET
w.frozen_balance = w.frozen_balance - LEAST(
r.total_deduct,
w.frozen_balance
),
w.balance = w.balance - (
r.total_deduct - LEAST(
r.total_deduct,
w.frozen_balance
)
),
w.version = w.version + 1,
w.update_time = NOW()
WHERE
w.del_state = 0;
-- 插入退款流水(金额为负数)
INSERT INTO
agent_wallet_transaction (
delete_time,
del_state,
version,
agent_id,
transaction_type,
amount,
balance_before,
balance_after,
frozen_balance_before,
frozen_balance_after,
transaction_id,
related_user_id,
remark
)
SELECT
NULL,
0,
0,
r.agent_id,
'refund',
- r.total_deduct,
r.balance_before,
r.balance_before - (
r.total_deduct - LEAST(
r.total_deduct,
r.frozen_before
)
),
r.frozen_before,
r.frozen_before - LEAST(
r.total_deduct,
r.frozen_before
),
@order_no,
NULL,
'订单退款修复(支付宝已退,库内补单)'
FROM _repair_wallet_snapshot r;
DROP TEMPORARY TABLE IF EXISTS _repair_wallet_snapshot;
COMMIT;
-- ---------- 事务结束 ----------
-- 6) 校验(可选)
-- 订单应为 refunded
-- SELECT id, order_no, status, refund_time FROM `order` WHERE id = @order_id;
-- 应有 success 退款记录refund_amount = 99.5
-- SELECT * FROM order_refund WHERE order_id = @order_id AND del_state = 0;
-- 佣金 refunded_amount 按 99.5 比例增加,满额则 status=2
-- SELECT id, agent_id, order_id, amount, refunded_amount, status FROM agent_commission WHERE order_id = @order_id;