CouponFontServiceImpl.java 9.0 KB

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