scaffold-coupon 优惠券模块
模块概述
scaffold-coupon 是 Scaffold v2 的优惠券管理模块,提供完整的优惠券生命周期管理:模板创建、审核、发放、领取、核销、统计。支持多种券类型(满减/折扣/立减)、多发放渠道(内部渠道 + 微信卡券)、多种核销方式(扫码/手动/线上)。采用 SPI + 策略模式实现可插拔扩展。
功能列表
- 优惠券模板管理:创建/更新/删除/审核/变更状态,支持满减券、折扣券、立减券
- 优惠券发放:创建发放批次、指定用户发放、暂停/恢复发放
- 用户优惠券:领取/查询我的券/下单时可用券查询
- 优惠券核销:扫码核销、手动核销、核销回退、生成核销码
- 优惠券统计:全局统计概览、按模板统计
- 定时任务:过期提醒(每天 9 点)、过期状态更新(每小时)
- 多渠道策略:内部渠道已完成,微信卡券渠道(骨架已就绪)
核心组件
分层架构
| 层 |
类 |
职责 |
| Controller |
CouponTemplateController, CouponPublishController, CouponUserController, CouponStatisticsController, CouponVerifyController, MobileCouponController |
REST 接口 |
| Service |
CouponTemplateService, CouponPublishService, CouponUserService, CouponStatisticsService, CouponVerifyService, CouponNotifyService |
业务逻辑 |
| Repository |
CouponTemplateRepository, CouponChannelConfigRepository, CouponPublishBatchRepository, CouponUserRepository, CouponVerifyRecordRepository, CouponVerifyCodeRepository, CouponNotifyLogRepository |
数据访问 |
| Mapper |
对应 7 个实体的 Mapper |
ORM 映射 |
数据实体
| 实体 |
说明 |
| CouponTemplate |
优惠券模板,定义券类型/面额/使用条件/有效期/库存等 |
| CouponUser |
用户持有的优惠券 |
| CouponPublishBatch |
发放批次 |
| CouponChannelConfig |
渠道配置(内部/微信) |
| CouponNotifyLog |
通知日志 |
| CouponVerifyCode |
核销码 |
| CouponVerifyRecord |
核销记录 |
枚举类型
| 枚举 |
值 |
说明 |
| CouponType |
FULL_REDUCTION / DISCOUNT / FIXED |
满减券 / 折扣券 / 立减券 |
| CouponCategory |
GENERAL / CATEGORY / PRODUCT |
通用 / 品类 / 单品 |
| CouponValidityType |
FIXED / RELATIVE |
固定时间段 / 领取后 N 天 |
| CouponStatus |
DRAFT / ENABLED / DISABLED / EXPIRED |
草稿/启用/禁用/过期 |
| CouponUserStatus |
UNUSED / USED / EXPIRED |
未使用/已使用/已过期 |
| PublishType |
AUTO / MANUAL |
自动发放/手动发放 |
| VerifyType |
ONLINE / MANUAL / SCAN |
线上/手动/扫码 |
| RefundPolicy |
REFUNDABLE / NON_REFUNDABLE |
可退/不可退 |
状态字段规范:
enabled 字段遵循布尔语义:1 = 启用,0 = 禁用
SPI 扩展点
模块通过 SPI 机制实现 5 个可插拔扩展点,均定义了 Default 默认实现,业务模块可覆盖。
CouponStockOperator -- 库存操作
控制优惠券库存的扣减/回补/查询/限购检查。
| 方法 |
说明 |
| deductStock(templateId, count) |
扣减库存 |
| addStock(templateId, count) |
回补库存 |
| getStock(templateId) |
查询库存 |
| checkUserLimit(templateId, userId, perLimit) |
检查用户限领 |
| incrementUserClaimed(templateId, userId) |
记录用户已领数量 |
- 默认实现:
DbCouponStockOperator(数据库操作)
- 增强实现:
RedisCouponStockOperator(Redis 原子操作,依赖 scaffold-redis)
CouponProductChecker -- 商品范围校验
校验商品是否在优惠券适用范围内。
| 方法 |
说明 |
| isProductInScope(productId, scopeConfig) |
单个商品校验 |
| filterProducts(productIds, scopeConfig) |
批量过滤 |
- 默认实现:
DefaultCouponProductChecker(始终返回 true)
- 增强实现:
ProductCouponProductChecker(依赖 scaffold-product)
CouponNotifier -- 通知服务
发送优惠券相关通知(过期提醒、领取成功等)。
| 方法 |
说明 |
| notifyExpire(userId, couponName, expireTime) |
过期提醒 |
| notifyClaimSuccess(userId, couponName) |
领取成功通知 |
- 默认实现:
DefaultCouponNotifier(日志输出)
- 增强实现:
WechatCouponNotifier(微信模板消息,依赖 scaffold-wechat)
CouponApprovalHandler -- 审批流程
优惠券模板的审核流程对接。
| 方法 |
说明 |
| submitApproval(templateId, templateName) |
提交审核 |
| queryApprovalStatus(templateId) |
查询审核状态 |
- 默认实现:
DefaultCouponApprovalHandler(直接通过)
- 增强实现:
BpmCouponApprovalHandler(BPM 审批,依赖 scaffold-bpm)
CouponPaymentHandler -- 折扣计算
下单时计算优惠券折扣金额。
| 方法 |
说明 |
| calculateDiscount(couponUserId, orderAmount) |
计算折扣金额 |
- 默认实现:
DefaultCouponPaymentHandler(按模板规则计算)
渠道策略 CouponChannelStrategy
控制优惠券在不同渠道的发布/领取/核销/回退。支持内部渠道和微信卡券渠道。
| 方法 |
说明 |
| publish(template, config) |
发布到渠道 |
| sync(template, config) |
同步状态 |
| revoke(config) |
撤回 |
| claim(userId, template, config) |
渠道领取 |
| verify(couponUser, config) |
渠道核销 |
| rollbackVerify(couponUser, record, config) |
核销回退 |
- 内部渠道:
InternalCouponChannelStrategy(完整实现)
- 微信卡券渠道:
WechatCouponChannelStrategy(骨架已就绪,6 个 TODO 待接入 WxMpCardService)
配置参数
配置前缀:scaffold.coupon
| 参数 |
类型 |
默认值 |
说明 |
| enabled |
boolean |
true |
模块开关 |
API 接口列表
CouponTemplateController -- 优惠券模板管理 (/v1/coupon/template)
| 方法 |
路径 |
说明 |
| POST |
/create |
创建优惠券模板 |
| POST |
/update |
更新优惠券模板 |
| POST |
/delete/{id} |
删除优惠券模板 |
| POST |
/submitAudit/{id} |
提交审核 |
| POST |
/changeStatus?id=&status= |
变更状态 |
| GET |
/detail?id= |
模板详情 |
| POST |
/page |
分页查询 |
CouponPublishController -- 优惠券发放管理 (/v1/coupon/publish)
| 方法 |
路径 |
说明 |
| POST |
/create |
创建发放批次 |
| POST |
/assign |
指定用户发放 |
| POST |
/changeStatus?id=&status= |
暂停/恢复 |
| POST |
/page |
发放批次分页 |
CouponUserController -- 用户优惠券 (/v1/coupon/user)
| 方法 |
路径 |
说明 |
| POST |
/claim |
领取优惠券 |
| POST |
/myList |
我的券列表 |
| GET |
/detail?id= |
券详情 |
| POST |
/available?userId=&orderNo= |
下单时可用券 |
CouponVerifyController -- 优惠券核销管理 (/v1/coupon/verify)
| 方法 |
路径 |
说明 |
| POST |
/scan |
扫码核销 |
| POST |
/manual |
手动核销 |
| POST |
/rollback?id= |
核销回退 |
| POST |
/generateCode?couponUserId= |
生成核销码 |
| POST |
/page |
核销记录分页 |
| GET |
/detail?id= |
核销记录详情 |
CouponStatisticsController -- 优惠券数据统计 (/v1/coupon/statistics)
| 方法 |
路径 |
说明 |
| GET |
/overview |
全局统计概览 |
| GET |
/template?templateId= |
按模板统计 |
MobileCouponController -- 移动端优惠券 (/v1/mobile/coupon)
| 方法 |
路径 |
说明 |
| POST |
/list |
可领取优惠券列表 |
| POST |
/claim |
移动端领券 |
| POST |
/my |
我的优惠券 |
使用示例
1. 创建满减券模板
POST /v1/coupon/template/create
{
"name": "满100减20",
"type": "FULL_REDUCTION",
"category": "GENERAL",
"faceValue": 2000,
"minAmount": 10000,
"validityType": "RELATIVE",
"validDays": 30,
"totalStock": 1000,
"perLimit": 1,
"refundPolicy": "NON_REFUNDABLE"
}
2. 创建发放批次
POST /v1/coupon/publish/create
{
"templateId": 100,
"channel": "INTERNAL",
"publishType": "AUTO",
"startTime": "2026-04-27 00:00:00",
"endTime": "2026-05-27 23:59:59"
}
3. 用户领取优惠券
POST /v1/coupon/user/claim
{
"templateId": 100
}
4. 核销优惠券
POST /v1/coupon/verify/scan
{
"couponUserId": 200,
"verifyCode": "ABC123"
}
注意事项
- SPI 覆盖机制:默认 SPI 实现通过
@ConditionalOnMissingBean 注册,业务模块只需提供对应接口的实现类并标记为 @Component/@Service 即可覆盖
- 金额单位:faceValue(面额)和 minAmount(最低消费)统一使用分为单位
- 库存安全:默认使用数据库库存操作;生产环境建议启用
RedisCouponStockOperator,使用 Redis 原子操作防止超发
- 有效期:FIXED 类型为固定时间段(startTime/endTime),RELATIVE 类型为领取后 N 天生效
- 定时任务:过期提醒每天 9 点执行,过期状态更新每小时执行,需确保
@EnableScheduling 已开启
- 状态枚举:
enabled 字段遵循布尔语义:1 = 启用,0 = 禁用
CouponStatus、CouponUserStatus 为多态状态机,不遵循布尔语义规范
待完善功能
- 微信卡券渠道接入(WechatCouponChannelStrategy 中 6 个 TODO):
- 调用 WxJava 的 WxMpCardService 创建/同步/删除/领取/核销/取消核销卡券