From 50911137cb8bbfefff3b11fd1dd217a4ca16743b Mon Sep 17 00:00:00 2001 From: Chopper Date: Mon, 21 Jun 2021 11:55:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B4=AD=E7=89=A9=E8=BD=A6=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/aop/limiter/LimitInterceptor.java | 7 +- .../java/cn/lili/common/enums/ResultCode.java | 78 +++++++++- .../order/cart/render/TradeBuilder.java | 47 ++++--- .../cart/render/impl/CheckDataRender.java | 86 ++++++++++- .../cart/render/impl/FullDiscountRender.java | 42 +++--- .../cart/render/impl/SkuFreightRender.java | 13 +- .../order/cart/service/CartService.java | 13 -- .../order/cart/service/CartServiceImpl.java | 133 +++++++++--------- .../order/serviceimpl/OrderServiceImpl.java | 21 +-- 9 files changed, 284 insertions(+), 156 deletions(-) diff --git a/framework/src/main/java/cn/lili/common/aop/limiter/LimitInterceptor.java b/framework/src/main/java/cn/lili/common/aop/limiter/LimitInterceptor.java index 59ea7a02..4a0cf9c6 100644 --- a/framework/src/main/java/cn/lili/common/aop/limiter/LimitInterceptor.java +++ b/framework/src/main/java/cn/lili/common/aop/limiter/LimitInterceptor.java @@ -73,12 +73,11 @@ public class LimitInterceptor { } else { throw new ServiceException("访问过于频繁,请稍后再试"); } - } catch (NullPointerException e) { + } + //如果从redis中执行都值判定为空,则这里跳过 + catch (NullPointerException e) { return pjp.proceed(); } catch (Exception e) { - if (e instanceof ServiceException) { - throw new ServiceException(e.getLocalizedMessage()); - } throw new RuntimeException("服务器异常,请稍后再试"); } } diff --git a/framework/src/main/java/cn/lili/common/enums/ResultCode.java b/framework/src/main/java/cn/lili/common/enums/ResultCode.java index 90fd8a16..d6e4b16b 100644 --- a/framework/src/main/java/cn/lili/common/enums/ResultCode.java +++ b/framework/src/main/java/cn/lili/common/enums/ResultCode.java @@ -97,8 +97,8 @@ public enum ResultCode { USER_RECEIPT_NOT_EXIST(20014, "会员发票信息不存在"), USER_EDIT_ERROR(20015, "用户修改失败"), USER_OLD_PASSWORD_ERROR(20016, "旧密码不正确"), - USER_COLLECTION_EXIST(20017,"无法重复收藏"), - USER_GRADE_IS_DEFAULT(20018,"会员等级为默认会员等级"), + USER_COLLECTION_EXIST(20017, "无法重复收藏"), + USER_GRADE_IS_DEFAULT(20018, "会员等级为默认会员等级"), DELETE_EXIST(2001, "无法重复收藏"), /** @@ -125,62 +125,97 @@ public enum ResultCode { * 购物车 */ CART_ERROR(30001, "读取结算页的购物车异常"), + CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动不存在错误"), + CART_PINTUAN_LIMIT_ERROR(30003, "购买数量超过拼团活动限制数量"), SHIPPING_NOT_APPLY(30005, "购物商品不支持当前收货地址配送"), + /** * 订单 */ ORDER_ERROR(31001, "创建订单异常,请稍后重试"), + ORDER_NOT_EXIST(31002, "订单不存在"), + ORDER_DELIVERED_ERROR(31003, "订单状态错误,无法进行确认收货"), + ORDER_UPDATE_PRICE_ERROR(31004, "已支付的订单不能修改金额"), + ORDER_LOGISTICS_ERROR(31005, "物流错误"), + ORDER_DELIVER_ERROR(31006, "物流错误"), + ORDER_NOT_USER(31007, "非当前会员的订单"), + ORDER_TAKE_ERROR(31008, "当前订单无法核销"), + MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"), + ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"), /** * 支付 */ PAY_UN_WANTED(32000, "当前订单不需要付款,返回订单列表等待系统订单出库即可"), + PAY_SUCCESS(32001, "支付成功"), + PAY_INCONSISTENT_ERROR(32002, "付款金额和应付金额不一致"), + PAY_DOUBLE_ERROR(32003, "订单已支付,不能再次进行支付"), + PAY_CASHIER_ERROR(32004, "收银台信息获取错误"), + PAY_ERROR(32005, "支付业务异常,请稍后重试"), + PAY_BAN(32006, "当前订单不需要付款,请返回订单列表重新操作"), + PAY_PARTIAL_ERROR(32007, "该订单已部分支付,请前往订单中心进行支付"), + PAY_NOT_SUPPORT(32008, "支付暂不支持"), + PAY_CLIENT_TYPE_ERROR(32009, "错误的客户端"), + PAY_POINT_ENOUGH(32010, "积分不足,不能兑换"), + PAY_NOT_EXIST_ORDER(32011, "支付订单不存在"), /** * 售后 */ AFTER_SALES_NOT_PAY_ERROR(33001, "当前订单未支付,不能申请售后"), + AFTER_SALES_CANCEL_ERROR(33002, "当前售后单无法取消"), + AFTER_SALES_BAN(33003, "订单状态不允许申请售后,请联系平台或商家"), + AFTER_SALES_DOUBLE_ERROR(33004, "售后已审核,无法重复操作"), + AFTER_SALES_LOGISTICS_ERROR(33005, "物流公司错误,请重新选择"), + AFTER_STATUS_ERROR(33006, "售后状态错误,请刷新页面"), /** * 投诉 */ COMPLAINT_ORDER_ITEM_EMPTY_ERROR(33100, "订单不存在"), + COMPLAINT_SKU_EMPTY_ERROR(33101, "商品已下架,如需投诉请联系平台客服"), + COMPLAINT_ERROR(33102, "投诉异常,请稍后重试"), /** * 余额 */ WALLET_NOT_EXIT_ERROR(34000, "钱包不存在,请联系管理员"), + WALLET_INSUFFICIENT(34001, "余额不足以支付订单,请充值!"), + WALLET_WITHDRAWAL_INSUFFICIENT(34002, "可提现金额不足!"), + WALLET_ERROR_INSUFFICIENT(34003, "零钱提现失败!"), + WALLET_REMARK_ERROR(34004, "请填写审核备注!"), + WALLET_APPLY_ERROR(34005, "提现申请异常!"), /** @@ -197,52 +232,74 @@ public enum ResultCode { * 优惠券 */ COUPON_EDIT_STATUS_SUCCESS(41001, "修改状态成功!"), + COUPON_CANCELLATION_SUCCESS(41002, "会员优惠券作废成功"), + COUPON_EXPIRED(41003, "优惠券已使用/已过期,不能使用"), + COUPON_EDIT_STATUS_ERROR(41004, "优惠券修改状态失败!"), /** * 拼团 */ PINTUAN_MANUAL_OPEN_SUCCESS(42001, "手动开启拼团活动成功"), + PINTUAN_MANUAL_CLOSE_SUCCESS(42002, "手动关闭拼团活动成功"), + PINTUAN_ADD_SUCCESS(42003, "添加拼团活动成功"), + PINTUAN_EDIT_SUCCESS(42004, "修改拼团活动成功"), + PINTUAN_DELETE_SUCCESS(42005, "删除拼团活动成功"), + PINTUAN_MANUAL_OPEN_ERROR(42006, "手动开启拼团活动失败"), + PINTUAN_MANUAL_CLOSE_ERROR(42007, "手动关闭拼团活动失败"), + PINTUAN_ADD_ERROR(42008, "添加拼团活动失败"), + PINTUAN_EDIT_ERROR(42009, "修改拼团活动失败"), + PINTUAN_DELETE_ERROR(42010, "删除拼团活动失败"), /** * 满额活动 */ FULL_DISCOUNT_EDIT_SUCCESS(43001, "修改满优惠活动成功"), + FULL_DISCOUNT_EDIT_DELETE(43002, "删除满优惠活动成功"), /** * 店铺 */ STORE_NOT_EXIST(50001, "此店铺不存在"), + STORE_NAME_EXIST_ERROR(50002, "店铺名称已存在!"), + STORE_APPLY_DOUBLE_ERROR(50003, "已有店铺,无需重复申请!"), /** * 结算单 */ BILL_CHECK_ERROR(51001, "只有已出账结算单可以核对"), + BILL_COMPLETE_ERROR(51002, "只有已审核结算单可以支付"), /** * 文章 */ ARTICLE_CATEGORY_NAME_EXIST(60001, "文章分类名称已存在"), + ARTICLE_CATEGORY_PARENT_NOT_EXIST(60002, "文章分类父分类不存在"), + ARTICLE_CATEGORY_BEYOND_TWO(60003, "最多为二级分类,操作失败"), + ARTICLE_CATEGORY_DELETE_ERROR(60004, "该文章分类下存在子分类,不能删除"), + ARTICLE_CATEGORY_HAS_ARTICLE(60005, "该文章分类下存在文章,不能删除"), + ARTICLE_CATEGORY_NO_DELETION(60007, "默认文章分类不能进行删除"), + ARTICLE_NO_DELETION(60008, "默认文章不能进行删除"), @@ -250,8 +307,11 @@ public enum ResultCode { * 页面 */ PAGE_NOT_EXIST(61001, "页面不存在"), + PAGE_OPEN_DELETE_ERROR(61002, "当前页面为开启状态,无法删除"), + PAGE_DELETE_ERROR(61003, "当前页面为唯一页面,无法删除"), + PAGE_RELEASE_ERROR(61004, "页面已发布,无需重复提交"), /** @@ -268,39 +328,49 @@ public enum ResultCode { * 站内信 */ NOTICE_NOT_EXIST(80101, "当前消息模板不存在"), + NOTICE_ERROR(80102, "修改站内信异常,请稍后重试"), /** * OSS */ OSS_NOT_EXIST(80201, "OSS未配置"), + OSS_EXCEPTION(80202, "文件上传失败,请稍后重试"), /** * 验证码 */ VERIFICATION_SEND_SUCCESS(80301, "短信验证码,发送成功"), + VERIFICATION_ERROR(80302, "验证失败"), + VERIFICATION_SMS_ERROR(80303, "短信验证码错误,请重新校验"), + VERIFICATION_SMS_EXPIRED_ERROR(80304, "验证码已失效,请重新校验"), /** * 配置错误 */ ALIPAY_NOT_SETTING(80401, "支付宝支付未配置"), + ALIPAY_EXCEPTION(80402, "支付宝支付错误,请稍后重试"), + ALIPAY_PARAMS_EXCEPTION(80403, "支付宝参数异常"), /** * 微信相关异常 */ WECHAT_CONNECT_NOT_SETTING(80500, "微信联合登陆信息未配置"), + WECHAT_PAYMENT_NOT_SETTING(80501, "微信支付信息未配置"), + WECHAT_QRCODE_ERROR(80502, "微信二维码生成异常"), + WECHAT_MP_MESSAGE_ERROR(80503, "微信小程序小消息订阅异常"), - APP_VERSION_EXIST(80600, "APP版本已存在") - ; + APP_VERSION_EXIST(80600, "APP版本已存在"); + private final Integer code; private final String message; diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java b/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java index ba32de5a..d51ddd1c 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/TradeBuilder.java @@ -16,7 +16,7 @@ import java.util.List; import java.util.stream.Collectors; /** - * TradeBuilder + * 交易构造&&创建 * * @author Chopper * @date2020-04-01 9:47 下午 @@ -24,36 +24,41 @@ import java.util.stream.Collectors; @Service @Slf4j public class TradeBuilder { - //购物车渲染 + + //购物车渲染步骤 @Autowired private List cartRenderSteps; + //交易 @Autowired private TradeService tradeService; + //购物车业务 + @Autowired + private CartService cartService; + + /** * 渲染整比交易 + * 0-> 校验商品, 1-》 满优惠渲染, 2->渲染优惠, 3->优惠券渲染, 4->计算运费, 5->计算价格, 6->分销渲染, 7->扩展操作 */ int[] defaultRender = {0, 1, 2, 4, 5, 6, 7}; /** * 购物车购物车渲染 + * 0-> 校验商品, 1-》 满优惠渲染, 2->渲染优惠, 5->计算价格 */ int[] cartRender = {0, 1, 2, 5}; - /** - * 0-> 校验商品 1-》 满优惠渲染 2->渲染优惠 3->优惠券渲染 4->计算运费 5->计算价格 6->分销渲染 7->扩展操作 - */ - @Autowired - private CartService cartService; - /** * 构造购物车 + * 购物车与结算信息不一致的地方主要是优惠券计算和运费计算,其他规则都是一致都 * * @param checkedWay 购物车类型 * @return 购物车展示信息 */ public TradeDTO buildCart(CartTypeEnum checkedWay) { + //读取对应购物车的商品信息 TradeDTO tradeDTO = cartService.readDTO(checkedWay); //购物车需要将交易中的优惠券取消掉 @@ -67,7 +72,7 @@ public class TradeBuilder { try { cartRenderSteps.get(index).render(tradeDTO); } catch (Exception e) { - log.error("购物车渲染异常:", e); + log.error("购物车{}渲染异常:", cartRenderSteps.get(index).getClass(), e); } } return tradeDTO; @@ -80,28 +85,26 @@ public class TradeBuilder { * @return 购物车展示信息 */ public TradeDTO buildTrade(CartTypeEnum checkedWay) { + //读取对应购物车的商品信息 TradeDTO tradeDTO = cartService.readDTO(checkedWay); - tradeDTO.setNotSupportFreight(null); + //将购物车到sku未选择信息过滤 List collect = tradeDTO.getSkuList().parallelStream().filter(i -> Boolean.TRUE.equals(i.getChecked())).collect(Collectors.toList()); - //拼团类型订单预处理 - if (checkedWay.equals(CartTypeEnum.PINTUAN)) { - for (CartSkuVO cartSkuVO : collect) { - cartSkuVO.setPintuanId(""); - } - } tradeDTO.setSkuList(collect); //按照计划进行渲染 for (int index : defaultRender) { try { cartRenderSteps.get(index).render(tradeDTO); } catch (Exception e) { - log.error("购物车渲染异常:", e); + log.error("购物车{}渲染异常:", cartRenderSteps.get(index).getClass(), e); } } + //购物车信息接受 List cartVOList = new ArrayList<>(); - for (CartVO i : tradeDTO.getCartList()) { - i.setSkuList(i.getSkuList().stream().filter(j -> Boolean.TRUE.equals(j.getChecked())).collect(Collectors.toList())); - cartVOList.add(i); + //循环购物车信息 + for (CartVO cartVO : tradeDTO.getCartList()) { + //如果商品选中,则加入到对应购物车 + cartVO.setSkuList(cartVO.getSkuList().stream().filter(j -> Boolean.TRUE.equals(j.getChecked())).collect(Collectors.toList())); + cartVOList.add(cartVO); } tradeDTO.setCartList(cartVOList); return tradeDTO; @@ -111,12 +114,10 @@ public class TradeBuilder { * 创建一笔交易 * * @param checkedWay 购物车类型 - * @param parentOrderSn 是否为其他订单下的订单,如果是则为依赖订单的sn,否则为空 * @return 交易信息 */ - public Trade createTrade(CartTypeEnum checkedWay, String parentOrderSn) { + public Trade createTrade(CartTypeEnum checkedWay) { TradeDTO tradeDTO = this.buildTrade(checkedWay); - tradeDTO.setParentOrderSn(parentOrderSn); return tradeService.createTrade(tradeDTO); } } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java index f5a5476d..29757f33 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/CheckDataRender.java @@ -1,18 +1,28 @@ package cn.lili.modules.order.cart.render.impl; +import cn.hutool.core.text.CharSequenceUtil; +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.enums.GoodsAuthEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.order.cart.entity.dto.TradeDTO; +import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; 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 lombok.RequiredArgsConstructor; +import cn.lili.modules.order.order.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + /** * 商品有效性校验 * @@ -26,10 +36,31 @@ public class CheckDataRender implements CartRenderStep { @Autowired private GoodsSkuService goodsSkuService; + @Autowired + private OrderService orderService; + @Override public void render(TradeDTO tradeDTO) { + //校验商品有效性 + checkData(tradeDTO); + //店铺分组数据初始化 + groupStore(tradeDTO); + //预校验 + preCalibration(tradeDTO); + + } + + /** + * 校验商品属性 + * + * @param tradeDTO + */ + private void checkData(TradeDTO tradeDTO) { + //循环购物车中的商品 for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { + //缓存中的商品信息 GoodsSku dataSku = goodsSkuService.getGoodsSkuByIdFromCache(cartSkuVO.getGoodsSku().getId()); + //商品有效性判定 if (dataSku == null || dataSku.getUpdateTime().before(cartSkuVO.getGoodsSku().getUpdateTime())) { //设置购物车未选中 cartSkuVO.setChecked(false); @@ -39,6 +70,7 @@ public class CheckDataRender implements CartRenderStep { cartSkuVO.setErrorMessage("商品信息发生变化,已失效"); continue; } + // 商品上架状态判定 if (!GoodsAuthEnum.PASS.name().equals(dataSku.getIsAuth()) || !GoodsStatusEnum.UPPER.name().equals(dataSku.getMarketEnable())) { //设置购物车未选中 cartSkuVO.setChecked(false); @@ -48,17 +80,59 @@ public class CheckDataRender implements CartRenderStep { cartSkuVO.setErrorMessage("商品已下架"); continue; } - //商品库存不足 - if (dataSku.getQuantity() <= 0) { + // 商品库存判定 + if (dataSku.getQuantity() < cartSkuVO.getNum()) { //设置购物车未选中 cartSkuVO.setChecked(false); - //设置购物车此sku商品已失效 - cartSkuVO.setInvalid(true); //设置失效消息 - cartSkuVO.setErrorMessage("商品库存不足"); + cartSkuVO.setErrorMessage("商品库存不足,现有库存数量[" + dataSku.getQuantity() + "]"); } //写入初始价格 cartSkuVO.getPriceDetailDTO().setGoodsPrice(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); } } + + /** + * 店铺分组 + * + * @param tradeDTO + */ + private void groupStore(TradeDTO tradeDTO) { + // 渲染的购物车 + List cartList = new ArrayList<>(); + + // 根据店铺分组 + Map> storeCollect = tradeDTO.getSkuList().parallelStream().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()); + storeCart.getValue().stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).findFirst().ifPresent(cartSkuVO -> cartVO.setChecked(true)); + cartList.add(cartVO); + } + } + tradeDTO.setCartList(cartList); + } + + /** + * 订单预校验 + * 1、自己拼团自己创建都拼团判定 + * + * @param tradeDTO + */ + private void preCalibration(TradeDTO tradeDTO) { + //拼团判定,不能参与自己创建的拼团 + if (tradeDTO.getParentOrderSn() != null) { + //订单接受 + cn.lili.modules.order.order.entity.dos.Order parentOrder = orderService.getBySn(tradeDTO.getParentOrderSn()); + //参与活动判定 + if (parentOrder.getMemberId().equals(UserContext.getCurrentUser().getId())) { + throw new ServiceException("不能参与自己发起的拼团活动!"); + } + } + } + } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java index 33fa9b8c..0b728c64 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/FullDiscountRender.java @@ -1,15 +1,12 @@ package cn.lili.modules.order.cart.render.impl; -import cn.hutool.core.text.CharSequenceUtil; import cn.lili.modules.order.cart.entity.dto.TradeDTO; -import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum; -import cn.lili.modules.promotion.entity.dos.PromotionGoods; -import cn.lili.modules.promotion.service.FullDiscountService; import cn.lili.modules.order.cart.entity.vo.CartSkuVO; import cn.lili.modules.order.cart.entity.vo.CartVO; import cn.lili.modules.order.cart.entity.vo.FullDiscountVO; import cn.lili.modules.order.cart.render.CartRenderStep; -import lombok.RequiredArgsConstructor; +import cn.lili.modules.promotion.entity.dos.PromotionGoods; +import cn.lili.modules.promotion.service.FullDiscountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; @@ -38,60 +35,63 @@ public class FullDiscountRender implements CartRenderStep { // 获取购物车中所有的商品 List cartSkuList = tradeDTO.getSkuList(); - // 渲染的购物车 - List cartList = new ArrayList<>(); - - // 确定有哪些商家 + // 店铺id集合 List storeIds = new ArrayList<>(); - // 根据店铺分组 - Map> storeCollect = cartSkuList.parallelStream().collect(Collectors.groupingBy(CartSkuVO::getStoreId)); + // 店铺集合 + List cartList = tradeDTO.getCartList(); + + + // 获取店铺id + Map> storeCollect = tradeDTO.getSkuList().parallelStream().collect(Collectors.groupingBy(CartSkuVO::getStoreId)); for (Map.Entry> storeCart : storeCollect.entrySet()) { if (!storeCart.getValue().isEmpty()) { storeIds.add(storeCart.getKey()); - CartVO cartVO = new CartVO(storeCart.getValue().get(0)); - if (CharSequenceUtil.isEmpty(cartVO.getDeliveryMethod())) { - cartVO.setDeliveryMethod(DeliveryMethodEnum.LOGISTICS.name()); - } - cartVO.setSkuList(storeCart.getValue()); - storeCart.getValue().stream().filter(i -> Boolean.TRUE.equals(i.getChecked())).findFirst().ifPresent(cartSkuVO -> cartVO.setChecked(true)); - cartList.add(cartVO); - } } + // 获取当前店铺进行到满减活动 List fullDiscounts = fullDiscountService.currentPromotion(storeIds); + //循环满减信息 for (FullDiscountVO fullDiscount : fullDiscounts) { + //判定参与活动的商品 if (fullDiscount.getPromotionGoodsList() != null || fullDiscount.getNumber() == -1) { + //循环店铺购物车 for (CartVO cart : cartList) { + //如果购物车中的店铺id与活动店铺id相等,则进行促销计算 if (fullDiscount.getStoreId().equals(cart.getStoreId())) { + //写入满减活动 cart.setFullDiscount(fullDiscount); List skuIds; + // 参与活动的sku判定 if (fullDiscount.getNumber() != -1) { skuIds = initFullDiscountGoods(fullDiscount, cartSkuList); } else { skuIds = cart.getSkuList().stream().map(i -> i.getGoodsSku().getId()).collect(Collectors.toList()); } + //记录参与满减活动的sku cart.setFullDiscountSkuIds(skuIds); } } } } - tradeDTO.setCartList(cartList); } /** * 获取参与满优惠的商品id * * @param fullDiscount 满优惠信息 - * @param cartSkuVOS 购物车商品sku信息 + * @param cartSkuVOS 购物车商品sku信息 * @return 参与满优惠的商品id */ public List initFullDiscountGoods(FullDiscountVO fullDiscount, List cartSkuVOS) { List goodsIds = new ArrayList<>(); + //判定参与活动的商品 for (PromotionGoods promotionGoods : fullDiscount.getPromotionGoodsList()) { + //sku 集合判定 for (CartSkuVO cartSkuVO : cartSkuVOS) { + //如果参加,则记录商品sku if (cartSkuVO.getGoodsSku().getId().equals(promotionGoods.getSkuId())) { goodsIds.add(promotionGoods.getSkuId()); } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java index b159eee0..633e700b 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/render/impl/SkuFreightRender.java @@ -1,6 +1,8 @@ package cn.lili.modules.order.cart.render.impl; import cn.hutool.core.util.NumberUtil; +import cn.lili.common.enums.ResultCode; +import cn.lili.common.exception.ServiceException; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.order.cart.entity.dto.TradeDTO; @@ -36,24 +38,24 @@ public class SkuFreightRender implements CartRenderStep { List cartSkuVOS = tradeDTO.getSkuList(); //会员收货地址问题处理 MemberAddress memberAddress = tradeDTO.getMemberAddress(); + //如果收货地址为空,则抛出异常 if (memberAddress == null) { - return; + throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); } //循环渲染购物车商品运费价格 forSku: for (CartSkuVO cartSkuVO : cartSkuVOS) { + //获取sku运费模版 String freightTemplateId = cartSkuVO.getGoodsSku().getFreightTemplateId(); - //免运费则跳出运费计算 if (Boolean.TRUE.equals(cartSkuVO.getIsFreeFreight()) || freightTemplateId == null) { continue; } - //寻找对应对商品运费计算模版 FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateId); if (freightTemplate != null && freightTemplate.getFreightTemplateChildList() != null && !freightTemplate.getFreightTemplateChildList().isEmpty()) { //店铺支付运费则跳过 - if(freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())){ + if (freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())) { break; } FreightTemplateChild freightTemplateChild = null; @@ -68,7 +70,7 @@ public class SkuFreightRender implements CartRenderStep { break; } } - + //如果没有匹配到物流规则,则说明不支持配送 if (freightTemplateChild == null) { if (tradeDTO.getNotSupportFreight() == null) { tradeDTO.setNotSupportFreight(new ArrayList<>()); @@ -77,6 +79,7 @@ public class SkuFreightRender implements CartRenderStep { continue forSku; } + //物流规则模型创立 FreightTemplateChildDTO freightTemplateChildDTO = new FreightTemplateChildDTO(freightTemplateChild); freightTemplateChildDTO.setPricingMethod(freightTemplate.getPricingMethod()); diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java index 09531030..2d997b3f 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartService.java @@ -1,16 +1,12 @@ package cn.lili.modules.order.cart.service; -import cn.lili.modules.member.entity.dos.MemberAddress; 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.vo.CartSkuVO; import cn.lili.modules.order.cart.entity.vo.TradeParams; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.vo.ReceiptVO; -import java.util.List; - /** * 购物车业务层 * @@ -171,13 +167,4 @@ public interface CartService { * @return 交易信息 */ Trade createTrade(TradeParams tradeParams); - - /** - * 检查商品是否在配送范围 - * - * @param skuList 商品列表 - * @param memberAddress 配送地址 - */ - void checkAddressScope(List skuList, MemberAddress memberAddress); - } diff --git a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java index b14d949c..c317dfe1 100644 --- a/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/cart/service/CartServiceImpl.java @@ -10,7 +10,6 @@ import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.goods.entity.dos.GoodsSku; import cn.lili.modules.goods.entity.enums.GoodsAuthEnum; import cn.lili.modules.goods.entity.enums.GoodsStatusEnum; -import cn.lili.modules.goods.entity.enums.GoodsTypeEnum; import cn.lili.modules.goods.service.GoodsSkuService; import cn.lili.modules.member.entity.dos.MemberAddress; import cn.lili.modules.order.cart.entity.dto.MemberCouponDTO; @@ -25,19 +24,17 @@ import cn.lili.modules.order.cart.render.TradeBuilder; import cn.lili.modules.order.order.entity.dos.Trade; import cn.lili.modules.order.order.entity.vo.ReceiptVO; import cn.lili.modules.promotion.entity.dos.MemberCoupon; +import cn.lili.modules.promotion.entity.dos.Pintuan; import cn.lili.modules.promotion.entity.dos.PromotionGoods; import cn.lili.modules.promotion.entity.enums.CouponScopeTypeEnum; import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum; import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum; import cn.lili.modules.promotion.service.MemberAddressService; import cn.lili.modules.promotion.service.MemberCouponService; +import cn.lili.modules.promotion.service.PintuanService; import cn.lili.modules.promotion.service.PromotionGoodsService; import cn.lili.modules.search.entity.dos.EsGoodsIndex; import cn.lili.modules.search.service.EsGoodsSearchService; -import cn.lili.modules.store.entity.dos.FreightTemplateChild; -import cn.lili.modules.store.entity.enums.FreightTemplateEnum; -import cn.lili.modules.store.entity.vos.FreightTemplateVO; -import cn.lili.modules.store.service.FreightTemplateService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -79,9 +76,10 @@ public class CartServiceImpl implements CartService { //ES商品 @Autowired private EsGoodsSearchService esGoodsSearchService; - //运费模板 + + //拼团服务 @Autowired - private FreightTemplateService freightTemplateService; + private PintuanService pintuanService; //交易 @Autowired private TradeBuilder tradeBuilder; @@ -136,10 +134,16 @@ public class CartServiceImpl implements CartService { promotionGoodsService.updatePromotion(cartSkuVO); //再设置加入购物车的数量 this.checkSetGoodsQuantity(cartSkuVO, skuId, num); + + //拼团判定 + checkPintuan(cartTypeEnum, cartSkuVO); + //计算购物车小计 cartSkuVO.setSubTotal(CurrencyUtil.mul(cartSkuVO.getPurchasePrice(), cartSkuVO.getNum())); cartSkuVOS.add(cartSkuVO); } + + tradeDTO.setCartTypeEnum(cartTypeEnum); // 如购物车发生更改,则重置优惠券 tradeDTO.setStoreCoupons(null); @@ -501,61 +505,15 @@ public class CartServiceImpl implements CartService { //设置基础属性 tradeDTO.setClientType(tradeParams.getClient()); tradeDTO.setStoreRemark(tradeParams.getRemark()); - //过滤勾选商品 - List collect = tradeDTO.getSkuList().parallelStream().filter(i -> Boolean.TRUE.equals(i.getChecked())).collect(Collectors.toList()); - //校验收获地址 - MemberAddress memberAddress = tradeDTO.getMemberAddress(); - this.checkAddressScope(collect, memberAddress); + tradeDTO.setParentOrderSn(tradeParams.getParentOrderSn()); + //将购物车信息写入缓存,后续逻辑调用校验 this.resetTradeDTO(tradeDTO); //构建交易 - Trade trade = tradeBuilder.createTrade(cartTypeEnum, tradeParams.getParentOrderSn()); + Trade trade = tradeBuilder.createTrade(cartTypeEnum); this.cleanChecked(tradeDTO); return trade; } - /** - * 检查商品是否在配送范围 - * - * @param skuList 商品列表 - * @param memberAddress 配送地址 - */ - @Override - public void checkAddressScope(List skuList, MemberAddress memberAddress) { - //如果收货地址为空,则抛出异常 - if (memberAddress == null) { - throw new ServiceException(ResultCode.MEMBER_ADDRESS_NOT_EXIST); - } - //循环购物车列表计算运费 - for (CartSkuVO cartSkuVO : skuList) { - GoodsSku goodsSku = cartSkuVO.getGoodsSku(); - //如果是虚拟商品无需运费 - if (goodsSku.getGoodsType() != null && goodsSku.getGoodsType().equals(GoodsTypeEnum.VIRTUAL_GOODS.name())) { - break; - } - //获取运费模板ID - String freightTemplateId = cartSkuVO.getGoodsSku().getFreightTemplateId(); - FreightTemplateVO freightTemplate = freightTemplateService.getFreightTemplate(freightTemplateId); - //店铺支付运费则跳过 - if (freightTemplate.getPricingMethod().equals(FreightTemplateEnum.FREE.name())) { - break; - } - //收货地址判定 - forTemplates: - if (freightTemplate != null && freightTemplate.getFreightTemplateChildList() != null && !freightTemplate.getFreightTemplateChildList().isEmpty()) { - //获取市级别id - String addressId = memberAddress.getConsigneeAddressIdPath().split(",")[1]; - //获取匹配的收货地址 - for (FreightTemplateChild templateChild : freightTemplate.getFreightTemplateChildList()) { - //如果当前模版包含,则返回 - if (templateChild.getAreaId().contains(addressId)) { - break forTemplates; - } - } - throw new ServiceException(ResultCode.SHIPPING_NOT_APPLY, cartSkuVO.getGoodsSku().getGoodsName()); - - } - } - } /** * 获取购物车类型 @@ -576,6 +534,13 @@ public class CartServiceImpl implements CartService { return cartTypeEnum; } + /** + * 使用优惠券判定 + * + * @param tradeDTO 交易对象 + * @param memberCoupon 会员优惠券 + * @param cartTypeEnum 购物车 + */ private void useCoupon(TradeDTO tradeDTO, MemberCoupon memberCoupon, CartTypeEnum cartTypeEnum) { //如果是平台优惠券 if (Boolean.TRUE.equals(memberCoupon.getIsPlatform())) { @@ -583,24 +548,34 @@ public class CartServiceImpl implements CartService { Double cartPrice = 0d; for (CartSkuVO cartSkuVO : tradeDTO.getSkuList()) { // 获取商品的促销信息 - Optional promotionOptional = cartSkuVO.getPromotions().parallelStream().filter(i -> (i.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name()) && cartTypeEnum.equals(CartTypeEnum.PINTUAN)) - || i.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())).findAny(); + Optional promotionOptional = + cartSkuVO.getPromotions().parallelStream().filter(promotionGoods -> + (promotionGoods.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name()) && + cartTypeEnum.equals(CartTypeEnum.PINTUAN)) || + promotionGoods.getPromotionType().equals(PromotionTypeEnum.SECKILL.name())).findAny(); + //有促销金额则用促销金额,否则用商品原价 if (promotionOptional.isPresent()) { - cartPrice += CurrencyUtil.mul(promotionOptional.get().getPrice(), cartSkuVO.getNum()); + cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(promotionOptional.get().getPrice(), cartSkuVO.getNum())); } else { - cartPrice += CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum()); + cartPrice = CurrencyUtil.add(cartPrice, CurrencyUtil.mul(cartSkuVO.getGoodsSku().getPrice(), cartSkuVO.getNum())); } } + //如果购物车金额大于消费门槛则使用 if (memberCoupon.getConsumeThreshold() <= cartPrice) { tradeDTO.setPlatformCoupon(new MemberCouponDTO(memberCoupon)); + //选择平台优惠券,则将品台优惠券清空 tradeDTO.setStoreCoupons(new HashMap<>()); } - } else { + } + //否则为店铺优惠券 + else { + //过滤对应店铺购物车 CartSkuVO cartVO = tradeDTO.getSkuList().stream().filter(i -> i.getStoreId().equals(memberCoupon.getStoreId())).findFirst().orElse(null); // 优惠券消费门槛 <= 商品购买时的成交价(单品) * 购买数量 if (cartVO != null && memberCoupon.getConsumeThreshold() <= CurrencyUtil.mul(cartVO.getPurchasePrice(), cartVO.getNum())) { tradeDTO.getStoreCoupons().put(memberCoupon.getStoreId(), new MemberCouponDTO(memberCoupon)); + //选择店铺优惠券,则将品台优惠券清空 tradeDTO.setPlatformCoupon(null); } } @@ -615,9 +590,12 @@ public class CartServiceImpl implements CartService { */ private boolean checkCoupon(MemberCoupon memberCoupon, TradeDTO tradeDTO) { List cartSkuVOS; + //如果是店铺优惠券,判定的内容 if (Boolean.FALSE.equals(memberCoupon.getIsPlatform())) { cartSkuVOS = tradeDTO.getSkuList().stream().filter(i -> i.getStoreId().equals(memberCoupon.getStoreId())).collect(Collectors.toList()); - } else { + } + //否则为平台优惠券,筛选商品为全部商品 + else { cartSkuVOS = tradeDTO.getSkuList(); } @@ -635,8 +613,33 @@ public class CartServiceImpl implements CartService { return true; } - @Autowired - public void setTradeBuilder(TradeBuilder tradeBuilder) { - this.tradeBuilder = tradeBuilder; + /** + * 校验拼团信息 + * + * @param cartTypeEnum 购物车枚举 + * @param cartSkuVO 购物车信息 + */ + private void checkPintuan(CartTypeEnum cartTypeEnum, CartSkuVO cartSkuVO) { + + //拼团活动的话,需要对限购数量进行判定 + if (cartTypeEnum.equals(CartTypeEnum.PINTUAN)) { + //获取拼团信息 + List currentPromotion = cartSkuVO.getPromotions().stream().filter( + promotionGoods -> (promotionGoods.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name()))) + .collect(Collectors.toList()); + //拼团活动判定 + if (currentPromotion.size() > 0) { + //写入拼团信息 + cartSkuVO.setPintuanId(currentPromotion.get(0).getPromotionId()); + } else { + throw new ServiceException(ResultCode.CART_PINTUAN_NOT_EXIST_ERROR); + } + + Pintuan pintuan = pintuanService.getPintuanById(cartSkuVO.getPintuanId()); + Integer limitNum = pintuan.getLimitNum(); + if (limitNum != 0 && cartSkuVO.getNum() > limitNum) { + throw new ServiceException(ResultCode.CART_PINTUAN_LIMIT_ERROR); + } + } } } diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java index cda73774..5a4a7503 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java @@ -134,35 +134,26 @@ public class OrderServiceImpl extends ServiceImpl implements //存放自订单/订单日志 List orderItems = new ArrayList<>(); List orderLogs = new ArrayList<>(); - //拼团判定,不能参与自己创建的拼团 - if (tradeDTO.getParentOrderSn() != null) { - Order parentOrder = this.getBySn(tradeDTO.getParentOrderSn()); - if (parentOrder.getMemberId().equals(UserContext.getCurrentUser().getId())) { - throw new ServiceException("不能参与自己发起的拼团活动!"); - } - } + //订单集合 List orderVOS = new ArrayList<>(); - //循环购物车商品集合 + //循环购物车 tradeDTO.getCartList().forEach(item -> { Order order = new Order(item, tradeDTO); - if (OrderTypeEnum.PINTUAN.name().equals(order.getOrderType())) { - Pintuan pintuan = pintuanService.getPintuanById(order.getPromotionId()); - Integer limitNum = pintuan.getLimitNum(); - if (limitNum != 0 && order.getGoodsNum() > limitNum) { - throw new ServiceException("购买数量超过拼团活动限制数量"); - } - } //构建orderVO对象 OrderVO orderVO = new OrderVO(); BeanUtil.copyProperties(order, orderVO); + //持久化DO orders.add(order); String message = "订单[" + item.getSn() + "]创建"; + //记录日志 orderLogs.add(new OrderLog(item.getSn(), UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(), UserContext.getCurrentUser().getUsername(), message)); item.getSkuList().forEach( sku -> orderItems.add(new OrderItem(sku, item, tradeDTO)) ); + //写入子订单信息 orderVO.setOrderItems(orderItems); + //orderVO 记录 orderVOS.add(orderVO); }); tradeDTO.setOrderVO(orderVOS);