From f7fe9ad7b0c19f2c2fc12bc518b34ee991ac5283 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 1 May 2023 16:00:37 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=95=86=E5=9F=8E=EF=BC=9A=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E8=B4=AD=E7=89=A9=E8=BD=A6=E7=9A=84=E5=A4=B1=E6=95=88?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=AE=9E=E7=8E=B0=EF=BC=8C=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?=20SPU=20=E6=98=AF=E5=90=A6=E4=B8=8B=E6=9E=B6=202.=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=EF=BC=9A=E5=A2=9E=E5=8A=A0=E8=B4=AD=E7=89=A9=E8=BD=A6?= =?UTF-8?q?=E5=A4=B1=E6=95=88=E7=9A=84=E9=87=8D=E9=80=89=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/sku/dto/ProductSkuRespDTO.java | 11 ----- .../trade/enums/ErrorCodeConstants.java | 1 - .../app/base/sku/AppProductSkuBaseRespVO.java | 6 +-- .../app/cart/TradeCartController.java | 11 ++++- .../AppTradeCartItemUpdateSelectedReqVO.java | 21 --------- .../app/cart/vo/AppTradeCartResetReqVO.java | 26 ++++++++++ .../trade/convert/cart/TradeCartConvert.java | 8 ++-- .../trade/dal/mysql/cart/TradeCartMapper.java | 7 ++- .../trade/service/cart/TradeCartService.java | 13 ++++- .../service/cart/TradeCartServiceImpl.java | 47 +++++++++++++++++-- .../service/order/TradeOrderServiceImpl.java | 8 +--- 11 files changed, 103 insertions(+), 56 deletions(-) delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java index 9197c6147..7f5e7aed8 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/dto/ProductSkuRespDTO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.product.api.sku.dto; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import lombok.Data; import java.util.List; @@ -22,10 +21,6 @@ public class ProductSkuRespDTO { * SPU 编号 */ private Long spuId; - /** - * SPU 名字 - */ - private String spuName; /** * 属性数组 @@ -51,12 +46,6 @@ public class ProductSkuRespDTO { * 图片地址 */ private String picUrl; - /** - * SKU 状态 - *

- * 枚举 {@link CommonStatusEnum} - */ - private Integer status; /** * 库存 */ diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index af387ab85..d6c314147 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -14,7 +14,6 @@ public interface ErrorCodeConstants { // ========== Order 模块 1-011-000-000 ========== ErrorCode ORDER_CREATE_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品 SKU 不存在"); ErrorCode ORDER_CREATE_SPU_NOT_SALE = new ErrorCode(1011000002, "商品 SPU 不可售卖"); - ErrorCode ORDER_CREATE_SKU_NOT_SALE = new ErrorCode(1011000003, "商品 SKU 不可售卖"); ErrorCode ORDER_CREATE_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品 SKU 库存不足"); ErrorCode ORDER_CREATE_SPU_NOT_FOUND = new ErrorCode(1011000005, "商品 SPU 不可售卖"); ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在"); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java index 053e329b4..bb2c60482 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/sku/AppProductSkuBaseRespVO.java @@ -17,12 +17,12 @@ public class AppProductSkuBaseRespVO { @Schema(description = "主键", required = true, example = "1024") private Long id; - @Schema(description = "商品 SKU 名字", required = true, example = "芋道") - private String name; - @Schema(description = "图片地址", example = "https://www.iocoder.cn/xx.png") private String picUrl; + @Schema(description = "销售价格,单位:分", required = true, example = "100") + private Integer price; + @Schema(description = "库存", required = true, example = "1") private Integer stock; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java index d00c2b0f3..79105ced6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/TradeCartController.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; import io.swagger.v3.oas.annotations.Operation; @@ -42,11 +43,19 @@ public class TradeCartController { @PutMapping("/update") @Operation(summary = "更新购物车商品") @PreAuthenticated - public CommonResult updateCartItemQuantity(@Valid @RequestBody AppTradeCartUpdateReqVO updateReqVO) { + public CommonResult updateCart(@Valid @RequestBody AppTradeCartUpdateReqVO updateReqVO) { cartService.updateCart(getLoginUserId(), updateReqVO); return success(true); } + @PutMapping("/reset") + @Operation(summary = "重置购物车商品") + @PreAuthenticated + public CommonResult resetCart(@Valid @RequestBody AppTradeCartResetReqVO updateReqVO) { + cartService.resetCart(getLoginUserId(), updateReqVO); + return success(true); + } + @DeleteMapping("/delete") @Operation(summary = "删除购物车商品") @Parameter(name = "ids", description = "购物车商品编号", required = true, example = "1024,2048") diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java deleted file mode 100644 index 62327f320..000000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartItemUpdateSelectedReqVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.trade.controller.app.cart.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import javax.validation.constraints.NotNull; -import java.util.Collection; - -@Schema(description = "用户 App - 购物车更新是否选中 Request VO") -@Data -public class AppTradeCartItemUpdateSelectedReqVO { - - @Schema(description = "商品 SKU 编号列表", required = true, example = "1024,2048") - @NotNull(message = "商品 SKU 编号列表不能为空") - private Collection skuIds; - - @Schema(description = "是否选中", required = true, example = "true") - @NotNull(message = "是否选中不能为空") - private Boolean selected; - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java new file mode 100644 index 000000000..eb8a81c80 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/vo/AppTradeCartResetReqVO.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.trade.controller.app.cart.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +@Schema(description = "用户 App - 购物车重置 Request VO") +@Data +public class AppTradeCartResetReqVO { + + @Schema(description = "编号", required = true, example = "1024") + @NotNull(message = "编号不能为空") + private Long id; + + @Schema(description = "商品 SKU 编号", required = true,example = "1024") + @NotNull(message = "商品 SKU 编号不能为空") + private Long skuId; + + @Schema(description = "商品数量", required = true, example = "1") + @NotNull(message = "数量不能为空") + @Min(message = "数量必须大于 0", value = 1L) + private Integer count; + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java index c40ce377f..519b82fc9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java @@ -34,17 +34,17 @@ public interface TradeCartConvert { ProductSpuRespDTO spu = spuMap.get(cart.getSpuId()); ProductSkuRespDTO sku = skuMap.get(cart.getSkuId()); cartVO.setSpu(convert(spu)).setSku(convert(sku)); - // 如果 spu 或 sku 不存在,或者 spu 被禁用,说明是非法的,或者 sku 库存不足 + // 如果 SPU 不存在,或者下架,或者库存不足,说明是无效的 if (spu == null - || sku == null || !ProductSpuStatusEnum.isEnable(spu.getStatus()) - || sku.getStock() <= 0) { + || spu.getStock() <= 0) { invalidList.add(cartVO); } else { + // 虽然 SKU 可能也会不存在,但是可以通过购物车重新选择 validList.add(cartVO); } }); - return new AppTradeCartListRespVO().setValidList(validList).setValidList(invalidList); + return new AppTradeCartListRespVO().setValidList(validList).setInvalidList(invalidList); } AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu); AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java index b1a834c38..6c44dc279 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/TradeCartMapper.java @@ -45,8 +45,11 @@ public interface TradeCartMapper extends BaseMapperX { .eq(TradeCartDO::getUserId, userId)); } - default List selectListByUserId(Long userId) { - return selectList(TradeCartDO::getUserId, userId); + default List selectListByUserId(Long userId, Boolean addStatus, Boolean orderStatus) { + return selectList(new LambdaQueryWrapper() + .eq(TradeCartDO::getUserId, userId) + .eq(TradeCartDO::getAddStatus, addStatus) + .eq(TradeCartDO::getOrderStatus, orderStatus)); } default void updateByIds(Collection ids, TradeCartDO updateObject) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java index bb06374b6..9b87762c9 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartService.java @@ -1,7 +1,8 @@ package cn.iocoder.yudao.module.trade.service.cart; -import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; import javax.validation.Valid; @@ -31,6 +32,16 @@ public interface TradeCartService { */ void updateCart(Long userId, AppTradeCartUpdateReqVO updateCountReqVO); + /** + * 重置购物车商品 + * + * 使用场景:在一个购物车项对应的商品失效(例如说 SPU 被下架),可以重新选择对应的 SKU + * + * @param userId 用户编号 + * @param updateReqVO 重置信息 + */ + void resetCart(Long userId, AppTradeCartResetReqVO updateReqVO); + /** * 删除购物车商品 * diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java index 9539a19c5..ffd75a07a 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/TradeCartServiceImpl.java @@ -1,18 +1,19 @@ package cn.iocoder.yudao.module.trade.service.cart; import cn.hutool.core.collection.CollUtil; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; +import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO; import cn.iocoder.yudao.module.trade.convert.cart.TradeCartConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.mysql.cart.TradeCartMapper; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -86,6 +87,28 @@ public class TradeCartServiceImpl implements TradeCartService { .setCount(updateReqVO.getCount())); } + @Override + @Transactional(rollbackFor = Exception.class) + public void resetCart(Long userId, AppTradeCartResetReqVO resetReqVO) { + // 第一步:删除原本的购物项 + TradeCartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId); + if (oldCart == null) { + throw exception(CARD_ITEM_NOT_FOUND); + } + cartMapper.deleteById(oldCart.getId()); + + // 第二步:添加新的购物项 + TradeCartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId(), + true, false); + if (newCart != null) { + updateCart(userId, new AppTradeCartUpdateReqVO() + .setId(newCart.getId()).setCount(resetReqVO.getCount())); + } else { + addCart(userId, new AppTradeCartAddReqVO().setAddStatus(true) + .setSkuId(resetReqVO.getSkuId()).setCount(resetReqVO.getCount())); + } + } + /** * 购物车删除商品 * @@ -111,8 +134,8 @@ public class TradeCartServiceImpl implements TradeCartService { @Override public AppTradeCartListRespVO getCartList(Long userId) { - // 获得购物车的商品 - List carts = cartMapper.selectListByUserId(userId); + // 获得购物车的商品,只查询未下单的 + List carts = cartMapper.selectListByUserId(userId, true, false); carts.sort(Comparator.comparing(TradeCartDO::getId).reversed()); // 如果未空,则返回空结果 if (CollUtil.isEmpty(carts)) { @@ -122,12 +145,26 @@ public class TradeCartServiceImpl implements TradeCartService { // 查询 SPU、SKU 列表 List spus = productSpuApi.getSpuList(convertSet(carts, TradeCartDO::getSpuId)); - List skus = productSkuApi.getSkuList(convertSet(carts, TradeCartDO::getSpuId)); + List skus = productSkuApi.getSkuList(convertSet(carts, TradeCartDO::getSkuId)); + + // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除 + deleteCartIfSpuDeleted(carts, spus); // 拼接数据 return TradeCartConvert.INSTANCE.convertList(carts, spus, skus); } + private void deleteCartIfSpuDeleted(List carts, List spus) { + // 如果 SPU 被删除,则删除购物车对应的商品。延迟删除 + carts.removeIf(cart -> { + if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) { + cartMapper.deleteById(cart.getId()); + return true; + } + return false; + }); + } + /** * 校验商品 SKU 是否合法 * 1. 是否存在 @@ -140,7 +177,7 @@ public class TradeCartServiceImpl implements TradeCartService { */ private ProductSkuRespDTO checkProductSku(Long skuId, Integer count) { ProductSkuRespDTO sku = productSkuApi.getSku(skuId); - if (sku == null || CommonStatusEnum.DISABLE.getStatus().equals(sku.getStatus())) { + if (sku == null) { throw exception(SKU_NOT_EXISTS); } if (count > sku.getStock()) { diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index 86d84c415..464cb86a7 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -5,7 +5,6 @@ import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -125,15 +124,10 @@ public class TradeOrderServiceImpl implements TradeOrderService { if (items.size() != skus.size()) { throw exception(ORDER_CREATE_SKU_NOT_FOUND); } - // 校验是否禁用 or 库存不足 + // 校验库存不足 Map skuMap = convertMap(skus, ProductSkuRespDTO::getId); items.forEach(item -> { ProductSkuRespDTO sku = skuMap.get(item.getSkuId()); - // SKU 禁用 - if (ObjectUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), sku.getStatus())) { - throw exception(ORDER_CREATE_SKU_NOT_SALE); - } - // SKU 库存不足 if (item.getCount() > sku.getStock()) { throw exception(ErrorCodeConstants.ORDER_CREATE_SKU_STOCK_NOT_ENOUGH); }