购物车:调整购物车接口

This commit is contained in:
YunaiV 2023-08-30 19:14:28 +08:00
parent 73f1636daa
commit 059202a588
9 changed files with 34 additions and 95 deletions

View File

@ -42,6 +42,14 @@ public class AppFavoriteController {
return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId())); return success(productFavoriteService.createFavorite(getLoginUserId(), reqVO.getSpuId()));
} }
@PostMapping(value = "/create-list")
@Operation(summary = "添加多个商品收藏")
@PreAuthenticated
public CommonResult<Boolean> createFavoriteList(@RequestBody @Valid AppFavoriteBatchReqVO reqVO) {
// todo @jason待实现如果有已经收藏的不用报错忽略即可
return success(true);
}
@DeleteMapping(value = "/delete") @DeleteMapping(value = "/delete")
@Operation(summary = "取消单个商品收藏") @Operation(summary = "取消单个商品收藏")
@PreAuthenticated @PreAuthenticated

View File

@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.List; import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@ -78,13 +77,6 @@ public class AppCartController {
return success(cartService.getCartCount(getLoginUserId())); return success(cartService.getCartCount(getLoginUserId()));
} }
@GetMapping("get-count-map")
@Operation(summary = "查询用户在购物车中的商品 SPU 数量 Map")
@PreAuthenticated
public CommonResult<Map<Long, Integer>> getCartCountMap() {
return success(cartService.getCartCountMap(getLoginUserId()));
}
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "查询用户的购物车列表") @Operation(summary = "查询用户的购物车列表")
@PreAuthenticated @PreAuthenticated

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO; import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi; import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.*; import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
@ -91,15 +90,11 @@ public class AppTradeOrderController {
// 查询订单项 // 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
// 查询商品属性
List<ProductPropertyValueDetailRespDTO> propertyValueDetails = productPropertyValueApi
.getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems));
// 查询物流公司 // 查询物流公司
DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ? DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ?
deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null; deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null;
// 最终组合 // 最终组合
return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express));
propertyValueDetails, tradeOrderProperties, express));
} }
@GetMapping("/get-express-track-list") @GetMapping("/get-express-track-list")

View File

@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils; import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
@ -82,14 +83,16 @@ public interface TradeOrderConvert {
TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item); TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item);
default ProductSkuUpdateStockReqDTO convert(List<TradeOrderItemDO> list) {
return new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(list));
}
List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
@Mappings({ @Mappings({
@Mapping(source = "skuId", target = "id"), @Mapping(source = "skuId", target = "id"),
@Mapping(source = "count", target = "incrCount"), @Mapping(source = "count", target = "incrCount"),
}) })
ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean); ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean);
List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list);
default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems, default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) { TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) {
PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO()
@ -97,9 +100,7 @@ public interface TradeOrderConvert {
// 商户相关字段 // 商户相关字段
createReqDTO.setMerchantOrderId(String.valueOf(order.getId())); createReqDTO.setMerchantOrderId(String.valueOf(order.getId()));
String subject = calculateRespBO.getItems().get(0).getSpuName(); String subject = calculateRespBO.getItems().get(0).getSpuName();
if (calculateRespBO.getItems().size() > 1) { subject = StrUtils.maxLength(subject, PayOrderCreateReqDTO.SUBJECT_MAX_LENGTH); // 避免超过 32
subject += " 等多件";
}
createReqDTO.setSubject(subject); createReqDTO.setSubject(subject);
createReqDTO.setBody(subject); // TODO 芋艿临时写死 createReqDTO.setBody(subject); // TODO 芋艿临时写死
// 订单相关字段 // 订单相关字段
@ -107,16 +108,6 @@ public interface TradeOrderConvert {
return createReqDTO; return createReqDTO;
} }
default Set<Long> convertPropertyValueIds(List<TradeOrderItemDO> list) {
if (CollUtil.isEmpty(list)) {
return new HashSet<>();
}
return list.stream().filter(item -> item.getProperties() != null)
.flatMap(p -> p.getProperties().stream()) // 遍历多个 Property 属性
.map(TradeOrderItemDO.Property::getValueId) // 将每个 Property 转换成对应的 propertyId最后形成集合
.collect(Collectors.toSet());
}
// TODO 芋艿可简化 // TODO 芋艿可简化
default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult, default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult,
List<TradeOrderItemDO> orderItems, List<TradeOrderItemDO> orderItems,
@ -170,31 +161,13 @@ public interface TradeOrderConvert {
// TODO 芋艿可简化 // TODO 芋艿可简化
default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems, default AppTradeOrderDetailRespVO convert02(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
List<ProductPropertyValueDetailRespDTO> propertyValueDetails, TradeOrderProperties tradeOrderProperties, TradeOrderProperties tradeOrderProperties,
DeliveryExpressDO express) { DeliveryExpressDO express) {
AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems); AppTradeOrderDetailRespVO orderVO = convert3(order, orderItems);
orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime())); orderVO.setPayExpireTime(addTime(tradeOrderProperties.getExpireTime()));
if (StrUtil.isNotEmpty(order.getPayChannelCode())) { if (StrUtil.isNotEmpty(order.getPayChannelCode())) {
orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode())); orderVO.setPayChannelName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.CHANNEL_CODE, order.getPayChannelCode()));
} }
// 处理商品属性
Map<Long, ProductPropertyValueDetailRespDTO> propertyValueDetailMap = convertMap(propertyValueDetails, ProductPropertyValueDetailRespDTO::getValueId);
for (int i = 0; i < orderItems.size(); i++) {
List<TradeOrderItemDO.Property> properties = orderItems.get(i).getProperties();
if (CollUtil.isEmpty(properties)) {
continue;
}
AppTradeOrderItemRespVO item = orderVO.getItems().get(i);
item.setProperties(new ArrayList<>(properties.size()));
// 遍历每个 properties设置到 TradeOrderPageItemRespVO.Item
properties.forEach(property -> {
ProductPropertyValueDetailRespDTO propertyValueDetail = propertyValueDetailMap.get(property.getValueId());
if (propertyValueDetail == null) {
return;
}
item.getProperties().add(convert02(propertyValueDetail));
});
}
// 处理收货地址 // 处理收货地址
orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId())); orderVO.setReceiverAreaName(AreaUtils.format(order.getReceiverAreaId()));
if (express != null) { if (express != null) {

View File

@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.trade.dal.mysql.cart;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -27,25 +26,11 @@ public interface CartMapper extends BaseMapperX<CartDO> {
List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>() List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
.select("SUM(count) AS sumCount") .select("SUM(count) AS sumCount")
.eq("user_id", userId) .eq("user_id", userId)
.eq("add_status", true) // 只计算添加到购物车中的 .eq("selected", true)); // 只计算选中的
.eq("order_status", false)); // 必须未下单
// 获得数量 // 获得数量
return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0; return CollUtil.getFirst(result) != null ? MapUtil.getInt(result.get(0), "sumCount") : 0;
} }
default Map<Long, Integer> selectSumMapByUserId(Long userId) {
// SQL sum 查询
List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
.select("spu_id, SUM(count) AS sumCount")
.eq("user_id", userId)
.eq("add_status", true) // 只计算添加到购物车中的
.eq("order_status", false) // 必须未下单
.groupBy("spu_id"));
// 获得数量
return CollectionUtils.convertMap(result, item -> MapUtil.getLong(item, "spu_id"),
item -> MapUtil.getInt(item, "sumCount"));
}
default CartDO selectById(Long id, Long userId) { default CartDO selectById(Long id, Long userId) {
return selectOne(CartDO::getId, id, return selectOne(CartDO::getId, id,
CartDO::getUserId, userId); CartDO::getUserId, userId);

View File

@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -84,12 +83,4 @@ public interface CartService {
*/ */
List<CartDO> getCartList(Long userId, Set<Long> ids); List<CartDO> getCartList(Long userId, Set<Long> ids);
/**
* 获得用户的购物车商品 SPU 数量的 Map
*
* @param userId 用户编号
* @return 购物车商品 SPU 数量的 Map
*/
Map<Long, Integer> getCartCountMap(Long userId);
} }

View File

@ -50,19 +50,14 @@ public class CartServiceImpl implements CartService {
Integer count = addReqVO.getCount(); Integer count = addReqVO.getCount();
ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count); ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count);
// 情况零特殊count 小于等于 0说明前端项目删除
// 情况一存在则进行数量更新 // 情况一存在则进行数量更新
if (cart != null) { if (cart != null) {
// 特殊情况如果 count 小于等于 0说明前端想要删除 cartMapper.updateById(new CartDO().setId(cart.getId()).setSelected(true)
if (count <= 0) { .setCount(cart.getCount() + count));
cartMapper.deleteById(cart.getId());
} else {
cartMapper.updateById(new CartDO().setId(cart.getId()).setCount(count));
}
return cart.getId(); return cart.getId();
// 情况二不存在则进行插入 // 情况二不存在则进行插入
} else { } else {
cart = new CartDO().setUserId(userId) cart = new CartDO().setUserId(userId).setSelected(true)
.setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count); .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count);
cartMapper.insert(cart); cartMapper.insert(cart);
} }
@ -101,7 +96,6 @@ public class CartServiceImpl implements CartService {
cartMapper.deleteById(oldCart.getId()); cartMapper.deleteById(oldCart.getId());
// 第二步添加新的购物项 // 第二步添加新的购物项
// TODO 芋艿直接改成 addCart 貌似就行
CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId()); CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId());
if (newCart != null) { if (newCart != null) {
updateCartCount(userId, new AppCartUpdateCountReqVO() updateCartCount(userId, new AppCartUpdateCountReqVO()
@ -136,12 +130,6 @@ public class CartServiceImpl implements CartService {
return cartMapper.selectSumByUserId(userId); return cartMapper.selectSumByUserId(userId);
} }
@Override
public Map<Long, Integer> getCartCountMap(Long userId) {
// TODO 芋艿需要算上 selected
return cartMapper.selectSumMapByUserId(userId);
}
@Override @Override
public AppCartListRespVO getCartList(Long userId) { public AppCartListRespVO getCartList(Long userId) {
// 获得购物车的商品 // 获得购物车的商品

View File

@ -26,7 +26,6 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi;
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
@ -70,6 +69,7 @@ import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@ -93,7 +93,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private TradeOrderItemMapper tradeOrderItemMapper; private TradeOrderItemMapper tradeOrderItemMapper;
@Resource @Resource
private CartService tradeCartService; private CartService cartService;
@Resource @Resource
private TradePriceService tradePriceService; private TradePriceService tradePriceService;
@Resource @Resource
@ -168,7 +168,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
*/ */
private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
// 1. 如果来自购物车则获得购物车的商品 // 1. 如果来自购物车则获得购物车的商品
List<CartDO> cartList = tradeCartService.getCartList(userId, List<CartDO> cartList = cartService.getCartList(userId,
convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId)); convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId));
// 2. 计算价格 // 2. 计算价格
@ -190,6 +190,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
// 订单创建完后的逻辑 // 订单创建完后的逻辑
afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO);
// 3.3 校验订单类型 // 3.3 校验订单类型
// TODO @puhui999这个逻辑先抽个小方法未来要通过设计模式把这些拼团之类的逻辑抽象出去
// 拼团 // 拼团
if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
MemberUserRespDTO user = memberUserApi.getUser(userId); MemberUserRespDTO user = memberUserApi.getUser(userId);
@ -292,11 +293,15 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems,
TradePriceCalculateRespBO calculateRespBO) { TradePriceCalculateRespBO calculateRespBO) {
// 下单时扣减商品库存 // 下单时扣减商品库存
productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems))); productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems));
// 删除购物车商品 TODO 芋艿待实现 // 删除购物车商品
Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
if (CollUtil.isNotEmpty(cartIds)) {
cartService.deleteCart(userId, cartIds);
}
// 扣减积分抵扣金额 TODO 芋艿待实现 // 扣减积分 TODO 芋艿待实现
// 有使用优惠券时更新 // 有使用优惠券时更新
if (createReqVO.getCouponId() != null) { if (createReqVO.getCouponId() != null) {

View File

@ -15,6 +15,8 @@ import java.time.LocalDateTime;
@Data @Data
public class PayOrderCreateReqDTO implements Serializable { public class PayOrderCreateReqDTO implements Serializable {
public static final int SUBJECT_MAX_LENGTH = 32;
/** /**
* 应用编号 * 应用编号
*/ */
@ -37,7 +39,7 @@ public class PayOrderCreateReqDTO implements Serializable {
* 商品标题 * 商品标题
*/ */
@NotEmpty(message = "商品标题不能为空") @NotEmpty(message = "商品标题不能为空")
@Length(max = 32, message = "商品标题不能超过 32") @Length(max = SUBJECT_MAX_LENGTH, message = "商品标题不能超过 32")
private String subject; private String subject;
/** /**
* 商品描述 * 商品描述