rk
2025-12-15 a1a6e227628810259fcba0fff146792e97a80b8a
server/dmmall_service/src/main/java/com/doumee/service/business/impl/MemberCouponServiceImpl.java
@@ -7,31 +7,31 @@
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.CouponMapper;
import com.doumee.dao.business.MemberCouponJoinMapper;
import com.doumee.dao.business.MemberCouponMapper;
import com.doumee.dao.business.MemberMapper;
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 org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 用户优惠券关联表Service实现
@@ -43,6 +43,12 @@
    @Autowired
    private MemberCouponMapper memberCouponMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;
    @Autowired
    private MemberCouponJoinMapper memberCouponJoinMapper;
@@ -209,6 +215,10 @@
        return page;
    }
    /**
     * 优惠券数量
     * @param price
@@ -220,7 +230,6 @@
    public long memberCouponNum( BigDecimal price, Integer memberId,Integer couponType) {
        long count = memberCouponMapper.selectCount(new QueryWrapper<MemberCoupon>()
                .eq("MEMBER_ID",memberId)
                .eq("TYPE",Constants.ONE)
                .eq("STATUS",Constants.ZERO)
                .eq("TYPE",couponType)
                .apply("LIMIT_PRICE >= "+price+" ")
@@ -317,4 +326,152 @@
    }
    /**
     * 根据商品信息获取适用的优惠券
     */
    @Override
    public List<MemberCoupon> getApplyCoupon(List<PayDetailRequest> requestList,Integer memberId){
        List<MemberCoupon> memberCouponList = new ArrayList<>();
        List<GoodsSku> goodsSkuList = goodsSkuMapper.selectList(new QueryWrapper<GoodsSku>()
                .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<Goods> goodsList = goodsMapper.selectJoinList(Goods.class,
                new MPJLambdaWrapper<Goods>()
                        .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<PayDetailRequest> 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<OrderGoodsCalculateResponse> goodsCalculateList = ListUtil.copyProperties(goodsList,OrderGoodsCalculateResponse::new);
        //获取所有满足金额且可用的优惠券
        List<MemberCoupon> allCoupon =  memberCouponMapper.selectList(new QueryWrapper<MemberCoupon>().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<String> 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<OrderGoodsCalculateResponse> 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<String> 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<String> idList,List<OrderGoodsCalculateResponse> 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<Integer> isVaildUse(List<String> idList,List<OrderGoodsCalculateResponse> goodsList,Integer vaildType){
//        List<OrderGoodsCalculateResponse> 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<>();
//    }
}