| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- package com.cyksj.service.coupon.impl;
- import cn.hutool.core.date.DateTime;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.lang.Assert;
- import cn.hutool.core.util.StrUtil;
- import com.baomidou.mybatisplus.core.toolkit.Wrappers;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.cyksj.common.constant.Constant;
- import com.cyksj.common.exception.BusinessRuntimeException;
- import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
- import com.cyksj.common.util.Jsons;
- import com.cyksj.enums.GatewayApiCode;
- import com.cyksj.mapper.OrderDonMapper;
- import com.cyksj.mapper.UserMapper;
- import com.cyksj.mapper.channel.ChannelPopularizeMapper;
- import com.cyksj.mapper.manage.coupon.*;
- import com.cyksj.model.entity.*;
- import com.cyksj.model.request.ChannelPopularizeCouponReq;
- import com.cyksj.model.request.CouponCollectReq;
- import com.cyksj.model.views.*;
- import com.cyksj.service.coupon.CouponFontService;
- import com.ejlchina.searcher.BeanSearcher;
- 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.math.BigDecimal;
- import java.util.*;
- /*
- *项目名: 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();
- private final CouponRecommendMapper recommendMapper;
- private final ChannelPopularizeMapper channelPopularizeMapper;
- private final UserMapper userMapper;
- private final OrderDonMapper orderDonMapper;
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void collectCoupon(CouponCollectReq couponCollectReq, Long userId) {
- collectCommonCheck(couponCollectReq.getCouponId(), userId);
- CouponActive couponActive = couponActiveMapper.selectById(couponCollectReq.getCouponActiveId());
- if (couponActive == null) {
- throw BusinessRuntimeException.getInstance("该发放优惠券不存在");
- }
- if (couponActive.getRemainNum() <= 0) {
- throw BusinessRuntimeException.getInstance("该优惠券已领取完");
- }
- receiveCouponUser(couponCollectReq.getCouponId(), userId, CouponUser.Channel.center);
- 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)
- public void collectRecommendCoupon(CouponCollectReq couponCollectReq, Long userId) {
- collectCommonCheck(couponCollectReq.getCouponId(), userId);
- CouponRecommend couponRecommend = recommendMapper.selectOne(Wrappers.lambdaQuery(CouponRecommend.class).eq(CouponRecommend::getCouponId, couponCollectReq.getCouponId()).last("limit 1"));
- if (couponRecommend == null || !couponRecommend.getDeleted() || !couponRecommend.getStatus()) {
- return;
- }
- Date upTime = couponRecommend.getUpTime();
- Date downTime = couponRecommend.getDownTime();
- if (upTime != null && upTime.after(DateTime.now())) {
- return;
- }
- if (downTime != null && downTime.before(DateTime.now())) {
- return;
- }
- receiveCouponUser(couponCollectReq.getCouponId(), userId, CouponUser.Channel.recommend);
- }
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void collectWholeRecommendCoupon(Long userId) {
- CouponNewUserView couponNewUserView = beanSearcher.searchFirst(CouponNewUserView.class, MapUtils.builder().field(CouponNewUserView::getUserId, userId).op(Operator.Equal).build());
- Boolean isNewUser = true;
- if (couponNewUserView != null) {
- isNewUser = false;
- }
- //查询所有可领取的推荐优惠券
- List<CouponAvailableRecommendView> couponAvailableRecommendViews = recommendMapper.getRecommendCouponList(userId, isNewUser);
- couponAvailableRecommendViews.stream().forEach(data -> {
- //领取优惠券
- CouponUser couponUser = new CouponUser();
- couponUser.setUserId(userId);
- couponUser.setCouponId(data.getCouponId());
- //推荐渠道
- couponUser.setChannel(CouponUser.Channel.recommend);
- couponUser.setStatus(CouponUser.Status.unused);
- couponUser.setRecommendId(data.getRecommendId());
- //优惠券有效时间
- this.updateCouponUserValidTime(data.getCouponId(), couponUser);
- try {
- couponUserMapper.insert(couponUser);
- } catch (DuplicateKeyException e) {
- //插入失败继续插入 不影响
- log.info("用户:{}一键领取推荐优惠券{}插入数据错误", userId, data.getCouponId());
- }
- });
- }
- @Override
- public Page<CouponUserView> getAvailableCouponList(Long skuId, Long couponId, Long userId, Boolean isRenew, Long start, Long limit) {
- DateTime now = DateTime.now();
- Long goodsId = null;
- //实物还是虚物
- GoodsDonSkuView goodsDonSkuView = beanSearcher.searchFirst(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, skuId).op(Operator.Equal).build());
- if (goodsDonSkuView == null) {
- return new Page<>();
- }
- BigDecimal skuMoney = goodsDonSkuView.getMoney();
- if (goodsDonSkuView.getType() == 2) {
- goodsId = goodsDonSkuView.getGoodsId();
- }
- Page<CouponUserView> availableCouponList = couponUserMapper.getAvailableCouponList(skuId, skuMoney, couponId, goodsId, userId, isRenew, new Page<>(start, limit));
- Optional.ofNullable(availableCouponList).ifPresent(page->{
- page.getRecords().stream().forEach(data->{
- String str = couponSkuMapper.selectGoodsSkuStr(data.getCouponId());
- data.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
- List<CouponSkuView> couponSkus = couponSkuMapper.getGoodsSkuByCouponId(data.getCouponId());
- try {
- data.setGoodsSkuIds(Jsons.toJson(couponSkus));
- } catch (Exception e) {
- }
- if (!data.getIsAvailable()) {
- data.setReason(String.format("仅限%s", data.getGoodsSkuStr()));
- if (data.getUseScope() == Coupon.UseScope.renew) {
- data.setReason(String.format("%s续费时可使用", data.getReason()));
- } else if (data.getUseScope() == Coupon.UseScope.orders) {
- data.setReason(String.format("%s下单时可使用", data.getReason()));
- }
- }
- if (goodsDonSkuView.getType() == 2 && data.getType() == Coupon.Type.reduce) {
- if (data.getIsAvailable() && skuMoney.compareTo(data.getReduceCondition()) < 0) {
- data.setIsAvailable(false);
- data.setReason(String.format("满%s可用", data.getReduceCondition().divide(BigDecimal.valueOf(100))));
- }
- }
- if (isRenew != null && isRenew && data.getUseScope() == Coupon.UseScope.orders) {
- data.setReason("仅下单可使用");
- }
- //为了重新校验
- data.setCouponUserStatus(CouponUser.Status.unused);
- this.setCouponUserStatus(data, now);
- });
- });
- if (goodsDonSkuView.getType() == 2) {
- availableCouponList.getRecords().sort(Comparator.comparing(CouponUserView::getIsAvailable).reversed());
- }
- 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(() -> {
- if (data.getCouponUserStatus() != CouponUser.Status.notEffective) {
- CouponUser couponUser = new CouponUser();
- couponUser.setId(data.getId());
- couponUser.setStatus(data.getCouponUserStatus());
- couponUserMapper.updateById(couponUser);
- }
- });
- }
- }
- @Override
- public Integer collectRecommendCouponNum(Long userId, Boolean isNewUser) {
- List<CouponAvailableRecommendView> recommendCouponList = Optional.ofNullable(recommendMapper.getRecommendCouponList(userId, isNewUser)).orElse(new ArrayList<>());
- return recommendCouponList.size();
- }
- public void collectCommonCheck(Long couponId, Long userId) {
- Coupon coupon = couponMapper.selectById(couponId);
- 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::getUserId, userId).eq(CouponUser::getCouponId, couponId));
- if (couponUser != null) {
- if (couponUser.getChannel() == CouponUser.Channel.exCode) {
- throw BusinessRuntimeException.getInstance("您已兑换过该优惠券..");
- }
- throw BusinessRuntimeException.getInstance("您已领取该优惠券..");
- }
- }
- @Override
- public void updateCouponUserValidTime(Long couponId, CouponUser couponUser) {
- Coupon entity = couponMapper.getCouponById(couponId);
- Optional.ofNullable(entity).ifPresent(coupon -> {
- if (coupon.getIsValidTime()) {
- couponUser.setValidStartTime(coupon.getValidStartTime());
- couponUser.setValidEndTime(coupon.getValidEndTime());
- return;
- }
- couponUser.setValidStartTime(DateTime.now());
- if (coupon.getValidHours() > 0) {
- couponUser.setValidEndTime(DateUtil.offsetHour(couponUser.getValidStartTime(), coupon.getValidHours()));
- return;
- }
- couponUser.setValidEndTime(DateUtil.offsetDay(couponUser.getValidStartTime(), coupon.getValidDays()));
- });
- }
- @Override
- public void updateOrderDonCouponStatus(OrderDon orderDon) {
- log.info("订单:{}退款,优惠券返还start...", orderDon.getId());
- CouponUser couponUser = couponUserMapper.selectById(orderDon.getCouponUserId());
- if (CouponUser.Channel.exCode == couponUser.getChannel()) {
- //兑换码兑换的优惠券退款时,直接删除
- couponUserMapper.deleteById(couponUser.getId());
- } else {
- CouponUserView couponUserView = beanSearcher.searchFirst(CouponUserView.class, MapUtils.builder()
- .field(CouponUserView::getCouponId, couponUser.getCouponId()).op(Operator.Equal)
- .field(CouponUserView::getUserId, orderDon.getUserId()).op(Operator.Equal)
- .build());
- couponUserView.setCouponUserStatus(CouponUser.Status.unused);
- this.setCouponUserStatus(couponUserView, DateTime.now());
- couponUser.setStatus(couponUserView.getCouponUserStatus());
- couponUserMapper.updateById(couponUser);
- }
- log.info("订单:{}退款,优惠券返还end...", orderDon.getId());
- }
- @Override
- public void receiveChannelPopularizeCoupon(ChannelPopularizeCouponReq req) {
- Long userId = req.getUserId();
- Long popularizeId = req.getPopularizeId();
- Long couponId = req.getCouponId();
- ChannelPopularize channelPopularize = checkPopularizeChannelCoupon(userId, popularizeId);
- String couponIds = channelPopularize.getCouponIds();
- List<Long> couponIdList = null;
- try {
- couponIdList = Jsons.parseList(couponIds, Long.class);
- if (!couponIdList.contains(couponId)) {
- throw BusinessRuntimeException.getInstance("链接未关联该优惠券");
- }
- } catch (Exception e) {
- throw BusinessRuntimeException.getInstance("链接未关联该优惠券");
- }
- //优惠券领取状态校验
- collectCommonCheck(couponId, userId);
- //领取优惠券
- receiveCouponUser(couponId, userId, CouponUser.Channel.channel_popularize);
- }
- @Override
- public void collectAllChannelCoupons(long userId, Long popularizeId) {
- ChannelPopularize channelPopularize = checkPopularizeChannelCoupon(userId, popularizeId);
- String couponIds = channelPopularize.getCouponIds();
- List<Long> couponIdList = null;
- try {
- couponIdList = Jsons.parseList(couponIds, Long.class);
- } catch (Exception e) {
- throw BusinessRuntimeException.getInstance("链接未关联优惠券");
- }
- //一键领取优惠券
- couponIdList.forEach(couponId -> {
- try {
- receiveCouponUser(couponId, userId, CouponUser.Channel.channel_popularize);
- } catch (Exception e) {
- }
- });
- }
- public ChannelPopularize checkPopularizeChannelCoupon(Long userId, Long popularizeId) {
- //是否是该渠道来源新用户
- User user = userMapper.selectById(userId);
- if (user == null) {
- throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_USER_NO_FIND);
- }
- if (!user.getPopularizeId().equals(popularizeId)) {
- throw BusinessRuntimeException.getInstance("渠道推广新用户才能领取该优惠券");
- }
- //渠道链接是否存在
- ChannelPopularize channelPopularize = channelPopularizeMapper.selectById(popularizeId);
- Assert.notNull(channelPopularize, "链接不存在");
- //是否关联该优惠券
- String couponIds = channelPopularize.getCouponIds();
- if (StrUtil.isEmpty(couponIds)) {
- throw BusinessRuntimeException.getInstance("链接未关联优惠券");
- }
- return channelPopularize;
- }
- /**
- * 领取优惠券
- */
- public void receiveCouponUser(Long couponId, Long userId, CouponUser.Channel channel) {
- CouponUser couponUser = new CouponUser();
- couponUser.setUserId(userId);
- couponUser.setCouponId(couponId);
- couponUser.setChannel(channel);
- couponUser.setStatus(CouponUser.Status.unused);
- //优惠券有效时间
- this.updateCouponUserValidTime(couponId, couponUser);
- try {
- couponUserMapper.insert(couponUser);
- } catch (DuplicateKeyException e) {
- log.info("用户:{}重复领取优惠券{}插入数据错误", userId, couponId);
- }
- }
- @Override
- public CouponUserView getNewUserWelfareCoupons(long userId,Long couponId) {
- return couponUserMapper.getNewUserWelfareCouponsByUserId(userId, couponId);
- }
- @Override
- public CouponUserView getCouponDetailById(long userId, Long couponId) {
- CouponUserView couponUserView = couponUserMapper.getCouponDetailById(userId, couponId);
- if (couponUserView != null) {
- String str = couponSkuMapper.selectGoodsSkuStr(couponUserView.getCouponId());
- couponUserView.setGoodsSkuStr(str.replaceAll(",", "/").replaceAll(";", ""));
- }
- return couponUserView;
- }
- @Override
- public CouponUserView receiveCoupon(long userId, Long couponId, CouponUser.Channel channel) {
- try {
- receiveCouponUser(couponId, userId, channel);
- } catch (Exception e) {
- return null;
- }
- return getCouponDetailById(userId, couponId);
- }
- @Override
- public List<CouponView> getGoodsUserActivityCoupons(long userId) throws Exception {
- UserActivityDistributeDetailView goodsActivity = getGoodsActivity();
- if (goodsActivity == null) {
- return null;
- }
- String couponIds = goodsActivity.getCouponIds();
- List<Long> couponIdList = Jsons.parseList(couponIds, Long.class);
- //是否领取过
- Integer selectCount = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class).in(CouponUser::getCouponId, couponIdList).eq(CouponUser::getUserId, userId));
- if (selectCount == couponIdList.size()) {
- return null;
- }
- //未领取
- //是否购买过
- List<Long> skuIdList = couponMapper.getCouponSkuIds(couponIdList);
- Integer orderCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).in(OrderDon::getSkuId, skuIdList));
- if (orderCount == 0) {
- return null;
- }
- List<CouponView> couponViews = beanSearcher.searchAll(CouponView.class, MapUtils.builder().field(CouponView::getCouponId, couponIdList).op(Operator.InList).orderBy(CouponView::getCouponId).build());
- return couponViews;
- }
- @Override
- public void collectAllGoodsActivityCoupons(long userId) throws Exception {
- UserActivityDistributeDetailView goodsActivity = getGoodsActivity();
- if (goodsActivity != null) {
- String couponIds = goodsActivity.getCouponIds();
- List<Long> couponIdList = Jsons.parseList(couponIds, Long.class);
- //是否领取过
- Integer selectCount = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class).in(CouponUser::getCouponId, couponIdList).eq(CouponUser::getUserId, userId));
- if (selectCount != couponIdList.size()) {
- //未领取
- //是否购买过
- List<Long> skuIdList = couponMapper.getCouponSkuIds(couponIdList);
- Integer orderCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).in(OrderDon::getSkuId, skuIdList));
- if (orderCount != 0) {
- //一键领取优惠券
- couponIdList.forEach(couponId -> {
- try {
- receiveCouponUser(couponId, userId, CouponUser.Channel.ptfq);
- } catch (Exception e) {
- }
- });
- }
- }
- }
- }
- public UserActivityDistributeDetailView getGoodsActivity() {
- String dateStr = DateTime.now().toString();
- String time = String.format(" and (ua.start_time is null or (ua.start_time < '%s' and ua.end_time > '%s'))", dateStr, dateStr);
- UserActivityDistributeDetailView goodsActivity = beanSearcher.searchFirst(UserActivityDistributeDetailView.class, MapUtils.builder()
- .field(UserActivityDistributeDetailView::getType, 3)
- .put("time", time)
- .build());
- return goodsActivity;
- }
- }
|