package com.cyksj.service.coupon.impl; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.cyksj.common.annotation.NoSubmit; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.mapper.manage.coupon.CouponActiveMapper; import com.cyksj.mapper.manage.coupon.CouponMapper; import com.cyksj.mapper.manage.coupon.CouponSkuMapper; import com.cyksj.mapper.manage.coupon.CouponUserMapper; import com.cyksj.model.entity.Coupon; import com.cyksj.model.entity.CouponActive; import com.cyksj.model.entity.CouponUser; import com.cyksj.model.request.CouponCollectReq; import com.cyksj.model.views.CouponAvailableRecommendView; import com.cyksj.model.views.CouponNewUserView; import com.cyksj.model.views.CouponUserView; import com.cyksj.service.coupon.CouponFontService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; /* *项目名: netflix *文件名: CouponFontServiceImpl *创建者: JavaZou *创建时间:2022/11/18 13:34 */ @Service @RequiredArgsConstructor @Slf4j public class CouponFontServiceImpl implements CouponFontService { private final CouponMapper couponMapper; private final CouponActiveMapper couponActiveMapper; private final CouponUserMapper couponUserMapper; private final BeanSearcher beanSearcher; private final CouponSkuMapper couponSkuMapper; private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance(); @Override @Transactional(rollbackFor = Throwable.class) public void collectCoupon(CouponCollectReq couponCollectReq, Long userId) { collectCommonCheck(couponCollectReq, userId); CouponActive couponActive = couponActiveMapper.selectById(couponCollectReq.getCouponActiveId()); if (couponActive == null) { throw BusinessRuntimeException.getInstance("该发放优惠卷不存在"); } if (couponActive.getRemainNum() <= 0) { throw BusinessRuntimeException.getInstance("该优惠卷已领取完"); } CouponUser couponUser = new CouponUser(); couponUser.setUserId(userId); couponUser.setCouponId(couponCollectReq.getCouponId()); //领卷中心 couponUser.setChannel(CouponUser.Channel.center); couponUser.setStatus(CouponUser.Status.unused); couponUser.setCouponActiveId(couponCollectReq.getCouponActiveId()); try { couponUserMapper.insert(couponUser); } catch (DuplicateKeyException e) { log.info("用户:{}重复领取优惠卷{}插入数据错误", userId, couponCollectReq.getCouponId()); throw BusinessRuntimeException.getInstance("已领取成功"); } if (couponActive != null) { //发放优惠卷记录剩余数量 Integer remainNum = couponActive.getRemainNum(); Integer update = couponActiveMapper.subRemainNum(couponActive.getId(), remainNum); if (update != 1) { throw BusinessRuntimeException.getInstance("系统繁忙,请稍后再试.."); } } } @Override @Transactional(rollbackFor = Throwable.class) @NoSubmit @Deprecated public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) { collectCommonCheck(couponCollectReq, userId); CouponUser couponUser = new CouponUser(); couponUser.setUserId(userId); couponUser.setCouponId(couponCollectReq.getCouponId()); //推荐渠道 couponUser.setChannel(CouponUser.Channel.recommend); couponUser.setStatus(CouponUser.Status.unused); try { couponUserMapper.insert(couponUser); } catch (DuplicateKeyException e) { log.info("用户:{}重复领取推荐优惠卷{}插入数据错误", userId, couponCollectReq.getCouponId()); throw BusinessRuntimeException.getInstance("已领取成功"); } } @Override @Transactional(rollbackFor = Throwable.class) @NoSubmit public void collectWholeRecommendCoupon(Long userId) { CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build()); //查询所有可领取的推荐优惠卷 List couponAvailableRecommendViews = beanSearcher.searchAll(CouponAvailableRecommendView.class, null); couponAvailableRecommendViews.stream().filter(data->{ if (data.getScope() == Coupon.Scope.newUser && couponNewUserView != null) { return false; } return true; }).forEach(data -> { //领取优惠卷 CouponUser couponUser = new CouponUser(); couponUser.setUserId(userId); couponUser.setCouponId(data.getCouponId()); //推荐渠道 couponUser.setChannel(CouponUser.Channel.recommend); couponUser.setStatus(CouponUser.Status.unused); try { couponUserMapper.insert(couponUser); } catch (DuplicateKeyException e) { //插入失败继续插入 不影响 log.info("用户:{}一键领取推荐优惠卷{}插入数据错误", userId, data.getCouponId()); } }); } @Override public void handleCouponStatus(SearchResult search) { DateTime now = DateTime.now(); search.getDataList().forEach(data -> { if (!data.getIsValidTime()) { data.setValidStartTime(data.getCreatedTime()); data.setValidEndTime(DateUtil.offsetDay(data.getValidStartTime(), data.getValidDays())); } this.setCouponUserStatus(data, now); String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId()); data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", "")); }); } @Override public Page getAvailableCouponList(Long skuId, Long userId, Boolean isRenew, Long start, Long limit) { DateTime now = DateTime.now(); Page availableCouponList = couponUserMapper.getAvailableCouponList(skuId, userId, isRenew, new Page<>(start, limit)); Optional.ofNullable(availableCouponList).ifPresent(page->{ page.getRecords().stream().forEach(data->{ if (!data.getIsValidTime()) { data.setValidStartTime(data.getCreatedTime()); data.setValidEndTime(DateUtil.offsetDay(data.getValidStartTime(), data.getValidDays())); } String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId()); data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", "")); if (!data.getIsAvailable()) { data.setReason(String.format("仅限%s", data.getGoodsSkuStr())); } if (isRenew != null && isRenew) { data.setReason(String.format("续费时,不可使用")); } this.setCouponUserStatus(data, now); }); }); return availableCouponList; } /** * 设置用户优惠卷状态 */ @Override public void setCouponUserStatus(CouponUserView data, DateTime now) { Boolean isFlag = false; if (data.getCouponUserStatus() == CouponUser.Status.unused) { if (data.getExpiryStatus() != null && !data.getExpiryStatus()) { data.setCouponUserStatus(CouponUser.Status.invalid); data.setIsAvailable(false); data.setReason("该优惠卷已失效"); isFlag = true; } else if (now.isAfter(data.getValidEndTime())) { data.setCouponUserStatus(CouponUser.Status.expired); data.setIsAvailable(false); data.setReason("该优惠卷已过期"); isFlag = true; } else if (now.isBefore(data.getValidStartTime())) { data.setCouponUserStatus(CouponUser.Status.notEffective); data.setIsAvailable(false); data.setReason("该优惠卷未生效"); isFlag = true; } } if (isFlag) { TASK_EXECUTOR.execute(() -> { CouponUser couponUser = new CouponUser(); couponUser.setId(data.getId()); couponUser.setStatus(data.getCouponUserStatus()); couponUserMapper.updateById(couponUser); }); } } public void collectCommonCheck(CouponCollectReq couponCollectReq, Long userId) { Coupon coupon = couponMapper.selectById(couponCollectReq.getCouponId()); if (coupon == null || !coupon.getDeleted()) { throw BusinessRuntimeException.getInstance("该优惠卷不存在"); } //是否可领取 if (coupon.getScope() == Coupon.Scope.newUser) { //注册后从没产生过虚拟订单的用户,产生过退款后也不是新用户 CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build()); if (couponNewUserView != null) { throw BusinessRuntimeException.getInstance("该优惠卷只能新用户才能领取"); } } CouponUser couponUser = couponUserMapper.selectOne(Wrappers.lambdaQuery(CouponUser.class).eq(CouponUser::getCouponId, couponCollectReq.getCouponId())); if (couponUser != null) { if (couponUser.getChannel() == CouponUser.Channel.exCode) { throw BusinessRuntimeException.getInstance("您已兑换过该优惠卷.."); } throw BusinessRuntimeException.getInstance("您已领取该优惠卷.."); } } }