| package com.matrix.system.shopXcx.api.service; | 
|   | 
| import com.matrix.component.redis.RedisUserLoginUtils; | 
| import com.matrix.core.exception.GlobleException; | 
| import com.matrix.core.tools.LogUtil; | 
| import com.matrix.system.common.dao.BusParameterSettingsDao; | 
| import com.matrix.system.shopXcx.api.pojo.OrderCouponGroup; | 
| import com.matrix.system.shopXcx.api.pojo.OrderItemDto; | 
| import com.matrix.system.shopXcx.bean.ShopCoupon; | 
| import com.matrix.system.shopXcx.bean.ShopShoppingCart; | 
| import com.matrix.system.shopXcx.dao.ShopProductDao; | 
| import com.matrix.system.shopXcx.dao.ShopShoppingCartDao; | 
| import com.matrix.system.shopXcx.dao.ShopSkuDao; | 
| import org.apache.commons.collections.CollectionUtils; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Service; | 
|   | 
| import java.math.BigDecimal; | 
| import java.util.*; | 
|   | 
| /** | 
|  * 购物车前台展示对象 | 
|  */ | 
| @Service | 
| public class OrderCouponGroupService { | 
|     @Autowired | 
|     private ShopShoppingCartDao shoppingCartDao; | 
|     @Autowired | 
|     private RedisUserLoginUtils redisUserLoginUtils; | 
|   | 
|     @Autowired | 
|     WxShopCouponService shopCouponService; | 
|   | 
|     @Autowired | 
|     BusParameterSettingsDao busParameterSettingsDao; | 
|   | 
|     @Autowired | 
|     ShopProductDao shopProductDao; | 
|   | 
|     @Autowired | 
|     ShopSkuDao shopSkuDao; | 
|   | 
|     /** | 
|      * 初始化OrderCouponElement | 
|      * @param skuId | 
|      * @param count | 
|      * @param payType | 
|      * @return | 
|      */ | 
|     public OrderItemDto buildOrderCouponElement(OrderItemDto orderItemDto){ | 
|         orderItemDto.setShopSku(shopSkuDao.selectById(orderItemDto.getSkuId())); | 
|         orderItemDto.setShopProduct(shopProductDao.selectById(orderItemDto.getProductId())); | 
|         return orderItemDto; | 
|     } | 
|   | 
|     /** | 
|      * 计算用户的产品可以参与的店铺优惠活动分组 | 
|      */ | 
|     public List<OrderCouponGroup> buildOrderCouponGroupList(List<OrderItemDto> list) { | 
|   | 
|         //定义购物车优惠分组 | 
|         List<OrderCouponGroup> orderCouponGroupList = new ArrayList<>(); | 
|         // 1表示没有优惠的默认分组 | 
|         OrderCouponGroup def = new OrderCouponGroup(); | 
|         def.setSatisfactionCoupon(true); | 
|         def.setMsg("商城"); | 
|         def.setOrderItemDtos(new ArrayList<>()); | 
|         // 组合默认分组 | 
|         orderCouponGroupList.add(def); | 
|   | 
|         // 记录所有优惠券,一个优惠券(活动)表示一组 | 
|         Map<Integer, ShopCoupon> shopCouponMap = new HashMap<>(); | 
|   | 
|         //查询购物车中的产品匹配上的所有优惠活动 | 
|         for (OrderItemDto orderItemDto : list) { | 
|   | 
|             if(orderItemDto.getPayType()== ShopShoppingCart.CAR_TYPE_SCORE){ | 
|                 // 积分兑换产品不参加优惠 | 
|                 def.getOrderItemDtos().add(orderItemDto); | 
|             }else{ | 
|                 List<ShopCoupon> shopCouponList = shopCouponService.getHdListByProductId(orderItemDto.getProductId()); | 
|                 if (CollectionUtils.isNotEmpty(shopCouponList)) { | 
|                     // 把所有的优惠券和购物车条目先关联一下,后续可以计算优惠升级的情况 | 
|                     orderItemDto.setShopCoupons(shopCouponList); | 
|                     for (ShopCoupon shopCoupon : shopCouponList) { | 
|                         shopCouponMap.put(shopCoupon.getId(), shopCoupon); | 
|                     } | 
|                 } else { | 
|                     // 该产品没有参加优惠券 | 
|                     def.getOrderItemDtos().add(orderItemDto); | 
|                 } | 
|             } | 
|   | 
|         } | 
|   | 
|         //计算没有优惠组的价格 | 
|         countPrice(def); | 
|   | 
|   | 
|         /* | 
|          * 计算优惠券分组 1、获取到所有的优惠券,从最高满减开始,找寻合适的产品,找到后加入对应的购物车组 | 
|          * 2、计算组内价格 | 
|          */ | 
|         Set<Integer> keys = shopCouponMap.keySet(); | 
|         List<ShopCoupon> allShopCoupons = new ArrayList<>(); | 
|         for (Integer key : keys) { | 
|             allShopCoupons.add(shopCouponMap.get(key)); | 
|         } | 
|   | 
|         //根据优惠力度排序,优惠力度大的先参与计算 | 
|         Collections.sort(allShopCoupons, new Comparator() { | 
|             @Override | 
|             public int compare(Object o1, Object o2) { | 
|                 ShopCoupon e1 = (ShopCoupon) o1; | 
|                 ShopCoupon e2 = (ShopCoupon) o2; | 
|                 return e2.getMinAmount().compareTo(e1.getMinAmount()); | 
|             } | 
|         }); | 
|   | 
|   | 
|         // 进行购物车和优惠券的匹配,匹配成功的加入到优惠组中, | 
|         for (int i = 0; i < allShopCoupons.size(); i++) { | 
|             ShopCoupon shopCoupon = allShopCoupons.get(i); | 
|             OrderCouponGroup shopCarVo = new OrderCouponGroup(); | 
|             shopCarVo.setCoupon(shopCoupon); | 
|             shopCarVo.setOrderItemDtos(new ArrayList<>()); | 
|             orderCouponGroupList.add(i, shopCarVo); | 
|   | 
|             // 获取所有购物车条目 | 
|             for (OrderItemDto orderItemDto : list) { | 
|                 // 如果匹配到的产品已经出现在其他优惠组中,则需要判断是否移除之前的组 | 
|                 boolean needRemove = false; | 
|   | 
|                 // 判断当前购物车条目是否已经在合适的组里了 | 
|                 if (isInGroupAndSatisfaction(orderItemDto, orderCouponGroupList)) { | 
|                     continue; | 
|   | 
|                 } else if (isInGroupNotSatisfaction(orderItemDto, orderCouponGroupList)) { | 
|                     needRemove = true; | 
|                 } | 
|   | 
|                 List<ShopCoupon> cartCouons = orderItemDto.getShopCoupons(); | 
|                 if (cartCouons != null) { | 
|                     // 获取每个购物车条目满足的优惠 | 
|                     for (ShopCoupon cartCouon : cartCouons) { | 
|                         if (cartCouon.getId().equals(shopCoupon.getId())) { | 
|                             //匹配成功,加入本组 | 
|                             LogUtil.debug("购物车" + orderItemDto.getProductId() + "和优惠券" + cartCouon.getCName() + "匹配"); | 
|                             if (needRemove) { | 
|                                 removeNotSatisfaction(orderItemDto, orderCouponGroupList); | 
|                             } | 
|                             shopCarVo.getOrderItemDtos().add(orderItemDto); | 
|                             break; | 
|                         } | 
|                     } | 
|                 } | 
|   | 
|             } | 
|   | 
|             // 计算本组优惠券是否已经满足优惠条件 | 
|             countPrice(shopCarVo); | 
|         } | 
|   | 
|   | 
|         // 因为有些优惠中可能没有产品,所以要去除cartList中没有产品的分组 | 
|         List<OrderCouponGroup> cartListCopy = new ArrayList<>(); | 
|         for (OrderCouponGroup orderCouponGroup : orderCouponGroupList) { | 
|             if (CollectionUtils.isNotEmpty(orderCouponGroup.getOrderItemDtos())) { | 
|                 cartListCopy.add(orderCouponGroup); | 
|             } | 
|         } | 
|         return cartListCopy; | 
|     } | 
|   | 
|   | 
|     /** | 
|      * 购车条目在组中并且组是否已经满足优惠的 | 
|      * | 
|      * @param cartList | 
|      * @return | 
|      */ | 
|     private boolean isInGroupAndSatisfaction(OrderItemDto orderItemDto, List<OrderCouponGroup> cartList) { | 
|         boolean result = false; | 
|         for (OrderCouponGroup cartVo : cartList) { | 
|             if (cartVo.isSatisfactionCoupon() && cartVo.getOrderItemDtos().contains(orderItemDto)) { | 
|                 result = true; | 
|             } | 
|         } | 
|         return result; | 
|     } | 
|   | 
|     /** | 
|      * 购物车条目在组中,但是组中产品没有达到优惠条件 | 
|      * @param cartList | 
|      * @return | 
|      */ | 
|     private boolean isInGroupNotSatisfaction(OrderItemDto orderItemDto, List<OrderCouponGroup> cartList) { | 
|         boolean result = false; | 
|         for (OrderCouponGroup cartVo : cartList) { | 
|             if (!cartVo.isSatisfactionCoupon() && cartVo.getOrderItemDtos().contains(orderItemDto)) { | 
|                 result = true; | 
|             } | 
|         } | 
|         return result; | 
|     } | 
|   | 
|     /** | 
|      * 删除购物车条目所在分组中的引用 | 
|      * | 
|      * @param cartList | 
|      */ | 
|     private void removeNotSatisfaction(OrderItemDto orderItemDto, List<OrderCouponGroup> cartList) { | 
|         for (OrderCouponGroup cartVo : cartList) { | 
|             if (cartVo.getOrderItemDtos().remove(orderItemDto)) { | 
|                 LogUtil.debug("删除购物车所在组" + cartVo.getCoupon().getCName() + "," + orderItemDto.getProductId()); | 
|             } | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 计算购物车价格和优惠信息 | 
|      * | 
|      * @author JIANGYOUYAO | 
|      * @email 935090232@qq.com | 
|      * @date 2019年8月27日 | 
|      */ | 
|     private void countPrice(OrderCouponGroup orderCouponGroup) { | 
|         List<OrderItemDto> orderItemDtoList = orderCouponGroup.getOrderItemDtos(); | 
|         // 计算总价 | 
|         BigDecimal sum = BigDecimal.ZERO; | 
|         //抵扣总积分 | 
|         BigDecimal scoreSum = BigDecimal.ZERO; | 
|   | 
|         for (OrderItemDto orderCouponElement : orderItemDtoList) { | 
|             if(ShopShoppingCart.CAR_TYPE_MICRO==orderCouponElement.getPayType()){ | 
|                 //直接购买 | 
|                 sum = sum.add(orderCouponElement.getShopSku().getPrice().multiply(BigDecimal.valueOf(orderCouponElement.getCount()))); | 
|   | 
|             }else if(ShopShoppingCart.CAR_TYPE_SCORE==orderCouponElement.getPayType()){ | 
|                 //积分兑换 | 
|                 sum = sum.add(orderCouponElement.getShopSku().getScorePrice().multiply(BigDecimal.valueOf(orderCouponElement.getCount()))); | 
|                 scoreSum = scoreSum.add(new BigDecimal(orderCouponElement.getShopSku().getScoreCount() * orderCouponElement.getCount())); | 
|             }else{ | 
|                 throw new GlobleException("参数错误"); | 
|             } | 
|         } | 
|   | 
|         if (orderCouponGroup.getCoupon() != null) { | 
|             // 存在优惠券 | 
|             if (sum.compareTo(orderCouponGroup.getCoupon().getMinAmount()) >= 0) { | 
|                 //标记为合理分组 | 
|                 orderCouponGroup.setSatisfactionCoupon(true); | 
|                 if (sum.compareTo(orderCouponGroup.getCoupon().getMinAmount()) >= 0) { | 
|                     orderCouponGroup.setSubtotal(sum.subtract(orderCouponGroup.getCoupon().getOffsetAmount())); | 
|                     orderCouponGroup.setSrcPrice(sum); | 
|                     orderCouponGroup.setCouponPrice(orderCouponGroup.getCoupon().getOffsetAmount()); | 
|                     orderCouponGroup.setMsg(orderCouponGroup.getCoupon().getCName() + ",已优惠" | 
|                             + orderCouponGroup.getCoupon().getOffsetAmount().stripTrailingZeros().toPlainString() + "元"); | 
|                 } | 
|             } | 
|             if (sum.compareTo(orderCouponGroup.getCoupon().getMinAmount()) < 0) { | 
|                 orderCouponGroup.setSatisfactionCoupon(false); | 
|                 orderCouponGroup.setSubtotal(sum); | 
|                 orderCouponGroup.setSrcPrice(sum); | 
|                 orderCouponGroup.setMsg(orderCouponGroup.getCoupon().getCName()); | 
|                 if (sum.doubleValue() > 0) { | 
|                     orderCouponGroup.setMsg(orderCouponGroup.getCoupon().getCName() + ",再买" | 
|                             + (orderCouponGroup.getCoupon().getMinAmount().subtract(sum)).stripTrailingZeros() | 
|                             .toPlainString() | 
|                             + "元立减" + orderCouponGroup.getCoupon().getOffsetAmount().stripTrailingZeros().toPlainString() | 
|                             + "元"); | 
|                 } | 
|             } | 
|         } else { | 
|             orderCouponGroup.setSubtotal(sum); | 
|             orderCouponGroup.setSrcPrice(sum); | 
|             orderCouponGroup.setSatisfactionCoupon(true); | 
|         } | 
|         orderCouponGroup.setScorePay(scoreSum); | 
|     } | 
|   | 
| } |