促销

ECstore中促销的几大模块

  • 商品促销
    商品促销是指基于商品开展的各种促销规则,优惠直接显示在购物车中。
    
  • 订单促销
    订单促销则是针对订单、购物车中所有商品的促销,优惠在购物车下订单结算时显示。
    
  • 优惠券
    优惠券在促销这块的规则是订单促销的一种
    

ECstore中促销的几大因素

  • 优先级
    执行顺序以数值 从高到低 执行
    
  • 排它原则
    优惠规则的冲突解决。如:商品促销中,同种方案在``同一商品``上适用排他原则。
    
  • 优惠条件
    判断该促销是否适用于当前场景,如:当订单商品总价满X时,对所有商品优惠。
    
    • 应用条件(优惠方案要应用到的商品)
      指定优惠方案的应用范围,特指订单促销当中,商品促销中没有此项。
      
  • 优惠方案
    指满足应用条件的商品或者订单等享受的优惠结果。如:符合应用条件的商品送赠品。
    

优惠条件-概念

优惠条件,就ecstore系统来说就是商品促销或者订单促销中的优惠条件,是一个过滤规则

包括聚合器和条件项,一个聚合器可以包含多个聚合器和条件项

  • 聚合器
    优惠条件的基础、每个条件都是从聚合器开始的,聚合器是优惠条件的一个容器,
    可以容纳更多的聚合器和条件项组成一个完整的促销过滤条件。
    public function getItem()
    返回标准化数据
    
    下面以商品聚合器为例:
    class b2c_sales_goods_aggregator_combine extends b2c_sales_goods_aggregator{
        public function getItem() {
            // 其实一个aggregator 只有一条记录的哈
            return array(
                'b2c_sales_goods_aggregator_combine' => array(
                    'name'=>app::get('b2c')->_('商品条件'),
                    'value'=>'goods_combine',
                    'object'=>'b2c_sales_goods_aggregator_combine',
                    'support'=>array(
                        'aggregator'=>'all',
                        'item'=>array(
                            'goods' => app::get('b2c')->_('-----商品属性-----'),
                            'brand' => app::get('b2c')->_('-----商品品牌-----'),
                            'type'  => app::get('b2c')->_('-----商品类型-----'),
                            'cat'   => app::get('b2c')->_('-----商品分类-----'),
                        )
                    ),
                )
            );
        }
    }
    该数组为其返回值。item属性标明了包含项{goods:商品属性;brand:商品品牌;type:商品类型;cat:商品分类}
    
    具体商品项加载项相关请看下边 ··促销概念-项·· 的介绍
    
  • 基于聚合器详细的阐述了包含哪些具体的属性。
    
    接上:以商品属性为例说明。
    
    class b2c_sales_goods_item_goods extends b2c_sales_goods_item{
        public function getItem() {
            return array(
                'goods_goods_id'      => array('name'=>app::get('b2c')->_('商品'),       'path'=>'goods_id',      'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('contain'), 'input'=>'dialog', 'table'=>'goods',),
                'goods_brand_id'      => array('name'=>app::get('b2c')->_('商品品牌'),   'path'=>'brand_id',      'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('contain'), 'input'=>'checkbox', 'options'=>'table:SELECT brand_id AS id,brand_name AS name FROM sdb_b2c_brand'),
                'goods_cat_id'        => array('name'=>app::get('b2c')->_('商品分类'),   'path'=>'cat_id',        'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('contain'), 'input'=>'checkbox', 'options'=>'table:SELECT cat_id AS id,cat_name AS name, parent_id AS pid FROM sdb_b2c_goods_cat'),
                'goods_type_id'       => array('name'=>app::get('b2c')->_('商品类型'),   'path'=>'type_id',       'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('contain'), 'input'=>'checkbox', 'options'=>'table:SELECT type_id AS id,name FROM sdb_b2c_goods_type'),
    
                'goods_name'          => array('name'=>app::get('b2c')->_('商品名称'),   'path'=>'name',          'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','contain','contain1')),
                'goods_brief'         => array('name'=>app::get('b2c')->_('商品简介'),   'path'=>'brief',         'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','contain','contain1','null')),
                'goods_intro'         => array('name'=>app::get('b2c')->_('商品介绍'),   'path'=>'intro',         'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','contain','contain1','null')),
                'goods_mktprice'      => array('name'=>app::get('b2c')->_('商品市场价'), 'path'=>'mktprice',      'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'unsigned'),
                'goods_cost'          => array('name'=>app::get('b2c')->_('商品成本价'), 'path'=>'cost',          'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'unsigned'),
                'goods_price'         => array('name'=>app::get('b2c')->_('商品销售价'), 'path'=>'price',         'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'unsigned'),
                'goods_bn'            => array('name'=>app::get('b2c')->_('商品货号'),   'path'=>'bn',            'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','contain','contain1'),  'vtype'=>'alphaint'),
                'goods_weight'        => array('name'=>app::get('b2c')->_('商品重量'),   'path'=>'weight',        'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'unsigned'),
                'goods_unit'          => array('name'=>app::get('b2c')->_('商品单位'),   'path'=>'unit',          'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','contain','contain1'),  'vtype'=>'alphanum'),
                'goods_store'         => array('name'=>app::get('b2c')->_('商品库存'),   'path'=>'store',         'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
                'goods_score'         => array('name'=>app::get('b2c')->_('商品积分'),   'path'=>'score',         'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
                'goods_last_modify'   => array('name'=>app::get('b2c')->_('修改时间'),   'path'=>'last_modify',   'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'input'=>'datetime','vtype'=>'date'),
                'goods_rank'          => array('name'=>app::get('b2c')->_('商品评分'),   'path'=>'rank',          'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'number'),
                'goods_rank_count'    => array('name'=>app::get('b2c')->_('评分次数'),   'path'=>'rank_count',    'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
                'goods_view_count'    => array('name'=>app::get('b2c')->_('浏览次数'),   'path'=>'view_count',    'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
                'goods_buy_count'     => array('name'=>app::get('b2c')->_('购买次数'),   'path'=>'buy_count',     'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
                'goods_comment_count' => array('name'=>app::get('b2c')->_('评论次数'),   'path'=>'comment_count', 'type'=>'goods', 'object'=>'b2c_sales_goods_item_goods', 'operator'=>array('equal','equal1'),  'vtype'=>'digits'),
            );
        }
    }
    
    getItem()详解
    | name     | 名称 |
    | path     | 购物车中的相对路径 |
    | type     | 类型 |
    | object   | 所属对象 |
    | operator | 操作符 |
    | name     | 名称 |
    | input    | html显示类型,默认text文本框 dialog弹窗 对应属性table 弹窗罗列的数据表名称 |
    | input    | checkbox 对应属性options 支持sql语句 如上 |
    | input    | datetime 日期 |
    
    

促销-service

促销的service

  • b2c_promotion_tpl_goods_apps 商品 预过滤 条件模板
    <service id="b2c_promotion_tpl_goods_apps">
        <class>b2c_promotion_conditions_goods_allgoods</class>
        <class>b2c_promotion_conditions_goods_brand</class>
        <class>b2c_promotion_conditions_goods_cat</class>
        <class>b2c_promotion_conditions_goods_selectgoods</class>
        <class>b2c_promotion_conditions_goods_type</class>
        <class>b2c_promotion_conditions_goods_typeandbrand</class>
    </service>
    
    以b2c_promotion_conditions_goods_brand举例说明。
    
    class b2c_promotion_conditions_goods_brand{
        var $tpl_name = "商品品牌";
        var $tpl_type = 'config';  // 类型 分为 html(写死的html) | config(可选项的) | auto(全开放的配置)
    
        function getConfig($aData = array()) {
            return  array(
                'type'=> 'b2c_sales_goods_aggregator_combine',
                'aggregator'=> 'all',
                'conditions'=> array(
                    0 => array(
                        'type' => 'b2c_sales_goods_item_goods',
                        'attribute' => 'goods_brand_id'
                    )
                )
            );
        }
    }
    
    tpl_name 模板显示title
    tpl_type 模板类型
    
    getConfig函数
    	tpl_type 为 html 类型时 返回html
    	tpl_type 为 config 类型时 返回标准化数组
    	tpl_type 为 auto 返回空数组即可
    
  • b2c_promotion_tpl_order_apps 订单促销 条件模板
    <service id="b2c_promotion_tpl_order_apps">
        <class>b2c_promotion_conditions_order_allorderallgoods</class>
        <class>b2c_promotion_conditions_order_itemsquanityallgoods</class>
        <class>b2c_promotion_conditions_order_itemsquanityuserdefinedgoods</class>
        <class>b2c_promotion_conditions_order_subtotalallgoods</class>
        <class>b2c_promotion_conditions_order_subtotalselectgoods</class>
        <class>b2c_promotion_conditions_order_subtotaluserdefinedgoods</class>
    </service>
    
    注:参数同上(预过滤 条件模板)
    
  • b2c_promotion_solution_tpl_apps 优惠方案模板
    <service id="b2c_promotion_solution_tpl_apps">
        <class>b2c_promotion_solutions_byfixed</class>
        <class>b2c_promotion_solutions_bypercent</class>
        <class>b2c_promotion_solutions_tofixed</class>
        <class>b2c_promotion_solutions_topercent</class>
        <class>b2c_promotion_solutions_addscore</class>
        <class>b2c_promotion_solutions_toscore</class>
    </service>
    
    public function config($aData = array())
    @return 优惠方案html模板
    
    /*
     * 优惠方案应用
     * @param array $object  // 引用的一个商品信息
     * @param array $aConfig // 优惠的设置
     * @param array $cart_object // 购物车信息(预过滤的时候这个为null)
     * @return void // 引用处理了,没有返回值
     */
    public function apply(&$object,$aConfig,&$cart_object = null) {
      ......
    }
    
    /*
     * 优惠方案应用
     *
     * 应用于订单促销中针对于订单项
     *
     * @param array $object  // 引用的一个商品信息
     * @param array $aConfig // 优惠的设置
     * @return void // 引用处理了,没有返回值
     */
    public function apply_order(&$object, &$aConfig,&$cart_object = null) {
      .....
    }
    
    public function get_status()
    @return bool
    @当前类型促销是否可用。场景:积分促销(后台积分未开启时 此处返回false)
    
  • b2c_sales_basic_operator_apps 促销操作符
    <service id="b2c_sales_basic_operator_apps">
        <class>b2c_sales_basic_operator_equal</class>
        <class>b2c_sales_basic_operator_equal1</class>
        <class>b2c_sales_basic_operator_contain</class>
        <class>b2c_sales_basic_operator_contain1</class>
        <class>b2c_sales_basic_operator_belong</class>
        <class>b2c_sales_basic_operator_null</class>
    </service>
    
    /*
     * @操作符数组
     *
     * @return array
     */
    public function getOperators()
    
    /*
     * validate
     *
     * @param string $operator  // 操作符
     * @param mix $value        // 规则里设定的值
     * @param mix $validate     // 购物车项中取出的对应的'attribute'[path] 的值
     * @return boolean
     */
    public function validate($operator,$value,$validate)
    
  • b2c_sales_goods_aggregator_apps 商品促销 预过滤 聚合器
    <service id="b2c_sales_goods_aggregator_apps">
        <class>b2c_sales_goods_aggregator_combine</class>
    </service>
    
    注:参考··优惠条件-概念 聚合器··
    
  • b2c_sales_goods_item_apps 商品促销 预过滤 项
    <service id="b2c_sales_goods_item_apps">
        <class>b2c_sales_goods_item_goods</class>
        <class>b2c_sales_goods_item_brand</class>
        <class>b2c_sales_goods_item_cat</class>
        <class>b2c_sales_goods_item_type</class>
    </service>
    
    注:参考··优惠条件-概念 项··
    
  • b2c_sales_order_aggregator_apps 订单促销 聚合器
    <service id="b2c_sales_order_aggregator_apps">
        <class>b2c_sales_order_aggregator_combine</class>
        <class>b2c_sales_order_aggregator_found</class>
        <class>b2c_sales_order_aggregator_subselect</class>
    </service>
    
    注: 参考··优惠条件-概念 聚合器··
    
  • b2c_sales_order_item_apps 订单促销 项
    <service id="b2c_sales_order_item_apps">
        <class>b2c_sales_order_item_goods</class>
        <class>b2c_sales_order_item_subgoods</class>
        <class>b2c_sales_order_item_order</class>
    </service>
    
    注:参考··优惠条件-概念 项··
    

添加一个后台促销规则

简单介绍

我们先介绍系统的优惠条件模板和应用条件模板等的配置添加。

这里我们以添加商品促销规则为例,订单促销规则类似。

商品促销针对的是一个产品的促销规则,显示在商品详情页,优惠直接显示在购物车中。

首先在后台商品促销中点击添加规则,如图:

添加规则页面主要由三个部分组成,基本信息优惠条件优惠方案,分别如图:

基本信息:

基本信息包括以下几点:
规则名称:规则的名称
规则描述:规则的描述,例如可以显示在商品详情页
启用状态:即是否启用此条规则
优先级:
是否排它:是否跟其他规则进行排斥选择
开始时间:
结束时间:
会员级别:指哪些等级的会员可以享受优惠

优惠条件:

优惠条件就是一组过滤条件,界定商品和订单的应用条件
它一般包括几个优惠条件模板,例如:
商品促销中:
自定义商品促销模板(此条模板需要安装app(proundefined))
商品类型+商品品牌
商品类型
指定商品
商品分类
商品品牌
所有商品

订单促销中:
用户自定义订单促销模板(此条模板需要安装app(proundefined))
当订单商品总价满X,对指定的商品优惠
当订单商品总价满X时,对所有商品优惠
当订单商品数量满X,给予优惠
对所有订单给予优惠

优惠方案:

指满足应用条件的商品或者订单等享受的优惠结果。

商品促销中一般包括以下几点:
符合应用条件的商品X倍积分
符合应用条件的商品赠送积分
符合应用条件的商品以固定折扣出售
符合应用条件的商品固定价格购买
符合应用条件的商品减去固定折扣出售
符合应用条件的商品减固定价格购买
符合应用条件的商品送赠品

订单促销中:
(商品促销中的几条优惠模板)
订单免运费
订单X倍积分
订单赠送积分
订单以固定折扣出售
订单固定价格购买
订单减去固定折扣出售
订单减固定价格购买
订单送赠品
注:对于以上所讲的优惠条件模板,我们做个解释,优惠条件中的自定义促销模板是需要安装名叫
proundefined的app的,而其他固定的模板列表其实际上是一个自定义的过滤条件的一个实际规则抽
出来作为单独的规则,本质都是自定义一个过滤条件,只不过把它固化了而已,方便直接选择。

案例讲解

我们添加一个自定义商品促销模版的优惠条件

的规则,然后它的优惠条件如下:

这里优惠条件的标准数据格式是这样的:
return array(
	'type'=> array(
		'input'=> 'hidden',
		'desc'=> null,
		'default'=> $this->default,    // 默认值 如果有模板设置 按模板设定 如果有值 则按值的
		'support'=>$aTemp[get_class($this)]['support'],
	),
	'aggregator'=> array(
		'input'=> 'select', // select | hidden
		'vtype'=> null,     // 验证类型(保留)
		'desc'=> null,      // 描述 标准为空 如果为空的话 使用default的名称 只在input='hidden'时有效
		'options'=> array(
			'any'=>array('name'=>app::get('b2c')->_('任意一条规则')),
			'all'=>array('name'=>app::get('b2c')->_('所有规则')),
		),
		'default'=> 'all'    // 默认值 如果有模板设置 按模板设定 如果有值 则按值的
	),
	'value'=> array(
		'input'=> 'select', // select | hidden
		'vtype'=> null,     // 验证类型(保留)
		'desc'=> null,      // 描述 标准为空 如果为空的话 使用default的名称 只在input='hidden'时有效
		'options'=> array(
			'0'=>array('name'=>app::get('b2c')->_('不符合')),
			'1'=>array('name'=>app::get('b2c')->_('符合')),
	    ),
		'default'=> '1'    //
	),
	'conditions'=> array()
);

数组中的conditions就是我们具体的一条过滤语句了
我们这次添加的规则的conditions的数据格式为:
array (
	'type' => 'b2c_sales_goods_aggregator_combine',
	'aggregator' => 'all', // 'all'|'any' [and连接条件 或 or连接条件]
	'value' => '1', // 0|1   不满足以下条件 | 满足以下条件  (//不满足? 暂无很好的处理方法 可以用子查询实现 效率太低了 1暂时写死)
	'conditions' => array (
		2 => array (
			'type' => 'b2c_sales_goods_item_goods',
			'attribute' => 'goods_type_id',
			'operator' => '()',
			'value' => array (
				0 => '5',
			),
		),
		1 => array (
			'type' => 'b2c_sales_goods_item_goods',
			'attribute' => 'goods_price',  // 商品的属性
			'operator' => '>=',            // 操作
			'value' => '200',              // 值 string | array
		),
		0 => array (
			'type' => 'b2c_sales_goods_item_goods',
			'attribute' => 'goods_brand_id',
			'operator' => '()',
			'value' => array (
				0 => '2',
			),
		),
	),
)

应用的优惠方案如下:

下面重点讲优惠条件的添加,我们这里仍然讲的是怎么组合,具体的代码方法稍后祥讲,这里商品自定义促销模版如下:

集合器分为两种,一种是“所有规则”,它下面产生的条件是“与”的关系,即所有条件都符合则应用这个促销规则;另一种是“任一规则”,即其下面任意一个条件符合则应用这个规则,是一种“或”的关系。

集合器 匹配值 匹配结果
所有规则 符合 所有条件都符合则应用此规则
所有规则 不符合 所有条件都不符合则应用此规则
任意一条规则 符合 任意一条条件都符合则应用此规则
任意一条规则 不符合 任意一条条件都不符合则应用此规则

这里的“添加一个条件”,主要包括“条件组合”,“商品属性”,“商品品牌”,“商品类型”,“商品分类”五种条件,“条件组合”,就是再添加一个集合器,即:

只不过此集合器属于上面集合器的子类;而其他的几个条件则是单独的条件了,可以根据需求自己选择。

促销规则主要数据表

商品预过滤

  • 商品促销规则表 sdb_b2c_sales_rule_goods
    商品预过滤基表
    
    rule_id 规则id
    name 规则名称
    description 规则描述
    create_time 修改时间
    from_time 起始时间
    to_time 截止时间
    member_lv_ids 会员级别集合
    status 开启状态//status 标志是否使用该规则执行预过滤
    conditions 规则条件
    stop_rules_processing 是否排斥
    sort_order 优先级
    action_solution 动作方案
    free_shipping 免运费
    c_template 过滤条件模板
    s_template 优惠方案模板
    apply_time 预过滤时间

  • 商品与商品促销规则表 sdb_b2c_goods_promotion_ref
    商品预过滤规则添加之后需要手动应用该规则。应用之后会把对应数据插入到预过滤关联表,关联到具体商品
    
    ref_id id
    goods_id 商品ID
    rule_id 规则ID
    description 规则描述
    member_lv_ids 会员级别集合
    from_time 起始时间
    to_time 截止时间//预定字段
    status 状态
    stop_rules_processing 是否排斥其他规则
    sort_order 优先级
    action_solution 动作方案
    free_shipping 免运费

订单促销

  • 订单促销规则表 sdb_b2c_sales_rule_order
    订单促销结构(优惠券形成的规则也会在该表记录 rule_type)
    
    rule_id 规则id
    name 规则名称
    description 规则描述
    from_time 起始时间
    to_time 截止时间
    member_lv_ids 会员级别集合
    status 开启状态
    conditions 规则条件
    action_conditions 动作执行条件
    stop_rules_processing 是否排斥
    sort_order 优先级
    action_solution 动作方案
    free_shipping 免运费/满足过滤条件的商品免运费/全场免运费
    rule_type N:普通规则/C:优惠券规则
    c_template 过滤条件模板
    s_template 优惠方案模板

优惠券

  • 优惠券表 sdb_b2c_coupons
    优惠券结构,基本信息会存储在sdb_b2c_coupons表中,形成的具体规则会放入sales_rule_order中
    
    cpns_id 优惠券方案id
    cpns_name 优惠券名称
    pmt_id *暂时废弃
    cpns_prefix 生成优惠券前缀/号码(当全局时为号码)
    cpns_gen_quantity 总数量
    cpns_key 优惠券生成的key
    cpns_status 是否启用优惠券方案状态
    cpns_type 优惠券类型:一张无限使用/多张使用一次/外部优惠券
    cpns_point 兑换优惠券积分
    rule_id 相关的订单促销规则ID // rule_type ='C'
  • 用户优惠券表 sdb_b2c_member_coupon
    记录该会员兑换的优惠券信息
    
    memc_code
    cpns_id
    member_id
    memc_gen_orderid
    memc_source 全体优惠券/会员优惠券/ShopEx优惠券
    memc_enabled
    memc_used_times
    memc_gen_time