package com.mzl.flower.service.impl.coupon; 
 | 
  
 | 
import cn.hutool.core.util.IdUtil; 
 | 
import com.alibaba.fastjson.JSON; 
 | 
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 
 | 
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 
 | 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 
 | 
import com.mzl.flower.config.exception.ValidationException; 
 | 
import com.mzl.flower.config.security.SecurityUtils; 
 | 
import com.mzl.flower.dto.request.coupon.*; 
 | 
import com.mzl.flower.dto.response.coupon.CouponRecordVO; 
 | 
import com.mzl.flower.entity.coupon.CouponRecordDO; 
 | 
import com.mzl.flower.entity.coupon.CouponTemplateDO; 
 | 
import com.mzl.flower.entity.customer.Customer; 
 | 
import com.mzl.flower.enums.*; 
 | 
import com.mzl.flower.mapper.coupon.CouponRecordMapper; 
 | 
import com.mzl.flower.mapper.coupon.CouponRecordMapperCustom; 
 | 
import com.mzl.flower.mapper.customer.CustomerMapper; 
 | 
import com.mzl.flower.service.coupon.CouponRecordService; 
 | 
import com.mzl.flower.service.coupon.CouponTemplateService2; 
 | 
import com.mzl.flower.service.customer.CustomerService; 
 | 
import com.mzl.flower.service.system.UserService; 
 | 
import lombok.extern.slf4j.Slf4j; 
 | 
import org.apache.commons.collections4.CollectionUtils; 
 | 
import org.apache.commons.lang3.StringUtils; 
 | 
import org.redisson.api.RLock; 
 | 
import org.redisson.api.RedissonClient; 
 | 
import org.springframework.beans.BeanUtils; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.stereotype.Service; 
 | 
import org.springframework.transaction.annotation.Transactional; 
 | 
  
 | 
import java.math.BigDecimal; 
 | 
import java.time.LocalDateTime; 
 | 
import java.time.temporal.TemporalAdjusters; 
 | 
import java.util.List; 
 | 
import java.util.Objects; 
 | 
import java.util.concurrent.TimeUnit; 
 | 
import java.util.stream.Collectors; 
 | 
  
 | 
/** 
 | 
 * <p> 
 | 
 *  服务实现类 
 | 
 * </p> 
 | 
 * 
 | 
 * @author @TaoJie 
 | 
 * @since 2024-08-27 
 | 
 */ 
 | 
@Slf4j 
 | 
@Service 
 | 
public class CouponRecordServiceImpl extends ServiceImpl<CouponRecordMapper, CouponRecordDO> implements CouponRecordService { 
 | 
  
 | 
    @Autowired 
 | 
    private CouponRecordMapperCustom couponRecordMapperCustom; 
 | 
  
 | 
    @Autowired 
 | 
    private CouponTemplateService2 couponTemplateService; 
 | 
  
 | 
    @Autowired 
 | 
    private UserService userService; 
 | 
  
 | 
    @Autowired 
 | 
    private CustomerMapper customerMapper; 
 | 
  
 | 
    @Autowired 
 | 
    private CustomerService customerService; 
 | 
  
 | 
  
 | 
    @Override 
 | 
    public List<CouponRecordVO> getList(QueryCouponRecordDTO dto) { 
 | 
        return couponRecordMapperCustom.getList(dto); 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    RedissonClient redissonClient; 
 | 
  
 | 
    private static final String COUPON_KEY="com:mzl:flower:service:impl:coupon:%s"; 
 | 
  
 | 
    @Transactional 
 | 
    @Override 
 | 
    public boolean createCouponRecord(CreateCouponRecordDTO dto) { 
 | 
  
 | 
        final CouponTemplateDO couponTemplateDO = couponTemplateService.getById(dto.getCouponId()); 
 | 
        if(couponTemplateDO==null){ 
 | 
            throw new ValidationException("优惠券不存在"); 
 | 
        } 
 | 
  
 | 
        final Customer customer = customerMapper.selectById(dto.getCustomerId()); 
 | 
        if(null==customer){ 
 | 
            throw new ValidationException("商户信息不存在"); 
 | 
        } 
 | 
  
 | 
        RLock lock = redissonClient.getLock(String.format(COUPON_KEY, couponTemplateDO.getId())); 
 | 
        try { 
 | 
            // 获取锁,最多等待 10 秒,锁自动释放时间 30 秒 
 | 
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { 
 | 
                try { 
 | 
                    // 活动优惠券 根据优惠券的发放数量来控制有没有超发 
 | 
                    if(StringUtils.isNotBlank(couponTemplateDO.getCategory()) && 
 | 
                            couponTemplateDO.getCategory().equals(CouponCategoryEnum.ACTIVITY.getStatus()) 
 | 
                    ){ 
 | 
                        // 获取当前优惠券已经领取的数量 
 | 
                        final Integer gainTotal = getExistGainCouponRecordAmountById(couponTemplateDO.getId()); 
 | 
                        if(couponTemplateDO.getCouponAmount().compareTo(gainTotal)<=0){ 
 | 
                            throw new ValidationException("当前优惠券已经领完!"); 
 | 
                        } 
 | 
                    } 
 | 
                    if(StringUtils.isNotBlank(couponTemplateDO.getCategory()) 
 | 
                            && couponTemplateDO.getCategory().equals(CouponCategoryEnum.POINT.getStatus() 
 | 
                    )){ 
 | 
                        // 获取当前优惠券已经领取的数量 
 | 
  
 | 
                        if(couponTemplateDO.getCouponAmount()<=0){ 
 | 
                            throw new ValidationException("当前优惠券已经领完!"); 
 | 
                        }else{ 
 | 
                            couponTemplateDO.setCouponAmount(couponTemplateDO.getCouponAmount()-1); 
 | 
                            // 更新库存 
 | 
                            couponTemplateService.updateById(couponTemplateDO); 
 | 
                        } 
 | 
  
 | 
                    } 
 | 
  
 | 
                    // 根据用户领取设置的getLimit 查看当前用户是否已经超领优惠券 
 | 
                    if(StringUtils.isNotBlank(couponTemplateDO.getCategory()) && couponTemplateDO.getCategory().equals(CouponCategoryEnum.ACTIVITY.getStatus()) ){ 
 | 
                        // 查看当前优惠券的领取时间在不在设置的领取时间范围类 
 | 
                        LocalDateTime now = LocalDateTime.now(); 
 | 
                        // 判断当前时间是否在领取时间范围内 
 | 
                        if (!(now.isAfter(couponTemplateDO.getGetStartDate()) && now.isBefore(couponTemplateDO.getGetEndDate()))) { 
 | 
                            throw new ValidationException("当前时间不在优惠券的领取时间范围内,无法操作!"); 
 | 
                        } 
 | 
  
 | 
                        // 获取当前优惠券已经领取的数量 
 | 
                        final Integer customGainTotal = getUserGainCouponRecordAmountById(couponTemplateDO.getId(),customer.getId()); 
 | 
                        if(couponTemplateDO.getGetLimit().compareTo(customGainTotal)<=0){ 
 | 
                            throw new ValidationException("超出个人领取限制,每人限领"+couponTemplateDO.getGetLimit()+"张!"); 
 | 
                        } 
 | 
                    } 
 | 
  
 | 
  
 | 
                    CouponRecordDO couponRecordDO=new CouponRecordDO(); 
 | 
                    BeanUtils.copyProperties(dto,couponRecordDO); 
 | 
                    couponRecordDO.create(SecurityUtils.getUserId()); 
 | 
                    // 设置为待使用状态 
 | 
                    couponRecordDO.setStatus(CouponUsedStatusEnum.UNUSED.getType()); 
 | 
  
 | 
                    // 根据商户设置用户id 
 | 
                    if(StringUtils.isBlank(dto.getUserId()) && StringUtils.isNotBlank(customer.getUserId())){ 
 | 
                        couponRecordDO.setUserId(customer.getUserId()); 
 | 
                    } 
 | 
  
 | 
                    // 优惠券字段冗余 
 | 
                    couponRecordDO.setCategory(couponTemplateDO.getCategory()); 
 | 
                    couponRecordDO.setCouponCode(couponTemplateDO.getCouponCode()); 
 | 
                    couponRecordDO.setCouponName(couponTemplateDO.getCouponName()); 
 | 
                    couponRecordDO.setCouponDiscountValue(couponTemplateDO.getCouponDiscountValue()); 
 | 
                    couponRecordDO.setMinOrderAmount(couponTemplateDO.getMinOrderAmount()); 
 | 
                    couponRecordDO.setGetType(couponTemplateDO.getGetType()); 
 | 
                    couponRecordDO.setCouponDiscountType(couponTemplateDO.getCouponDiscountType()); 
 | 
                    couponRecordDO.setGetUserType(couponTemplateDO.getGetUserType()); 
 | 
                    couponRecordDO.setPoint(couponTemplateDO.getPoint()); 
 | 
                    couponRecordDO.setMemberId(couponTemplateDO.getMemberId()); 
 | 
                    couponRecordDO.setImageUrl(couponTemplateDO.getImageUrl()); 
 | 
  
 | 
  
 | 
                    // 根据优惠券模板来计算优惠券的生效开始时间和结束时间 
 | 
                    if(StringUtils.isNotBlank(couponTemplateDO.getCategory()) && couponTemplateDO.getCategory().equals(CouponCategoryEnum.MEMBER.getStatus())){ 
 | 
                        // 如果是会员优惠券的话,则设置为优惠券的使用条件为优惠券的时间 
 | 
                        couponRecordDO.setEffectiveStart(couponTemplateDO.getUsageStartDate()); 
 | 
                        couponRecordDO.setEffectiveEnd(couponTemplateDO.getUsageEndDate()); 
 | 
                    }else{ 
 | 
                        // 非会员的根据领取时间类型来计算优惠券的时间 
 | 
                        if(StringUtils.isNotBlank(couponTemplateDO.getUsageType()) && couponTemplateDO.getUsageType().equals(CouponUsageTypeEnum.GET.getType())){ 
 | 
                            // 与领取时间一致 
 | 
                            couponRecordDO.setEffectiveStart(couponTemplateDO.getGetStartDate()); 
 | 
                            couponRecordDO.setEffectiveEnd(couponTemplateDO.getGetEndDate()); 
 | 
                        } 
 | 
                        if(StringUtils.isNotBlank(couponTemplateDO.getUsageType()) && couponTemplateDO.getUsageType().equals(CouponUsageTypeEnum.FIXED.getType())){ 
 | 
                            // 固定时间 
 | 
                            couponRecordDO.setEffectiveStart(couponTemplateDO.getUsageStartDate()); 
 | 
                            couponRecordDO.setEffectiveEnd(couponTemplateDO.getUsageEndDate()); 
 | 
                        } 
 | 
                        if(StringUtils.isNotBlank(couponTemplateDO.getUsageType()) && couponTemplateDO.getUsageType().equals(CouponUsageTypeEnum.GET_AFTER_TIME.getType())){ 
 | 
                            // 领取后有段时间 领取后有效时间 
 | 
                            // 根据发放后有效期来设置时间 
 | 
                            if (couponTemplateDO.getUsageTimeNum() == null || couponTemplateDO.getUsageTimeNum() <= 0) { 
 | 
                                throw new ValidationException("使用时间数量必须为正整数"); 
 | 
                            } 
 | 
                            LocalDateTime currentTime = LocalDateTime.now(); 
 | 
                            couponRecordDO.setEffectiveStart(currentTime); 
 | 
                            if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.DAY.getType())) { 
 | 
                                // 天 
 | 
                                couponRecordDO.setEffectiveEnd(currentTime.plusDays(couponTemplateDO.getUsageTimeNum())); 
 | 
                            } 
 | 
                            if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.HOUR.getType())) { 
 | 
                                // 小时 
 | 
                                couponRecordDO.setEffectiveEnd(currentTime.plusHours(couponTemplateDO.getUsageTimeNum())); 
 | 
                            } 
 | 
                            if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.MINUTE.getType())) { 
 | 
                                // 分钟 
 | 
                                couponRecordDO.setEffectiveEnd(currentTime.plusMinutes(couponTemplateDO.getUsageTimeNum())); 
 | 
                            } 
 | 
  
 | 
                        } 
 | 
                    } 
 | 
  
 | 
                    // 手动设置ID 
 | 
                    couponRecordDO.setId(IdUtil.simpleUUID()); 
 | 
                    return baseMapper.insert(couponRecordDO)>0; 
 | 
  
 | 
                } finally { 
 | 
                    lock.unlock(); 
 | 
                } 
 | 
            } 
 | 
        } catch (InterruptedException e) { 
 | 
            Thread.currentThread().interrupt(); 
 | 
            // 处理异常 
 | 
        } 
 | 
  
 | 
        return false; 
 | 
  
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean updateCouponRecord(CreateCouponRecordDTO dto) { 
 | 
        CouponRecordDO couponRecordDO=baseMapper.selectById(dto.getId()); 
 | 
        BeanUtils.copyProperties(dto,couponRecordDO); 
 | 
        couponRecordDO.update(SecurityUtils.getUserId()); 
 | 
  
 | 
        // 优惠券字段冗余 
 | 
        final CouponTemplateDO couponTemplateDO = couponTemplateService.getById(dto.getCouponId()); 
 | 
        if(null!=couponTemplateDO){ 
 | 
            couponRecordDO.setCategory(couponTemplateDO.getCategory()); 
 | 
            couponRecordDO.setCouponCode(couponTemplateDO.getCouponCode()); 
 | 
            couponRecordDO.setCouponName(couponTemplateDO.getCouponName()); 
 | 
            couponRecordDO.setCouponDiscountValue(couponTemplateDO.getCouponDiscountValue()); 
 | 
            couponRecordDO.setMinOrderAmount(couponTemplateDO.getMinOrderAmount()); 
 | 
        } 
 | 
  
 | 
  
 | 
        return baseMapper.updateById(couponRecordDO)>0; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean deleteCouponRecord(String id) { 
 | 
        return baseMapper.deleteById(id)>0; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public CouponRecordVO getCouponRecordById(String id) { 
 | 
        QueryCouponRecordDTO dto=new QueryCouponRecordDTO(); 
 | 
        dto.setId(id); 
 | 
        final List<CouponRecordVO> list = couponRecordMapperCustom.getList(dto); 
 | 
        if(CollectionUtils.isNotEmpty(list)){ 
 | 
            return list.get(0); 
 | 
        } 
 | 
        return null; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Page<CouponRecordVO> getPage(Page page, QueryCouponRecordDTO dto) { 
 | 
        List<CouponRecordVO> result=couponRecordMapperCustom.getPage(page,dto); 
 | 
        return page.setRecords(result); 
 | 
    } 
 | 
  
 | 
    @Transactional 
 | 
    @Override 
 | 
    public boolean grantVipCouponRecordList() { 
 | 
  
 | 
        try{ 
 | 
  
 | 
            LocalDateTime now = LocalDateTime.now(); 
 | 
            LocalDateTime firstDayStart = now.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0); 
 | 
            LocalDateTime lastDayEnd = now.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(0); 
 | 
  
 | 
            // 获取所有会员模版列表 
 | 
            List<CouponTemplateDO> vipTemplateList= couponTemplateService.getVipCouponTemplate(); 
 | 
  
 | 
            // 遍历所有相同等级用户信息,并根据优惠券设置的规则构造优惠券 
 | 
            final List<CouponTemplateDO> updateCouponTemplateList = vipTemplateList.stream().map(couponTemplateDO -> { 
 | 
                // 获取当前等级下的所有用户 
 | 
                final List<Customer> customerList = customerService.getCustomerListByLevelId(couponTemplateDO.getMemberId()); 
 | 
  
 | 
                final List<CouponRecordDO> gradeCouponRecordList = customerList.stream().map(customer -> { 
 | 
                    CouponRecordDO couponRecordDO = new CouponRecordDO(); 
 | 
                    BeanUtils.copyProperties(couponTemplateDO, couponRecordDO); 
 | 
                    couponRecordDO.setId(IdUtil.simpleUUID()); 
 | 
                    couponRecordDO.setCouponId(couponTemplateDO.getId()); 
 | 
                    couponRecordDO.setUserId(customer.getUserId()); 
 | 
                    couponRecordDO.setCustomerId(customer.getId()); 
 | 
                    couponRecordDO.setStatus(CouponUsedStatusEnum.UNUSED.getType()); 
 | 
                    couponRecordDO.setEffectiveStart(firstDayStart); 
 | 
                    couponRecordDO.setEffectiveEnd(lastDayEnd); 
 | 
                    couponRecordDO.setMemberId(couponTemplateDO.getMemberId()); 
 | 
                    couponRecordDO.setImageUrl(couponTemplateDO.getImageUrl()); 
 | 
                    // 创建信息 
 | 
                    couponRecordDO.create(); 
 | 
                    if(!checkCurMonVipCouponExists(couponRecordDO.getCouponId(),couponRecordDO.getCustomerId(),firstDayStart,lastDayEnd)){ 
 | 
                        return couponRecordDO; 
 | 
                    }else{ 
 | 
                        return null; 
 | 
                    } 
 | 
  
 | 
                }).filter(Objects::nonNull) 
 | 
                        .collect(Collectors.toList()); 
 | 
  
 | 
                // 批量保存等级下的优惠券信息 
 | 
                saveBatch(gradeCouponRecordList); 
 | 
  
 | 
                couponTemplateDO.setUsageStartDate(firstDayStart); 
 | 
                couponTemplateDO.setUsageEndDate(lastDayEnd); 
 | 
                couponTemplateDO.setGetStartDate(firstDayStart); 
 | 
                couponTemplateDO.setGetEndDate(lastDayEnd); 
 | 
  
 | 
                // 设置总数为当前会员的人数 
 | 
                couponTemplateDO.setCouponAmount(CollectionUtils.isNotEmpty(customerList)?customerList.size():0); 
 | 
  
 | 
                // 设置默认类型固定 
 | 
                couponTemplateDO.setUsageType(CouponUsageTypeEnum.FIXED.getType()); 
 | 
  
 | 
                return couponTemplateDO; 
 | 
  
 | 
            }).collect(Collectors.toList()); 
 | 
  
 | 
            // 批量更新原模版时间 
 | 
            couponTemplateService.updateBatchById(updateCouponTemplateList); 
 | 
  
 | 
            return true; 
 | 
        }catch (Exception e){ 
 | 
            // 报错日志信息报错 
 | 
            log.error(e.getMessage()); 
 | 
            return false; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean expiredCouponRecordLastMon() { 
 | 
  
 | 
        try{ 
 | 
            LocalDateTime now = LocalDateTime.now(); 
 | 
            LocalDateTime firstDayStart = now.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0); 
 | 
            LocalDateTime lastDayEnd = now.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(0); 
 | 
  
 | 
            // 只要找出时间小于当月的首天的设置成过期就可以 
 | 
  
 | 
            QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
            queryWrapper.lambda().eq(CouponRecordDO::getOrderId,"") 
 | 
                    .lt(CouponRecordDO::getEffectiveEnd,firstDayStart); 
 | 
  
 | 
            final List<CouponRecordDO> couponRecordDOS = baseMapper.selectList(queryWrapper); 
 | 
  
 | 
            final List<CouponRecordDO> expiredCouponRecordList = couponRecordDOS.stream().map(couponRecordDO -> { 
 | 
                couponRecordDO.setStatus(CouponUsedStatusEnum.EXPIRED.getType()); 
 | 
                return couponRecordDO; 
 | 
            }).collect(Collectors.toList()); 
 | 
  
 | 
            //更新 
 | 
            updateBatchById(expiredCouponRecordList); 
 | 
  
 | 
            return true; 
 | 
        }catch (Exception e){ 
 | 
            log.error(e.getMessage()); 
 | 
            return false; 
 | 
        } 
 | 
  
 | 
  
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer statisCouponTemplateCount(QueryCouponStatisticsBO queryCouponStatisticsBO) { 
 | 
        return couponRecordMapperCustom.statisCouponTemplateCount(queryCouponStatisticsBO); 
 | 
    } 
 | 
    @Override 
 | 
    public Integer statisCouponTemplateCurMonCount(QueryCouponStatisticsBO queryCouponStatisticsBO) { 
 | 
        return couponRecordMapperCustom.statisCouponTemplateCurMonCount(queryCouponStatisticsBO); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer statisCouponPointCurMonPontAmonut(QueryCouponStatisticsBO queryCouponStatisticsBO) { 
 | 
        return couponRecordMapperCustom.statisCouponPointCurMonPointAmonut(queryCouponStatisticsBO); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer getExistCouponAmount(QueryExistCouponDTO dto) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted, TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(StringUtils.isNotBlank(dto.getCouponId()), CouponRecordDO::getCouponId,dto.getCouponId()) 
 | 
                .eq(null!=dto.getCustomerId(),CouponRecordDO::getCustomerId,dto.getCustomerId()) 
 | 
                .eq(StringUtils.isNotBlank(dto.getCategory()),CouponRecordDO::getCategory,dto.getCategory()); 
 | 
  
 | 
        return baseMapper.selectCount(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer getExistGainCouponRecordAmountById(String couponId) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted, TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(StringUtils.isNotBlank(couponId), CouponRecordDO::getCouponId,couponId) 
 | 
                ; 
 | 
        return baseMapper.selectCount(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer getUserGainCouponRecordAmountById(String couponId, Long customerId) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted, TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(StringUtils.isNotBlank(couponId), CouponRecordDO::getCouponId,couponId) 
 | 
                .eq(null!=customerId,CouponRecordDO::getCustomerId,customerId) 
 | 
                ; 
 | 
  
 | 
        return baseMapper.selectCount(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public Integer getUserGainCouponRecordAmountByUserId(String couponId, String userId) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted, TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(StringUtils.isNotBlank(couponId), CouponRecordDO::getCouponId,couponId) 
 | 
                .eq(null!=userId,CouponRecordDO::getUserId,userId) 
 | 
        ; 
 | 
  
 | 
        return baseMapper.selectCount(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public List<CouponRecordVO> getMineCouponRecordList(QueryMineCouponRecordDTO dto) { 
 | 
        checkCouponExpired(dto); 
 | 
        return couponRecordMapperCustom.getMineCouponRecordList(dto); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void checkCouponExpired(QueryMineCouponRecordDTO dto) { 
 | 
        if(StringUtils.isBlank(dto.getUserId())){ 
 | 
            dto.setUserId(SecurityUtils.getUserId()); 
 | 
        } 
 | 
        // 将未使用的优惠券直接过期 
 | 
        couponRecordMapperCustom.checkCouponExpired(dto); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean checkCurMonVipCouponExists(String couponId, Long customId, LocalDateTime startDateTime, LocalDateTime endDateTime) { 
 | 
  
 | 
        LocalDateTime now = LocalDateTime.now(); 
 | 
        LocalDateTime firstDayStart = now.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0); 
 | 
        LocalDateTime lastDayEnd = now.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(0); 
 | 
        if(null==startDateTime){ 
 | 
            startDateTime=firstDayStart; 
 | 
        } 
 | 
        if(null==endDateTime){ 
 | 
            endDateTime=lastDayEnd; 
 | 
        } 
 | 
  
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted,TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(CouponRecordDO::getCouponId,couponId) 
 | 
                .eq(CouponRecordDO::getCustomerId,customId) 
 | 
                .eq(CouponRecordDO::getEffectiveStart,startDateTime) 
 | 
                .eq(CouponRecordDO::getEffectiveEnd,endDateTime); 
 | 
        return  baseMapper.selectCount(queryWrapper)>0; 
 | 
  
 | 
    } 
 | 
  
 | 
    @Transactional 
 | 
    @Override 
 | 
    public boolean useCoupon(String couponId, String orderId, BigDecimal orderMount) { 
 | 
        // 优惠券为空 
 | 
        if(StringUtils.isBlank(couponId)){ 
 | 
            throw new ValidationException("无效的优惠券"); 
 | 
        } 
 | 
        if(StringUtils.isBlank(orderId)){ 
 | 
            throw new ValidationException("订单id不能为空"); 
 | 
        } 
 | 
        if(orderMount.compareTo(BigDecimal.ZERO)<=0){ 
 | 
            throw new ValidationException("订单金额不能小于0"); 
 | 
        } 
 | 
  
 | 
        // 验证优惠券存在且有效 
 | 
        final CouponRecordDO couponRecordDO = baseMapper.selectById(couponId); 
 | 
        if(null==couponRecordDO || StringUtils.isNotBlank(couponRecordDO.getOrderId()) ){ 
 | 
            throw new ValidationException("无效的优惠券"); 
 | 
        } 
 | 
  
 | 
        if(couponRecordDO.getStatus().equals(CouponUsedStatusEnum.USED.getType())){ 
 | 
            throw new ValidationException("优惠券已经被使用"); 
 | 
        } 
 | 
        if(couponRecordDO.getStatus().equals(CouponUsedStatusEnum.EXPIRED.getType()) || LocalDateTime.now().isAfter(couponRecordDO.getEffectiveEnd())){ 
 | 
            throw new ValidationException("优惠券已过期"); 
 | 
        } 
 | 
  
 | 
        // 根据类型判断是无门槛还是满减,如果是无门槛 
 | 
        if(couponRecordDO.getCouponDiscountType().equals(CouponTypeEnum.ZERO.getType())){ 
 | 
            // 无门槛,查看金额是否大于满减值 
 | 
            if(orderMount.compareTo(couponRecordDO.getCouponDiscountValue())<0){ 
 | 
                throw new ValidationException(String.format("订单金额(%s)小于无门槛的金额(%s)", orderMount, couponRecordDO.getCouponDiscountValue())); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        if(couponRecordDO.getCouponDiscountType().equals(CouponTypeEnum.DISCOUNT.getType())){ 
 | 
            //满减,查看金额是否满足最小订单额 
 | 
            if(orderMount.compareTo(couponRecordDO.getMinOrderAmount())<0){ 
 | 
                throw new ValidationException(String.format("订单金额(%s)小于最低折扣订单金额(%s)", orderMount, couponRecordDO.getMinOrderAmount())); 
 | 
            } 
 | 
  
 | 
            if(orderMount.compareTo(couponRecordDO.getCouponDiscountValue())<0){ 
 | 
                throw new ValidationException(String.format("订单金额(%s)小于折扣的金额(%s)", orderMount, couponRecordDO.getCouponDiscountValue())); 
 | 
            } 
 | 
        } 
 | 
  
 | 
        // 查看当前的优惠券是否是当前人员的 
 | 
        if(!SecurityUtils.getUserId().equals(couponRecordDO.getUserId())){ 
 | 
            throw new ValidationException("优惠券不属于当前人员"); 
 | 
        } 
 | 
  
 | 
        // 优惠券使用操作 
 | 
        couponRecordDO.setStatus(CouponUsedStatusEnum.USED.getType()); 
 | 
        couponRecordDO.setUsedTime(LocalDateTime.now()); 
 | 
        couponRecordDO.setOrderId(orderId); 
 | 
  
 | 
        return baseMapper.updateById(couponRecordDO)>0; 
 | 
  
 | 
    } 
 | 
  
 | 
  
 | 
    @Transactional 
 | 
    @Override 
 | 
    public boolean cancelCouponUsage(String orderId) { 
 | 
        // 查询订单使用的优惠券 
 | 
        final CouponRecordDO couponRecordDO = getCouponByOrderId(orderId); 
 | 
        if(null==couponRecordDO){ 
 | 
            return false; 
 | 
        } 
 | 
        log.info("优惠券退回之前:"+ JSON.toJSONString(couponRecordDO)); 
 | 
        couponRecordDO.setStatus(CouponUsedStatusEnum.UNUSED.getType()); 
 | 
        couponRecordDO.setUsedTime(null); 
 | 
        couponRecordDO.setOrderId(null); 
 | 
        log.info("优惠券退回之后:"+ JSON.toJSONString(couponRecordDO)); 
 | 
        return baseMapper.updateById(couponRecordDO)>0; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public List<CouponRecordDO> getCouponListByOrderId(String orderId) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted,TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(CouponRecordDO::getOrderId,orderId); 
 | 
  
 | 
        return baseMapper.selectList(queryWrapper); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public CouponRecordDO getCouponByOrderId(String orderId) { 
 | 
        final List<CouponRecordDO> couponRecordDOList = getCouponListByOrderId(orderId); 
 | 
        if(CollectionUtils.isNotEmpty(couponRecordDOList)){ 
 | 
            return couponRecordDOList.get(0); 
 | 
        } 
 | 
        return null; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean checkUserCouponExists(String couponId, Long customId) { 
 | 
        QueryWrapper<CouponRecordDO> queryWrapper=new QueryWrapper<>(); 
 | 
        queryWrapper.lambda().eq(CouponRecordDO::getDeleted,TrueOrFalseEnum.FALSE.isFlag()) 
 | 
                .eq(CouponRecordDO::getCouponId,couponId) 
 | 
                .eq(CouponRecordDO::getCustomerId,customId) 
 | 
        ; 
 | 
        return baseMapper.selectCount(queryWrapper)>0; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean expireCouponRecordAll() { 
 | 
  
 | 
        return couponRecordMapperCustom.expireCouponRecordAll(); 
 | 
    } 
 | 
} 
 |