|
@@ -134,20 +134,20 @@ public class CouponServiceImpl implements CouponService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takType) {
|
|
|
+ public Boolean takeCoupon(Long templateId, Set<Long> userIds, CouponTakeTypeEnum takeType) {
|
|
|
+ // 1. 校验并过滤用户
|
|
|
CouponTemplateDO template = couponTemplateService.getCouponTemplate(templateId);
|
|
|
- // 校验并过滤用户
|
|
|
- userIds = validateAndFilterTakeUserId(template, userIds, takType);
|
|
|
+ userIds = validateAndFilterTakeUserId(template, userIds, takeType);
|
|
|
|
|
|
+ // 2. 批量保存优惠劵
|
|
|
+ // TODO @疯狂:这里可以使用 CollectionUtils.convertList 更简洁;stream 可以简化很多代码,常用的 stream 操作,使用 util 可以进一步简洁,同时提升可读性
|
|
|
List<CouponDO> couponList = userIds.stream()
|
|
|
.map(userId -> CouponConvert.INSTANCE.convert(template, userId))
|
|
|
.collect(Collectors.toList());
|
|
|
- // 批量保存
|
|
|
couponMapper.insertBatch(couponList);
|
|
|
|
|
|
- // 增加优惠劵模板的领取数量
|
|
|
+ // 3. 增加优惠劵模板的领取数量
|
|
|
couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
|
|
|
-
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -159,55 +159,48 @@ public class CouponServiceImpl implements CouponService {
|
|
|
* @param takeType 领取方式
|
|
|
* @return 可领取此券的用户列表
|
|
|
*/
|
|
|
+ // TODO @疯狂:我建议哈,校验模版,和过滤用户分成两个方法;混在一起,有点小重,后续单测可能也比较难写哈;
|
|
|
private Set<Long> validateAndFilterTakeUserId(CouponTemplateDO couponTemplate, Set<Long> userIds, CouponTakeTypeEnum takeType) {
|
|
|
- // 校验模板
|
|
|
+ // 1.1 校验模板
|
|
|
if (couponTemplate == null) {
|
|
|
throw exception(COUPON_TEMPLATE_NOT_EXISTS);
|
|
|
}
|
|
|
-
|
|
|
- if (couponTemplate.getTotalCount() > 0) {
|
|
|
- // 校验剩余数量
|
|
|
- if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
|
|
|
- throw exception(COUPON_TEMPLATE_TASK_EMPTY);
|
|
|
- }
|
|
|
+ // 1.2 校验剩余数量
|
|
|
+ if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
|
|
|
+ throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
|
|
|
}
|
|
|
-
|
|
|
- // 校验"固定日期"的有效期类型是否过期
|
|
|
+ // 1.3 校验"固定日期"的有效期类型是否过期
|
|
|
if (CouponTemplateValidityTypeEnum.DATE.getType().equals(couponTemplate.getValidityType())) {
|
|
|
if (LocalDateTimeUtils.beforeNow(couponTemplate.getValidEndTime())) {
|
|
|
throw exception(COUPON_TEMPLATE_EXPIRED);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- // 校验领取方式
|
|
|
+ // 1.4 校验领取方式
|
|
|
+ // TODO @疯狂:如果要做这样的判断,使用 !ObjectUtils.equalsAny() 会更简洁
|
|
|
if (!CouponTakeTypeEnum.COMMON.getValue().equals(couponTemplate.getTakeType())) {
|
|
|
if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {
|
|
|
throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 获取领取过此券的用户
|
|
|
- List<CouponDO> takedList = couponMapper.selectByTemplateIdAndUserId(couponTemplate.getId(), userIds);
|
|
|
-
|
|
|
+ // 2.1 过滤掉,已经领取到上限的用户
|
|
|
+ List<CouponDO> alreadyTakeCoupons = couponMapper.selectByTemplateIdAndUserId(couponTemplate.getId(), userIds);
|
|
|
// 校验新人券
|
|
|
+ // TODO @疯狂:我在想,这个判断,是不是和下面的 couponTemplate.getTakeLimitCount() > 0 冗余了;可以先都过滤,然后最终去判断 userIds 是不是空了;
|
|
|
if (CouponTakeTypeEnum.BY_REGISTER.equals(takeType)) {
|
|
|
- if (!takedList.isEmpty()) {
|
|
|
- throw exception(COUPON_TEMPLATE_USER_TASKED);
|
|
|
+ if (!alreadyTakeCoupons.isEmpty()) {
|
|
|
+ throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
// 校验领取数量限制
|
|
|
if (couponTemplate.getTakeLimitCount() > 0) {
|
|
|
- // 统计用户的领取数量
|
|
|
- Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(takedList, CouponDO::getUserId, Collectors.summingInt(c -> 1));
|
|
|
- //过滤掉达到领取数量限制的用户
|
|
|
+ Map<Long, Integer> userTakeCountMap = CollStreamUtil.groupBy(alreadyTakeCoupons, CouponDO::getUserId, Collectors.summingInt(c -> 1));
|
|
|
userIds.removeIf(userId -> MapUtil.getInt(userTakeCountMap, userId, 0) >= couponTemplate.getTakeLimitCount());
|
|
|
- // 用户全部领取过此优惠券
|
|
|
+ // 2.2 如果所有用户都领取过,则抛出异常
|
|
|
if (userIds.isEmpty()) {
|
|
|
- throw exception(COUPON_TEMPLATE_USER_TASKED);
|
|
|
+ throw exception(COUPON_TEMPLATE_USER_ALREADY_TAKE);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
return userIds;
|
|
|
}
|
|
|
|