Commit 059202a58897d704feb095d3861815ade3323ad0

Authored by YunaiV
1 parent 73f1636d

购物车:调整购物车接口

yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/AppFavoriteController.java
... ... @@ -42,6 +42,14 @@ public class AppFavoriteController {
42 42 return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId()));
43 43 }
44 44  
  45 + @PostMapping(value = "/create-list")
  46 + @Operation(summary = "添加多个商品收藏")
  47 + @PreAuthenticated
  48 + public CommonResult<Boolean> createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) {
  49 + // todo @jason:待实现;如果有已经收藏的,不用报错,忽略即可;
  50 + return success(true);
  51 + }
  52 +
45 53 @DeleteMapping(value = "/delete")
46 54 @Operation(summary = "取消单个商品收藏")
47 55 @PreAuthenticated
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/cart/AppCartController.java
... ... @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
15 15 import javax.annotation.Resource;
16 16 import javax.validation.Valid;
17 17 import java.util.List;
18   -import java.util.Map;
19 18  
20 19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 20 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
... ... @@ -78,13 +77,6 @@ public class AppCartController {
78 77 return success(cartService.getCartCount(getLoginUserId()));
79 78 }
80 79  
81   - @GetMapping("get-count-map")
82   - @Operation(summary = "查询用户在购物车中的商品 SPU 数量 Map")
83   - @PreAuthenticated
84   - public CommonResult<Map<Long, Integer>> getCartCountMap() {
85   - return success(cartService.getCartCountMap(getLoginUserId()));
86   - }
87   -
88 80 @GetMapping("/list")
89 81 @Operation(summary = "查询用户的购物车列表")
90 82 @PreAuthenticated
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
... ... @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
6 6 import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
7 7 import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
8   -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
9 8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
10 9 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
11 10 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
... ... @@ -91,15 +90,11 @@ public class AppTradeOrderController {
91 90  
92 91 // 查询订单项
93 92 List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
94   - // 查询商品属性
95   - List<ProductPropertyValueDetailRespDTO> propertyValueDetails = productPropertyValueApi
96   - .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems));
97 93 // 查询物流公司
98 94 DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ?
99 95 deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null;
100 96 // 最终组合
101   - return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems,
102   - propertyValueDetails, tradeOrderProperties, express));
  97 + return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express));
103 98 }
104 99  
105 100 @GetMapping("/get-express-track-list")
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
... ... @@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  7 +import cn.iocoder.yudao.framework.common.util.string.StrUtils;
7 8 import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
8 9 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
9 10 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
... ... @@ -82,14 +83,16 @@ public interface TradeOrderConvert {
82 83  
83 84 TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item);
84 85  
  86 + default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
  87 + return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list));
  88 + }
  89 + List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
85 90 @Mappings({
86 91 @Mapping(source = "skuId", target = "id"),
87 92 @Mapping(source = "count", target = "incrCount"),
88 93 })
89 94 ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean);
90 95  
91   - List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
92   -
93 96 default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
94 97 TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) {
95 98 PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO()
... ... @@ -97,9 +100,7 @@ public interface TradeOrderConvert {
97 100 // 商户相关字段
98 101 createReqDTO.setMerchantOrderId(String.valueOf(order.getId()));
99 102 String subject = calculateRespBO.getItems().get(0).getSpuName();
100   - if (calculateRespBO.getItems().size() > 1) {
101   - subject += " 等多件";
102   - }
  103 + subject = StrUtils.maxLength(subject, PayOrderCreateReqDTO.SUBJECT_MAX_LENGTH); // 避免超过 32 位
103 104 createReqDTO.setSubject(subject);
104 105 createReqDTO.setBody(subject); // TODO 芋艿:临时写死
105 106 // 订单相关字段
... ... @@ -107,16 +108,6 @@ public interface TradeOrderConvert {
107 108 return createReqDTO;
108 109 }
109 110  
110   - default Set<Long> convertPropertyValueIds(List<TradeOrderItemDO> list) {
111   - if (CollUtil.isEmpty(list)) {
112   - return new HashSet<>();
113   - }
114   - return list.stream().filter(item -> item.getProperties() != null)
115   - .flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
116   - .map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId,最后形成集合
117   - .collect(Collectors.toSet());
118   - }
119   -
120 111 // TODO 芋艿:可简化
121 112 default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult,
122 113 List<TradeOrderItemDO> orderItems,
... ... @@ -170,31 +161,13 @@ public interface TradeOrderConvert {
170 161  
171 162 // TODO 芋艿:可简化
172 163 default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
173   - List<ProductPropertyValueDetailRespDTO> propertyValueDetails, TradeOrderProperties tradeOrderProperties,
  164 + TradeOrderProperties tradeOrderProperties,
174 165 DeliveryExpressDO express) {
175 166 AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
176 167 orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime()));
177 168 if (StrUtil.isNotEmpty(order.getPayChannelCode())) {
178 169 orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode()));
179 170 }
180   - // 处理商品属性
181   - Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
182   - for (int i = 0; i < orderItems.size(); i++) {
183   - List<TradeOrderItemDO.Property> properties = orderItems.get(i).getProperties();
184   - if (CollUtil.isEmpty(properties)) {
185   - continue;
186   - }
187   - AppTradeOrderItemRespVO item = orderVO.getItems().get(i);
188   - item.setProperties(new ArrayList<>(properties.size()));
189   - // 遍历每个 properties,设置到 TradeOrderPageItemRespVO.Item 中
190   - properties.forEach(property -> {
191   - ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId());
192   - if (propertyValueDetail == null) {
193   - return;
194   - }
195   - item.getProperties().add(convert02(propertyValueDetail));
196   - });
197   - }
198 171 // 处理收货地址
199 172 orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId()));
200 173 if (express != null) {
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/cart/CartMapper.java
... ... @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.dal.mysql.cart;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.map.MapUtil;
5   -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
6 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
7 6 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
8 7 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
... ... @@ -27,25 +26,11 @@ public interface CartMapper extends BaseMapperX&lt;CartDO&gt; {
27 26 List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
28 27 .select("SUM(count) AS sumCount")
29 28 .eq("user_id", userId)
30   - .eq("add_status", true) // 只计算添加到购物车中的
31   - .eq("order_status", false)); // 必须未下单
  29 + .eq("selected", true)); // 只计算选中的
32 30 // 获得数量
33 31 return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0;
34 32 }
35 33  
36   - default Map<Long, Integer> selectSumMapByUserId(Long userId) {
37   - // SQL sum 查询
38   - List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
39   - .select("spu_id, SUM(count) AS sumCount")
40   - .eq("user_id", userId)
41   - .eq("add_status", true) // 只计算添加到购物车中的
42   - .eq("order_status", false) // 必须未下单
43   - .groupBy("spu_id"));
44   - // 获得数量
45   - return CollectionUtils.convertMap(result, item -> MapUtil.getLong(item, "spu_id"),
46   - item -> MapUtil.getInt(item, "sumCount"));
47   - }
48   -
49 34 default CartDO selectById(Long id, Long userId) {
50 35 return selectOne(CartDO::getId, id,
51 36 CartDO::getUserId, userId);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartService.java
... ... @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
6 6 import javax.validation.Valid;
7 7 import java.util.Collection;
8 8 import java.util.List;
9   -import java.util.Map;
10 9 import java.util.Set;
11 10  
12 11 /**
... ... @@ -84,12 +83,4 @@ public interface CartService {
84 83 */
85 84 List<CartDO> getCartList(Long userId, Set<Long> ids);
86 85  
87   - /**
88   - * 获得用户的购物车商品 SPU 数量的 Map
89   - *
90   - * @param userId 用户编号
91   - * @return 购物车商品 SPU 数量的 Map
92   - */
93   - Map<Long, Integer> getCartCountMap(Long userId);
94   -
95 86 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/cart/CartServiceImpl.java
... ... @@ -50,19 +50,14 @@ public class CartServiceImpl implements CartService {
50 50 Integer count = addReqVO.getCount();
51 51 ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count);
52 52  
53   - // 情况零:特殊,count 小于等于 0,说明前端项目删除
54 53 // 情况一:存在,则进行数量更新
55 54 if (cart != null) {
56   - // 特殊情况,如果 count 小于等于 0,说明前端想要删除
57   - if (count <= 0) {
58   - cartMapper.deleteById(cart.getId());
59   - } else {
60   - cartMapper.updateById(new CartDO().setId(cart.getId()).setCount(count));
61   - }
  55 + cartMapper.updateById(new CartDO().setId(cart.getId()).setSelected(true)
  56 + .setCount(cart.getCount() + count));
62 57 return cart.getId();
63 58 // 情况二:不存在,则进行插入
64 59 } else {
65   - cart = new CartDO().setUserId(userId)
  60 + cart = new CartDO().setUserId(userId).setSelected(true)
66 61 .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count);
67 62 cartMapper.insert(cart);
68 63 }
... ... @@ -101,7 +96,6 @@ public class CartServiceImpl implements CartService {
101 96 cartMapper.deleteById(oldCart.getId());
102 97  
103 98 // 第二步:添加新的购物项
104   - // TODO 芋艿:直接改成 addCart 貌似就行
105 99 CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId());
106 100 if (newCart != null) {
107 101 updateCartCount(userId, new AppCartUpdateCountReqVO()
... ... @@ -137,12 +131,6 @@ public class CartServiceImpl implements CartService {
137 131 }
138 132  
139 133 @Override
140   - public Map<Long, Integer> getCartCountMap(Long userId) {
141   - // TODO 芋艿:需要算上 selected
142   - return cartMapper.selectSumMapByUserId(userId);
143   - }
144   -
145   - @Override
146 134 public AppCartListRespVO getCartList(Long userId) {
147 135 // 获得购物车的商品
148 136 List<CartDO> carts = cartMapper.selectListByUserId(userId);
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
... ... @@ -26,7 +26,6 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
26 26 import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
27 27 import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
28 28 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
29   -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
30 29 import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
31 30 import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
32 31 import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
... ... @@ -70,6 +69,7 @@ import javax.annotation.Resource;
70 69 import java.time.LocalDateTime;
71 70 import java.util.List;
72 71 import java.util.Objects;
  72 +import java.util.Set;
73 73  
74 74 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
75 75 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
... ... @@ -93,7 +93,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
93 93 private TradeOrderItemMapper tradeOrderItemMapper;
94 94  
95 95 @Resource
96   - private CartService tradeCartService;
  96 + private CartService cartService;
97 97 @Resource
98 98 private TradePriceService tradePriceService;
99 99 @Resource
... ... @@ -168,7 +168,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
168 168 */
169 169 private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
170 170 // 1. 如果来自购物车,则获得购物车的商品
171   - List<CartDO> cartList = tradeCartService.getCartList(userId,
  171 + List<CartDO> cartList = cartService.getCartList(userId,
172 172 convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId));
173 173  
174 174 // 2. 计算价格
... ... @@ -190,6 +190,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
190 190 // 订单创建完后的逻辑
191 191 afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
192 192 // 3.3 校验订单类型
  193 + // TODO @puhui999:这个逻辑,先抽个小方法;未来要通过设计模式,把这些拼团之类的逻辑,抽象出去
193 194 // 拼团
194 195 if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
195 196 MemberUserRespDTO user = memberUserApi.getUser(userId);
... ... @@ -292,11 +293,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
292 293 TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
293 294 TradePriceCalculateRespBO calculateRespBO) {
294 295 // 下单时扣减商品库存
295   - productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems)));
  296 + productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
296 297  
297   - // 删除购物车商品 TODO 芋艿:待实现
  298 + // 删除购物车商品
  299 + Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
  300 + if (CollUtil.isNotEmpty(cartIds)) {
  301 + cartService.deleteCart(userId, cartIds);
  302 + }
298 303  
299   - // 扣减积分,抵扣金额 TODO 芋艿:待实现
  304 + // 扣减积分 TODO 芋艿:待实现
300 305  
301 306 // 有使用优惠券时更新
302 307 if (createReqVO.getCouponId() != null) {
... ...
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java
... ... @@ -15,6 +15,8 @@ import java.time.LocalDateTime;
15 15 @Data
16 16 public class PayOrderCreateReqDTO implements Serializable {
17 17  
  18 + public static final int SUBJECT_MAX_LENGTH = 32;
  19 +
18 20 /**
19 21 * 应用编号
20 22 */
... ... @@ -37,7 +39,7 @@ public class PayOrderCreateReqDTO implements Serializable {
37 39 * 商品标题
38 40 */
39 41 @NotEmpty(message = "商品标题不能为空")
40   - @Length(max = 32, message = "商品标题不能超过 32")
  42 + @Length(max = SUBJECT_MAX_LENGTH, message = "商品标题不能超过 32")
41 43 private String subject;
42 44 /**
43 45 * 商品描述
... ...