package cn.lili.modules.order.cart.render.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import cn.lili.common.enums.PromotionTypeEnum; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.dos.Wholesale; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; import cn.lili.modules.goods.entity.enums.GoodsSalesModeEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.goods.service.WholesaleService; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.order.cart.entity.dto.TradeDTO; import cn.lili.modules.order.cart.entity.enums.CartTypeEnum; import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; import cn.lili.modules.order.cart.entity.enums.RenderStepEnums; import cn.lili.modules.order.cart.entity.vo.CartSkuVO; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.cart.render.CartRenderStep; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.entity.dos.Pintuan; import cn.lili.modules.promotion.entity.dos.PointsGoods; import cn.lili.modules.promotion.entity.vos.CouponVO; import cn.lili.modules.promotion.service.PromotionGoodsService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; /** * 商品有效性校验 * * @author Chopper * @since 2020-07-02 14:47 */ @Service @Slf4j public class CheckDataRender implements CartRenderStep { @Autowired private GoodsSkuService goodsSkuService; @Autowired private OrderService orderService; @Autowired private MemberService memberService; @Autowired private WholesaleService wholesaleService; /** * 商品索引 */ @Autowired private PromotionGoodsService promotionGoodsService; @Override public RenderStepEnums step() { return RenderStepEnums.CHECK_DATA; } @Override public void render(TradeDTO tradeDTO) { //校验商品有效性 checkData(tradeDTO); //预校验 preCalibration(tradeDTO); //批量销售预处理 preSaleModel(tradeDTO); //店铺分组数据初始化 groupStore(tradeDTO); } /** * 校验商品属性 * * @param tradeDTO 购物车视图 */ private void checkData(TradeDTO tradeDTO) { List cartSkuVOS = tradeDTO.getSkuList(); //循环购物车中的商品 for (CartSkuVO cartSkuVO : cartSkuVOS) { //如果失效,确认sku为未选中状态 if (Boolean.TRUE.equals(cartSkuVO.getInvalid())) { //设置购物车未选中 cartSkuVO.setChecked(false); } //缓存中的商品信息 GoodsSku dataSku = goodsSkuService.getGoodsSkuByIdFromCache(cartSkuVO.getGoodsSku().getId()); //商品上架状态判定 sku为空、sku非上架状态、sku审核不通过 boolean checkGoodsStatus = dataSku == null || !GoodsAuthEnum.PASS.name().equals(dataSku.getAuthFlag()) || !GoodsStatusEnum.UPPER.name().equals(dataSku.getMarketEnable()); //商品有效性判定 sku不为空且sku的更新时间不为空且sku的更新时间在购物车sku的更新时间之后 boolean checkGoodsValid = dataSku != null && dataSku.getUpdateTime() != null && cartSkuVO.getGoodsSku() != null && cartSkuVO.getGoodsSku().getUpdateTime() != null && dataSku.getUpdateTime().after(cartSkuVO.getGoodsSku().getUpdateTime()); if (checkGoodsStatus || checkGoodsValid) { if (checkGoodsValid) { cartSkuVO.rebuildBySku(dataSku); } if (checkGoodsStatus) { //设置购物车未选中 cartSkuVO.setChecked(false); //设置购物车此sku商品已失效 cartSkuVO.setInvalid(true); //设置失效消息 cartSkuVO.setErrorMessage("商品已下架"); continue; } } //商品库存判定 if (dataSku.getQuantity() < cartSkuVO.getNum()) { //设置购物车未选中 cartSkuVO.setChecked(false); //设置失效消息 cartSkuVO.setErrorMessage("商品库存不足,现有库存数量[" + dataSku.getQuantity() + "]"); } //如果存在商品促销活动,则判定商品促销状态 if (!cartSkuVO.getCartType().equals(CartTypeEnum.POINTS) && (CollUtil.isNotEmpty(cartSkuVO.getNotFilterPromotionMap()) || Boolean.TRUE.equals(cartSkuVO.getGoodsSku().getPromotionFlag()))) { //获取当前最新的促销信息 cartSkuVO.setPromotionMap(this.promotionGoodsService.getCurrentGoodsPromotion(cartSkuVO.getGoodsSku(), tradeDTO.getCartTypeEnum().name())); //设定商品价格 Double goodsPrice = cartSkuVO.getGoodsSku().getPromotionFlag() != null && cartSkuVO.getGoodsSku().getPromotionFlag() ? cartSkuVO.getGoodsSku().getPromotionPrice() : cartSkuVO.getGoodsSku().getPrice(); cartSkuVO.setPurchasePrice(goodsPrice); cartSkuVO.setUtilPrice(goodsPrice); cartSkuVO.setSubTotal(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); } } } /** * 店铺分组 * * @param tradeDTO */ private void groupStore(TradeDTO tradeDTO) { //渲染的购物车 List cartList = new ArrayList<>(); if (tradeDTO.getCartList() == null || tradeDTO.getCartList().size() == 0) { //根据店铺分组 Map> storeCollect = tradeDTO.getSkuList().stream().collect(Collectors.groupingBy(CartSkuVO::getStoreId)); for (Map.Entry> storeCart : storeCollect.entrySet()) { if (!storeCart.getValue().isEmpty()) { CartVO cartVO = new CartVO(storeCart.getValue().get(0)); if (CharSequenceUtil.isEmpty(cartVO.getDeliveryMethod())) { cartVO.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.name()); } cartVO.setSkuList(storeCart.getValue()); try { //筛选属于当前店铺的优惠券 storeCart.getValue().forEach(i -> i.getPromotionMap().forEach((key, value) -> { if (key.contains(PromotionTypeEnum.COUPON.name())) { JSONObject promotionsObj = JSONUtil.parseObj(value); Coupon coupon = JSONUtil.toBean(promotionsObj, Coupon.class); if (key.contains(PromotionTypeEnum.COUPON.name()) && coupon.getStoreId().equals(storeCart.getKey())) { cartVO.getCanReceiveCoupon().add(new CouponVO(coupon)); } } })); } catch (Exception e) { log.error("筛选属于当前店铺的优惠券发生异常!", e); } storeCart.getValue().stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).findFirst().ifPresent(cartSkuVO -> cartVO.setChecked(true)); cartList.add(cartVO); } } tradeDTO.setCartList(cartList); } } /** * 订单预校验 * 1、自己拼团自己创建都拼团判定、拼团限购 * 2、积分购买,积分足够与否 * * @param tradeDTO */ private void preCalibration(TradeDTO tradeDTO) { //拼团订单预校验 if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.PINTUAN)) { //拼团判定,不能参与自己创建的拼团 if (tradeDTO.getParentOrderSn() != null) { //订单接收 Order parentOrder = orderService.getBySn(tradeDTO.getParentOrderSn()); //参与活动判定 if (parentOrder.getMemberId().equals(UserContext.getCurrentUser().getId())) { throw new ServiceException(ResultCode.PINTUAN_JOIN_ERROR); } } //判断拼团商品的限购数量 if (tradeDTO.getSkuList().get(0).getPromotionMap() != null && !tradeDTO.getSkuList().get(0).getPromotionMap().isEmpty()) { Optional> pintuanPromotions = tradeDTO.getSkuList().get(0).getPromotionMap().entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.PINTUAN.name())).findFirst(); if (pintuanPromotions.isPresent()) { JSONObject promotionsObj = JSONUtil.parseObj(pintuanPromotions.get().getValue()); Pintuan pintuan = promotionsObj.toBean(Pintuan.class); Integer limitNum = pintuan.getLimitNum(); for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { if (limitNum != 0 && cartSkuVO.getNum() > limitNum) { throw new ServiceException(ResultCode.PINTUAN_LIMIT_NUM_ERROR); } } } } //积分商品,判断用户积分是否满足 } else if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.POINTS) && tradeDTO.getSkuList().get(0).getPromotionMap() != null && !tradeDTO.getSkuList().get(0).getPromotionMap().isEmpty()) { //获取积分商品VO Optional> pointsPromotions = tradeDTO.getSkuList().get(0).getPromotionMap().entrySet().stream().filter(i -> i.getKey().contains(PromotionTypeEnum.POINTS_GOODS.name())).findFirst(); if (pointsPromotions.isPresent()) { JSONObject promotionsObj = JSONUtil.parseObj(pointsPromotions.get().getValue()); PointsGoods pointsGoods = promotionsObj.toBean(PointsGoods.class); if (pointsGoods == null) { throw new ServiceException(ResultCode.POINT_GOODS_ERROR); } Member member = memberService.getUserInfo(); if (member.getPoint() < pointsGoods.getPoints()) { throw new ServiceException(ResultCode.USER_POINTS_ERROR); } } } } /** * 商品销售模式特殊处理 * * @param tradeDTO 交易信息 */ private void preSaleModel(TradeDTO tradeDTO) { // 寻找同goods下销售模式为批发的商品 Map> goodsGroup = tradeDTO.getCheckedSkuList().stream().filter(i -> i.getGoodsSku().getSalesModel().equals(GoodsSalesModeEnum.WHOLESALE.name())).collect(Collectors.groupingBy(i -> i.getGoodsSku().getGoodsId())); if (CollUtil.isNotEmpty(goodsGroup)) { goodsGroup.forEach((k, v) -> { // 获取购买总数 int sum = v.stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).mapToInt(CartSkuVO::getNum).sum(); int fSum = v.stream().filter(i -> Boolean.FALSE.equals(i.getChecked())).mapToInt(CartSkuVO::getNum).sum(); // 匹配符合的批发规则 Wholesale match = wholesaleService.match(k, sum); if (match != null) { v.forEach(i -> { // 将符合规则的商品设置批发价格 if (Boolean.TRUE.equals(i.getChecked())) { i.setPurchasePrice(match.getPrice()); i.getGoodsSku().setPrice(match.getPrice()); i.getGoodsSku().setCost(match.getPrice()); i.setUtilPrice(match.getPrice()); i.setSubTotal(CurrencyUtil.mul(i.getPurchasePrice(), i.getNum())); } else { i.setPurchasePrice(wholesaleService.match(k, fSum).getPrice()); i.getGoodsSku().setPrice(i.getPurchasePrice()); i.getGoodsSku().setCost(i.getPurchasePrice()); i.setUtilPrice(i.getPurchasePrice()); i.setSubTotal(CurrencyUtil.mul(i.getPurchasePrice(), i.getNum())); } }); } }); } } }