From c5126c583b7e6bcdb774147306a2b21acb8face9 Mon Sep 17 00:00:00 2001 From: Break Date: Mon, 1 Jun 2026 11:49:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A5=E5=89=8D=E7=9A=84?= =?UTF-8?q?=E8=80=81=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._historical_order_price_semantics.down.sql | 43 +++++++++++ ...ix_historical_order_price_semantics.up.sql | 76 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 migrations/000151_fix_historical_order_price_semantics.down.sql create mode 100644 migrations/000151_fix_historical_order_price_semantics.up.sql diff --git a/migrations/000151_fix_historical_order_price_semantics.down.sql b/migrations/000151_fix_historical_order_price_semantics.down.sql new file mode 100644 index 0000000..7496e0b --- /dev/null +++ b/migrations/000151_fix_historical_order_price_semantics.down.sql @@ -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; diff --git a/migrations/000151_fix_historical_order_price_semantics.up.sql b/migrations/000151_fix_historical_order_price_semantics.up.sql new file mode 100644 index 0000000..7eacebf --- /dev/null +++ b/migrations/000151_fix_historical_order_price_semantics.up.sql @@ -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;