UserCouponServiceImpl.java 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package com.kym.service.miniapp.impl;
  2. import cn.dev33.satoken.stp.StpUtil;
  3. import com.github.pagehelper.PageHelper;
  4. import com.github.yulichang.base.MPJBaseServiceImpl;
  5. import com.github.yulichang.toolkit.JoinWrappers;
  6. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  7. import com.kym.common.exception.BusinessException;
  8. import com.kym.common.utils.CommUtil;
  9. import com.kym.entity.admin.Coupon;
  10. import com.kym.entity.admin.queryParams.CouponQueryParam;
  11. import com.kym.entity.common.PageBean;
  12. import com.kym.entity.common.RedisKeys;
  13. import com.kym.entity.miniapp.OrderCoupon;
  14. import com.kym.entity.miniapp.User;
  15. import com.kym.entity.miniapp.UserCoupon;
  16. import com.kym.entity.miniapp.vo.UserCouponVo;
  17. import com.kym.entity.miniapp.vo.UserOrderCouponVo;
  18. import com.kym.mapper.miniapp.UserCouponMapper;
  19. import com.kym.service.admin.ActivityService;
  20. import com.kym.service.admin.CouponService;
  21. import com.kym.service.miniapp.UserCouponService;
  22. import com.kym.service.miniapp.UserService;
  23. import org.springframework.beans.BeanUtils;
  24. import org.springframework.data.redis.core.RedisTemplate;
  25. import org.springframework.stereotype.Service;
  26. import java.time.LocalDateTime;
  27. import java.time.LocalTime;
  28. import java.util.List;
  29. import java.util.Map;
  30. import java.util.stream.Collectors;
  31. /**
  32. * <p>
  33. * 用户优惠券关联表 服务实现类
  34. * </p>
  35. *
  36. * @author skyline
  37. * @since 2024-04-29
  38. */
  39. @Service
  40. public class UserCouponServiceImpl extends MPJBaseServiceImpl<UserCouponMapper, UserCoupon> implements UserCouponService {
  41. private final RedisTemplate<String, String> redisTemplate;
  42. private final ActivityService activityService;
  43. private final UserService userService;
  44. private final CouponService couponService;
  45. public UserCouponServiceImpl(RedisTemplate<String, String> redisTemplate, ActivityService activityService,
  46. UserService userService, CouponService couponService) {
  47. this.redisTemplate = redisTemplate;
  48. this.activityService = activityService;
  49. this.userService = userService;
  50. this.couponService = couponService;
  51. }
  52. @Override
  53. public PageBean<UserCouponVo> listUserCoupons(CouponQueryParam params) {
  54. var users = userService.lambdaQuery()
  55. .like(CommUtil.isNotEmptyAndNull(params.getMobilePhone()), User::getMobilePhone, params.getMobilePhone())
  56. .list();
  57. var userId2Mobile = users.stream().collect(Collectors.toMap(User::getId, User::getMobilePhone));
  58. var userIds = users.stream().map(User::getId).toList();
  59. PageHelper.startPage(params.getPageNum(), params.getPageSize());
  60. var list = lambdaQuery()
  61. .in(CommUtil.isNotEmptyAndNull(userIds), UserCoupon::getUserId, userIds)
  62. .eq(CommUtil.isNotEmptyAndNull(params.getActivityId()), UserCoupon::getId, params.getCouponId())
  63. .like(CommUtil.isNotEmptyAndNull(params.getActivityName()), UserCoupon::getActivityName, params.getActivityName())
  64. .eq(CommUtil.isNotEmptyAndNull(params.getCouponId()), UserCoupon::getId, params.getCouponId())
  65. .like(CommUtil.isNotEmptyAndNull(params.getCouponName()), UserCoupon::getCouponName, params.getCouponName())
  66. .eq(CommUtil.isNotEmptyAndNull(params.getCouponType()), UserCoupon::getCouponType, params.getCouponType())
  67. .eq(CommUtil.isNotEmptyAndNull(params.getUsageStatus()), UserCoupon::getUsageStatus, params.getUsageStatus())
  68. .orderByDesc(UserCoupon::getId)
  69. .list();
  70. var voList = list.stream().map(userCoupon -> {
  71. var vo = new UserCouponVo();
  72. BeanUtils.copyProperties(userCoupon, vo);
  73. vo.setMobilePhone(userId2Mobile.get(userCoupon.getUserId()));
  74. return vo;
  75. }).toList();
  76. var res = new PageBean<>(voList);
  77. return new PageBean<>(voList).setList(res);
  78. }
  79. @Override
  80. public void collectCoupon(Long couponId) {
  81. // 优惠券状态校验
  82. var coupon = couponService.lambdaQuery()
  83. .eq(Coupon::getId, couponId)
  84. .in(Coupon::getStatus, Coupon.STATUS_未开始, Coupon.STATUS_进行中)
  85. .one();
  86. if (coupon == null) {
  87. throw new BusinessException("优惠券不存在或已失效!");
  88. }
  89. if (coupon.getClaimedQuantity() >= coupon.getQuantity() && coupon.getQuantity() > 0) {
  90. throw new BusinessException("优惠券已领完!");
  91. }
  92. // 重复领取校验
  93. var userId = StpUtil.getLoginIdAsLong();
  94. var exist = redisTemplate.opsForSet().isMember(RedisKeys.COUPON_ID_TO_USERS, couponId + ":" + userId);
  95. if (Boolean.TRUE.equals(exist)) {
  96. throw new BusinessException("优惠券已领取,请勿重复领取!");
  97. }
  98. // 活动
  99. var activity = activityService.getById(coupon.getActivityId());
  100. // 更新优惠券已领取数量
  101. coupon.setClaimedQuantity(coupon.getClaimedQuantity() + 1);
  102. // 校验优惠券数量是否已领完
  103. if (coupon.getClaimedQuantity() >= coupon.getQuantity() && coupon.getQuantity() > 0) {
  104. coupon.setStatus(Coupon.STATUS_已结束);
  105. }
  106. couponService.updateById(coupon);
  107. // 存入缓存和数据库
  108. redisTemplate.opsForSet().add(RedisKeys.COUPON_ID_TO_USERS, couponId + ":" + userId);
  109. var userCoupon = new UserCoupon();
  110. userCoupon.setActivityId(coupon.getActivityId());
  111. userCoupon.setActivityName(activity.getName());
  112. userCoupon.setCouponId(coupon.getId());
  113. userCoupon.setCouponName(coupon.getName());
  114. userCoupon.setUserId(userId);
  115. userCoupon.setStartTime(LocalDateTime.now());
  116. userCoupon.setEndTime(LocalDateTime.now().with(LocalTime.MAX).plusDays(coupon.getValidity() - 1));
  117. userCoupon.setValidity(coupon.getValidity());
  118. userCoupon.setCouponType(coupon.getCouponType());
  119. userCoupon.setDiscount(coupon.getDiscount());
  120. userCoupon.setMinServiceMoney(coupon.getMinServiceMoney());
  121. userCoupon.setAllowStacke(coupon.getAllowStacke());
  122. userCoupon.setStatus(UserCoupon.STATUS_有效);
  123. userCoupon.setRemark(coupon.getRemark());
  124. // userCouponSender.sendMessage(userCoupon);
  125. save(userCoupon);
  126. // todo 优惠券活动终止时处理redis数据,优惠券失效或者使用之后该做什么操作?
  127. }
  128. /**
  129. * 通过订单号查询订单使用的优惠券信息
  130. *
  131. * @param startChargeSeq
  132. * @return
  133. */
  134. @Override
  135. public UserOrderCouponVo getUserOrderCoupon(String startChargeSeq) {
  136. var userId = StpUtil.getLoginIdAsLong();
  137. MPJLambdaWrapper<UserCoupon> wrapper = JoinWrappers.lambda(UserCoupon.class)
  138. .selectAsClass(UserCoupon.class, UserOrderCouponVo.class)
  139. .selectAs(OrderCoupon::getStartChargeSeq, UserOrderCouponVo::getStartChargeSeq)
  140. .selectAs(OrderCoupon::getDiscountAmount, UserOrderCouponVo::getOrderDiscountAmount)
  141. .rightJoin(OrderCoupon.class, on -> on.eq(OrderCoupon::getCouponId, UserCoupon::getCouponId).eq(OrderCoupon::getUserId, UserCoupon::getUserId))
  142. .eq(OrderCoupon::getStartChargeSeq, startChargeSeq)
  143. .eq(OrderCoupon::getUserId, userId)
  144. .eq(OrderCoupon::getStatus, OrderCoupon.STATUS_使用成功);
  145. return selectJoinOne(UserOrderCouponVo.class, wrapper);
  146. }
  147. @Override
  148. public List<UserCoupon> listStationAvailableCoupons(Map<String, ?> params) {
  149. return baseMapper.listStationAvailableCoupons(params);
  150. }
  151. }