一、背景随着vivo商城业务架构的不断升级,将整个商城复杂多变的营销方式拆分为独立的促销体系。拆分后的推广系统,初期只负责营销活动玩法的维护。促销中最重要的定价业务仍然留在商城主站的业务中。下单和下单三部分的定价逻辑是分开维护的,并不统一。显然,随着促销折扣的增加或玩法的改变,商城端的重复业务开发量会大幅增加。促销系统是独立的,定价相关的业务能力也应该由促销系统从业务边界提供。因此,促销方需要从头开始设计促销定价相关的能力。2.原有定价业务2.1定价业务场景商城原有定价业务主要涉及业务详情页、购物车、订单确认、订单提交。如果将每一个影响最终售价的折扣称为一个定价因素,那么上述场景中对售价产生影响的定价因素可以分为三类:促销活动(单品折扣、订单折扣)、优惠券(coupons),vouchers)virtualdeduction(points,renewalincentives)对于各个定价场景和定价因素有如下关系:2.2原定价模型在定价业务的具体实现中各个定价因素中有一定的优先级关系,如如下图所示,也在一定程度上说明了原有的定价业务模型:3.促销定价模型3.1层次模型促销系统从无到有构建基本的定价能力,系统必须具备一定的稳定性和可扩展性。保,这也对促销系统的定价模式提出了一定的要求。最好有一个经过一定实践经验验证的通用基础定价模型,所以我们采用传统电子商务模式久经考验的定价模式:阶梯定价。所谓分级定价,是指传统电商中折扣所涉及的三个层次:商品层、店铺层、平台层。一般情况下,不同级别的折扣默认可以叠加,同级别的折扣默认相互排斥。.这里需要说明的是,在计算每个级别的折扣时,是否满足部分折扣的阈值条件取决于原价。默认情况下,取决于上一级折扣的计算价格,即产品级折扣的计算取决于产品的原价,店铺级折扣取决于产品级折扣的计算价格,平台级折扣取决于商店级折扣的计算价格。叠加规则特别说明:正常折扣叠加是指可以同时享受两种折扣。不同级别折扣默认叠加,同级别折扣默认不叠加。例如,在正常情况下,优惠券下的各种折扣只能使用一张优惠券。但在某些场景下,商家会规定同级折扣可以叠加。同时叠加的使用场景会分为普通叠加和平行叠加。例如:订单折扣和优惠券两种类型。叠加为正常叠加(是否满足优惠券阈值的判断取决于订单折扣后的价格),优惠券与代金券的叠加为平行叠加(判断是否满足优惠券与代金券的阈值取决于之前折扣后的价格)。同级折扣按不同维度分类:强制/选择性、叠加(平行叠加/正常叠加)/非叠加。3.2新定价模型3.3核心定价流程3.3.1主要流程根据前述定价模型可知,计算优惠价的顺序为:商品层(CalcItem)、门店层(CalcShop)、平台层(CalcGroup)、另外,根据一些特殊的业务场景,增加了可能的中断业务逻辑(CalcInterrupt),所以可以得到下图所示的最粗粒度的定价过程;这三层优惠价格的计算在内部是如何实现的?经过业务抽象后,这三个层级的计算可以转化为一个通用的计算折扣逻辑,只有折扣层级的区分。3.3.2一般流程通过业务抽象,找到三个层次的折扣计算的一般逻辑:获取当前级别促销查询(GetCurrentLevelPromotionGetter)、过滤促销查询(FilterPromotionGetter)、查询促销(GetPromotion),过滤促销(FilterPromotion)通过定价引擎(CalcEngine)计算折扣,并对定价结果进行过滤(FilterCalcResult),所以我们得到如下大致的定价流程:定价过程,从下面的详细过程中可以了解到更多的实现。3.3.3详细流程一般定价流程中之所以有多个过滤节点,是因为业务中有一些特殊的过滤逻辑。此折扣只能通过特殊渠道等方式享受。因此,需要抽象出一种通用的、可扩展的过滤机制来满足业务需求,所以会根据不同的维度定制一些链式过滤器。部分业务,如终端、支付方式、外部业务方等,在实际实施中可以非常灵活的支持。上面的过滤器是如何制定的?它与业务有何关系?上图中列出了一些业务自定义过滤器排序器。自定义过滤器后,会自动注册到统一的折扣业务过滤器工厂。在前述的定价过程中,当你需要使用相关过滤器时,只需要带上相关过滤器的Context参数就可以自动从过滤器工厂获取匹配的过滤器。3.3.4完整完整流程将前面的一系列流程进行组合组装,可以得到一个完整完整的定价流程图,如下:支持业务变化的自定义过滤器,既保证了核心的稳定性,又保留了灵活的扩展能力。4.系统核心设计一般定价执行过程中的一个节点是“计算引擎”,即定价引擎。这是整个定价逻辑中最核心的底层能力,用来决定每一个折扣是否能被用户享受到。4.1统一折扣模型由于定价中心正在建设中,促销系统中的各种促销活动,独立的优惠券和代金券,以及留在商城主站的未迁移折扣已经存在,所以我想用它来兼容so优惠类型较多,需要建立统一的优惠模型,在建设过程中,需要对现有的优惠模型进行适配和转换为统一的模型。统一折扣模型中的一些关键信息包括:折扣标识、折扣类型、折扣模板id、起止时间、折扣参数和部分扩展参数等。4.2折扣模板1)在进行促销定价时,每个具体的折扣都会对应独特的折扣模板。每个折扣模板本质上都是一个JSON字符串,但是这些JSON字符串是按照一定的特殊逻辑规则创建元信息数据进行转化的,这些元信息在被定价引擎解释执行的时候,都会返回布尔类型来表示是否它通过与否。2)基础元信息数据有几种类型:**AndMeta(AND)**对应逻辑关系中的“与”关系,表示对此类元信息所包含的子元信息的解释和执行元信息返回true为true。;**OrMeta(or)**对应逻辑关系中的“或”关系,即对此类元信息所包含的子元信息的任何解释和执行都返回true;**NotMeta(非)**对应于逻辑关系中的“非”关系,表示该类型的元信息中包含的子元信息被解释为假,当前元信息为真;**ConditionalMeta(condition)**如果条件参数不存在或者是由从上下文中获取的参数指定的如果布尔值不为true,则当前元信息返回true,否则根据解释执行的结果将元信息中包含的子元信息作为当前元信息的执行结果;**ComplexMeta(组合元信息)**元信息作为所有模板元信息的总载体包含两个重要的信息条件和动作。两者的关系是只有condition条件满足后,才会执行后续action,而condition和action可能是上述各种元信息的复杂组合。3)模板元信息关系:4)折扣模板示例:{"type":"COMPLEX","condition":{"type":"AND","metas":[{"type":"CONDITIONAL",“metas”:[{“type”:“CONDITION”,“metaCode”:“terminalCheckCondition”}],“param”:“needTerminalCheck”},{“type”:“CONDITION”,“metaCode”:“amountOverCondition”}]},"action":{"type":"AND","metas":[{"type":"ACTION","metaCode":"cutPriceAction"},{"type":"ACTION","metaCode":"freezeCouponAction"}]}}4.3定价引擎定价引擎本质上是对相应折扣模板的解释和执行,配合相关上下文计算折扣。关键代码如下:privatebooleanexecuteMeta(Metameta,EngineContextcontext){if(metainstanceofAndMeta){returnexecuteAndMeta((AndMeta)meta,context);}elseif(metainstanceofOrMeta){returnexecuteOrMeta((OrMeta)meta,context);}elseif(metainstanceofNotMeta){returnexecuteNotMeta((NotMeta)元,上下文);}elseif(metainstanceofComplexMeta){returnexecuteComplexMeta((ComplexMeta)meta,context);}elseif(metainstanceofConditionalMeta){returnexecuteConditionalMeta((ConditionalMeta)meta,context);}else{returnexecuteIMeta(meta,context);}}......privatebooleanexecuteComplexMeta(ComplexMetacomplexMeta,EngineContextcontext){Metacondition=complexMeta.getCondition();元操作=complexMeta.getAction();returnexecuteMeta(condition,context)&&executeMeta(action,context);}privatebooleanexecuteConditionalMeta(ConditionalMetaconditionalMeta,EngineContextcontext){PromotionContextpromotionContext=context.getPromotionContext();}如果(promotionContext==null||promotionContext.getParameters()==null){returntrue;}StringconditionParam=conditionalMeta.getParameter();字符串sNeedProcess=promotionContext.getParameters().get(条件参数);如果(sNeedProcess==null){返回真;}booleanneedProcess=Boolean.parseBoolean(sNeedProcess);如果(needProcess){返回executeMeta(conditionalMeta.getMetas().get(0),context);}else{返回真;}}privatebooleanexecuteIMeta(Metameta,EngineContextcontext){IMetaiMeta=MetaFactory.get(meta.getMetaDef().getMetaCode());if(iMeta==null){thrownewCalcException("metanotfound,metaCode="+meta.getMetaDef().getMetaCode());}returniMeta.execute(context);}5.小结通过前面几章的描述,我们基本上把vivo商城推广系统建设定价中心的关键思想定价中心讲解完了,核心基础整个晋升体系的建立,而这仅仅是开始。围绕整个商城的促销定价中心还有其他的东西要搭建,比如整个商城的营销价格能力矩阵、价格监控、商城时光机等等,有机会我们会输出相关的文章在后续跟大家交流学习。作者:vivo互联网服务器团队-魏富平
