CouponReceiveServiceImpl.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package com.ylx.massage.service.impl;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  4. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  5. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  6. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7. import com.ylx.common.core.domain.R;
  8. import com.ylx.common.core.domain.model.WxLoginUser;
  9. import com.ylx.massage.domain.Coupon;
  10. import com.ylx.massage.domain.UserCouponRelation;
  11. import com.ylx.massage.domain.vo.ClaimCouponRequestVO;
  12. import com.ylx.massage.domain.vo.CouponReceiveVo;
  13. import com.ylx.massage.domain.vo.CouponReceivesVO;
  14. import com.ylx.massage.mapper.CouponReceiveMapper;
  15. import com.ylx.massage.domain.CouponReceive;
  16. import com.ylx.massage.mapper.UserCouponRelationMapper;
  17. import com.ylx.massage.service.CouponReceiveService;
  18. import com.ylx.massage.service.CouponService;
  19. import com.ylx.massage.utils.DateTimeUtils;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.apache.commons.compress.utils.Lists;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.data.redis.core.StringRedisTemplate;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import javax.annotation.Resource;
  27. import java.math.BigDecimal;
  28. import java.math.RoundingMode;
  29. import java.time.LocalDateTime;
  30. import java.util.ArrayList;
  31. import java.util.Collections;
  32. import java.util.Date;
  33. import java.util.List;
  34. import java.util.concurrent.TimeUnit;
  35. import java.util.stream.Collectors;
  36. import static com.ylx.common.utils.SecurityUtils.getWxLoginUser;
  37. /**
  38. * 优惠券领取表(CouponReceive)表服务实现类
  39. *
  40. * @author makejava
  41. * @since 2024-05-14 11:25:45
  42. */
  43. @Slf4j
  44. @Service("couponReceiveService")
  45. public class CouponReceiveServiceImpl extends ServiceImpl<CouponReceiveMapper, CouponReceive> implements CouponReceiveService {
  46. private static final String SHARE_LOCK_KEY = "coupon_center:receiveCoupon:lock:";
  47. private static final long LOCK_EXPIRE_TIME = 2L; // 锁过期时间2秒
  48. @Resource
  49. private CouponService couponService;
  50. @Resource
  51. private CouponReceiveMapper couponReceiveMapper;
  52. @Resource
  53. private UserCouponRelationMapper userCouponRelationMapper;
  54. @Autowired
  55. private StringRedisTemplate redisTemplate;
  56. @Override
  57. public Coupon submit(CouponReceive couponReceive) {
  58. Coupon coupon = couponService.getById(couponReceive.getCouponId());
  59. if (coupon == null) {
  60. return null;
  61. }
  62. LambdaQueryWrapper<CouponReceive> queryWrapper = new LambdaQueryWrapper<>();
  63. queryWrapper.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId()).eq(CouponReceive::getCouponId, couponReceive.getCouponId());
  64. //限制领取数量
  65. List<CouponReceive> one = this.list(queryWrapper);
  66. if (coupon.getUserLimit() <= one.size()) {
  67. return null;
  68. }
  69. couponReceive.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays()));
  70. this.save(couponReceive);
  71. return coupon;
  72. }
  73. @Override
  74. @Transactional(rollbackFor = Exception.class)
  75. public Integer submits(CouponReceivesVO couponReceive) {
  76. LambdaQueryWrapper<Coupon> queryWrapper = new LambdaQueryWrapper<>();
  77. queryWrapper.in(Coupon::getId, couponReceive.getCouponIds());
  78. List<Coupon> list = couponService.list(queryWrapper);
  79. if (CollectionUtil.isEmpty(list)) {
  80. log.info("优惠卷不存在");
  81. return null;
  82. }
  83. ArrayList<CouponReceive> couponReceives = Lists.newArrayList();
  84. list.forEach(coupon -> {
  85. CouponReceive couponRec = new CouponReceive();
  86. couponRec.setId(Long.toString(IdWorker.getId(couponRec)));
  87. couponRec.setCouponId(coupon.getId());
  88. couponRec.setReceiveOpenId(couponReceive.getOpenId());
  89. /*couponRec.setDeptId(coupon.getDeptId());
  90. couponRec.setDeptName(coupon.getDeptName());*/
  91. couponRec.setCouponStatus(0);
  92. couponRec.setExpirationTime(DateTimeUtils.addDays(new Date(), coupon.getTermDays()));
  93. couponReceives.add(couponRec);
  94. });
  95. return couponReceiveMapper.insertBatch(couponReceives);
  96. }
  97. @Override
  98. @Transactional(rollbackFor = Exception.class)
  99. public R<?> receiveVolution(ClaimCouponRequestVO claimCouponRequestVO) {
  100. // 1、查询用户信息
  101. WxLoginUser wxLoginUser = getWxLoginUser();
  102. String openid = wxLoginUser.getCOpenid();
  103. log.info("当前用户的openId:{}", openid);
  104. //2、保存优惠券信息到coupon_receive表
  105. // 构建防重复提交的key:用户openId + 优惠卷id
  106. String lockKey = SHARE_LOCK_KEY + wxLoginUser.getCOpenid() + ":" + claimCouponRequestVO.getTemplateId();
  107. // 尝试获取锁,防止重复提交
  108. Boolean lockResult = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
  109. if (Boolean.FALSE.equals(lockResult)) {
  110. return R.fail("操作过于频繁,请稍后再试");
  111. }
  112. CouponReceive couponReceive = new CouponReceive();
  113. couponReceive.setIssuerCouponId(claimCouponRequestVO.getUserId());
  114. couponReceive.setCouponId(claimCouponRequestVO.getTemplateId());
  115. couponReceive.setCouponType(Integer.parseInt(claimCouponRequestVO.getType()));
  116. couponReceive.setReceiveOpenId(wxLoginUser.getCOpenid());
  117. couponReceive.setReceiveTime(LocalDateTime.now());
  118. //设置领取人手机号
  119. couponReceive.setReceiveUserPhone(wxLoginUser.getCPhone());
  120. //获取当前有效期类型
  121. String validityType = claimCouponRequestVO.getValidityType();
  122. switch (validityType) {
  123. // 固定日期范围
  124. case "1":
  125. couponReceive.setValidityType(1);
  126. couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime());
  127. couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime());
  128. break;
  129. //领券后N天有效
  130. case "2":
  131. couponReceive.setValidityType(2);
  132. couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays()));
  133. break;
  134. //长期有效
  135. case "3":
  136. couponReceive.setValidityType(3);
  137. break;
  138. default:
  139. throw new IllegalArgumentException("有效期类型错误");
  140. }
  141. // 设置使用状态:待使用
  142. couponReceive.setCouponStatus(0);
  143. int insert = couponReceiveMapper.insert(couponReceive);
  144. if (insert == 0) {
  145. return R.fail("优惠券领取失败");
  146. }
  147. // 3、将优惠券id和用户id做绑定插入用户优惠券关联表
  148. UserCouponRelation userCouponRelation = new UserCouponRelation();
  149. userCouponRelation.setOpenId(wxLoginUser.getCOpenid());
  150. userCouponRelation.setCouponId(claimCouponRequestVO.getTemplateId());
  151. userCouponRelation.setCouponName(claimCouponRequestVO.getName());
  152. userCouponRelation.setImageUrl(claimCouponRequestVO.getImageUrl());
  153. userCouponRelation.setCouponType(Integer.parseInt(claimCouponRequestVO.getType()));
  154. //设置状态为未使用
  155. userCouponRelation.setCouponStatus(0);
  156. switch (validityType) {
  157. // 固定日期范围
  158. case "1":
  159. userCouponRelation.setValidityType(Integer.parseInt(validityType));
  160. couponReceive.setValidStartTime(claimCouponRequestVO.getValidStartTime());
  161. couponReceive.setExpirationTime(claimCouponRequestVO.getValidEndTime());
  162. break;
  163. //领券后N天有效
  164. case "2":
  165. userCouponRelation.setValidityType(Integer.parseInt(validityType));
  166. couponReceive.setValidDays(Integer.parseInt(claimCouponRequestVO.getValidDays()));
  167. break;
  168. //长期有效
  169. case "3":
  170. userCouponRelation.setValidityType(Integer.parseInt(validityType));
  171. break;
  172. default:
  173. throw new IllegalArgumentException("有效期类型错误");
  174. }
  175. //市场售价
  176. BigDecimal marketPrice = BigDecimal.ZERO;
  177. //2-折扣券
  178. if ("2".equals(claimCouponRequestVO.getType())) {
  179. marketPrice = claimCouponRequestVO.getRuleMinSpendAmount().multiply(claimCouponRequestVO.getRuleDiscountRate())
  180. .divide(new BigDecimal("10")).setScale(2, RoundingMode.HALF_UP);
  181. } else if ("3".equals(claimCouponRequestVO.getType())) {
  182. //满减券
  183. marketPrice = claimCouponRequestVO.getRuleReductionAmount();
  184. } else if ("1".equals(claimCouponRequestVO.getType())) {
  185. //兑换券
  186. marketPrice = claimCouponRequestVO.getCostPrice();
  187. }
  188. userCouponRelation.setMarketPrice(marketPrice);
  189. // 设置券来源 0:券中心
  190. userCouponRelation.setTicketSource(0);
  191. userCouponRelation.setCountry(claimCouponRequestVO.getCountry());
  192. userCouponRelation.setCountryAll(claimCouponRequestVO.getCountryAll());
  193. userCouponRelation.setLocality(claimCouponRequestVO.getLocality());
  194. userCouponRelation.setMerchantId(claimCouponRequestVO.getMerchantId());
  195. userCouponRelation.setStoreName(claimCouponRequestVO.getStoreName());
  196. userCouponRelation.setCenterShareUserId(claimCouponRequestVO.getUserId());
  197. userCouponRelation.setRuleMinSpendAmount(claimCouponRequestVO.getRuleMinSpendAmount());
  198. userCouponRelation.setRuleDiscountRate(claimCouponRequestVO.getRuleDiscountRate());
  199. userCouponRelation.setRuleDiscountCapAmount(claimCouponRequestVO.getRuleDiscountCapAmount());
  200. userCouponRelation.setRuleReductionAmount(claimCouponRequestVO.getRuleReductionAmount());
  201. userCouponRelation.setReceiveTime(LocalDateTime.now());
  202. userCouponRelationMapper.insert(userCouponRelation);
  203. return R.ok("领取成功");
  204. }
  205. @Override
  206. public List<CouponReceiveVo> getByOpenId(String openid) {
  207. List<CouponReceiveVo> CouponReceiveVos = couponReceiveMapper.getByOpenId(openid);
  208. CouponReceiveVos.forEach(couponReceiveVo -> {
  209. if(couponReceiveVo.getExpirationTime() == null){
  210. couponReceiveVo.setExpirationTimeString("长期有效");
  211. }else{
  212. couponReceiveVo.setExpirationTimeString(DateTimeUtils.formatDate(couponReceiveVo.getExpirationTime(), DateTimeUtils.DATE_FORMAT));
  213. }
  214. });
  215. return CouponReceiveVos;
  216. }
  217. @Override
  218. @Transactional(rollbackFor = Exception.class)
  219. public void removeCoupons(List<CouponReceiveVo> coupons) {
  220. boolean b = this.removeByIds(coupons.stream().map(CouponReceiveVo::getId).collect(Collectors.toList()));
  221. //使用数量+1
  222. coupons.forEach(coup -> {
  223. UpdateWrapper<Coupon> wrapper = new UpdateWrapper<>();
  224. wrapper.lambda().eq(Coupon::getId, coup.getCouponId());
  225. wrapper.setSql(" used_num = used_num + " + 1);
  226. couponService.update(wrapper);
  227. });
  228. }
  229. @Override
  230. public List<Coupon> couponWindows(CouponReceive couponReceive) {
  231. //判断是否领过优惠卷
  232. //查询领取优惠卷
  233. LambdaQueryWrapper<CouponReceive> query = new LambdaQueryWrapper<>();
  234. query.eq(CouponReceive::getReceiveOpenId, couponReceive.getReceiveOpenId());
  235. List<CouponReceive> couponReceive1 = this.list(query);
  236. //如果没有领取优惠卷
  237. if (CollectionUtil.isEmpty(couponReceive1)) {
  238. //查询优惠卷
  239. LambdaQueryWrapper<Coupon> couponLambdaQueryWrapper = new LambdaQueryWrapper<>();
  240. couponLambdaQueryWrapper.eq(Coupon::getStatus, 1);
  241. //couponLambdaQueryWrapper.eq(Coupon::getStatus, 1).like(Coupon::getDeptName, couponReceive.getDeptName());
  242. //返回新人优惠卷列表
  243. return couponService.list(couponLambdaQueryWrapper);
  244. } else {
  245. return Collections.emptyList();
  246. }
  247. }
  248. }