「退一件,到底该退多少钱?」——优惠分摊、券生命周期与大促交付

3 评论 144 浏览 0 收藏 23 分钟

「电商产品能力拆解」第 9 篇 · 促销体系下篇。上篇解决规则层:促销怎么分类、按什么顺序计算、多个优惠如何叠加互斥。

下篇继续往后追三步:整单优惠如何分摊到商品行、券如何从发放走到核销与返还、大促前如何用沙箱、压测和熔断守住系统。

双11结束后的第三天,客服群收到一条投诉:

「我买了 2 件商品 A 和 1 件商品 B,一共付了 120 元。现在只退 1 件 A,为什么系统只退我 30 元?」

这笔订单的商品、优惠和三种退款结果如下:

结算页的 120 元没有算错。事故出在售后没有读取下单时的商品行与单件分摊快照,而是按退款时的活动状态重新计算:双11满减已经结束,系统只识别到店铺券,又把商品 B 的单品直降错误扣到 A 上,最后再按数量除以 2,最终只退了 30 元。

这种错误平时藏在订单总额下面,只有用户部分退款时才会暴露。

老张看完只问了小A 三个问题:

  1. 整单优惠按什么基数分到每个商品行?
  2. 退款时读取下单快照,还是按当前活动重新计算?
  3. 券被使用、取消、退款后,额度和状态分别怎么回退?

这三个问题,对应促销下篇最容易被低估的三个深水区。

今天回答 3 个核心问题(下篇):

  • 问题 1 · 钱怎么落下去:整单优惠如何分摊到商品行,尾差放哪里,退款读什么
  • 问题 2 · 券怎么走完一生:从模板、发放、领取到锁定、核销、返还,状态如何治理
  • 问题 3 · 大促怎么扛住:如何用沙箱试算、容量压测、预算熔断和降级预案守住活动

这三件事看起来分散,实际上共用同一个底层要求:

每一元优惠都要知道从哪里来、落到哪里、由谁承担,以及异常时怎么退回。

问题 1 · 钱怎么落下去:优惠总额不等于商品实付

为什么整单优惠必须分摊

订单满减、满折和优惠券通常按整单判断门槛,但交易系统最终处理的对象是商品行。

下面这些场景都需要商品级实付:

  • 用户只退其中一件商品
  • 订单拆成多个包裹,部分发货、部分取消
  • 平台与不同商家分别承担优惠成本
  • 财务按商品、商家、品类核算收入和补贴
  • 发票、佣金、积分按实付金额计算

所以订单不能只保存:

订单优惠总额 = 50 元

还要保存:

满减 30 元:A 分摊 17.65,B 分摊 12.35

店铺券 20 元:A 分摊 11.76,B 分摊 8.24

优惠总额回答的是「这单便宜了多少」,分摊明细回答的是「每件商品实际卖了多少钱」。

先立住一个核心概念:1 个金额起点 + 5 层扣减

理解整套计算,不用先背公式。金额会按照平台定义的顺序,从上到下一层层流动:

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

这里最容易混淆的是两件事:

  1. 单品促销不需要再平均分摊。它属于哪一件商品,就直接记在哪个商品行的销售价右侧。
  2. 金额类资产不是促销优惠。优惠改变商品成交金额;礼品卡、余额和储值卡等改变的是用户用什么资产支付。两者都影响现金实付,但记账、退款和对账方式不同。

积分要看平台定义:如果积分用于兑换优惠,它进入优惠层;如果积分可以按固定汇率抵现,并作为用户账户资产扣减,则进入资产层。分类依据不是名称,而是它改变成交价,还是承担支付。

先定分摊基数,再谈公式

最常见的分摊方法,是按参与优惠商品的金额占比分摊:

商品分摊优惠

= 整单优惠 × 商品分摊基数 ÷ 全部参与商品分摊基数之和

难点不在公式,而在「分摊基数」取什么金额。

常见口径有三种:

沿用开头的订单:

商品 A:2 件 × 50 元 = 100 元

商品 B:单品直降后 70 元

订单满减:30 元

如果满减按 L1 单品促销后的金额分摊:

A 分摊满减 = 30 × 100 ÷ 170 = 17.65

B 分摊满减 = 30 × 70 ÷ 170 = 12.35

如果错误地按原价平均分:

A 分摊 15

B 分摊 15

两种算法的订单总额都对,但商品实付不同。部分退款、商家结算和毛利分析都会跟着不同。

这里最重要的原则是:

每一层优惠,都按进入这一层之前的有效金额分摊;不参与该优惠的商品,不进入分母。

多层优惠不能一次性打散

有些人在设计系统时为了省事,会把所有优惠统一加总后一次性分摊:

单品直降 + 订单满减 + 品类券 + 平台券 = 总优惠

再按商品原价比例拆下去。

这样做会丢掉三个关键信息:

  1. 适用范围不同:品类券只能落到指定品类,不能分到其他商品
  2. 成本承担方不同:商家满减、平台券、品牌补贴不能混成一笔
  3. 退款策略不同:有的优惠按商品退,有的券满足条件后才返还

正确做法是按平台确定的计算顺序逐层处理:

L1 单品促销:直接记在商品行销售价右侧

→ L2-1 订单满减:按本层计算前的商品金额比例分摊

→ L2-2 订单满折:在满减后的剩余金额上计算并分摊

→ L3 优惠券:在券适用商品间继续按比例分摊

→ L4 金额类资产:按平台顺序扣减,单独记录资产流水

→ L5 外部支付:支付最终剩余金额

每层都留下:

  • 优惠规则 ID 与版本
  • 参与商品范围
  • 分摊前金额
  • 分摊金额
  • 成本承担主体
  • 取整与尾差结果

这样退款时不需要重新猜一遍当时发生了什么。

尾差不是数学问题,是账务归属问题

金额保留到分时,按比例计算几乎一定会出现尾差。

下面用「10 元优惠分给 3 件等额商品」说明尾差如何产生和归属:

系统必须定义尾差归属,常见策略包括:

  • 落到金额最大的商品行
  • 落到最后一个参与分摊的商品行
  • 按小数余数从大到小补分
  • 固定落到指定承担方的结算行

不管采用哪一种,都要满足两个条件:

  1. 商品行分摊合计必须等于订单优惠总额
  2. 同一笔订单在支付、退款、结算和对账中必须读取同一结果

推荐采用「最大余数法」:先向下取整到分,再按未取整余数从大到小补齐尾差。它比固定塞给最后一行更稳定,也更容易解释。

退一件,到底该退多少钱

部分退款的基础公式可以先写成:

本次可退金额

= 本次退款数量对应的单件成交快照之和

– 已退金额

– 不应退回的权益价值

+ 应退运费

这里的「单件成交快照」,不是退款时用商品行金额临时除以数量,而是下单成功时已经逐件固化的:

单件基础价 – 单件商品优惠 – 单件订单优惠分摊 – 单件券优惠分摊

仍以开头订单为例,下面把「逐层分摊 → 商品行成交 → 单件快照 → 本次退款」串成一条轨迹:

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

可直接套用:把完整计算交给 Excel

正文只需要记住三条:

  1. 单品促销直接记在商品行销售价右侧。
  2. 满减、满折和优惠券按平台顺序逐层计算,每一层都用上一层的剩余金额重新按比例分摊。
  3. 礼品卡、积分、余额和储值卡属于金额类资产,在优惠计算完成后按平台顺序扣减,并与商品成交金额分开记账。

完整变量、逐层公式、尾差和金额守恒校验已经拆到配套 Excel:

《促销优惠分摊与资产抵扣计算器》

查看配套 Excel:促销优惠分摊与资产抵扣计算器_v1.0.xlsx

使用时只需要修改黄色输入格:

  • 商品销售价与单品促销
  • 满减金额、满折折扣率和优惠券金额
  • 礼品卡、积分、余额与储值卡抵扣
  • 需要退款的商品行

表格会自动计算每个商品行的满减、满折、券分摊、最终成交金额、支付构成和基础退款额。它负责「换数字就能用」,正文继续负责解释为什么必须逐层计算。

如果两件 A 都退完后,剩余商品 B 不再满足「满 150 减 20」的券门槛,要不要追回券优惠?

这没有唯一答案,但必须提前选定业务策略:

多数场景更适合把原分摊成交价作为默认退款上限,再针对明显的凑单退款、批量套利做风控治理,而不是让每一笔正常退款都现场重算整套促销。

一句话记住:

正向计算决定怎么卖,分摊快照决定怎么退。

问题 2 · 券怎么走完一生:它不是一张图片,是一份有额度的承诺

小A 第一次做优惠券,只设计了三个状态:

未使用 → 已使用 → 已过期

上线后马上遇到五个问题:

  • 用户点领取时显示成功,券包里却没有
  • 两台手机同时结算,同一张券被用了两次
  • 订单取消后,券没有退回
  • 活动下线了,已领取的券还能不能用
  • 券库存发完了,运营却看不出发给了谁

问题的根源是把「券模板」「券库存」和「用户持有的券」混成了一个对象。

券体系至少有三层对象

模板是一套规则,批次是一轮投放,用户券才是可以被锁定和核销的资产。

一张券的完整状态机

建议至少覆盖这些主状态:

几个最容易出事故的节点:

  1. 领取:领取成功必须同时解决资格、库存和幂等。不能先提示成功,再异步发现库存没了;也不能因为用户连点两次就发两张。
  2. 锁定:用户提交订单但尚未支付时,券不能继续被其他订单使用。系统要记录锁定订单和锁定超时时间。
  3. 核销:一般在支付成功后核销,而不是创建订单时核销。否则未支付订单取消后,会制造大量人工返券。
  4. 解锁:订单超时关闭、支付失败或用户主动取消时,券要从锁定状态恢复。恢复前还要判断券是否已经过期、批次是否作废。
  5. 退款返还:返不返、什么时候返、返多久有效,都不能临时决定。

退款后,券到底返不返

至少要区分四类场景:

这里还有一个隐藏问题:原券返还时已经过期怎么办?

常见做法有三种:

  1. 过期不返,规则最简单但体验最差
  2. 原券返还并延长固定天数
  3. 发一张等值补偿券,重新计算有效期

对于商家缺货、平台取消等非用户责任场景,更适合补发等值券,并记录原券与补偿券的关联关系。否则客服只看到一张新券,不知道为什么发;财务也无法追踪补偿成本。

券库存和预算必须是两本账

发 10 万张满 100 减 20 的券,不等于一定花 200 万。

至少要同时管理:

  • 发行库存:还能发多少张
  • 锁定库存:已被订单占用但未核销多少张
  • 核销数量:真正使用了多少张
  • 预算占用:锁定订单预计消耗多少补贴
  • 实际成本:支付成功后真实承担多少

只控券张数,不控预算,会遇到高面额券集中核销;只控预算,不控库存,又会出现领券成功率和用户承诺失控。

所以券系统的核心不是「发得出去」,而是:

发放有库存、使用有锁、核销有凭证、退款有去向、成本能对账。

问题 3 · 大促怎么扛住:活动配置完成,只代表风险刚刚开始

大促开始 3 分钟,监控突然发现某组优惠叠加后,部分商品成交价已经低于成本价。

订单还在持续增长,运营第一反应是下线活动。但真正执行时才发现:

  • 不知道哪些订单已经锁定优惠预算
  • 不知道暂停后,已领取的券还能不能用
  • 不知道未支付订单应该继续履约还是释放资格
  • 不知道规则恢复后是否会重复核销、重复扣预算

平时一条活动出错,可能影响几百单;大促中的一条规则出错,几分钟就可能穿透预算。产品经理要交付的不是一个“活动开关”,而是一条从风险发现、运行监控到异常止损和恢复对账的完整链路。

上线前 1:规则沙箱,先把最坏结果算出来

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

沙箱交付的不是“测试通过”,而是最坏结果、产生路径、风险样本和上线护栏

上线前 2:容量压测,压的不是页面,是计算链路

压测要覆盖从展示到资源释放的完整计算链路,而不是只压下单接口。

压测结论必须给出峰值 TPS、响应上限、队列水位、扩容点、限流阈值和恢复条件;重点验证整点开抢等瞬时尖峰,而不是日均流量。

生效中 1:预算监控与熔断,让错误来不及变贵

预算护栏要同时覆盖四个粒度:

支付存在延迟,熔断应按风险敞口计算:

预算风险敞口 = 已核销成本 + 已锁定预计成本

达到阈值后自动执行预案:先停止新增优惠承诺,已锁定预算的订单按存量策略处理。

生效中 2:降级和止损,先保交易正确

大促时不是所有能力都同等重要。

这里有一条不能破的底线:

可以少展示、少推荐、少发券,但不能让同一订单在提交前后出现两套价格。

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

活动后:对账与复盘,把临时处置变成下次规则

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

一张表走完大促上线检查

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

自查清单:你的促销下半场稳不稳

优惠分摊

  • 每层优惠是否按自己的适用商品和阶段前金额分摊?
  • 商品行分摊之和是否始终等于订单优惠总额?
  • 尾差策略是否固定,支付、退款、结算是否读取同一份结果?
  • 部分退款读取下单快照,还是会按当前活动重新计算?
  • 平台、商家、品牌承担的优惠成本是否分别记录?

券生命周期

  • 券模板、发放批次和用户券实例是否分开建模?
  • 领取、锁定、核销、解锁、过期和作废是否有完整状态?
  • 支付失败、订单取消、整单退款和部分退款分别如何返券?
  • 过期券因平台责任需要返还时,是否有补偿券机制?
  • 券库存、预算占用和实际核销成本是否分别可查?

大促交付

  • 上线前是否试算过最坏优惠组合,而不只是单活动正确性?
  • 压测是否覆盖试算、领券、锁券、核销和释放整条链路?
  • 预算是否同时计算已核销成本和已锁定风险敞口?
  • 活动是否有明确的预警、限流、熔断和恢复阈值?
  • 暂停后,已领券、未支付订单和已下单用户如何处理?
  • 活动结束后,库存、预算、核销、退款和补贴是否完成对账复盘?

总结:上下两篇 · 8 条促销体系认知

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

下期预告—— 促销体系讲完,下一篇进入营销玩法。促销解决的是「怎么算便宜」,营销要解决的是「为什么用户愿意来、愿意参与,还愿意带别人来」。

作者:Zoe产品手记 公众号:Zoe产品手记

本文由 @Zoe产品手记 原创发布于人人都是产品经理。未经作者许可,禁止转载

题图来自 Unsplash,基于CC0协议

更多精彩内容,请关注人人都是产品经理微信公众号或下载App
评论
评论请登录
  1. 优惠分摊按进入前金额基数这个原则特别重要,否则不同优惠的适用范围和承担方混在一起,退款时根本算不清。

    来自广东 回复
  2. 逐层分摊逻辑清晰,但落地时商品行快照存储和尾差一致性对数据基建要求很高,小团队可能卡在数据模型上,未必能一步到位。

    来自广东 回复
  3. 整单优惠分摊不是简单的除法,关键在每层优惠按自己进入前的金额比例分摊,部分退款必须读下单快照而不是重新计算,否则退错钱。尾差用最大余数法固定归属,这样退款、结算、对账才不会乱。

    来自广东 回复