


























「电商产品能力拆解」第 9 篇 · 促销体系下篇。上篇解决规则层:促销怎么分类、按什么顺序计算、多个优惠如何叠加互斥。
下篇继续往后追三步:整单优惠如何分摊到商品行、券如何从发放走到核销与返还、大促前如何用沙箱、压测和熔断守住系统。

双11结束后的第三天,客服群收到一条投诉:
「我买了 2 件商品 A 和 1 件商品 B,一共付了 120 元。现在只退 1 件 A,为什么系统只退我 30 元?」
这笔订单的商品、优惠和三种退款结果如下:

结算页的 120 元没有算错。事故出在售后没有读取下单时的商品行与单件分摊快照,而是按退款时的活动状态重新计算:双11满减已经结束,系统只识别到店铺券,又把商品 B 的单品直降错误扣到 A 上,最后再按数量除以 2,最终只退了 30 元。
这种错误平时藏在订单总额下面,只有用户部分退款时才会暴露。
老张看完只问了小A 三个问题:
这三个问题,对应促销下篇最容易被低估的三个深水区。
今天回答 3 个核心问题(下篇):
这三件事看起来分散,实际上共用同一个底层要求:
每一元优惠都要知道从哪里来、落到哪里、由谁承担,以及异常时怎么退回。
订单满减、满折和优惠券通常按整单判断门槛,但交易系统最终处理的对象是商品行。
下面这些场景都需要商品级实付:
所以订单不能只保存:
订单优惠总额 = 50 元
还要保存:
满减 30 元:A 分摊 17.65,B 分摊 12.35
店铺券 20 元:A 分摊 11.76,B 分摊 8.24

优惠总额回答的是「这单便宜了多少」,分摊明细回答的是「每件商品实际卖了多少钱」。
理解整套计算,不用先背公式。金额会按照平台定义的顺序,从上到下一层层流动:

用一组数字走一遍,会更直观:

这里最容易混淆的是两件事:
积分要看平台定义:如果积分用于兑换优惠,它进入优惠层;如果积分可以按固定汇率抵现,并作为用户账户资产扣减,则进入资产层。分类依据不是名称,而是它改变成交价,还是承担支付。
最常见的分摊方法,是按参与优惠商品的金额占比分摊:
商品分摊优惠
= 整单优惠 × 商品分摊基数 ÷ 全部参与商品分摊基数之和
难点不在公式,而在「分摊基数」取什么金额。
常见口径有三种:

沿用开头的订单:
商品 A:2 件 × 50 元 = 100 元
商品 B:单品直降后 70 元
订单满减:30 元
如果满减按 L1 单品促销后的金额分摊:
A 分摊满减 = 30 × 100 ÷ 170 = 17.65
B 分摊满减 = 30 × 70 ÷ 170 = 12.35
如果错误地按原价平均分:
A 分摊 15
B 分摊 15
两种算法的订单总额都对,但商品实付不同。部分退款、商家结算和毛利分析都会跟着不同。
这里最重要的原则是:
每一层优惠,都按进入这一层之前的有效金额分摊;不参与该优惠的商品,不进入分母。
有些人在设计系统时为了省事,会把所有优惠统一加总后一次性分摊:
单品直降 + 订单满减 + 品类券 + 平台券 = 总优惠
再按商品原价比例拆下去。
这样做会丢掉三个关键信息:

正确做法是按平台确定的计算顺序逐层处理:
L1 单品促销:直接记在商品行销售价右侧
→ L2-1 订单满减:按本层计算前的商品金额比例分摊
→ L2-2 订单满折:在满减后的剩余金额上计算并分摊
→ L3 优惠券:在券适用商品间继续按比例分摊
→ L4 金额类资产:按平台顺序扣减,单独记录资产流水
→ L5 外部支付:支付最终剩余金额
每层都留下:
这样退款时不需要重新猜一遍当时发生了什么。
金额保留到分时,按比例计算几乎一定会出现尾差。
下面用「10 元优惠分给 3 件等额商品」说明尾差如何产生和归属:

系统必须定义尾差归属,常见策略包括:
不管采用哪一种,都要满足两个条件:
推荐采用「最大余数法」:先向下取整到分,再按未取整余数从大到小补齐尾差。它比固定塞给最后一行更稳定,也更容易解释。
部分退款的基础公式可以先写成:
本次可退金额
= 本次退款数量对应的单件成交快照之和
– 已退金额
– 不应退回的权益价值
+ 应退运费
这里的「单件成交快照」,不是退款时用商品行金额临时除以数量,而是下单成功时已经逐件固化的:
单件基础价 – 单件商品优惠 – 单件订单优惠分摊 – 单件券优惠分摊
仍以开头订单为例,下面把「逐层分摊 → 商品行成交 → 单件快照 → 本次退款」串成一条轨迹:

退款服务只读取对应单件快照,再处理已退金额、不可退权益和运费;不调用促销引擎重新计算历史成交价。

正文只需要记住三条:
完整变量、逐层公式、尾差和金额守恒校验已经拆到配套 Excel:
《促销优惠分摊与资产抵扣计算器》
查看配套 Excel:促销优惠分摊与资产抵扣计算器_v1.0.xlsx
使用时只需要修改黄色输入格:
表格会自动计算每个商品行的满减、满折、券分摊、最终成交金额、支付构成和基础退款额。它负责「换数字就能用」,正文继续负责解释为什么必须逐层计算。
如果两件 A 都退完后,剩余商品 B 不再满足「满 150 减 20」的券门槛,要不要追回券优惠?
这没有唯一答案,但必须提前选定业务策略:

多数场景更适合把原分摊成交价作为默认退款上限,再针对明显的凑单退款、批量套利做风控治理,而不是让每一笔正常退款都现场重算整套促销。
一句话记住:
正向计算决定怎么卖,分摊快照决定怎么退。
小A 第一次做优惠券,只设计了三个状态:
未使用 → 已使用 → 已过期
上线后马上遇到五个问题:
问题的根源是把「券模板」「券库存」和「用户持有的券」混成了一个对象。


模板是一套规则,批次是一轮投放,用户券才是可以被锁定和核销的资产。
建议至少覆盖这些主状态:

几个最容易出事故的节点:
至少要区分四类场景:


这里还有一个隐藏问题:原券返还时已经过期怎么办?
常见做法有三种:
对于商家缺货、平台取消等非用户责任场景,更适合补发等值券,并记录原券与补偿券的关联关系。否则客服只看到一张新券,不知道为什么发;财务也无法追踪补偿成本。
发 10 万张满 100 减 20 的券,不等于一定花 200 万。
至少要同时管理:
只控券张数,不控预算,会遇到高面额券集中核销;只控预算,不控库存,又会出现领券成功率和用户承诺失控。
所以券系统的核心不是「发得出去」,而是:
发放有库存、使用有锁、核销有凭证、退款有去向、成本能对账。
大促开始 3 分钟,监控突然发现某组优惠叠加后,部分商品成交价已经低于成本价。
订单还在持续增长,运营第一反应是下线活动。但真正执行时才发现:
平时一条活动出错,可能影响几百单;大促中的一条规则出错,几分钟就可能穿透预算。产品经理要交付的不是一个“活动开关”,而是一条从风险发现、运行监控到异常止损和恢复对账的完整链路。

审批前导入典型购物车完成离线试算,不真实发券、不创建订单。

沙箱交付的不是“测试通过”,而是最坏结果、产生路径、风险样本和上线护栏。
压测要覆盖从展示到资源释放的完整计算链路,而不是只压下单接口。

压测结论必须给出峰值 TPS、响应上限、队列水位、扩容点、限流阈值和恢复条件;重点验证整点开抢等瞬时尖峰,而不是日均流量。
预算护栏要同时覆盖四个粒度:

支付存在延迟,熔断应按风险敞口计算:
预算风险敞口 = 已核销成本 + 已锁定预计成本

达到阈值后自动执行预案:先停止新增优惠承诺,已锁定预算的订单按存量策略处理。
大促时不是所有能力都同等重要。

这里有一条不能破的底线:
可以少展示、少推荐、少发券,但不能让同一订单在提交前后出现两套价格。

「暂停活动」不是一个按钮,而是一组对新流量、存量订单和用户承诺分别执行的策略。

活动结束不等于交付结束:临时处置必须沉淀为下一次可自动执行的规则。

产品经理真正要交付的,不只是一份活动需求文档,而是一套从规则上线到异常止损的运行方案。

一句话总结: 促销不是让价格变便宜,而是让每一元优惠都可计算、可追溯、可止损。

下期预告—— 促销体系讲完,下一篇进入营销玩法。促销解决的是「怎么算便宜」,营销要解决的是「为什么用户愿意来、愿意参与,还愿意带别人来」。
作者:Zoe产品手记 公众号:Zoe产品手记
本文由 @Zoe产品手记 原创发布于人人都是产品经理。未经作者许可,禁止转载
题图来自 Unsplash,基于CC0协议
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。