From b7b21b6aa1debe2d473bbe83ebfcc2bc58878373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=89=E6=9D=A5=E6=8A=80=E6=9C=AF?= <1490493387@qq.com> Date: Fri, 13 Aug 2021 00:44:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=E5=95=86=E5=93=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../youlai/mall/oms/pojo/dto/CartItemDTO.java | 56 +++++++ .../com/youlai/mall/oms/pojo/vo/CartVO.java | 44 ------ .../mall/oms/constant/OmsConstants.java | 5 - .../oms/controller/app/CartController.java | 12 +- .../oms/controller/app/OrderController.java | 25 +-- .../youlai/mall/oms/service/ICartService.java | 7 +- .../oms/service/impl/CartServiceImpl.java | 39 ++--- .../oms/service/impl/OrderServiceImpl.java | 83 +++++----- .../youlai/mall/pms/api/GoodsFeignClient.java | 4 +- .../youlai/mall/pms/api/StockFeignClient.java | 7 +- .../{SkuLockDTO.java => LockStockDTO.java} | 2 +- .../youlai/mall/pms/pojo/dto/app/SkuDTO.java | 6 +- .../mall/pms/pojo/vo/app/GoodsDetailVO.java | 114 ++++++++++++++ .../youlai/mall/pms/pojo/vo/app/GoodsVO.java | 18 +++ .../com/youlai/mall/pms/PmsApplication.java | 3 + .../mall/pms/config/BloomFilterConfig.java | 12 +- .../controller/app/CategoryController.java | 2 +- .../pms/controller/app/GoodsController.java | 86 ++++++----- .../pms/controller/app/ProductController.java | 71 --------- .../pms/controller/app/StockController.java | 58 +++++++ .../youlai/mall/pms/mapper/PmsSkuMapper.java | 6 +- .../pms/service/IPmsAttributeService.java | 1 - .../mall/pms/service/IPmsSkuService.java | 4 +- .../mall/pms/service/IProductService.java | 11 -- .../pms/service/impl/PmsSkuServiceImpl.java | 18 +-- .../pms/service/impl/PmsSpuServiceImpl.java | 144 +++++++++++------- .../pms/service/impl/ProductServiceImpl.java | 109 ------------- .../mall/pms/serviceapp/IGoodsService.java | 13 ++ .../pms/serviceapp/impl/GoodsServiceImpl.java | 115 ++++++++++++++ .../main/resources/mapper/PmsSkuMapper.xml | 33 ++-- .../main/resources/mapper/PmsSpuMapper.xml | 57 ++++--- .../web/exception/GlobalExceptionHandler.java | 2 +- 32 files changed, 666 insertions(+), 501 deletions(-) create mode 100644 mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/dto/CartItemDTO.java delete mode 100644 mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/vo/CartVO.java rename mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/{SkuLockDTO.java => LockStockDTO.java} (93%) create mode 100644 mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsDetailVO.java create mode 100644 mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsVO.java delete mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/ProductController.java create mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/StockController.java delete mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IProductService.java delete mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/ProductServiceImpl.java create mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/IGoodsService.java create mode 100644 mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/impl/GoodsServiceImpl.java diff --git a/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/dto/CartItemDTO.java b/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/dto/CartItemDTO.java new file mode 100644 index 00000000..2c81dc03 --- /dev/null +++ b/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/dto/CartItemDTO.java @@ -0,0 +1,56 @@ +package com.youlai.mall.oms.pojo.dto; + +import lombok.*; + +import java.io.Serializable; + +/** + * 购物车商品传输层实体 + */ +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Builder +@Data +public class CartItemDTO implements Serializable { + + + private Long skuId; + + /** + * 商品库存单元名称 + */ + private String skuName; + + /** + * 商品库存单元编码 + */ + private String skuSn; + + /** + * 商品库存单元图片 + */ + private String picUrl; + + private Integer count; // 商品数量 + + /** + * 加入购物车价格,因会变动,不能作为订单计算因子,订单验价时需重新获取商品价格即可 + */ + private Long price; + + private Long coupon; + + private Boolean checked; + + /** + * 商品库存数量,页面控制能选择最大数量 + */ + private Integer stock; + + /** + * 商品名称 + */ + private String goodsName; + +} diff --git a/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/vo/CartVO.java b/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/vo/CartVO.java deleted file mode 100644 index 33633194..00000000 --- a/mall-oms/oms-api/src/main/java/com/youlai/mall/oms/pojo/vo/CartVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.youlai.mall.oms.pojo.vo; - -import lombok.*; - -import java.io.Serializable; -import java.util.List; - -/** - * 购物车实体类 - */ -@NoArgsConstructor -@AllArgsConstructor -@ToString -@Builder -@Data -public class CartVO implements Serializable { - - private List items; - - @Data - public static class CartItem { - - private Long skuId; - - private String skuName; // 标题 - - private String skuCode; - - private String pic; - - private Integer count; // 商品数量 - - private Long price; // 加入购物车价格,因会变动,不能作为订单计算因子,订单验价时需重新获取商品价格即可 - - private Long coupon; - - private Boolean checked; - - private Integer stock;// 商品库存数量,页面控制能选择最大数量 - - private String spuName; - - } -} diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/constant/OmsConstants.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/constant/OmsConstants.java index 9049ad22..a6b21f2a 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/constant/OmsConstants.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/constant/OmsConstants.java @@ -15,10 +15,5 @@ public interface OmsConstants { */ String RELEASE_LOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; - /** - * 释放锁成功返回值 - */ - Long RELEASE_LOCK_SUCCESS_RESULT = 1L; - } diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java index eb67214b..94f74f88 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/CartController.java @@ -2,7 +2,8 @@ package com.youlai.mall.oms.controller.app; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.youlai.common.result.Result; -import com.youlai.mall.oms.pojo.vo.CartVO; +import com.youlai.common.web.util.JwtUtils; +import com.youlai.mall.oms.pojo.dto.CartItemDTO; import com.youlai.mall.oms.service.ICartService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -11,6 +12,8 @@ import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import java.util.List; + /** * @author huawei * @email huawei_code@163.com @@ -30,8 +33,9 @@ public class CartController { @GetMapping @ApiOperationSupport(order = 1) public Result getCart() { - CartVO cart = cartService.getCart(); - return Result.success(cart); + Long memberId = JwtUtils.getUserId(); + List result = cartService.listCartItemByMemberId(memberId); + return Result.success(result); } @ApiOperation(value = "删除购物车") @@ -54,7 +58,7 @@ public class CartController { @ApiOperation(value = "更新购物车商品") @PutMapping("/skuId/{skuId}") @ApiOperationSupport(order = 4) - public Result updateCartItem(@PathVariable Long skuId,@RequestBody CartVO.CartItem cartItem) { + public Result updateCartItem(@PathVariable Long skuId,@RequestBody CartItemDTO cartItem) { cartItem.setSkuId(skuId); boolean result = cartService.updateCartItem(cartItem); return Result.judge(result); diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java index f67ebb25..e1704c55 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/controller/app/OrderController.java @@ -5,14 +5,15 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.youlai.common.result.Result; import com.youlai.common.web.util.JwtUtils; import com.youlai.mall.oms.enums.PayTypeEnum; -import com.youlai.mall.oms.pojo.entity.OmsOrder; import com.youlai.mall.oms.pojo.dto.OrderConfirmDTO; +import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO; +import com.youlai.mall.oms.pojo.entity.OmsOrder; import com.youlai.mall.oms.pojo.vo.OrderConfirmVO; import com.youlai.mall.oms.pojo.vo.OrderSubmitVO; -import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO; import com.youlai.mall.oms.service.IOrderService; -import io.swagger.annotations.*; -import lombok.AllArgsConstructor; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; @@ -28,18 +29,13 @@ import javax.validation.Valid; @RestController @RequestMapping("/app-api/v1/orders") @Slf4j -@AllArgsConstructor +@RequiredArgsConstructor public class OrderController { - private IOrderService orderService; + final IOrderService orderService; @ApiOperation("订单列表") @GetMapping - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", defaultValue = "1", value = "页码", paramType = "query", dataType = "Long"), - @ApiImplicitParam(name = "limit", defaultValue = "10", value = "每页数量", paramType = "query", dataType = "Long"), - @ApiImplicitParam(name = "status", value = "订单状态", paramType = "query", dataType = "Integer") - }) public Result list( @RequestParam(defaultValue = "1") Long page, @RequestParam(defaultValue = "10") Long limit, @@ -53,7 +49,6 @@ public class OrderController { } @ApiOperation("订单确认") - @ApiImplicitParam(name = "orderConfirm", value = "确认订单信息", required = true, paramType = "body", dataType = "OrderConfirmDTO") @PostMapping("/_confirm") public Result confirm(@RequestBody OrderConfirmDTO orderConfirm) { OrderConfirmVO result = orderService.confirm(orderConfirm); @@ -61,7 +56,6 @@ public class OrderController { } @ApiOperation("订单提交") - @ApiImplicitParam(name = "orderSubmitDTO", value = "提交订单信息", required = true, paramType = "body", dataType = "orderSubmitDTO") @PostMapping("/_submit") public Result submit(@Valid @RequestBody OrderSubmitDTO orderSubmitDTO) { OrderSubmitVO result = orderService.submit(orderSubmitDTO); @@ -70,10 +64,6 @@ public class OrderController { @ApiOperation("订单支付") @PostMapping("/{orderId}/_pay") - @ApiImplicitParams({ - @ApiImplicitParam(name = "orderId", value = "订单ID", paramType = "path", dataType = "Long"), - @ApiImplicitParam(name = "payType", value = "支付方式", paramType = "query", dataType = "Integer") - }) public Result pay(@PathVariable Long orderId, Integer payType) { PayTypeEnum payTypeEnum = PayTypeEnum.getByCode(payType); switch (payTypeEnum) { @@ -88,7 +78,6 @@ public class OrderController { @ApiOperation("订单删除") @PostMapping("/{orderId}") - @ApiImplicitParam(name = "orderId", value = "订单ID", paramType = "path", dataType = "Long") public Result deleteOrder(@PathVariable Long orderId) { boolean result = orderService.deleteOrder(orderId); return Result.judge(result); diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/ICartService.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/ICartService.java index 7d18161f..b1dde3bd 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/ICartService.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/ICartService.java @@ -1,6 +1,6 @@ package com.youlai.mall.oms.service; -import com.youlai.mall.oms.pojo.vo.CartVO; +import com.youlai.mall.oms.pojo.dto.CartItemDTO; import java.util.List; @@ -10,15 +10,14 @@ import java.util.List; public interface ICartService { - CartVO getCart(); - List getCartItems(Long memberId); + List listCartItemByMemberId(Long memberId); boolean deleteCart(); boolean addCartItem(Long skuId); - boolean updateCartItem(CartVO.CartItem cartItem); + boolean updateCartItem(CartItemDTO cartItem); boolean removeCartItem(Long skuId); diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java index befc8e6e..a7f1625c 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/CartServiceImpl.java @@ -2,7 +2,7 @@ package com.youlai.mall.oms.service.impl; import com.youlai.common.web.util.JwtUtils; import com.youlai.mall.oms.constant.OmsConstants; -import com.youlai.mall.oms.pojo.vo.CartVO; +import com.youlai.mall.oms.pojo.dto.CartItemDTO; import com.youlai.mall.oms.service.ICartService; import com.youlai.mall.pms.api.GoodsFeignClient; import com.youlai.mall.pms.pojo.dto.app.SkuDTO; @@ -34,23 +34,10 @@ public class CartServiceImpl implements ICartService { private RedisTemplate redisTemplate; private GoodsFeignClient skuFeignService; - /** - * 获取用户购物车 - */ - @Override - public CartVO getCart() { - CartVO cart = new CartVO(); - Long memberId= JwtUtils.getUserId(); - BoundHashOperations cartHashOperations = getCartHashOperations(memberId); - List cartItems = cartHashOperations.values(); - cart.setItems(cartItems); - return cart; - } - @Override - public List getCartItems(Long memberId) { + public List listCartItemByMemberId(Long memberId) { BoundHashOperations cartHashOperations = getCartHashOperations(memberId); - List cartItems = cartHashOperations.values(); + List cartItems = cartHashOperations.values(); return cartItems; } @@ -73,28 +60,28 @@ public class CartServiceImpl implements ICartService { BoundHashOperations cartHashOperations = getCartHashOperations(memberId); String hKey = skuId + ""; - CartVO.CartItem cartItem; + CartItemDTO cartItem; // 购物车已存在该商品,更新商品数量 if (cartHashOperations.get(hKey) != null) { - cartItem = (CartVO.CartItem) cartHashOperations.get(hKey); + cartItem = (CartItemDTO) cartHashOperations.get(hKey); cartItem.setCount(cartItem.getCount() + 1); // 点击一次“加入购物车”,数量+1 cartItem.setChecked(true); cartHashOperations.put(hKey, cartItem); return true; } // 购物车不存在该商品,添加商品至购物车 - cartItem = new CartVO.CartItem(); + cartItem = new CartItemDTO(); CompletableFuture cartItemCompletableFuture = CompletableFuture.runAsync(() -> { SkuDTO sku = skuFeignService.getSkuById(skuId).getData(); if (sku != null) { cartItem.setSkuId(sku.getId()); cartItem.setCount(1); cartItem.setPrice(sku.getPrice()); - cartItem.setPic(sku.getPic()); + cartItem.setPicUrl(sku.getPicUrl()); cartItem.setSkuName(sku.getName()); cartItem.setStock(sku.getStock()); - cartItem.setSkuCode(sku.getCode()); - cartItem.setSpuName(sku.getSpuName()); + cartItem.setSkuSn(sku.getSn()); + cartItem.setGoodsName(sku.getGoodsName()); cartItem.setChecked(true); } }); @@ -107,12 +94,12 @@ public class CartServiceImpl implements ICartService { * 更新购物车总商品数量、选中状态 */ @Override - public boolean updateCartItem(CartVO.CartItem cartItem) { + public boolean updateCartItem(CartItemDTO cartItem) { Long memberId= JwtUtils.getUserId(); BoundHashOperations cartHashOperations = getCartHashOperations(memberId); String hKey = cartItem.getSkuId() + ""; if (cartHashOperations.get(hKey) != null) { - CartVO.CartItem cacheCartItem = (CartVO.CartItem) cartHashOperations.get(hKey); + CartItemDTO cacheCartItem = (CartItemDTO) cartHashOperations.get(hKey); if(cartItem.getChecked()!=null){ cacheCartItem.setChecked(cartItem.getChecked()); } @@ -145,7 +132,7 @@ public class CartServiceImpl implements ICartService { Long memberId= JwtUtils.getUserId(); BoundHashOperations cartHashOperations = getCartHashOperations(memberId); for (Object value : cartHashOperations.values()) { - CartVO.CartItem cartItem = (CartVO.CartItem) value; + CartItemDTO cartItem = (CartItemDTO) value; cartItem.setChecked(checked); String hKey = cartItem.getSkuId() + ""; cartHashOperations.put(hKey, cartItem); @@ -163,7 +150,7 @@ public class CartServiceImpl implements ICartService { Long memberId= JwtUtils.getUserId(); BoundHashOperations cartHashOperations = getCartHashOperations(memberId); for (Object value : cartHashOperations.values()) { - CartVO.CartItem cartItem = (CartVO.CartItem) value; + CartItemDTO cartItem = (CartItemDTO) value; if (cartItem.getChecked()) { cartHashOperations.delete(cartItem.getSkuId()+""); } diff --git a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java index 761b2097..01dafdbd 100644 --- a/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java +++ b/mall-oms/oms-boot/src/main/java/com/youlai/mall/oms/service/impl/OrderServiceImpl.java @@ -1,6 +1,7 @@ package com.youlai.mall.oms.service.impl; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -20,20 +21,21 @@ import com.youlai.mall.oms.pojo.entity.OmsOrderItem; import com.youlai.mall.oms.pojo.dto.OrderConfirmDTO; import com.youlai.mall.oms.pojo.dto.OrderItemDTO; import com.youlai.mall.oms.pojo.dto.OrderSubmitDTO; -import com.youlai.mall.oms.pojo.vo.CartVO; +import com.youlai.mall.oms.pojo.dto.CartItemDTO; import com.youlai.mall.oms.pojo.vo.OrderConfirmVO; import com.youlai.mall.oms.pojo.vo.OrderSubmitVO; import com.youlai.mall.oms.service.ICartService; import com.youlai.mall.oms.service.IOrderItemService; import com.youlai.mall.oms.service.IOrderService; import com.youlai.mall.pms.api.GoodsFeignClient; +import com.youlai.mall.pms.api.StockFeignClient; import com.youlai.mall.pms.pojo.dto.app.SkuDTO; -import com.youlai.mall.pms.pojo.dto.app.SkuLockDTO; +import com.youlai.mall.pms.pojo.dto.app.LockStockDTO; import com.youlai.mall.ums.api.MemberAddressFeignClient; import com.youlai.mall.ums.api.MemberFeignClient; import com.youlai.mall.ums.pojo.entity.UmsAddress; import io.seata.spring.annotation.GlobalTransactional; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.data.redis.core.StringRedisTemplate; @@ -51,21 +53,23 @@ import java.util.stream.Collectors; import static com.youlai.mall.oms.constant.OmsConstants.*; -@AllArgsConstructor +@RequiredArgsConstructor @Slf4j @Service public class OrderServiceImpl extends ServiceImpl implements IOrderService { - private ICartService cartService; - private GoodsFeignClient skuFeignService; - private MemberAddressFeignClient addressFeignService; - private IOrderItemService orderItemService; - private RabbitTemplate rabbitTemplate; - private StringRedisTemplate redisTemplate; - private ThreadPoolExecutor threadPoolExecutor; - private MemberFeignClient memberFeignClient; + final ICartService cartService; + + final MemberAddressFeignClient addressFeignService; + final IOrderItemService orderItemService; + final RabbitTemplate rabbitTemplate; + final StringRedisTemplate redisTemplate; + final ThreadPoolExecutor threadPoolExecutor; + final MemberFeignClient memberFeignClient; + final BusinessNoGenerator businessNoGenerator; - private BusinessNoGenerator businessNoGenerator; + final GoodsFeignClient goodsFeignClient; + final StockFeignClient stockFeignClient; /** * 订单确认 @@ -83,25 +87,25 @@ public class OrderServiceImpl extends ServiceImpl impleme .skuId(orderConfirmDTO.getSkuId()) .count(orderConfirmDTO.getCount()) .build(); - SkuDTO sku = skuFeignService.getSkuById(orderConfirmDTO.getSkuId()).getData(); + SkuDTO sku = goodsFeignClient.getSkuById(orderConfirmDTO.getSkuId()).getData(); orderItemDTO.setPrice(sku.getPrice()); - orderItemDTO.setPic(sku.getPic()); + orderItemDTO.setPic(sku.getPicUrl()); orderItemDTO.setSkuName(sku.getName()); - orderItemDTO.setSkuCode(sku.getCode()); - orderItemDTO.setSpuName(sku.getSpuName()); + orderItemDTO.setSkuCode(sku.getSn()); + orderItemDTO.setSpuName(sku.getGoodsName()); orderItems.add(orderItemDTO); } else { // 购物车中商品结算 - List cartItems = cartService.getCartItems(memberId); + List cartItems = cartService.listCartItemByMemberId(memberId); List items = cartItems.stream() - .filter(CartVO.CartItem::getChecked) + .filter(CartItemDTO::getChecked) .map(cartItem -> OrderItemDTO.builder() .skuId(cartItem.getSkuId()) .count(cartItem.getCount()) .price(cartItem.getPrice()) .skuName(cartItem.getSkuName()) - .skuCode(cartItem.getSkuCode()) - .spuName(cartItem.getSpuName()) - .pic(cartItem.getPic()) + .skuCode(cartItem.getSkuSn()) + .spuName(cartItem.getGoodsName()) + .pic(cartItem.getPicUrl()) .build()) .collect(Collectors.toList()); orderItems.addAll(items); @@ -124,7 +128,7 @@ public class OrderServiceImpl extends ServiceImpl impleme }, threadPoolExecutor); CompletableFuture.allOf(orderItemsCompletableFuture, addressesCompletableFuture, orderTokenCompletableFuture).join(); - log.info("订单确认响应:{}", orderConfirmVO.toString()); + log.info("订单确认响应:{}", orderConfirmVO); return orderConfirmVO; } @@ -138,43 +142,34 @@ public class OrderServiceImpl extends ServiceImpl impleme // 订单重复提交校验 String orderToken = submitDTO.getOrderToken(); DefaultRedisScript redisScript = new DefaultRedisScript<>(RELEASE_LOCK_LUA_SCRIPT, Long.class); - Long result = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken); - - if (!ObjectUtil.equals(result, RELEASE_LOCK_SUCCESS_RESULT)) { - throw new BizException("订单不可重复提交"); - } + Long execute = this.redisTemplate.execute(redisScript, Collections.singletonList(ORDER_TOKEN_PREFIX + orderToken), orderToken); + Assert.isTrue(execute.equals(1l),"订单不可重复提交"); List orderItems = submitDTO.getOrderItems(); - if (CollectionUtil.isEmpty(orderItems)) { - throw new BizException("订单没有商品,请选择商品后提交"); - } + Assert.isTrue(CollectionUtil.isNotEmpty(orderItems),"订单商品为空"); // 订单验价 Long currentTotalPrice = orderItems.stream().map(item -> { - SkuDTO sku = skuFeignService.getSkuById(item.getSkuId()).getData(); + SkuDTO sku = goodsFeignClient.getSkuById(item.getSkuId()).getData(); if (sku != null) { return sku.getPrice() * item.getCount(); } return 0l; }).reduce(0l, Long::sum); - if (currentTotalPrice.compareTo(submitDTO.getTotalPrice()) != 0) { - throw new BizException("页面已过期,请重新刷新页面再提交"); - } + Assert.isTrue(currentTotalPrice.compareTo(submitDTO.getTotalPrice()) == 0,"当前页面已过期,请重新刷新页面再提交"); // 校验库存是否足够和锁库存 - List skuLockList = orderItems.stream() - .map(item -> SkuLockDTO.builder().skuId(item.getSkuId()) + List skuLockList = orderItems.stream() + .map(item -> LockStockDTO.builder().skuId(item.getSkuId()) .count(item.getCount()) .orderToken(orderToken) .build()) .collect(Collectors.toList()); - Result lockResult = skuFeignService.lockStock(skuLockList); + Result lockResult = stockFeignClient.lockStock(skuLockList); - if (!Result.success().getCode().equals(lockResult.getCode())) { - throw new BizException(Result.failed().getMsg()); - } + Assert.isTrue(Result.success().getCode().equals(lockResult.getCode()),"锁定商品库存失败:{}",lockResult.getMsg()); // 创建订单(状态:待支付) OmsOrder order = new OmsOrder(); @@ -209,7 +204,7 @@ public class OrderServiceImpl extends ServiceImpl impleme OrderSubmitVO submitVO = new OrderSubmitVO(); submitVO.setOrderId(order.getId()); submitVO.setOrderSn(order.getOrderSn()); - log.info("订单提交响应:{}", submitVO.toString()); + log.info("订单提交响应:{}", submitVO); return submitVO; } @@ -238,7 +233,7 @@ public class OrderServiceImpl extends ServiceImpl impleme } // 扣减库存 - Result deductStockResult = skuFeignService.deductStock(order.getOrderSn()); + Result deductStockResult = stockFeignClient.deductStock(order.getOrderSn()); if (!Result.isSuccess(deductStockResult)) { throw new BizException("扣减商品库存失败"); } @@ -279,7 +274,7 @@ public class OrderServiceImpl extends ServiceImpl impleme boolean result = this.updateById(order); if (result) { // 释放被锁定的库存 - Result unlockResult = skuFeignService.unlockStock(order.getOrderSn()); + Result unlockResult = stockFeignClient.unlockStock(order.getOrderSn()); if (!Result.isSuccess(unlockResult)) { throw new BizException(unlockResult.getMsg()); } diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/GoodsFeignClient.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/GoodsFeignClient.java index a92074bd..75638e8c 100644 --- a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/GoodsFeignClient.java +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/GoodsFeignClient.java @@ -6,12 +6,12 @@ import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -@FeignClient(value = "mall-pms") +@FeignClient(value = "mall-pms",contextId = "goods") public interface GoodsFeignClient { /** * 获取商品信息 */ - @GetMapping("/app-api/v1/goods/{id}") + @GetMapping("/app-api/v1/stocks/{id}") Result getSkuById(@PathVariable Long id); } diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/StockFeignClient.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/StockFeignClient.java index 6944425e..655ce05f 100644 --- a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/StockFeignClient.java +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/api/StockFeignClient.java @@ -1,20 +1,19 @@ package com.youlai.mall.pms.api; import com.youlai.common.result.Result; -import com.youlai.mall.pms.pojo.dto.app.SkuLockDTO; +import com.youlai.mall.pms.pojo.dto.app.LockStockDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; - import java.util.List; -@FeignClient(value = "mall-pms") +@FeignClient(value = "mall-pms",contextId = "stock") public interface StockFeignClient { /** * 锁定库存 */ @PutMapping("/app-api/v1/stocks/_lock") - Result lockStock(@RequestBody List list); + Result lockStock(@RequestBody List list); /** * 解锁库存 diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuLockDTO.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/LockStockDTO.java similarity index 93% rename from mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuLockDTO.java rename to mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/LockStockDTO.java index acca4ff7..d42f8f22 100644 --- a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuLockDTO.java +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/LockStockDTO.java @@ -14,7 +14,7 @@ import lombok.NoArgsConstructor; @Builder @NoArgsConstructor @AllArgsConstructor -public class SkuLockDTO { +public class LockStockDTO { private Long skuId; diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuDTO.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuDTO.java index 5fc98583..c2b75bec 100644 --- a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuDTO.java +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/dto/app/SkuDTO.java @@ -12,12 +12,12 @@ import lombok.Data; public class SkuDTO { private Long id; - private String code; + private String sn; private String name; - private String pic; + private String picUrl; private Long price; private Integer stock; - private String spuName; + private String goodsName; } diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsDetailVO.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsDetailVO.java new file mode 100644 index 00000000..f58abc58 --- /dev/null +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsDetailVO.java @@ -0,0 +1,114 @@ +package com.youlai.mall.pms.pojo.vo.app; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + * 商品详情页-商品详细信息 + * + * @author xianrui + * @date 2021/8/8 + */ +@Data +@ApiModel("商品详情") +public class GoodsDetailVO { + + @ApiModelProperty("商品基本信息") + private GoodsInfo goodsInfo; + + @ApiModelProperty("商品属性列表") + private List attributeList; + + @ApiModelProperty("商品规格列表") + private List specList; + + @ApiModelProperty("商品库存单元列表") + private List skuList; + + @Data + @ApiModel("商品信息") + public static class GoodsInfo { + + @ApiModelProperty("商品ID") + private Long id; + + @ApiModelProperty("商品名称") + private String name; + + @ApiModelProperty("商品原价(单位:分)") + private Long originPrice; + + @ApiModelProperty("商品零售价(单位:分)") + private Long price; + + @ApiModelProperty("销量") + private Integer sales; + + @ApiModelProperty("商品图册") + private List album; + + @ApiModelProperty("商品详情") + private String detail; + } + + + @Data + @ApiModel("属性信息") + public static class Attribute { + @ApiModelProperty("属性ID") + private Long id; + @ApiModelProperty("属性名称") + private String name; + @ApiModelProperty("属性值") + private String value; + } + + @Data + @ApiModel("规格信息") + public static class Specification { + + @ApiModelProperty(value = "规格名称", example = "颜色") + private String name; + + @ApiModelProperty(value = "规格项列表", example = "[黑,白]") + private List values; + + @Data + @ApiModel("规格项") + public static class Value { + @ApiModelProperty("规格项ID") + private Long id; + + @ApiModelProperty("规格项值") + private String value; + } + } + + @Data + @ApiModel("商品库存单元") + public static class Sku { + @ApiModelProperty("库存单元ID") + private Long id; + + @ApiModelProperty("库存单元名称") + private String name; + + @ApiModelProperty("库存单元规格值ID集合,以英文逗号拼接") + private String specIds; + + @ApiModelProperty("价格") + private Long price; + + @ApiModelProperty("库存") + private Integer stock; + + @ApiModelProperty("商品图片URL") + private String picUrl; + + } + + +} diff --git a/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsVO.java b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsVO.java new file mode 100644 index 00000000..84386cfd --- /dev/null +++ b/mall-pms/pms-api/src/main/java/com/youlai/mall/pms/pojo/vo/app/GoodsVO.java @@ -0,0 +1,18 @@ +package com.youlai.mall.pms.pojo.vo.app; + +import lombok.Data; + +/** + * 商品列表页-商品基础信息 + * + * @author xianrui + * @date 2021/8/8 + */ +@Data +public class GoodsVO { + private Long id; + private String name; + private Long price; + private Integer sales; + private String picUrl; +} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/PmsApplication.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/PmsApplication.java index 00bd4458..ad83bd31 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/PmsApplication.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/PmsApplication.java @@ -4,8 +4,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.transaction.annotation.EnableTransactionManagement; +import java.util.Arrays; + @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) @EnableDiscoveryClient @EnableTransactionManagement diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/config/BloomFilterConfig.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/config/BloomFilterConfig.java index 51406bb3..66bb5caf 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/config/BloomFilterConfig.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/config/BloomFilterConfig.java @@ -2,9 +2,10 @@ package com.youlai.mall.pms.config; import com.google.common.base.Charsets; import com.google.common.hash.Funnel; +import com.youlai.mall.pms.common.constant.PmsConstants; import com.youlai.mall.pms.component.BloomRedisService; import com.youlai.mall.pms.pojo.entity.PmsSpu; -import com.youlai.mall.pms.service.IProductService; +import com.youlai.mall.pms.serviceapp.IGoodsService; import com.youlai.mall.pms.utils.BloomFilterUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -13,11 +14,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.CollectionUtils; - import java.util.List; -import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_REDIS_BLOOM_FILTER; - /** * @Author DaniR * @Description @@ -28,7 +26,7 @@ import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_REDIS_BLO @AllArgsConstructor public class BloomFilterConfig implements InitializingBean { - private final IProductService iProductService; + private final IGoodsService goodsService; private final RedisTemplate redisTemplate; @Bean @@ -48,11 +46,11 @@ public class BloomFilterConfig implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { - List list = iProductService.list(); + List list = goodsService.list(); log.info("加载产品到布隆过滤器当中,size:{}", list.size()); if (!CollectionUtils.isEmpty(list)) { list.stream().filter(item -> item.getId() > 0).forEach(item -> { - bloomRedisService().addByBloomFilter(PRODUCT_REDIS_BLOOM_FILTER, item.getId() + ""); + bloomRedisService().addByBloomFilter(PmsConstants.PRODUCT_REDIS_BLOOM_FILTER, item.getId() + ""); }); } } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/CategoryController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/CategoryController.java index 08828e39..f6ad98e8 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/CategoryController.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/CategoryController.java @@ -17,7 +17,7 @@ import java.util.List; /** * @author xianrui */ -@Api(tags = "移动端-分类信息") +@Api(tags = "移动端-商品分类") @RestController("appCategoryController") @RequestMapping("/app-api/v1/categories") @Slf4j diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/GoodsController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/GoodsController.java index 9f6287da..24d3c837 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/GoodsController.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/GoodsController.java @@ -1,64 +1,66 @@ package com.youlai.mall.pms.controller.app; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.youlai.common.result.Result; -import com.youlai.mall.pms.pojo.dto.app.SkuDTO; -import com.youlai.mall.pms.pojo.dto.app.SkuLockDTO; -import com.youlai.mall.pms.service.IPmsSkuService; +import com.youlai.mall.pms.pojo.entity.PmsSpu; +import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO; +import com.youlai.mall.pms.pojo.vo.app.GoodsVO; +import com.youlai.mall.pms.serviceapp.IGoodsService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import jodd.util.StringUtil; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.stream.Collectors; -@Api(tags = "移动端-商品") -@RestController("appGoodsController") +@Api(tags = "移动端-商品信息") +@RestController(value = "appGoodsController") @RequestMapping("/app-api/v1/goods") @AllArgsConstructor public class GoodsController { - private IPmsSkuService iPmsSkuService; + private IGoodsService goodsService; - @ApiOperation(value = "商品详情") - @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long") - @GetMapping("/{id}") - public Result detail(@PathVariable Long id) { - SkuDTO sku = iPmsSkuService.getSkuById(id); - return Result.success(sku); - } + @ApiOperation(value = "商品分页列表") + @ApiImplicitParams({ + @ApiImplicitParam(name = "page", value = "页码", example = "1", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "limit", value = "每页数量", example = "10", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "name", value = "商品名称", example = "华为P50", paramType = "query", dataType = "String"), + @ApiImplicitParam(name = "categoryId", value = "商品类目", example = "1", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "orderBy", value = "排序字段", example = "price", paramType = "query", dataType = "Long"), + @ApiImplicitParam(name = "isAsc", value = "是否升序", example = "false", paramType = "query", dataType = "Boolean") + }) + @GetMapping + public Result list(Integer page, Integer limit, String name, Long categoryId, String orderBy, Boolean isAsc) { + Page pageResult = goodsService.page(new Page<>(page, limit), new QueryWrapper() + .eq(categoryId != null, "category_id", categoryId) + .like(StrUtil.isNotBlank(name), "name", name) + .select("id", "name", "pic_url", "price", "sales") + .orderBy(StringUtil.isNotBlank(orderBy), isAsc, StrUtil.toUnderlineCase(orderBy)) + ); - @ApiOperation("获取商品的库存数量") - @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long") - @GetMapping("/{id}/stock") - public Result getStockById(@PathVariable Long id) { - Integer stock = iPmsSkuService.getStockById(id); - return Result.success(stock); + List list = pageResult.getRecords().stream() + .map(item -> { + GoodsVO goodsVO = new GoodsVO(); + BeanUtil.copyProperties(item, goodsVO); + return goodsVO; + }).collect(Collectors.toList()); + return Result.success(list, pageResult.getTotal()); } - @ApiOperation(value = "锁定库存") - @ApiImplicitParam(name = "list", value = "商品列表", required = true, paramType = "body", dataType = "SkuLockDTO") - @PutMapping("/stocks/_lock") - public Result lockStock(@RequestBody List list) { - boolean result = iPmsSkuService.lockStock(list); - return Result.judge(result); - } - - - @ApiOperation(value = "解锁库存") - @ApiImplicitParam(name = "orderToken", value = "订单令牌", required = true, paramType = "body", dataType = "String") - @PutMapping("/stocks/_unlock") - public Result unlockStock(String orderToken) { - boolean result = iPmsSkuService.unlockStock(orderToken); - return Result.judge(result); - } - - @ApiOperation(value = "扣减库存") - @ApiImplicitParam(name = "orderToken", value = "订单令牌", required = true, paramType = "body", dataType = "String") - @PutMapping("/stocks/_deduct") - public Result deductStock(String orderToken) { - boolean result = iPmsSkuService.deductStock(orderToken); - return Result.judge(result); + @ApiOperation(value = "商品详情") + @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long") + @GetMapping("/{id}") + public Result detail(@PathVariable Long id) { + GoodsDetailVO goodsDetailVO = goodsService.getGoodsById(id); + return Result.success(goodsDetailVO); } } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/ProductController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/ProductController.java deleted file mode 100644 index 9bebf9aa..00000000 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/ProductController.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.youlai.mall.pms.controller.app; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.youlai.common.result.Result; -import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO; -import com.youlai.mall.pms.pojo.entity.PmsSpu; -import com.youlai.mall.pms.pojo.dto.app.ProductDTO; -import com.youlai.mall.pms.service.IPmsSpuService; -import com.youlai.mall.pms.service.IProductService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; -import lombok.AllArgsConstructor; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.stream.Collectors; - -@Api(tags = "移动端-产品") -@RestController("appSpuController") -@RequestMapping("/app-api/v1/products") -@AllArgsConstructor -public class ProductController { - - private IPmsSpuService iPmsSpuService; - - private IProductService iProductService; - - @ApiOperation(value = "列表分页") - @ApiImplicitParams({ - @ApiImplicitParam(name = "page", value = "页码", defaultValue = "1", paramType = "query", dataType = "Long"), - @ApiImplicitParam(name = "limit", value = "每页数量", defaultValue = "10", paramType = "query", dataType = "Long"), - @ApiImplicitParam(name = "name", value = "商品名称", paramType = "query", dataType = "String"), - @ApiImplicitParam(name = "categoryId", value = "商品类目", paramType = "query", dataType = "Long") - }) - @GetMapping - public Result list( - Integer page, - Integer limit, - String name, - Long categoryId - ) { - Page result = iPmsSpuService.page(new Page<>(page, limit), new LambdaQueryWrapper() - .eq(categoryId != null, PmsSpu::getCategoryId, categoryId) - .like(StrUtil.isNotBlank(name), PmsSpu::getName, name) - .select(PmsSpu::getId, - PmsSpu::getName, - PmsSpu::getPicUrl, - PmsSpu::getPrice, - PmsSpu::getSales - ) - ); - List list = result.getRecords().stream() - .map(item -> JSONUtil.toBean(JSONUtil.toJsonStr(item), ProductDTO.class)) - .collect(Collectors.toList()); - return Result.success(list, result.getTotal()); - } - - @ApiOperation(value = "商品详情") - @ApiImplicitParam(name = "id", value = "商品ID", required = true, paramType = "path", dataType = "Long") - @GetMapping("/{id}") - public Result detail(@PathVariable Long id) { - ProductFormDTO product = iProductService.getProductById(id); - return Result.success(product); - } - -} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/StockController.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/StockController.java new file mode 100644 index 00000000..3658bfca --- /dev/null +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/controller/app/StockController.java @@ -0,0 +1,58 @@ +package com.youlai.mall.pms.controller.app; + +import com.youlai.common.result.Result; +import com.youlai.mall.pms.pojo.dto.app.SkuDTO; +import com.youlai.mall.pms.pojo.dto.app.LockStockDTO; +import com.youlai.mall.pms.service.IPmsSkuService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@Api(tags = "移动端-商品库存") +@RestController(value = "appStockController") +@RequestMapping("/app-api/v1/stocks") +@AllArgsConstructor +public class StockController { + + private IPmsSkuService iPmsSkuService; + + @ApiOperation(value = "商品库存单元详情") + @GetMapping("/{skuId}") + public Result detail(@PathVariable Long skuId) { + SkuDTO sku = iPmsSkuService.getSkuById(skuId); + return Result.success(sku); + } + + @ApiOperation("获取商品的库存数量") + @GetMapping("/{skuId}/stock") + public Result getStockById(@PathVariable Long skuId) { + Integer stock = iPmsSkuService.getStockById(skuId); + return Result.success(stock); + } + + + @ApiOperation(value = "锁定库存") + @PutMapping("/_lock") + public Result lockStock(@RequestBody List list) { + boolean result = iPmsSkuService.lockStock(list); + return Result.judge(result); + } + + + @ApiOperation(value = "解锁库存") + @PutMapping("/_unlock") + public Result unlockStock(String orderToken) { + boolean result = iPmsSkuService.unlockStock(orderToken); + return Result.judge(result); + } + + @ApiOperation(value = "扣减库存") + @PutMapping("/_deduct") + public Result deductStock(String orderToken) { + boolean result = iPmsSkuService.deductStock(orderToken); + return Result.judge(result); + } +} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/mapper/PmsSkuMapper.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/mapper/PmsSkuMapper.java index 96cedb79..e519618a 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/mapper/PmsSkuMapper.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/mapper/PmsSkuMapper.java @@ -17,10 +17,6 @@ public interface PmsSkuMapper extends BaseMapper { List listBySpuId(Long spuId); - @Select("") + SkuDTO getSkuById(Long id); } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsAttributeService.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsAttributeService.java index ec7e4638..f1511f92 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsAttributeService.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsAttributeService.java @@ -6,6 +6,5 @@ import com.youlai.mall.pms.pojo.entity.PmsAttribute; public interface IPmsAttributeService extends IService { - boolean saveBatch(AttributeFormDTO attributeForm); } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java index 96ce9eeb..61b3d67e 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IPmsSkuService.java @@ -3,7 +3,7 @@ package com.youlai.mall.pms.service; import com.baomidou.mybatisplus.extension.service.IService; import com.youlai.mall.pms.pojo.entity.PmsSku; import com.youlai.mall.pms.pojo.dto.app.SkuDTO; -import com.youlai.mall.pms.pojo.dto.app.SkuLockDTO; +import com.youlai.mall.pms.pojo.dto.app.LockStockDTO; import java.util.List; @@ -12,7 +12,7 @@ public interface IPmsSkuService extends IService { /** * 锁定库存 */ - boolean lockStock(List list); + boolean lockStock(List list); /** * 解锁库存 diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IProductService.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IProductService.java deleted file mode 100644 index 96ba1d41..00000000 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/IProductService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.youlai.mall.pms.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO; -import com.youlai.mall.pms.pojo.entity.PmsSpu; - - -public interface IProductService extends IService { - - ProductFormDTO getProductById(Long id); -} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java index 4849c93e..a218026e 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSkuServiceImpl.java @@ -11,7 +11,7 @@ import com.youlai.common.web.exception.BizException; import com.youlai.mall.pms.mapper.PmsSkuMapper; import com.youlai.mall.pms.pojo.entity.PmsSku; import com.youlai.mall.pms.pojo.dto.app.SkuDTO; -import com.youlai.mall.pms.pojo.dto.app.SkuLockDTO; +import com.youlai.mall.pms.pojo.dto.app.LockStockDTO; import com.youlai.mall.pms.service.IPmsSkuService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -39,7 +39,7 @@ public class PmsSkuServiceImpl extends ServiceImpl impleme * 创建订单时锁定库存 */ @Override - public boolean lockStock(List skuLockList) { + public boolean lockStock(List skuLockList) { log.info("=======================创建订单,开始锁定商品库存======================="); log.info("锁定商品信息:{}", skuLockList.toString()); if (CollectionUtil.isEmpty(skuLockList)) { @@ -64,17 +64,17 @@ public class PmsSkuServiceImpl extends ServiceImpl impleme }); // 锁定失败的商品集合 - List unlockSkuList = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList()); + List unlockSkuList = skuLockList.stream().filter(item -> !item.getLocked()).collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(unlockSkuList)) { // 恢复已被锁定的库存 - List lockSkuList = skuLockList.stream().filter(SkuLockDTO::getLocked).collect(Collectors.toList()); + List lockSkuList = skuLockList.stream().filter(LockStockDTO::getLocked).collect(Collectors.toList()); lockSkuList.forEach(item -> this.update(new LambdaUpdateWrapper() .eq(PmsSku::getId, item.getSkuId()) .setSql("locked_stock = locked_stock - " + item.getCount())) ); // 提示订单哪些商品库存不足 - List ids = unlockSkuList.stream().map(SkuLockDTO::getSkuId).collect(Collectors.toList()); + List ids = unlockSkuList.stream().map(LockStockDTO::getSkuId).collect(Collectors.toList()); throw new BizException("商品" + ids.toString() + "库存不足"); } @@ -96,7 +96,7 @@ public class PmsSkuServiceImpl extends ServiceImpl impleme return true; } - List skuLockList = JSONUtil.toList(json, SkuLockDTO.class); + List skuLockList = JSONUtil.toList(json, LockStockDTO.class); skuLockList.forEach(item -> this.update(new LambdaUpdateWrapper() @@ -121,13 +121,13 @@ public class PmsSkuServiceImpl extends ServiceImpl impleme return true; } - List skuLockList = JSONUtil.toList(json, SkuLockDTO.class); + List skuLockList = JSONUtil.toList(json, LockStockDTO.class); skuLockList.forEach(item -> { boolean result = this.update(new LambdaUpdateWrapper() .eq(PmsSku::getId, item.getSkuId()) - .setSql("inventory = inventory - " + item.getCount()) // 扣减库存 - .setSql("locked_inventory = locked_inventory - " + item.getCount()) + .setSql("stock = stock - " + item.getCount()) // 扣减库存 + .setSql("locked_stock = locked_stock - " + item.getCount()) ); if (!result) { throw new BizException("扣减库存失败,商品" + item.getSkuId() + "库存不足"); diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSpuServiceImpl.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSpuServiceImpl.java index 8aaefe50..1658cb87 100644 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSpuServiceImpl.java +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/PmsSpuServiceImpl.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; /** * @author xianrui + * @date 2021/08/08 */ @Service @RequiredArgsConstructor @@ -40,6 +41,14 @@ public class PmsSpuServiceImpl extends ServiceImpl impleme private final IPmsSpuAttributeValueService iPmsSpuAttributeValueService; private final BloomRedisService bloomRedisService; + /** + * 商品分页列表 + * + * @param page + * @param name + * @param categoryId + * @return + */ @Override public IPage list(Page page, String name, Long categoryId) { List list = this.baseMapper.list(page, name, categoryId); @@ -47,6 +56,12 @@ public class PmsSpuServiceImpl extends ServiceImpl impleme return page; } + /** + * 添加商品 + * + * @param goods + * @return + */ @Override @Transactional public boolean addGoods(GoodsFormDTO goods) { @@ -63,6 +78,12 @@ public class PmsSpuServiceImpl extends ServiceImpl impleme } + /** + * 修改商品 + * + * @param goods + * @return + */ @Transactional @Override public boolean updateGoods(GoodsFormDTO goods) { @@ -85,6 +106,73 @@ public class PmsSpuServiceImpl extends ServiceImpl impleme return saveResult; } + /** + * 获取商品(SPU)详情 + * + * @param id 商品(SPU)ID + * @return + */ + @Override + public GoodsDetailVO getGoodsById(Long id) { + GoodsDetailVO goodsDetailVO = new GoodsDetailVO(); + + PmsSpu spu = this.getById(id); + Assert.isTrue(spu != null, "商品不存在"); + + BeanUtil.copyProperties(spu, goodsDetailVO); + + // 商品图册JSON字符串转集合 + String album = spu.getAlbum(); + if (StrUtil.isNotBlank(album)) { + List picUrls = JSONUtil.toList(album, String.class); + goodsDetailVO.setSubPicUrls(picUrls); + } + + // 商品属性列表 + List attrList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper() + .eq(PmsSpuAttributeValue::getSpuId, id) + .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue()) + ); + goodsDetailVO.setAttrList(attrList); + + // 商品规格列表 + List specList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper() + .eq(PmsSpuAttributeValue::getSpuId, id) + .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue()) + ); + goodsDetailVO.setSpecList(specList); + + // 商品SKU列表 + List skuList = iPmsSkuService.list(new LambdaQueryWrapper().eq(PmsSku::getSpuId, id)); + goodsDetailVO.setSkuList(skuList); + return goodsDetailVO; + } + + + /** + * 批量删除商品(SPU) + * + * @param goodsIds + * @return + */ + @Override + @Transactional + public boolean removeByGoodsIds(List goodsIds) { + boolean result = true; + for (Long goodsId : goodsIds) { + // sku + iPmsSkuService.remove(new LambdaQueryWrapper().eq(PmsSku::getSpuId, goodsId)); + // 规格 + iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper().eq(PmsSpuAttributeValue::getId, goodsId)); + // 属性 + iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper().eq(PmsSpuAttributeValue::getSpuId, goodsId)); + // spu + result = this.removeById(goodsId); + } + return result; + } + + /** * 保存商品 * @@ -234,60 +322,4 @@ public class PmsSpuServiceImpl extends ServiceImpl impleme } return tempIdIdMap; } - - - @Override - public GoodsDetailVO getGoodsById(Long id) { - GoodsDetailVO goodsDetailVO = new GoodsDetailVO(); - - PmsSpu spu = this.getById(id); - Assert.isTrue(spu != null, "商品不存在"); - - BeanUtil.copyProperties(spu, goodsDetailVO); - - // 商品图册JSON字符串转JSON - String album = spu.getAlbum(); - if (StrUtil.isNotBlank(album)) { - List picUrls = JSONUtil.toList(album, String.class); - goodsDetailVO.setSubPicUrls(picUrls); - } - - // 商品属性列表 - List attrList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper() - .eq(PmsSpuAttributeValue::getSpuId, id) - .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue()) - ); - goodsDetailVO.setAttrList(attrList); - - // 商品规格列表 - List specList = iPmsSpuAttributeValueService.list(new LambdaQueryWrapper() - .eq(PmsSpuAttributeValue::getSpuId, id) - .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue()) - ); - goodsDetailVO.setSpecList(specList); - - // 商品SKU列表 - List skuList = iPmsSkuService.list(new LambdaQueryWrapper().eq(PmsSku::getSpuId, id)); - goodsDetailVO.setSkuList(skuList); - - return goodsDetailVO; - } - - - @Override - public boolean removeByGoodsIds(List goodsIds) { - boolean result = true; - for (Long goodsId : goodsIds) { - // sku - iPmsSkuService.remove(new LambdaQueryWrapper().eq(PmsSku::getSpuId, goodsId)); - // 规格 - iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper().eq(PmsSpuAttributeValue::getId, goodsId)); - // 属性 - iPmsSpuAttributeValueService.remove(new LambdaQueryWrapper().eq(PmsSpuAttributeValue::getSpuId, goodsId)); - // spu - result = this.removeById(goodsId); - } - return result; - } - } diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/ProductServiceImpl.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/ProductServiceImpl.java deleted file mode 100644 index a5da4c12..00000000 --- a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/service/impl/ProductServiceImpl.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.youlai.mall.pms.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.youlai.common.redis.utils.RedisUtils; -import com.youlai.mall.pms.config.ProductLocalCache; -import com.youlai.mall.pms.mapper.PmsSpuMapper; -import com.youlai.mall.pms.pojo.dto.app.ProductFormDTO; -import com.youlai.mall.pms.pojo.entity.PmsAttribute; -import com.youlai.mall.pms.pojo.entity.PmsSku; -import com.youlai.mall.pms.pojo.entity.PmsSpu; -import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue; -import com.youlai.mall.pms.service.IPmsAttributeService; -import com.youlai.mall.pms.service.IPmsSkuService; -import com.youlai.mall.pms.service.IPmsSpuAttributeValueService; -import com.youlai.mall.pms.service.IProductService; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RLock; -import org.redisson.api.RedissonClient; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static com.youlai.mall.pms.common.constant.PmsConstants.LOCK_PRODUCT_DETAIL; -import static com.youlai.mall.pms.common.constant.PmsConstants.PRODUCT_DETAIL_CACHE; - -/** - * @author haoxr - * @date 2020-11-06 - */ -@Service -@Slf4j -@AllArgsConstructor -public class ProductServiceImpl extends ServiceImpl implements IProductService { - - private final IPmsSkuService iPmsSkuService; - private final IPmsSpuAttributeValueService iPmsSpuAttributeValueService; - private final IPmsAttributeService iPmsSpecService; - private final RedisUtils redisUtils; - private final RedissonClient redissonClient; - private final ProductLocalCache productLocalCache; - - - @Override - public ProductFormDTO getProductById(Long spuId) { - //1、一级本地缓存设置 - ProductFormDTO product = productLocalCache.get(PRODUCT_DETAIL_CACHE + spuId); - /* if (null != product) { - log.info("get LocalCache product:" + product); - return product; - } - //2、二级缓存设置,Redis中获取商品详情信息 - product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId); - if (null != product) { - log.info("get redis product:" + product); - return product; - } - //3、分布式锁,保证原子操作 - RLock lock = redissonClient.getLock(LOCK_PRODUCT_DETAIL + spuId); - try { - if (lock.tryLock()) { - // spu - PmsSpu spu = this.getById(spuId); - SpuDTO SpuDTO = new SpuDTO(); - BeanUtil.copyProperties(spu, SpuDTO); - if (StrUtil.isNotBlank(spu.getAlbum())) { - // spu专辑图片转换处理 json字符串 -> List - List pics = JSONUtil.toList(JSONUtil.parseArray(spu.getAlbum()), String.class); - SpuDTO.setPics(pics); - } - // 属性 - List attrs = iPmsSpuAttributeValueService.list( - new LambdaQueryWrapper( - ).eq(PmsSpuAttributeValue::getSpuId, spuId) - ); - // 规格 - // List specs = iPmsSpecService.listBySpuId(spuId); - - List specs=null; - // sku - List skuList = iPmsSkuService.list(new LambdaQueryWrapper().eq(PmsSku::getSpuId, spuId)); - - // product = new ProductFormDTO(SpuDTO, attrs, specs, skuList); - product = new ProductFormDTO(); - //TODO 4、需要判断商品是否是秒杀商品,根据秒杀信息更新商品秒杀相关信息 - log.info("get db product:" + product); - redisUtils.set(PRODUCT_DETAIL_CACHE + spuId, product, 3600); - productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId,product); - } else { - log.info("get redis2 product:" + product); - product = (ProductFormDTO) redisUtils.get(PRODUCT_DETAIL_CACHE + spuId); - if (null!=product) { - productLocalCache.setLocalCache(PRODUCT_DETAIL_CACHE + spuId, product); - } - } - } finally { - if (lock.isLocked()) { - if (lock.isHeldByCurrentThread()) { - lock.unlock(); - } - } - }*/ - return product; - } -} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/IGoodsService.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/IGoodsService.java new file mode 100644 index 00000000..dfb1a88d --- /dev/null +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/IGoodsService.java @@ -0,0 +1,13 @@ +package com.youlai.mall.pms.serviceapp; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.youlai.mall.pms.pojo.entity.PmsSpu; +import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO; + +/** + * @author xianrui + * @date 2021/8/8 + */ +public interface IGoodsService extends IService { + GoodsDetailVO getGoodsById(Long id); +} diff --git a/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/impl/GoodsServiceImpl.java b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/impl/GoodsServiceImpl.java new file mode 100644 index 00000000..b35b1cd7 --- /dev/null +++ b/mall-pms/pms-boot/src/main/java/com/youlai/mall/pms/serviceapp/impl/GoodsServiceImpl.java @@ -0,0 +1,115 @@ +package com.youlai.mall.pms.serviceapp.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.youlai.mall.pms.common.enums.AttributeTypeEnum; +import com.youlai.mall.pms.mapper.PmsSpuMapper; +import com.youlai.mall.pms.pojo.entity.PmsSku; +import com.youlai.mall.pms.pojo.entity.PmsSpu; +import com.youlai.mall.pms.pojo.entity.PmsSpuAttributeValue; +import com.youlai.mall.pms.pojo.vo.app.GoodsDetailVO; +import com.youlai.mall.pms.service.IPmsSkuService; +import com.youlai.mall.pms.service.IPmsSpuAttributeValueService; +import com.youlai.mall.pms.serviceapp.IGoodsService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author xianrui + * @date 2021/8/8 + */ +@Service +@RequiredArgsConstructor +public class GoodsServiceImpl extends ServiceImpl implements IGoodsService { + + final IPmsSpuAttributeValueService spuAttributeValueService; + final IPmsSkuService skuService; + + @Override + public GoodsDetailVO getGoodsById(Long goodsId) { + + GoodsDetailVO goodsDetailVO = new GoodsDetailVO(); + PmsSpu pmsSpu = this.baseMapper.selectById(goodsId); + Assert.isTrue(pmsSpu != null, "商品不存在"); + // 商品基本信息 + GoodsDetailVO.GoodsInfo goodsInfo = new GoodsDetailVO.GoodsInfo(); + BeanUtil.copyProperties(pmsSpu, goodsInfo, "album"); + + List album = new ArrayList<>(); + + if (StrUtil.isNotBlank(pmsSpu.getPicUrl())) { + album.add(pmsSpu.getPicUrl()); + } + if (StrUtil.isNotBlank(pmsSpu.getAlbum())) { + album.addAll(JSONUtil.parseArray(pmsSpu.getAlbum()).toList(String.class)); + goodsInfo.setAlbum(album); + } + goodsDetailVO.setGoodsInfo(goodsInfo); + + // 商品属性列表 + List attributeList = spuAttributeValueService.list(new LambdaQueryWrapper() + .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.ATTRIBUTE.getValue()) + .eq(PmsSpuAttributeValue::getSpuId, goodsId) + .select(PmsSpuAttributeValue::getId, PmsSpuAttributeValue::getName, PmsSpuAttributeValue::getValue) + ).stream().map(item -> { + GoodsDetailVO.Attribute attribute = new GoodsDetailVO.Attribute(); + BeanUtil.copyProperties(item, attribute); + return attribute; + }).collect(Collectors.toList()); + goodsDetailVO.setAttributeList(attributeList); + + + // 商品规格列表 + List specSourceList = spuAttributeValueService.list(new LambdaQueryWrapper() + .eq(PmsSpuAttributeValue::getType, AttributeTypeEnum.SPECIFICATION.getValue()) + .eq(PmsSpuAttributeValue::getSpuId, goodsId) + .select(PmsSpuAttributeValue::getId, PmsSpuAttributeValue::getName, PmsSpuAttributeValue::getValue) + ); + + List specList = new ArrayList<>(); + // 规格Map [key:"颜色",value:[{id:1,value:"黑"},{id:2,value:"白"}]] + Map> specValueMap = specSourceList.stream() + .collect(Collectors.groupingBy(item -> item.getName())); + + for (Map.Entry> entry : specValueMap.entrySet()) { + String specName = entry.getKey(); + List specValueSourceList = entry.getValue(); + + // 规格映射处理 + GoodsDetailVO.Specification spec = new GoodsDetailVO.Specification(); + spec.setName(specName); + if (CollectionUtil.isNotEmpty(specValueSourceList)) { + List specValueList = specValueSourceList.stream().map(item -> { + GoodsDetailVO.Specification.Value specValue = new GoodsDetailVO.Specification.Value(); + specValue.setId(item.getId()); + specValue.setValue(item.getValue()); + return specValue; + }).collect(Collectors.toList()); + spec.setValues(specValueList); + specList.add(spec); + } + } + goodsDetailVO.setSpecList(specList); + // 商品SKU列表 + List skuSourceList = skuService.list(new LambdaQueryWrapper().eq(PmsSku::getSpuId, goodsId)); + if (CollectionUtil.isNotEmpty(skuSourceList)) { + List skuList = skuSourceList.stream().map(item -> { + GoodsDetailVO.Sku sku = new GoodsDetailVO.Sku(); + BeanUtil.copyProperties(item, sku); + return sku; + }).collect(Collectors.toList()); + goodsDetailVO.setSkuList(skuList); + } + return goodsDetailVO; + } +} diff --git a/mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml b/mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml index 30f58ec4..726b461c 100644 --- a/mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml +++ b/mall-pms/pms-boot/src/main/resources/mapper/PmsSkuMapper.xml @@ -5,23 +5,32 @@ - - - - - - - - - - - + + + + + + + + + + + - id,spu_id,name, + id + ,spu_id,name, sn,pic_url,specs, origin_price,price,stock, locked_stock,gmt_create,gmt_modified + + + diff --git a/mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml b/mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml index ca6a584b..a8c321c3 100644 --- a/mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml +++ b/mall-pms/pms-boot/src/main/resources/mapper/PmsSpuMapper.xml @@ -32,9 +32,16 @@ --> - - - + + + + + + + + + + @@ -46,28 +53,40 @@ status,gmt_create,gmt_modified + + + diff --git a/youlai-common/common-web/src/main/java/com/youlai/common/web/exception/GlobalExceptionHandler.java b/youlai-common/common-web/src/main/java/com/youlai/common/web/exception/GlobalExceptionHandler.java index 93ad4624..dd83139c 100644 --- a/youlai-common/common-web/src/main/java/com/youlai/common/web/exception/GlobalExceptionHandler.java +++ b/youlai-common/common-web/src/main/java/com/youlai/common/web/exception/GlobalExceptionHandler.java @@ -18,7 +18,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(IllegalArgumentException.class) public Result handleIllegalArgumentException(IllegalArgumentException e) { - log.error("非法参数异常,异常原因:{}",e.getMessage(),e); + log.error("业务异常:{}",e.getMessage(),e); return Result.failed(e.getMessage()); } -- GitLab