Compare commits

2 Commits

Author SHA1 Message Date
Break
c5126c583b 修复以前的老数据
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m51s
2026-06-01 11:49:24 +08:00
Break
918b9b4f25 退款也应该记录快照 2026-06-01 11:45:31 +08:00
3 changed files with 144 additions and 0 deletions

View File

@@ -312,6 +312,7 @@ func (s *Service) refundAgentWalletPayment(ctx context.Context, tx *gorm.DB, ref
refType := constants.ReferenceTypeRefund
refID := refund.ID
remark := fmt.Sprintf("订单%s退款退回预充值钱包", order.OrderNo)
assetType, assetID, assetIdentifier := buildRefundWalletTransactionAssetSnapshot(order)
transaction := &model.AgentWalletTransaction{
AgentWalletID: wallet.ID,
ShopID: wallet.ShopID,
@@ -325,6 +326,9 @@ func (s *Service) refundAgentWalletPayment(ctx context.Context, tx *gorm.DB, ref
ReferenceType: &refType,
ReferenceID: &refID,
RelatedShopID: relatedShopID,
AssetType: assetType,
AssetID: assetID,
AssetIdentifier: assetIdentifier,
Remark: &remark,
Creator: operatorID,
ShopIDTag: wallet.ShopIDTag,
@@ -965,3 +969,24 @@ func buildRefundResponse(r *model.RefundRequest) *dto.RefundResponse {
return resp
}
// buildRefundWalletTransactionAssetSnapshot 从订单中生成退款流水的资产快照。
func buildRefundWalletTransactionAssetSnapshot(order *model.Order) (string, uint, string) {
if order == nil {
return "", 0, ""
}
switch order.OrderType {
case model.OrderTypeSingleCard:
if order.IotCardID == nil {
return constants.AssetTypeIotCard, 0, order.AssetIdentifier
}
return constants.AssetTypeIotCard, *order.IotCardID, order.AssetIdentifier
case model.OrderTypeDevice:
if order.DeviceID == nil {
return constants.AssetTypeDevice, 0, order.AssetIdentifier
}
return constants.AssetTypeDevice, *order.DeviceID, order.AssetIdentifier
default:
return "", 0, order.AssetIdentifier
}
}

View File

@@ -0,0 +1,43 @@
-- 回滚历史价格修复
--
-- 警告:回滚会将 order_item.unit_price 恢复为成本价(旧语义),
-- 将 order.total_amount 恢复为成本价合计,
-- 并清除 package_usage.retail_amount。
-- 仅在确认需要回滚时执行。
BEGIN;
-- Step 1: 将 order_item 还原为旧语义
-- unit_price ← cost_price旧成本价
-- amount ← 重算小计
-- cost_price ← 0清除
UPDATE tb_order_item
SET
unit_price = cost_price,
amount = cost_price * quantity,
cost_price = 0
WHERE cost_price > 0
AND deleted_at IS NULL;
-- Step 2: 将 order.total_amount 恢复为成本价合计
UPDATE tb_order o
SET total_amount = sub.old_total
FROM (
SELECT
oi.order_id,
SUM(oi.unit_price * oi.quantity) AS old_total
FROM tb_order_item oi
WHERE oi.deleted_at IS NULL
GROUP BY oi.order_id
) sub
WHERE o.id = sub.order_id
AND o.deleted_at IS NULL
AND o.total_amount != sub.old_total;
-- Step 3: 清除 package_usage.retail_amount
UPDATE tb_package_usage
SET retail_amount = NULL
WHERE retail_amount IS NOT NULL
AND deleted_at IS NULL;
COMMIT;

View File

@@ -0,0 +1,76 @@
-- 历史订单价格语义修复
--
-- 背景:旧版代码将 order.total_amount 错误地设置为成本价(买家实付金额),
-- 而非零售价客户端展示价格。order_item.unit_price 同理。
-- 本迁移通过 tb_shop_package_allocation.retail_price 修复历史记录。
--
-- 识别条件order_item.unit_price = 该代理商对该套餐的当前成本价spa.cost_price
-- 且 order_item.cost_price = 0尚未修复
--
-- 注意:使用"当前"代理商零售价修复历史数据,若价格自下单以来已调整,
-- 修复后的价格为当前价格而非历史价格,属已知局限。
BEGIN;
-- Step 1: 同步修复 order_item 三个字段
-- cost_price ← 旧 unit_price成本价备份
-- unit_price ← 代理商当前零售价(优先)或套餐建议零售价(兜底)
-- amount ← 重算小计
WITH correct_item_prices AS (
SELECT
oi.id AS item_id,
oi.unit_price AS old_cost_price,
COALESCE(
NULLIF(spa.retail_price, 0),
NULLIF(p.suggested_retail_price, 0),
oi.unit_price
) AS new_unit_price,
oi.quantity
FROM tb_order_item oi
JOIN tb_order o
ON o.id = oi.order_id
AND o.deleted_at IS NULL
JOIN tb_shop_package_allocation spa
ON spa.shop_id = o.seller_shop_id
AND spa.package_id = oi.package_id
AND spa.deleted_at IS NULL
JOIN tb_package p
ON p.id = oi.package_id
WHERE oi.deleted_at IS NULL
AND oi.cost_price = 0 -- 尚未修复的记录
AND oi.unit_price > 0 -- 排除赠送套餐unit_price=0
AND oi.unit_price = spa.cost_price -- 旧语义标识unit_price 存的是代理成本价
)
UPDATE tb_order_item oi
SET
cost_price = c.old_cost_price,
unit_price = c.new_unit_price,
amount = c.new_unit_price * c.quantity
FROM correct_item_prices c
WHERE oi.id = c.item_id;
-- Step 2: 将 order.total_amount 更新为零售价合计
UPDATE tb_order o
SET total_amount = sub.new_total
FROM (
SELECT
oi.order_id,
SUM(oi.unit_price * oi.quantity) AS new_total
FROM tb_order_item oi
WHERE oi.deleted_at IS NULL
GROUP BY oi.order_id
) sub
WHERE o.id = sub.order_id
AND o.deleted_at IS NULL
AND o.total_amount != sub.new_total; -- 只更新实际需要变动的
-- Step 3: 回填 package_usage.retail_amount修复后的零售价快照
UPDATE tb_package_usage pu
SET retail_amount = o.total_amount
FROM tb_order o
WHERE pu.order_id = o.id
AND pu.order_id != 0
AND pu.retail_amount IS NULL
AND o.deleted_at IS NULL;
COMMIT;