文章目录
在电商系统或其他在线交易平台中,优惠券的使用逻辑往往是影响用户体验的重要一环。今天,我们就通过一个实际的代码示例,来深入探讨如何筛选和使用用户的优惠券。
代码分步讲解
1. 初始化结果集合
List<AvailableCouponVo> availableCouponVoList = new ArrayList<>();
首先,我们创建一个空的List
集合,用于存储最终可用的优惠券信息。
2. 获取用户未使用的优惠券
List<NoUseCouponVo> list = couponInfoMapper.findNoUseList(customerId);
通过customerId
查询用户未使用的优惠券列表。这个方法通常会调用数据库接口,返回用户所有未使用的优惠券。
3. 筛选优惠券类型
优惠券一般分为两种:现金券和折扣券。接下来,我们将根据类型分别处理。
3.1 处理现金券
List<NoUseCouponVo> typeList = list.stream().filter(item -> item.getCouponType() == 1)
.collect(Collectors.toList());
这里通过流操作过滤出所有类型为“现金券”的优惠券。对于每一张现金券,我们会进一步判断是否符合使用条件。
3.1.1 无门槛现金券
if (noUseCouponVo.getConditionAmount().doubleValue() == 0 && orderAmount.subtract(reduceAmount)
.doubleValue() >= 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
如果现金券没有使用门槛(ConditionAmount
为0),并且订单金额大于等于优惠券减免的金额,则将其加入可用优惠券列表。
3.1.2 有门槛现金券
if (noUseCouponVo.getConditionAmount().doubleValue() > 0 && orderAmount.subtract(
noUseCouponVo.getConditionAmount()).doubleValue() > 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
如果现金券有使用门槛(ConditionAmount
大于0),则需检查订单金额是否满足条件,满足时同样将其加入可用列表。
3.2 处理折扣券
List<NoUseCouponVo> typeList2 = list.stream().filter(item -> item.getCouponType() == 2)
.collect(Collectors.toList());
类似现金券,我们也要对折扣券进行过滤和处理。
3.2.1 无门槛折扣券
if (noUseCouponVo.getConditionAmount().doubleValue() == 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
如果折扣券没有使用门槛,直接计算折扣后的减免金额,并将其加入可用列表。
3.2.2 有门槛折扣券
if (noUseCouponVo.getConditionAmount().doubleValue() > 0 && orderAmount.subtract(
noUseCouponVo.getConditionAmount()).doubleValue() > 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
同样,如果折扣券有门槛条件,需判断订单金额是否满足,并计算折扣后的减免金额。
4. 排序与返回结果
if (!CollectionUtils.isEmpty(availableCouponVoList)) {
availableCouponVoList.sort((o1, o2) -> o2.getReduceAmount().compareTo(o1.getReduceAmount()));
}
return availableCouponVoList;
在获取所有符合条件的优惠券后,我们按照减免金额从大到小进行排序,并将最终结果返回给调用者。
5. 辅助方法
private AvailableCouponVo buildBestNoUseCouponVo(NoUseCouponVo noUseCouponVo, BigDecimal reduceAmount) {
AvailableCouponVo bestNoUseCouponVo = new AvailableCouponVo();
BeanUtils.copyProperties(noUseCouponVo, bestNoUseCouponVo);
bestNoUseCouponVo.setCouponId(noUseCouponVo.getId());
bestNoUseCouponVo.setReduceAmount(reduceAmount);
return bestNoUseCouponVo;
}
这个辅助方法用于将NoUseCouponVo
对象转换为AvailableCouponVo
对象,并设置减免金额。
完整代码展示
@Override
public List<AvailableCouponVo> findAvailableCoupon(Long customerId, BigDecimal orderAmount) {
List<AvailableCouponVo> availableCouponVoList = new ArrayList<>();
// 获取用户未使用的优惠券列表
List<NoUseCouponVo> list = couponInfoMapper.findNoUseList(customerId);
// 处理现金券
List<NoUseCouponVo> typeList = list.stream().filter(item -> item.getCouponType() == 1)
.collect(Collectors.toList());
for (NoUseCouponVo noUseCouponVo : typeList) {
BigDecimal reduceAmount = noUseCouponVo.getAmount();
if (noUseCouponVo.getConditionAmount().doubleValue() == 0 && orderAmount.subtract(reduceAmount)
.doubleValue() >= 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
if (noUseCouponVo.getConditionAmount().doubleValue() > 0 && orderAmount.subtract(
noUseCouponVo.getConditionAmount()).doubleValue() > 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
}
// 处理折扣券
List<NoUseCouponVo> typeList2 = list.stream().filter(item -> item.getCouponType() == 2)
.collect(Collectors.toList());
for (NoUseCouponVo noUseCouponVo : typeList2) {
BigDecimal discountAmount = orderAmount.multiply(noUseCouponVo.getDiscount()).divide(new BigDecimal("10"))
.setScale(2, RoundingMode.HALF_UP);
BigDecimal reduceAmount = orderAmount.subtract(discountAmount);
if (noUseCouponVo.getConditionAmount().doubleValue() == 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
if (noUseCouponVo.getConditionAmount().doubleValue() > 0 && orderAmount.subtract(
noUseCouponVo.getConditionAmount()).doubleValue() > 0) {
availableCouponVoList.add(this.buildBestNoUseCouponVo(noUseCouponVo, reduceAmount));
}
}
// 按减免金额排序并返回
if (!CollectionUtils.isEmpty(availableCouponVoList)) {
availableCouponVoList.sort((o1, o2) -> o2.getReduceAmount().compareTo(o1.getReduceAmount()));
}
return availableCouponVoList;
}
private AvailableCouponVo buildBestNoUseCouponVo(NoUseCouponVo noUseCouponVo, BigDecimal reduceAmount) {
AvailableCouponVo bestNoUseCouponVo = new AvailableCouponVo();
BeanUtils.copyProperties(noUseCouponVo, bestNoUseCouponVo);
bestNoUseCouponVo.setCouponId(noUseCouponVo.getId());
bestNoUseCouponVo.setReduceAmount(reduceAmount);
return bestNoUseCouponVo;
}
通过以上代码,我们实现了一个完整的优惠券筛选逻辑,该逻辑不仅考虑了现金券和折扣券的不同特点,还根据订单金额动态判断哪些优惠券可以使用。希望通过这篇博客,你对优惠券使用的实现逻辑有了更深入的理解。