龙空技术网

如何设计一个可扩展的优惠券功能

吾日三省Java 2341

前言:

目前咱们对“优惠券接口”大概比较珍视,小伙伴们都需要剖析一些“优惠券接口”的相关资讯。那么小编同时在网上收集了一些对于“优惠券接口””的相关资讯,希望兄弟们能喜欢,你们快快来学习一下吧!

本文主要分享了如何设计一个可扩展的优惠券功能。

一、功能特性介绍

1.每个条件的代码独立,相当于单独的实现类实现接口,就能通过配置添加到优惠券条件校验当中,支持多种条件灵活组合

2.新增一种使用条件可以不修改核心流程代码,不需要增加数据库表字段

3.可实现优惠券区分客户端展示,比如在APP可见可用,在小程序不可见不可用

4.可实现优惠券查询适用的商品列表

二、核心代码架构图

三、代码实现

1.数据库表结构设计

CREATE TABLE `mk_coupon_use_condition` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `bean_name` varchar(64) NOT NULL DEFAULT '' COMMENT 'bean名称(UseCondition的实现类)', `descrpition` varchar(255) DEFAULT NULL COMMENT '描述', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `uniq_beanname` (`bean_name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券使用条件';CREATE TABLE `mk_coupon_template` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(128) NOT NULL DEFAULT '' COMMENT '优惠券名称', `max_amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '最大优惠金额(元)', `discount` decimal(12,2) NOT NULL DEFAULT '1.00' COMMENT '折扣', `condition_amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '满X元可用', `begin_time` datetime NOT NULL COMMENT '发放开始时间', `end_time` datetime NOT NULL COMMENT '发放结束时间', `period_type` varchar(8) NOT NULL DEFAULT '' COMMENT '有效期计算方式(fix:领券起X小时内有效,ps:固定开始时间-结束时间)', `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '发放量', `left_num` int(11) NOT NULL DEFAULT '0' COMMENT '剩余量', `limit_num` int(11) NOT NULL DEFAULT '1' COMMENT '每用户限领量', `use_description` text COMMENT '使用说明', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券模板';CREATE TABLE `mk_coupon_template_condition` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `coupon_template_id` int(11) NOT NULL COMMENT 'mk_coupon_template.id', `use_condition` varchar(32) NOT NULL DEFAULT '' COMMENT '使用条件(bean名称,mk_coupon_use_condition.bean_name)', `use_condition_value` varchar(255) DEFAULT '' COMMENT '使用条件值', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_coupontemplateid` (`coupon_template_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券模板-使用条件';CREATE TABLE `mk_user_coupon` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `user_id` int(11) NOT NULL COMMENT 'bu_user_info.id', `coupon_template_id` int(11) NOT NULL COMMENT 'mk_coupon_template.id', `name` varchar(128) NOT NULL DEFAULT '' COMMENT '优惠券名称', `max_amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '最大优惠金额', `discount` decimal(12,2) NOT NULL DEFAULT '1.00' COMMENT '折扣', `condition_amount` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '满X金额可用', `begin_time` datetime NOT NULL COMMENT '有效期开始时间', `end_time` datetime NOT NULL COMMENT '有效期结束时间', `status` varchar(8) NOT NULL DEFAULT '' COMMENT '状态(nouse:未使用/已使用/已过期/未激活/已失效)', `max_num` int(11) NOT NULL COMMENT '最大叠加数', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE, KEY `idx_userid` (`user_id`), KEY `idx_coupontemplateid` (`coupon_template_id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户优惠券';

表说明:

mk_coupon_use_condition:主要是记录有哪些使用条件,代码中配置优惠券模板时有用

mk_coupon_template:优惠券发给用户前得先有个模板做配置

mk_coupon_template_condition:某个优惠券模板的使用条件(1对多),条件组合配置就是利用该表

mk_user_coupon:实际给到用户的优惠券,有未使用/已使用等状态,冗余了一部分券模板的数据

数据样例说明:

优惠券模板

优惠券模板使用条件

1)优惠券1只有1个条件CouponBaseCondition,可以理解为全场通用券,只要满足了基本条件就可以使用

2)优惠券2除了条件CouponBaseCondition,还有PlatformCondition,说明除了满足基本条件,还需要满足平台是app才能使用

3)优惠券3除了条件CouponBaseCondition,还有ProductCodeCondition,说明除了满足基本条件,还需要满足指定的商品编码AB3301或AB3302才能使用

2.抽象使用条件,定义一个接口,核心是canUse方法,另外2个方法有其他用途

UseParam说明:

例:如下为‘自动为用户选择最优的优惠券’的代码调用,runtimeAttach设计为Map就是为了灵活接收各种参数:

特殊业务场景说明:

canSee方法:用于解决某张优惠券只有在APP能使用,但是在小程序不能使用的业务场景,利用canSee方法返回true/false决定是否展示该张优惠券,例

filterProduct方法:用于解决根据某张优惠券查询适用商品的功能,一些大型的电商平台就提供该功能,方便用户快速找到能够使用该优惠券的商品列表,如果业务中不需要用到该功能可以忽略该方法

3.核心代码(UseCouponService)中提供4个方法(此处代码过多,就不贴了,可以通过gitee查看源码)

1)用户优惠券列表(未使用、即将过期、已使用、已过期)

应用场景:用户查看自己的优惠券列表

2)用户最优的可用优惠券

应用场景:商品展示券后价、支付时自动为用户选择优惠券

3)用户可用优惠券列表

应用场景:支付时展示选择优惠券的列表

4)判断优惠券能否使用

应用场景:创建订单时校验优惠券

核心思想:遍历优惠券的多个使用条件,判断有1个条件不满足就返回优惠券无法使用

tips:此处利用CompletableFuture优化性能,实现了多线程并发判断每个使用条件,只要有1个条件不满足就立马返回。

4.如何新增1种使用条件?

1)实现接口UseCondition,重写canUse方法,以下为‘首单可用’使用条件的demo代码

把Bean名称配置到券模板使用条件表mk_coupon_template_condition即可使用该条件,无需新增其他代码。

怎么样?如果你觉得有用的话,还不快快收藏起来!!!

附:涉及的代码目录

github:

gitee:

springcloud-template└── template-user     └──controller          └── CouponTestController -- 优惠券查询的测试代码演示     └── coupon          └── UseCouponService -- 优惠券查询的核心代码          └── UseCondition -- 抽象定义使用条件          └── UseParam -- 使用条件参数          └── SeeParam -- 可见条件参数          └── FilterParam -- 过滤商品参数          └── impl -- 使用条件实现类(条件就新增到这下面)               └── CouponBaseCondition -- 优惠券基础条件(必选)               └── FirstOrderCondition -- 首单可用               └── PinleiCondition -- 某商品品类可用               └── PlatformCondition -- 仅指定平台可见可用               └── ProductCodeCondition -- 指定商品可用               └── TagCondition -- 某标签下的商品可用               └── TimeRangeCondition -- 指定时间段可用

标签: #优惠券接口