最近在做自己的电商平台,其中涉及优惠券的设计与实现,在这篇文章中,我将分享我对优惠券设计和思考的一些见解。
优惠券在电商平台中算是用于营销场景使用最多的工具,它有几点特殊的特点:
- 规则简单,方便核算。
- 针对不同的用户群体发放不同类型的券,可以实现精细化营销。
- 使用门槛低,用户可以在平台上轻松领取和使用。
- 可以快速通过价格见面的方式完成交易。
- 并且可以通过平台不同的积分进行兑换。
优惠券的基础属性
券属性包括:名称、使用说明、面额、库存、类型(满减、折扣、直降)、使用范围、使用时间等。
- 满减类型,可能会涉及到满减的金额以及满减上限。
- 使用时间,可能是相对时间以及绝对时间。
- 使用范围,可能是全部商品、指定商品以及指定品类。
优惠券的三大要素
生产
优惠券的制作,会涉及到商品的费用核算,这一部分对于商家而言是较为敏感的行为,主要是为了控制相应的成本。用最小的成本获取最大的利益并且获得最大的客流量。
当然,这一部分主要是针对大型的电商平台,对于个人独立 IP 的内容,只需要做到在自己能够承担的范围内即可制作出相应的优惠券。
发放
在外卖平台上,优惠券的发放对应了某种载体,可能是营销活动、会员权益、积分兑换、任务奖励等。因此发送方式可以分为定向发放、统一领取。
定向发放:用户被动的行为。在用户满足一定条件时,平台会自动为用户发放优惠券。
统一领取/券码兑换发放:用户主动的行为。用户主动领取,平台会将优惠券发送到用户账户上。
两者本质上没有区别,主要区别在于技术上。定向发放,当设计到大量用户时,每个用户拿到优惠券的时间可能会有差异;统一领取,则需要考虑库存扣减的并发问题。
使用
在使用过程最重要的业务场景就是优惠券的查询以及优惠券的销毁。大多数用户使用场景,都是选择优惠券,再进行消费,例如:点外卖;但是也有部分场景是先消费,再选择优惠券,例如:打车。
在我所应用的平台上,只用考虑用户先选择优惠券,再进行消费。因此只需要结合实际的业务情况做好相关设计。通常在券的使用之后需要进行核销,通常只需要修改一下券的状态。
以下所有内容针对于个人的平台进行分享,不考虑大型电商、外卖平台。
当订单有券参与核算时候并且订单状态处于待支付状态,需要锁定券的状态use_status
,防止其他订单使用。当含券的订单取消之后,需要释放券的状态。
当券的使用时间超过了有效期,需要作废还未使用的券,需要一个后台定时任务进行处理,也可以采用懒处理的方式,即:用户查询优惠券列表的时候再去判断券是否在有效期。
优惠券表设计
针对当前的系统,我打算设计出两个表,一个是优惠券的基本信息表(coupon_info),一个是优惠券的使用记录表(coupon_logs)。
优惠券的基本信息表(coupon_info):优惠券名称、类型、折扣、满减、有效期等。
interface Coupon {
_id: string;
name: string;
type: "discount" | "max_out" | "no_threshold";
// 折扣
discount?: number;
// 满减
maxout?: [number, number];
// 直降
no_threshold?: number;
// 使用范围
usage: string[];
description?: string;
started_at?: Date;
expired_at?: Date;
}
优惠券的使用记录表(coupon_logs)
interface CouponUse {
_id: string;
coupon_id: string;
coupon_code: string;
user_id?: string;
use_status: "used" | "using" | "unused";
used_at?: Date;
order_id?: string;
}
实例:
在 coupon_info 中创建一种名为”Special Offer”的优惠券,它是一种折扣券,折扣为 10%,有效期为 2024 年 1 月 1 日至 2024 年 12 月 31 日,适用商品类型为”xxx”和”yyy”。
const couponData: Coupon = {
_id: "ef45322e6717e506109373e321e5c5c5",
name: "Special Offer",
type: "discount",
discount: 10, // 表示10%的折扣
usage: ["xxx", "yyy"], // 表示商品类型
description:
"Get 10% off on your next purchase.",
started_at: new Date("2024-01-01T00:00:00Z"), // 优惠券开始时间
expired_at: new Date("2024-12-31T23:59:59Z"), // 优惠券过期时间
};
当我需要生产出一张优惠券时,不需要考虑优惠券库存,会直接在 coupon_logs 中插入一条数据
const couponLogs: CouponLogs = {
_id: "33c5161d672089531178cda1533f5eff",
coupon_id: "ef45322e6717e506109373e321e5c5c5",
coupon_code: "XSW9AD2JVKL", // 用户可以通过这个激活码绑定这张优惠券
user_id: "",
use_status: "unused",
order_id: "",
used_at: "",
};
当用户使用优惠券时,需要修改 coupon_logs 中的数据,将 use_status 改为 “used”,并记录使用时间。
const couponLogs: CouponLogs = {
coupon_id: "ef45322e6717e506109373e321e5c5c5",
coupon_code: "XSW9AD2JVKL",
user_id: "25e993b76718786d10a5127338fee4d7",
use_status: "used",
order_id: "8df0e92f671c707010f7fd995595961f",
used_at: "2024-11-07T14:30:00Z",
};