CouponFontServiceImpl.java 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. package com.cyksj.service.coupon.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUtil;
  4. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  5. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  6. import com.cyksj.common.exception.BusinessRuntimeException;
  7. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  8. import com.cyksj.mapper.manage.coupon.*;
  9. import com.cyksj.model.entity.Coupon;
  10. import com.cyksj.model.entity.CouponActive;
  11. import com.cyksj.model.entity.CouponUser;
  12. import com.cyksj.model.request.CouponCollectReq;
  13. import com.cyksj.model.views.CouponAvailableRecommendView;
  14. import com.cyksj.model.views.CouponNewUserView;
  15. import com.cyksj.model.views.CouponUserView;
  16. import com.cyksj.model.views.GoodsDonSkuView;
  17. import com.cyksj.service.coupon.CouponFontService;
  18. import com.ejlchina.searcher.BeanSearcher;
  19. import com.ejlchina.searcher.param.Operator;
  20. import com.ejlchina.searcher.util.MapUtils;
  21. import lombok.RequiredArgsConstructor;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.springframework.dao.DuplicateKeyException;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import java.util.ArrayList;
  27. import java.util.List;
  28. import java.util.Optional;
  29. /*
  30. *项目名: netflix
  31. *文件名: CouponFontServiceImpl
  32. *创建者: JavaZou
  33. *创建时间:2022/11/18 13:34
  34. */
  35. @Service
  36. @RequiredArgsConstructor
  37. @Slf4j
  38. public class CouponFontServiceImpl implements CouponFontService {
  39. private final CouponMapper couponMapper;
  40. private final CouponActiveMapper couponActiveMapper;
  41. private final CouponUserMapper couponUserMapper;
  42. private final BeanSearcher beanSearcher;
  43. private final CouponSkuMapper couponSkuMapper;
  44. private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
  45. private final CouponRecommendMapper recommendMapper;
  46. @Override
  47. @Transactional(rollbackFor = Throwable.class)
  48. public void collectCoupon(CouponCollectReq couponCollectReq, Long userId) {
  49. collectCommonCheck(couponCollectReq, userId);
  50. CouponActive couponActive = couponActiveMapper.selectById(couponCollectReq.getCouponActiveId());
  51. if (couponActive == null) {
  52. throw BusinessRuntimeException.getInstance("该发放优惠券不存在");
  53. }
  54. if (couponActive.getRemainNum() <= 0) {
  55. throw BusinessRuntimeException.getInstance("该优惠券已领取完");
  56. }
  57. CouponUser couponUser = new CouponUser();
  58. couponUser.setUserId(userId);
  59. couponUser.setCouponId(couponCollectReq.getCouponId());
  60. //领券中心
  61. couponUser.setChannel(CouponUser.Channel.center);
  62. couponUser.setStatus(CouponUser.Status.unused);
  63. couponUser.setCouponActiveId(couponCollectReq.getCouponActiveId());
  64. //优惠券有效时间
  65. this.updateCouponUserValidTime(couponActive.getCouponId(), couponUser);
  66. try {
  67. couponUserMapper.insert(couponUser);
  68. } catch (DuplicateKeyException e) {
  69. log.info("用户:{}重复领取优惠券{}插入数据错误", userId, couponCollectReq.getCouponId());
  70. throw BusinessRuntimeException.getInstance("已领取成功");
  71. }
  72. if (couponActive != null) {
  73. //发放优惠券记录剩余数量
  74. Integer remainNum = couponActive.getRemainNum();
  75. Integer update = couponActiveMapper.subRemainNum(couponActive.getId(), remainNum);
  76. if (update != 1) {
  77. throw BusinessRuntimeException.getInstance("系统繁忙,请稍后再试..");
  78. }
  79. }
  80. }
  81. @Override
  82. @Transactional(rollbackFor = Throwable.class)
  83. public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) {
  84. collectCommonCheck(couponCollectReq, userId);
  85. CouponUser couponUser = new CouponUser();
  86. couponUser.setUserId(userId);
  87. couponUser.setCouponId(couponCollectReq.getCouponId());
  88. //推荐渠道
  89. couponUser.setChannel(CouponUser.Channel.recommend);
  90. couponUser.setStatus(CouponUser.Status.unused);
  91. couponUser.setRecommendId(couponCollectReq.getCouponRecommendId());
  92. //优惠券有效时间
  93. this.updateCouponUserValidTime(couponCollectReq.getCouponId(), couponUser);
  94. try {
  95. couponUserMapper.insert(couponUser);
  96. } catch (DuplicateKeyException e) {
  97. log.info("用户:{}重复领取推荐优惠券{}插入数据错误", userId, couponCollectReq.getCouponId());
  98. throw BusinessRuntimeException.getInstance("已领取成功");
  99. }
  100. }
  101. @Override
  102. @Transactional(rollbackFor = Throwable.class)
  103. public void collectWholeRecommendCoupon(Long userId) {
  104. CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
  105. Boolean isNewUser = true;
  106. if (couponNewUserView != null) {
  107. isNewUser = false;
  108. }
  109. //查询所有可领取的推荐优惠券
  110. List<CouponAvailableRecommendView> couponAvailableRecommendViews = recommendMapper.getRecommendCouponList(userId, isNewUser);
  111. couponAvailableRecommendViews.stream().forEach(data -> {
  112. //领取优惠券
  113. CouponUser couponUser = new CouponUser();
  114. couponUser.setUserId(userId);
  115. couponUser.setCouponId(data.getCouponId());
  116. //推荐渠道
  117. couponUser.setChannel(CouponUser.Channel.recommend);
  118. couponUser.setStatus(CouponUser.Status.unused);
  119. couponUser.setRecommendId(data.getRecommendId());
  120. //优惠券有效时间
  121. this.updateCouponUserValidTime(data.getCouponId(), couponUser);
  122. try {
  123. couponUserMapper.insert(couponUser);
  124. } catch (DuplicateKeyException e) {
  125. //插入失败继续插入 不影响
  126. log.info("用户:{}一键领取推荐优惠券{}插入数据错误", userId, data.getCouponId());
  127. }
  128. });
  129. }
  130. @Override
  131. public Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit) {
  132. DateTime now = DateTime.now();
  133. Long goodsId = null;
  134. //实物还是虚物
  135. GoodsDonSkuView goodsDonSkuView = beanSearcher.searchFirst(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, skuId).op(Operator.Equal).build());
  136. if (goodsDonSkuView.getType() == 2) {
  137. goodsId = goodsDonSkuView.getGoodsId();
  138. }
  139. Page<CouponUserView> availableCouponList = couponUserMapper.getAvailableCouponList(skuId, couponId, goodsId, userId, isRenew, new Page<>(start, limit));
  140. Optional.ofNullable(availableCouponList).ifPresent(page->{
  141. page.getRecords().stream().forEach(data->{
  142. String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
  143. data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
  144. if (!data.getIsAvailable()) {
  145. data.setReason(String.format("仅限%s", data.getGoodsSkuStr()));
  146. if (isRenew != null && isRenew && data.getIsRenew()) {
  147. data.setReason(String.format("%s续费时可使用", data.getReason()));
  148. }
  149. }
  150. if (isRenew != null && isRenew && !data.getIsRenew()) {
  151. data.setReason(String.format("续费时,不可使用"));
  152. }
  153. //为了重新校验
  154. data.setCouponUserStatus(CouponUser.Status.unused);
  155. this.setCouponUserStatus(data, now);
  156. });
  157. });
  158. return availableCouponList;
  159. }
  160. /**
  161. * 设置用户优惠券状态
  162. */
  163. @Override
  164. public void setCouponUserStatus(CouponUserView data, DateTime now) {
  165. Boolean isFlag = false;
  166. if (data.getCouponUserStatus() == CouponUser.Status.unused) {
  167. if (data.getExpiryStatus() != null && !data.getExpiryStatus()) {
  168. data.setCouponUserStatus(CouponUser.Status.invalid);
  169. data.setIsAvailable(false);
  170. data.setReason("该优惠券已失效");
  171. isFlag = true;
  172. } else if (now.isAfter(data.getValidEndTime())) {
  173. data.setCouponUserStatus(CouponUser.Status.expired);
  174. data.setIsAvailable(false);
  175. data.setReason("该优惠券已过期");
  176. isFlag = true;
  177. } else if (now.isBefore(data.getValidStartTime())) {
  178. data.setCouponUserStatus(CouponUser.Status.notEffective);
  179. data.setIsAvailable(false);
  180. data.setReason("该优惠券未生效");
  181. isFlag = true;
  182. }
  183. }
  184. if (isFlag) {
  185. TASK_EXECUTOR.execute(() -> {
  186. if (data.getCouponUserStatus() != CouponUser.Status.notEffective) {
  187. CouponUser couponUser = new CouponUser();
  188. couponUser.setId(data.getId());
  189. couponUser.setStatus(data.getCouponUserStatus());
  190. couponUserMapper.updateById(couponUser);
  191. }
  192. });
  193. }
  194. }
  195. @Override
  196. public Integer collectRecommendCouponNum(Long userId, Boolean isNewUser) {
  197. List<CouponAvailableRecommendView> recommendCouponList = Optional.ofNullable(recommendMapper.getRecommendCouponList(userId, isNewUser)).orElse(new ArrayList<>());
  198. return recommendCouponList.size();
  199. }
  200. public void collectCommonCheck(CouponCollectReq couponCollectReq, Long userId) {
  201. Coupon coupon = couponMapper.selectById(couponCollectReq.getCouponId());
  202. if (coupon == null || !coupon.getDeleted()) {
  203. throw BusinessRuntimeException.getInstance("该优惠券不存在");
  204. }
  205. //是否可领取
  206. if (coupon.getScope() == Coupon.Scope.newUser) {
  207. //注册后从没产生过虚拟订单的用户,产生过退款后也不是新用户
  208. CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
  209. if (couponNewUserView != null) {
  210. throw BusinessRuntimeException.getInstance("该优惠券只能新用户才能领取");
  211. }
  212. }
  213. CouponUser couponUser = couponUserMapper.selectOne(Wrappers.lambdaQuery(CouponUser.class).eq(CouponUser::getUserId, userId).eq(CouponUser::getCouponId, couponCollectReq.getCouponId()));
  214. if (couponUser != null) {
  215. if (couponUser.getChannel() == CouponUser.Channel.exCode) {
  216. throw BusinessRuntimeException.getInstance("您已兑换过该优惠券..");
  217. }
  218. throw BusinessRuntimeException.getInstance("您已领取该优惠券..");
  219. }
  220. }
  221. @Override
  222. public void updateCouponUserValidTime(Long couponId, CouponUser couponUser) {
  223. Coupon coupon = couponMapper.getCouponById(couponId);
  224. if (coupon.getIsValidTime()) {
  225. couponUser.setValidStartTime(coupon.getValidStartTime());
  226. couponUser.setValidEndTime(coupon.getValidEndTime());
  227. } else {
  228. couponUser.setValidStartTime(DateTime.now());
  229. couponUser.setValidEndTime(DateUtil.offsetDay(couponUser.getValidStartTime(), coupon.getValidDays()));
  230. }
  231. }
  232. }