电商平台-优惠券设计与架构

本文详细介绍了一款Java开源生鲜电商平台中的优惠券系统设计,包括优惠券基础信息表、领取记录表及消费记录表的设计,并提供了核心代码示例。

说明:现在电商白热化的程度,无论是生鲜电商还是其他的电商等等,都会有促销的这个体系,目的就是增加订单量与知名度等等

           那么对于Java开源生鲜电商平台而言,我们采用优惠券的这种方式进行促销。(补贴价格战对烧钱而言非常的恐怖的,太烧钱了)


1. 优惠券基础信息表

说明:任何一个优惠券或者说代金券都是有一个基础的说明,比如:优惠券名称,类型,价格,有效期,状态,说明等等基础信息。


CREATE TABLE `coupon` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自动增加ID',
  `region_id` bigint(20) DEFAULT NULL COMMENT '所属区域',
  `type` int(11) DEFAULT NULL COMMENT '所属类型,1为满减',
  `name` varchar(32) DEFAULT NULL COMMENT '优惠券名称',
  `img` varchar(64) DEFAULT NULL COMMENT '图片的URL地址',
  `start_time` datetime DEFAULT NULL COMMENT '优惠券开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '优惠券结束时间',
  `money` decimal(11,2) DEFAULT NULL COMMENT '优惠券金额,用整数,固定值目前。',
  `status` int(11) DEFAULT NULL COMMENT '状态,0表示未开始,1表示进行中,-1表示结束',
  `remarks` varchar(512) DEFAULT NULL COMMENT '优惠券的说明',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `full_money` decimal(12,2) DEFAULT NULL COMMENT '金额满',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='优惠券基础配置表';

说明:业务说可以规定某个区域,做优惠券,而且是纳新后才有,这样增加买家用户。价格可以后端进行设置。

           状态的意义在于,用户需要注册完成后,然后主动认领才有效,为什么要这样设计呢?目的只有一个:让用户在对APP这个软件玩一会儿,增加熟悉程度.

2. 优惠券领取记录表

说明:我们需要记录那个买家,什么时候进行的领取,领取的的时间,券的额度是多少等等,是否已经使用等信息


CREATE TABLE `coupon_receive` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自动增加ID',
  `buyer_id` bigint(20) DEFAULT NULL COMMENT '买家ID',
  `coupon_id` bigint(20) DEFAULT NULL COMMENT '优惠券编号',
  `coupon_money` decimal(12,2) DEFAULT NULL COMMENT '券额',
  `create_time` datetime DEFAULT NULL COMMENT '领取时间',
  `full_money` decimal(12,2) DEFAULT NULL COMMENT '金额满',
  `status` int(11) DEFAULT NULL COMMENT '状态,1为已使用,0为已领取未使用,-1为已过期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='优惠券领取记录表';

3.优惠券消费记录表

说明:优惠券消费记录表,是需要知道那个买家,那个优惠券,那个订单使用了优惠券,这边有个特别注意的地方是,这个优惠券的执行在支付成功后的回调。


CREATE TABLE `coupon_logs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自动增加ID',
  `buyer_id` bigint(20) DEFAULT NULL COMMENT '买家ID',
  `coupon_receive_id` bigint(20) DEFAULT NULL COMMENT '优惠券id',
  `order_number` varchar(64) DEFAULT NULL COMMENT '订单号',
  `order_original_amount` decimal(12,2) DEFAULT NULL COMMENT '原订单金额',
  `coupon_amount` decimal(11,2) DEFAULT NULL COMMENT '优惠券的金额',
  `order_final_amount` decimal(12,2) DEFAULT NULL COMMENT '抵扣优惠券之后的订单金额',
  `create_time` datetime DEFAULT NULL COMMENT '领取时间',
  `status` int(2) DEFAULT '0' COMMENT '日志状态: 默认为0,支付回调成功后为1',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='优惠券消费记录表';

说明:相对而言,优惠券的难度不算大,重点的是业务方面的指导与学习,包括数据库的架构与设计等等,还有就是思路的学习。

 

相关核心代码如下:

APP需要后台提供以下几个接口:

3.1 查询所有买家的优惠券。

3.2 判断买家是否可以领取优惠券。

3.3 买家主动领取优惠券


/**
 * 优惠券controller
 */
@RestController
@RequestMapping("/buyer/coupon")
public class CouponController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(CouponController.class);

    @Autowired
    private CouponReceiveService couponReceiveService;

    @Autowired
    private UsersService usersService;

    /**
     * 查询买家所有优惠券
     * 
     * @param request
     * @param response
     * @param buyerId
     * @return
     */
    @RequestMapping(value = "/list", method = { RequestMethod.GET, RequestMethod.POST })
    public JsonResult getCouponList(HttpServletRequest request, HttpServletResponse response, Long buyerId) {
        try {
            if (buyerId == null) {
                return new JsonResult(JsonResultCode.FAILURE, "买家不存在", "");
            }
            List<CouponReceive> result = couponReceiveService.selectAllByBuyerId(buyerId);
            return new JsonResult(JsonResultCode.SUCCESS, "查询成功", result);
        } catch (Exception ex) {
            logger.error("[CouponController][getCouponList] exception", ex);
            return new JsonResult(JsonResultCode.FAILURE, "系统错误,请稍后重试", "");
        }
    }

    /**
     * 判断买家是否可以领取优惠券
     * 
     * @param request
     * @param response
     * @param buyerId
     * @return
     */
    @RequestMapping(value = "/judge", method = { RequestMethod.GET, RequestMethod.POST })
    public JsonResult judgeReceive(HttpServletRequest request, HttpServletResponse response, Long buyerId) {
        try {
            // 判断当前用户是否可用
            Users users = usersService.getUsersById(buyerId);
            if (users == null) {
                logger.info("OrderController.judgeReceive.buyerId " + buyerId);
                return new JsonResult(JsonResultCode.FAILURE, "你的账号有误,请重新登录", "");
            }
            int status = users.getStatus();
            if (UserStatus.FORBIDDEN == status) {
                return new JsonResult(JsonResultCode.FAILURE, "你的账号已经被禁用了,请联系公司客服", "");
            }
            List<Coupon> result = couponReceiveService.selectByBuyerId(buyerId);
            if (CollectionUtils.isEmpty(result)) {
                result = new ArrayList<Coupon>();
            }
            return new JsonResult(JsonResultCode.SUCCESS, "查询成功", result);
        } catch (Exception ex) {
            logger.error("[CouponController][judgeReceive] exception", ex);
            return new JsonResult(JsonResultCode.FAILURE, "系统错误,请稍后重试", "");
        }
    }

    /**
     * 买家领取优惠券
     * 
     * @param request
     * @param response
     * @param buyerId
     * @return
     */
    @RequestMapping(value = "/add", method = { RequestMethod.GET, RequestMethod.POST })
    public JsonResult saveCoupon(HttpServletRequest request, HttpServletResponse response, Long buyerId,
            Long couponId) {
        try {
            // 判断当前用户是否可用
            Users users = usersService.getUsersById(buyerId);
            if (users == null) {
                logger.info("OrderController.saveCoupon.buyerId " + buyerId);
                return new JsonResult(JsonResultCode.FAILURE, "你的账号有误,请重新登录", "");
            }
            //判断当前用户的状态是否可用
            int status = users.getStatus();
            if (UserStatus.FORBIDDEN == status) {
                return new JsonResult(JsonResultCode.FAILURE, "你的账号已经被禁用了,请联系公司客服", "");
            }
            if (couponId == null) {
                return new JsonResult(JsonResultCode.SUCCESS, "活动已经结束", "");
            }
            //新增
            int result = couponReceiveService.insert(buyerId, couponId);
            if (result == -1) {
                return new JsonResult(JsonResultCode.SUCCESS, "领取失败,已经领取过优惠券了", "");
            } else if (result == 0) {
                return new JsonResult(JsonResultCode.FAILURE, "领取失败,活动已经结束", "");
            } else {
                return new JsonResult(JsonResultCode.SUCCESS, "领取成功", "");
            }
        } catch (Exception ex) {
            logger.error("[CouponController][saveCoupon] exception", ex);
            return new JsonResult(JsonResultCode.FAILURE, "系统错误,请稍后重试", "");
        }
    }
}
最终总结:用户优惠券会发放在买家的APP中的个人中心里面,然后进行点击查看与领取,然后在支付的时候会自动显示出优惠券的数据,非常的灵活与方便。
### 电商平台优惠券系统设计方案 #### 基本概述 优惠券作为电商平台的重要组成部分,其主要功能在于通过提供折扣或其他奖励来吸引用户消费并提升转化率。一套完整的优惠券系统通常由多个模块构成,这些模块共同协作以支持优惠券的创建、发放、使用以及后续的数据分析。 #### 系统架构设计 优惠券系统的架构可以分为以下几个核心层次: 1. **前端交互层** 用户界面负责展示可用优惠券列表,并允许用户取或应用优惠券到购物车结算流程中。此部分需考虑用户体验优化,例如清晰显示优惠条件和剩余数量等信息[^2]。 2. **业务逻辑层** 这一层实现了优惠券的主要操作逻辑,包括但不限于: - 创建新优惠券及其关联规则; - 验证用户的资格是否满足特定优惠的要求; - 处理优惠券的状态变化(如已过期、已被使用)。 3. **数据存储层** 数据库用于持久化保存所有的优惠券记录及相关元数据。常见的表结构可能涉及如下字段:`id`, `type`, `value`, `valid_from`, `valid_until`, `usage_limit_per_user`, 和 `status`等等。 4. **后台管理系统** 提供给管理员使用的工具集,用来定义新的优惠策略、监控现有优惠的表现情况以及调整参数设置。 #### 技术实现细节 以下是几个关键技术点的具体说明: - **优惠类型多样化** 支持多种类型的优惠形式,比如固定金额减免、百分比折扣或者满减门槛设定。每种模式都需要对应不同的计算方式,在编码时应采用灵活的设计模式以便扩展新增种类。 - **并发控制机制** 当大量请求同时尝试获取限量版优惠券时,必须实施有效的锁机制防止超发现象发生。Redis分布式锁是一种常用解决方案之一。 - **性能考量因素** 考量高吞吐量场景下的响应速度至关重要。可以通过缓存热门查询结果减少数据库压力;另外异步消息队列也可以帮助平滑突发流量带来的冲击。 ```python import redis from contextlib import contextmanager @contextmanager def acquire_lock_with_timeout(lock, timeout=10): """Acquire a distributed lock using Redis.""" client = redis.StrictRedis(host='localhost', port=6379, db=0) acquired = False while not acquired and timeout > 0: acquired = client.setnx(lock.key, 'true') if acquired: break time.sleep(0.1) timeout -= 0.1 try: yield acquired finally: if acquired: client.delete(lock.key) class CouponLock(object): def __init__(self, coupon_id): self.coupon_id = coupon_id self.key = f'coupon:{coupon_id}:lock' # Example usage of the above functions to manage concurrent access on coupons. with acquire_lock_with_timeout(CouponLock('COUPON_123')) as locked: if locked: process_coupon() ``` #### 测试验证环节 为了确保整个优惠券生命周期内的正常运作,全面而细致的功能测试必不可少。这不仅限于单元级别的单独组件检验,还包括端到端集成测试模拟真实环境下的各种边界状况。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值