前言
订单模块是电商系统的核心,而在订单模块中,订单价格计算是其中比较复杂的一个环节。订单价格计算主要涉及2个核心环节:
- 买家应该为这一笔订单支付多少钱?
- 完成支付后,如果买家对其中某一件商品做退款处理,应该退多少钱?
本文针对以上两个环节做详细说明。
案例介绍
为了方便理解以及引入后面的概念,我们先以各种常见的情况作为例子。这些例子从最简单的情况开始,逐渐引入其他各种影响因素,层层推进,最后引出本文要叙述的模型。在这一部分的描述,我会使用通俗易懂,也就是买家在购物过程中使用的语言。但在后续的下一部分,即建立模型的阶段,我们会使用对应的专业术语。
我们先从最简单的情况说起。
情况(1):单种商品购买1件。
案例:商品A单价5元,购买1件。
分析:如果以上述情况创建订单,很显然,买家应该支付5元,如果要退款,那么也应该是退款5元。
结果:买家需支付5元,商品A退款价(即退款一件时返还给买家的金额,下同)为5元。
说明 (1)本文中出现的“商品”,严格地讲,应该是“SKU”,为避免出现中英文混杂使用的情况,统一以“商品”进行说明。未特别说明的情况下,本文中出现的“商品”皆指“SKU”。 (2)退款按照最理想的状态,即不考虑商品折价,即买家实际为这件商品支付多少钱,则实际给买家退多少钱。
在情况(1)的基础上,我们稍微复杂一点点。
情况(2):单种商品购买多件。
案例:商品A单价5元,购买3件。
分析:如果以上述情况创建订单,容易计算的是,买家应该支付5x3=15元,如果要退款1件,那么需要给买家退款5元,2件为10元,3件为15元,即退款金额=单价x推荐件数。
结果:买家需支付15元,商品A退款价5元。
实际上,多种商品购买多件的情况也是类似的。
情况(3):多种商品购买多件。
案例:商品A单价5元,购买3件;商品B单价10元,购买2件。
分析:如果以上述情况创建订单,买家应该付款5x3+10x2=35元。如果要退款,也并不复杂,只需要计算对应商品的单价x退款数量,求和即可。
结果:买家需支付35元,商品A退款价5元,商品B退款价10元。
上面说的3种情况,基本上不会存在什么争议,简单直白,计算过程也非常浅显。接下去,我们引入电商中常见的营销活动——优惠券,情况将开始变得复杂起来。
情况(4):订单中使用优惠券。
案例:商品A单价5元,购买3件,商品A允许使用1张“满10元减6元”的优惠券。
分析:不难计算,买家应支付5x3-6=9元,但是如果需要退款1件,很显然不能像情况(1)中那样退5元了,因为如果1件退5元,那么如果3件退完,买家实际收到15元,大于买家付款的9元。这里有一个很重要的前提是:在无损耗情况下,买家完成所有商品退款,那么总退款金额应该等于付款金额。对于本案例情况,付款9元,总共3件,相当于实际每一件付款3元,那么退款1件,应该退款3元。
结果:买家需支付9元,商品A退款价3元。
再将上面的情况稍微复杂化一点。再引入部分不能使用该优惠券的商品。
情况(5):订单中部分商品可使用优惠券,部分商品不可使用优惠券。
案例:商品A单价5元,购买3件,商品A允许使用1张“满10元减6元”的优惠券。商品B单价10元,购买2件。该优惠券不适用于商品B。
分析:容易计算,买家应该支付5x3+10x2-6=29元,但在计算退款时,很显然商品B是没有被优惠的,那么单件支付10元,在退款时也应该退10元。
结果:买家需支付29元,商品A退款价3元,商品B退款价10元。
我们容易发现,在只有“优惠券”这种营销活动优惠项的情况下,判断满足使用条件后,计算应付金额只需计算总价再减去对应优惠金额即可。而在计算退款价时,稍微麻烦一点,需要判断这张优惠券具体使用到了哪些商品,再把优惠金额分摊到对应的商品上。
我们继续引入另一种优惠形式。
我们知道,在电商中,虽然营销活动有成百上千种,但万变不离其宗,总结起来,其实就两种方式:
(1)多件商品价格加起来,在总价上减免金额,使要付款的金额小于商品的价格之和。
(2)单件商品就降低金额,买一件就有优惠。
上述的“优惠券”就属于方式(1),我们引入方式(2)的优惠方式——秒杀。常见的营销文案例如“平时价19元,秒杀价15元”,这样买1件,如果没有“秒杀活动”,要支付19元,参与秒杀活动,就只需要支付15元。我们在情况(5)的基础上,引入参与“秒杀活动”的商品C。
情况(6):同时存在两种形式的优惠。
案例:商品A单价5元,购买3件,商品A允许使用1张“满10元减6元”的优惠券。商品B单价10元,购买2件。商品C秒杀价15元,购买1件。商品B和商品C不适用于该优惠券。
分析:有了前5项循序渐进的分析过程,不难分析,这种情况只需要在情况(5)的基础上直接加就可以了。
结果:买家需支付44元,商品A退款价3元,商品B退款价10元,商品C退款价15元。
实际上,运费也是不可忽视的一个环节,我们在情况(6)的基础上,再加上运费。
情况(7):包含运费。
案例:商品A单价5元,购买3件,商品A允许使用1张“满10元减6元”的优惠券。商品B单价10元,购买2件。商品C秒杀价15元,购买1件。商品B和商品C不适用于该优惠券。整个订单需支付运费10元。
分析:运费未参与任何商品营销减免计算,不需要分摊,直接往原订单的总价上加上运费即可。
结果:买家需支付54元,商品A退款价3元,商品B退款价10元,商品C退款价15元,运费退款价10元。
对于以上的例子,读者并不需要深究更复杂的排列组合的情况,文本中使用以上例子仅仅是为了让读者对于价格计算流程有一个大致的了解,下面我们引入本文的核心——订单价格计算模型。
基本概念
我们先介绍后续要使用的价格概念。
销售价
销售价指商品在实际参与售卖环节使用的价格。有一个简单的判断依据是,如果一个商品在不参与任何营销活动(例如秒杀、满减等),无任何优惠项减免的情况下,不计算运费购买单件要支付的价格就是“销售价”。
例如淘宝的“一口价”,以及京东的“京东价”,就是“销售价”。
参考价
参考价指商家设置用于和“销售价”形成对比,以便使销售价看起来优惠的价格,这几乎也是参考价的唯一用途了。参考价常以“划线价”的形式呈现(需要注意,不是所有的划线价都是参考价)。参考价其他常见的叫法还有:门市价、吊牌价、专柜价、指导价等等。
参考价不参与订单结算流程。
活动价
活动价指商品在参与营销活动时的售卖价格。例如参与“秒杀活动”的商品价格,常常会称之为“秒杀价”,这里的“秒杀价”就是商品参与“秒杀活动”的“活动价”。可以简单的将“活动价”认为是“商品参与活动时的销售价”。销售价和活动价本质上是一回事,区别就在于是否参加活动引起的叫法不同。
另外,我们将“会员价”这一种优惠方式仍计入“活动价”的范畴,例如销售价100元,会员打9折,则会员价90元。这里的会员价我们认定为参与会员活动的活动价。
后续的叙述中,所有通过改“销售价”形式的优惠,统一称该价格为“活动价”,不区分秒杀价、限时抢购价、会员价、VIP价等。
成交价
成交价指商品进入订单结算环节的价格。成交价是订单结算后续环节的起步,在后续的流程中,订单结算均只使用“成交价”,不再关心销售价和活动价。
实际上,绝大多数情况下,成交价无非就是取销售价、活动中的某一个值,作为“导购环节”和“阶段环节”的过渡。可以简单理解为,成交价就是在结算时实际使用的价格。
我们结合场景来说明。商品A销售价100元,活动价90元,那么进入订单环节的成交价就取活动价的90元;如果没有活动,成交价就取销售价的100元。如果商品A参加另一个活动——第二件半价,那么这时候买2件要分成2部分,第1件商品A成交价100元,第2件商品A成交价50元。这种优惠方式是通过改变成交价来实现的,实际上另一种方式是以优惠项方式实现。例如2件商品A成交价100元,优惠项中,项目名“第2件5折”,金额为“-50元”。
结算价
商品结算价指买家为一件商品实际支付的金额。
需要特别说明的一点是,很多平台对于“结算价”的叫法也不太一样,例如上述为了方便理解,就称为“退款价”。有些时候商家和买家沟通告知买家实际要支付多少金额的时候,有的时候也叫“到手价”。如果叫法不同,请读者注意区分。
结算价的一个很重要特征是:
付款金额=Σ结算价x数量
需要注意的一点是,结算价不仅仅用于商品,存在运费的订单,运费单独计算结算价,叫“运费结算价”,只不过运费项目往往只存在1项,就没有必要单独去讲它的结算价了。将商品和运费分开后,公司应为
付款金额=Σ商品结算价x数量 + 运费
补充说明: 更严格地讲,上面两个公司中的“付款金额”应改为“订单总价”。大多数情况下,买家的付款金额就是订单总价,但是还存在“支付环节”的优惠项目,导致实际支付金额小于订单总价,而在支付环节的优惠项目一般不参与订单结算逻辑,因此,我们一般不将支付环节的优惠项目所减的金额计入结算价逻辑中,以订单的角度,仍认定为买家支付金额=实际付款金额 + 支付环节优惠项目金额。
如未特别说明,本文所指的“订单总价”和“付款金额”实际上是同一个金额。
### 商品总价
商品总价分为“全部商品总价”和“部分商品总价”,两者区分仅在于计算时是否将所有商品全都算进去。计算公式为:
商品总价=Σ成交价x数量
部分商品总价一般用于判断是否达到优惠项条件时使用,例如有一张“满30元减10元”的优惠券可用于商品A和B,在订单中商品A成交价10元,购买2件,商品B成交价20元,购买1件,商品C成交价30元,购买1件。那么在判断该优惠券能否使用时,就需要判断商品A和商品B的“部分商品总价”,在本例子中,部分商品总价=10x2+20=40>30,因此可以使用该优惠券。
一般未特别说明的“商品总价”特指“全部商品总价”。
优惠项
优惠项指在商品总价基础上,能够达到减免应付金额的项目,是营销活动在订单中的呈现。前面提到了营销活动从本质上就两种优惠方式:
(1)以优惠项的方式减总金额。
(2)成交价取活动价而非销售价(活动价一般低于销售价)。
订单总价
订单总价指订单完成结算计算,得出的金额,也就是买家的应付金额。
计算流程
第一步:确定商品参与的营销活动以及采取的优惠呈现形式。
第二步:确定商品的成交价。
第三步:根据商品总价以及优惠项、运费等,确定订单总价。
第四步:将优惠项所减免的金额进行拆分,分摊到所使用的商品上。
第五步:根据商品的成交价以及被分摊减免的金额,确定结算价。
案例演示
类似以上的案例介绍,我们从浅入深提供若干个案例来演示以上的计算流程。
情况(1):商品参加秒杀活动,使用秒杀价。
案例:商品A销售价10元,秒杀价8元,购买3件。包邮。
分析:商品A使用秒杀价,此时订单结算环节的“成交价”应取“秒杀价”,即成交价为8元。无其他优惠项,因此结算价也是8元。订单总价=8x3+0=24元。
结果:商品A成交价8元,商品总价24元,订单总价24元,商品A结算价8元。
情况(2):商品参加满减活动。
案例:商品A销售价20元,购买2件;商品B销售价30元,购买2件;商品C销售价50元,购买1件。其中只有商品A和商品B参加“满49减20”活动,商品C不参加。运费10元。
分析:首先,由于满减活动属于“以优惠项方式减免金额”,因此不存在活动价,所有的“成交价”都取“销售价”。得出下表:
判断是否达到“满减条件”,则需要计算订单中参与活动的商品的“部分商品总价”,已知商品A和商品B参与该满减活动,得部分商品总价=20x2+30x2=100元,该金额大于满减门槛,因此可使用“满减”优惠。
计算商品总价=20x2+30x2+50x1=150元。
优惠项——满减优惠:-20元
运费:10元
因此订单总价=150-20+10=140元,买家应该为这一笔订单支付140元。下面计算商品结算价,满减优惠的20元需要分摊到对应商品上,运费不参与分摊。
现在要做的是,将这20元,分摊到对应的部分商品总价100元上,按照比例,可以得出每1元成交价分摊 20/100 = 0.2元。因此得出下表(为空表示不参与分摊):
我们进行验证,分摊到单件的满减金额乘购买数量,是否等于总满减金额。
4x2+6x2=20,正确。
再次分别以成交价和结算价各自求和进行验证。
订单总价=Σ成交价x购买数量 - 优惠项减免金额 + 运费 = 140元
订单总价=Σ结算价x购买数量 + 运费 = 16x2+24x2+50x1+10=140元
验证了以上计算的正确性。
因此结果为:
商品A:成交价20元,结算价16元
商品B:成交价30元,结算价24元
商品C:成交价50元,结算价50元
订单总价:140元
基于情况(2),我们再继续引入更为复杂的业务场景,一般来讲,只要理解了以下这种情况,基本上对于订单计算就可以熟能生巧了。一般来讲,很少会出现下述这么多优惠项叠加的情况,但本文讨论的是如果出现应该怎么处理而不是业务上这样设定是否合理。
情况(3):包含活动价、满减、优惠券等多种活动。
案例:商品A销售价20元,参与秒杀活动,秒杀价10元,购买2件;商品B销售价30元,购买2件;商品C销售价50元,购买1件。其中只有商品A和商品B参加“满49减20”活动,商品C不参加。商品B和商品C可使用1张“满100减11”的优惠券。运费10元。三种营销活动优惠可叠加。
分析:
(1)首先各营销活动的优惠形式。秒杀改成交价,满减和优惠券以优惠项的形式呈现。
(2)商品A的成交价取秒杀价,为10元,商品B和商品C成交价直接取销售价,分别为30元和50元。
(3)满减部分商品总价,需计算商品A和商品B,为10x2+30x2=80元,大于49元的门槛,因此可使用该项满减优惠。优惠券部分商品总价,需计算商品B和商品C,为30x2+50x1=110元,大于优惠券使用门槛的100元,该优惠券可使用。
计算商品总价=10x2+30x2+50x1=130元
优惠项1——满减优惠:-20元
优惠项2——优惠券:-11元
运费:10元
因此订单总价=130-20-11+10=109元
(4)下面计算各优惠项的分摊金额。满减部分总80元分摊20元,相当于每1元成交价分摊0.25元。优惠券部分总110元分摊11元,相当于每1元成交价分摊0.10元。得出下表:
我们以结算价角度验证订单总价,为7.5x2+19.5x2+45x1+10=109元,与上述结果一致。
实际上,只要我们总结以下规律,就可以很轻松地完成整个订单计算过程:
(1)先确定成交价,后续所有订单环节只用到成交价。
(2)使用部分商品总价确定可使用哪些优惠项。
(3)将使用的优惠项全部列出来,并分摊到实际使用的商品上(运费不参与分摊)。
(4)成交价减去优惠项分摊金额就是商品的结算价。
延伸
结算价有什么用?
从本文前面案例中发现,结算价只用在退款环节,这也是结算价在某些时候也被称为“退款价”的原因。由于结算价是“实际支付某商品花的钱”,所以后续与此相关的环节大多用的都是结算价。
例如,你肯定见过“某类商品付款累积满N元,就……”,这里计算“付款累积”环节,用的就是商品的结算价。又比如“推荐好友下单,返利XXX”活动,计算推荐人的返利金额的时候,一般也是采用结算价。
是否电商系统都要遵循这一套逻辑?
以上这套逻辑讲究的是学术上的“正确”,即本文解决在“如果要这么做”的前提下,“应该怎么做”的问题。实际业务并不一定需要这么复杂,可根据实际情况缩减逻辑。比如有的平台直接不允许退款,或者只允许退款一次等等,不同的平台可以有不同的业务设定。
事实上,本文所叙述的模型,不仅适用于电商的订单,其他类型的交易订单都可以参考本文叙述的模型来建立计算过程。这一点上是通用的。
简单模型
上述的完整模型,最复杂的环节就是在计算商品“结算价”上了,参与判断的因素实在太多,需要将一项项优惠券拆分到商品上进行分摊,非常复杂。这时候可以建立一个简单的模型,即虽然仍需分摊,但不管商品是否参与该优惠项,统一进行平均分摊。(甚至可以将运费也一起分摊),得出:
结算价=成交价*订单总价/商品总价
反向验证为
订单总价=Σ商品结算价x购买数量
采用以上这种计算方式,复杂度将大大降低,适合业务不太复杂以及退款概率比较小的中小型电商平台使用。
除不尽情况处理
上面的讨论从数学的角度是没问题的,但是一旦涉及到“金额”,就会有一个突出问题,那就是金额的小数位只能到分,不允许存在例如“0.1111111”形式的金额,因此我们可能会遇到以下这种情况:
商品A单价5元,购买3件,使用一张“满10减5”的优惠券,实际支付10元,但在计算结算价时,正确的应该是“3.33333.....”,但显然这不是一个正确的金额,因此只能记为“3.33”,但在相加时,总金额为“9.99”元,少于实付金额。
针对以上场景,一般有两种解决方案。方案一是结算价仍记为3.33,仅在退款环节做判断,如果存在全部商品退款的情况,少的0.01元于最后补上。方案二是将商品分成两行记录,一行为购买2件,结算价3.33,第二行为购买1件,结算价3.34。这两种方案都是可行的,需要根据其他环节的业务实施情况选择更容易处理的方案。