package com.doumee.service.business.impl; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.core.model.LoginUserInfo; import com.doumee.core.model.PageData; import com.doumee.core.model.PageWrap; import com.doumee.core.utils.Constants; import com.doumee.core.utils.DateUtil; import com.doumee.core.utils.ListUtil; import com.doumee.core.utils.Utils; import com.doumee.dao.business.*; import com.doumee.dao.business.model.*; import com.doumee.dao.web.dto.CouponDTO; import com.doumee.dao.web.dto.MemberCouponDTO; import com.doumee.dao.web.request.PayDetailRequest; import com.doumee.dao.web.response.goods.OrderGoodsCalculateResponse; import com.doumee.service.business.MemberCouponService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.xiaoymin.knife4j.core.util.CollectionUtils; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; /** * 用户优惠券关联表Service实现 * @author 江蹄蹄 * @date 2023/03/21 15:48 */ @Service public class MemberCouponServiceImpl implements MemberCouponService { @Autowired private MemberCouponMapper memberCouponMapper; @Autowired private GoodsMapper goodsMapper; @Autowired private GoodsSkuMapper goodsSkuMapper; @Autowired private MemberCouponJoinMapper memberCouponJoinMapper; @Autowired private CouponMapper couponMapper; @Autowired private MemberMapper memberMapper; @Override public Integer create(MemberCoupon memberCoupon) { LoginUserInfo loginUserInfo = (LoginUserInfo)SecurityUtils.getSubject().getPrincipal(); Coupon coupon = couponMapper.selectById(memberCoupon.getCouponId()); if(Objects.isNull(coupon)){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "未查询到优惠券信息"); } if(coupon.getStatus().equals(Constants.ONE)){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "该优惠券已禁用,无法兑换!"); } //查询已兑换数量 QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("COUPON_ID",coupon.getId()); Long exchangeNum = memberCouponMapper.selectCount(queryWrapper); if(exchangeNum.compareTo(coupon.getNum()) >= Constants.ZERO){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "该优惠券已兑换完,无法兑换!"); } //是否已兑换 queryWrapper.eq("MEMBER_ID",coupon.getId()); if(memberCouponMapper.selectCount(queryWrapper) > Constants.ZERO){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "已兑换该优惠券,无法兑换!"); }; MemberCoupon insert = new MemberCoupon(); Date now = new Date(); insert.setCreator(loginUserInfo.getId()); insert.setCreateDate(now); insert.setEditor(loginUserInfo.getId()); insert.setEditDate(now); insert.setIsdeleted(Constants.ZERO); insert.setRemark(memberCoupon.getRemark()); insert.setMemberId(loginUserInfo.getMemberId()); insert.setShopId(coupon.getShopId()); insert.setType(coupon.getType()); insert.setLimitPrice(coupon.getLimitPrice()); insert.setPrice(coupon.getPrice()); insert.setStartDate(now); //推迟天数 LocalDateTime localDateTime = LocalDateTime.now().minusDays(coupon.getValidDays()); insert.setEndDate(DateUtil.toDate(localDateTime)); insert.setGetMethod(Constants.ONE); insert.setIntegral(coupon.getIntegral()); insert.setStatus(Constants.ZERO); insert.setInfo(coupon.getInfo()); // insert.setBackIntegral(coupon.getB); insert.setName(coupon.getName()); insert.setCouponId(coupon.getId()); memberCouponMapper.insert(insert); return memberCoupon.getId(); } @Override public void deleteById(Integer id) { memberCouponMapper.deleteById(id); } @Override public void delete(MemberCoupon memberCoupon) { UpdateWrapper deleteWrapper = new UpdateWrapper<>(memberCoupon); memberCouponMapper.delete(deleteWrapper); } @Override public void deleteByIdInBatch(List ids) { if (CollectionUtils.isEmpty(ids)) { return; } memberCouponMapper.deleteBatchIds(ids); } @Override public void updateById(MemberCoupon memberCoupon) { memberCouponMapper.updateById(memberCoupon); } @Override public void updateByIdInBatch(List memberCoupons) { if (CollectionUtils.isEmpty(memberCoupons)) { return; } for (MemberCoupon memberCoupon: memberCoupons) { this.updateById(memberCoupon); } } @Override public MemberCoupon findById(Integer id) { return memberCouponMapper.selectById(id); } @Override public MemberCoupon findOne(MemberCoupon memberCoupon) { QueryWrapper wrapper = new QueryWrapper<>(memberCoupon); return memberCouponMapper.selectOne(wrapper); } @Override public List findList(MemberCoupon memberCoupon) { QueryWrapper wrapper = new QueryWrapper<>(memberCoupon); return memberCouponMapper.selectList(wrapper); } @Override public PageData findPage(PageWrap pageWrap) { IPage page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); Utils.MP.blankToNull(pageWrap.getModel()); queryWrapper.selectAll(MemberCoupon.class); queryWrapper.selectAs(Member::getNickname,MemberCoupon::getNikeName); queryWrapper.leftJoin(Member.class,Member::getId,MemberCoupon::getMemberId); queryWrapper.eq(MemberCoupon::getIsdeleted, Constants.ZERO); queryWrapper.eq(pageWrap.getModel().getStatus()!=null,MemberCoupon::getStatus, pageWrap.getModel().getStatus()); queryWrapper.eq(pageWrap.getModel().getGetMethod()!=null,MemberCoupon::getGetMethod, pageWrap.getModel().getGetMethod()); queryWrapper.and(StringUtils.isNotBlank(pageWrap.getModel().getNikeName()),ms -> ms.like( Member::getNickname, pageWrap.getModel().getNikeName()). or().eq( Member::getName, pageWrap.getModel().getNikeName()). or().eq( Member::getPhone, pageWrap.getModel().getNikeName())); queryWrapper.orderByDesc(MemberCoupon::getCreateDate); IPage result = memberCouponJoinMapper.selectJoinPage(page, MemberCoupon.class, queryWrapper); return PageData.from(result); } @Override public long count(MemberCoupon memberCoupon) { QueryWrapper wrapper = new QueryWrapper<>(memberCoupon); return memberCouponMapper.selectCount(wrapper); } /****************************************移动端接口开始********************************************************************/ /** * 优惠券列表 * @param pages * @param price * @param memberId * @param couponType * @return */ @Override public IPage memberCouponPage(IPage pages, BigDecimal price, Integer memberId,Integer couponType) { IPage page = memberCouponMapper.memberCouponPage(pages,new QueryWrapper() .eq("m.MEMBER_ID",memberId) .eq("m.TYPE",Constants.ONE) .eq("m.STATUS",Constants.ZERO) .eq("TYPE",couponType) .apply(!Objects.isNull(price)," m.LIMIT_PRICE >= "+price+" ") .apply(" now() between m.START_DATE and m.END_DATE ") .orderByDesc(" m.PRICE ") ); return page; } /** * 优惠券数量 * @param price * @param memberId * @param couponType * @return */ @Override public long memberCouponNum( BigDecimal price, Integer memberId,Integer couponType) { long count = memberCouponMapper.selectCount(new QueryWrapper() .eq("MEMBER_ID",memberId) .eq("STATUS",Constants.ZERO) .eq("TYPE",couponType) .apply("LIMIT_PRICE >= "+price+" ") .apply(" now() between START_DATE and END_DATE ") .orderByDesc(" PRICE ") ); return count; } @Override public PageData findMemberCouponDTO(PageWrap pageWrap) { IPage page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); Utils.MP.blankToNull(pageWrap.getModel()); queryWrapper.selectAs(MemberCoupon::getId,MemberCouponDTO::getId); queryWrapper.selectAs(Member::getId,MemberCouponDTO::getMemberId); queryWrapper.selectAs(Member::getImgurl,MemberCouponDTO::getImgurl); queryWrapper.selectAs(MemberCoupon::getShopId,MemberCouponDTO::getShopId); queryWrapper.selectAs(MemberCoupon::getType,MemberCouponDTO::getType); queryWrapper.selectAs(MemberCoupon::getLimitPrice,MemberCouponDTO::getLimitPrice); queryWrapper.selectAs(MemberCoupon::getPrice,MemberCouponDTO::getPrice); queryWrapper.selectAs(MemberCoupon::getStartDate,MemberCouponDTO::getStartDate); queryWrapper.selectAs(MemberCoupon::getEndDate,MemberCouponDTO::getEndDate); queryWrapper.selectAs(MemberCoupon::getUseDate,MemberCouponDTO::getUseDate); queryWrapper.selectAs(MemberCoupon::getStatus,MemberCouponDTO::getStatus); queryWrapper.leftJoin(MemberCoupon.class,MemberCoupon::getMemberId,Member::getId); queryWrapper.eq(MemberCoupon::getCouponId,pageWrap.getModel().getCouponId()) .like(StringUtils.isNotBlank(pageWrap.getModel().getNikeName()),Member::getNickname,pageWrap.getModel().getNikeName()) .eq(MemberCoupon::getStatus,pageWrap.getModel().getStatus()); IPage result = memberCouponJoinMapper.selectJoinPage(page, MemberCouponDTO.class, queryWrapper); if (CollectionUtils.isEmpty(result.getRecords())){ return PageData.from(new Page<>()); } result.getRecords().stream().filter(s->Constants.equalsInteger(Constants.ZERO,s.getStatus())) .forEach(s->{ s.setStatus(s.getEndDate().before(new Date()) ? -1 : 0); }); return PageData.from(result); } public void exchangeCoupon(Integer couponId, Integer memberId){ Coupon coupon = couponMapper.selectById(couponId); if(Objects.isNull(coupon)){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "未查询到优惠券信息"); } if(!coupon.getType().equals(Constants.ONE)){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "非平台优惠券,无法兑换!"); } if(coupon.getStatus().equals(Constants.ONE)){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "该优惠券已禁用,无法兑换!"); } //查询已兑换数量 QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("COUPON_ID",couponId); Long exchangeNum = memberCouponMapper.selectCount(queryWrapper); if(exchangeNum.compareTo(coupon.getNum())>=Constants.ZERO){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "该优惠券已兑换完,无法兑换!"); } //是否已兑换 queryWrapper.eq("MEMBER_ID",memberId); if(memberCouponMapper.selectCount(queryWrapper)>Constants.ZERO){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "已兑换该优惠券,无法兑换!"); }; //查询剩余咖豆是否足够购买 Member member = memberMapper.selectById(memberId); if(member.getIntegral().compareTo(coupon.getIntegral()) getApplyCoupon(List requestList,Integer memberId){ List memberCouponList = new ArrayList<>(); List goodsSkuList = goodsSkuMapper.selectList(new QueryWrapper() .lambda() .eq(GoodsSku::getIsdeleted,Constants.ZERO) .in(GoodsSku::getId,requestList.stream().map(i->i.getGoodsSkuId()).collect(Collectors.toList())) ); if(CollectionUtils.isEmpty(goodsSkuList)||!Constants.equalsInteger(goodsSkuList.size(),requestList.size())){ throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"商品SKU信息错误,请刷新重试"); } //查询商品列表 List goodsList = goodsMapper.selectJoinList(Goods.class, new MPJLambdaWrapper() .selectAs(GoodsSku::getPrice,Goods::getSkuPrice) .selectAs(GoodsSku::getId,Goods::getSkuId) .leftJoin(GoodsSku.class,GoodsSku::getGoodsId,Goods::getId) .in(GoodsSku::getId,requestList.stream().map(i->i.getGoodsSkuId()).collect(Collectors.toList()))); if(Objects.isNull(goodsList)){ return memberCouponList; } //获取选择的商品总金额 与 单个商品金额 BigDecimal totalAmount = BigDecimal.ZERO; for (Goods goods:goodsList) { List request = requestList.stream().filter(i->Constants.equalsInteger(i.getGoodsSkuId(), goods.getSkuId())).collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(request)){ goods.setSkuAmount(goods.getSkuPrice().multiply(new BigDecimal(request.get(Constants.ZERO).getGoodsNum()+""))); totalAmount = totalAmount.add(goods.getSkuAmount()); } } List goodsCalculateList = ListUtil.copyProperties(goodsList,OrderGoodsCalculateResponse::new); //获取所有满足金额且可用的优惠券 List allCoupon = memberCouponMapper.selectList(new QueryWrapper().lambda() .eq(MemberCoupon::getIsdeleted,Constants.ZERO) .eq(MemberCoupon::getStatus,Constants.ZERO) .apply(" LIMIT_PRICE <= " + totalAmount) .apply(" now() between START_DATE and END_DATE ")); if(CollectionUtils.isNotEmpty(allCoupon)){ for (MemberCoupon memberCoupon:allCoupon) { //适用类型:0=全场;1=品类;2=指定商品 if(Constants.equalsInteger(memberCoupon.getApplyType(),Constants.ZERO)){ memberCoupon.setValidAmount(memberCoupon.getPrice()); }else{ List applyIdList = Arrays.asList(memberCoupon.getApplyIds().split(",")); //获取有效可以使用优惠券的数据 isVaildUse(applyIdList,goodsCalculateList, Constants.equalsInteger(memberCoupon.getApplyType(),Constants.ONE)?Constants.ONE:Constants.ZERO); BigDecimal skuAmount = goodsCalculateList.stream().filter(i->i.getUseCoupon()).map(i->i.getSkuAmount()).reduce(BigDecimal.ZERO,BigDecimal::add); if(skuAmount.compareTo(memberCoupon.getLimitPrice())>=Constants.ZERO){ //根据金额计算实际折扣金额 BigDecimal couponPrice = skuAmount.multiply(memberCoupon.getPrice()).divide(new BigDecimal("100"),2, RoundingMode.HALF_UP); //折扣金额大于最大可折扣金额 则使用最大可折扣金额 memberCoupon.setValidAmount(couponPrice.compareTo(memberCoupon.getMaxPrice())>Constants.ZERO?memberCoupon.getMaxPrice():couponPrice); memberCouponList.add(memberCoupon); } } } } // 使用 Stream 排序 reversed() 表示倒序 memberCouponList = memberCouponList.stream().sorted(Comparator.comparing(MemberCoupon::getValidAmount,Comparator.nullsFirst(BigDecimal::compareTo)).reversed()) .collect(Collectors.toList()); return memberCouponList; } /** * 计算当前已选择优惠券每个商品占比金额 * @param coupon 优惠券信息 * @param goodsCalculateList 商品集合 * @param totalAmount 订单总金额 */ public void calculateCouponRata(MemberCoupon coupon,List goodsCalculateList,BigDecimal totalAmount){ //总余额 BigDecimal validAmount = coupon.getValidAmount(); //剩余可分配金额 BigDecimal surplusValidAmount = validAmount; //已用占比比例值 BigDecimal rata = BigDecimal.ZERO; //根据优惠券类型 计算可以使用优惠券的商品信息 适用类型:0=全场;1=品类;2=指定商品 if(!Constants.equalsInteger(coupon.getApplyType(),Constants.ZERO)){ List applyIdList = Arrays.asList(coupon.getApplyIds().split(",")); isVaildUse(applyIdList,goodsCalculateList, Constants.equalsInteger(coupon.getApplyType(),Constants.ONE)?Constants.ONE:Constants.ZERO); } //使用了优惠券的商品数量 Integer countCouponNum = goodsCalculateList.stream().filter(i->i.getUseCoupon()).collect(Collectors.toList()).size(); Integer useCouponNum = Constants.ZERO; for (int i = 0; i < goodsCalculateList.size(); i++) { if(!goodsCalculateList.get(i).getUseCoupon()){ goodsCalculateList.get(i).setCouponDeductCash(BigDecimal.ZERO); continue; } if(Constants.equalsInteger(useCouponNum+1,countCouponNum)){ goodsCalculateList.get(i).setOrderCouponRata(new BigDecimal("1").subtract(rata)); goodsCalculateList.get(i).setCouponDeductCash(surplusValidAmount); break; } goodsCalculateList.get(i).setOrderCouponRata(goodsCalculateList.get(i).getSkuAmount().divide(totalAmount,2,BigDecimal.ROUND_DOWN)); goodsCalculateList.get(i).setCouponDeductCash(validAmount.multiply(goodsCalculateList.get(i).getOrderCouponRata())); surplusValidAmount = surplusValidAmount.subtract(goodsCalculateList.get(i).getCouponDeductCash()); rata = rata.add(goodsCalculateList.get(i).getOrderCouponRata()); useCouponNum = useCouponNum + 1; } } /** * 判断是否可以有效使用 * @param idList * @param goodsList * @param vaildType 0=商品;1=品类 * @return */ public void isVaildUse(List idList,List goodsList,Integer vaildType){ for (OrderGoodsCalculateResponse response:goodsList) { response.setUseCoupon(idList.contains(Constants.equalsInteger(vaildType,Constants.ZERO)?response.getId().toString():response.getCategoryId().toString())?true:false); } } // public Set isVaildUse(List idList,List goodsList,Integer vaildType){ // List resultList = new ArrayList<>(); // for (String id:idList) { // if(Constants.equalsInteger(vaildType,Constants.ZERO)){ // resultList.addAll(goodsList.stream().filter(i->i.getId().toString().equals(id)).collect(Collectors.toList())); // }else{ // resultList.addAll(goodsList.stream().filter(i->i.getCategoryId().toString().equals(id)).collect(Collectors.toList())); // } // } // if(CollectionUtils.isNotEmpty(resultList)){ // return new HashSet<>(resultList.stream().map(i->i.getId()).collect(Collectors.toList())); // } // return new HashSet<>(); // } }