购物车:简化 cart 表命名

This commit is contained in:
YunaiV 2023-08-30 08:43:07 +08:00
parent cc71aabd3d
commit 5a788af084
18 changed files with 193 additions and 211 deletions

View File

@ -2,11 +2,8 @@ package cn.iocoder.yudao.module.trade.controller.app.cart;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; import cn.iocoder.yudao.module.trade.service.cart.CartService;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
import cn.iocoder.yudao.module.trade.service.cart.TradeCartService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -29,30 +26,38 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
@RequiredArgsConstructor @RequiredArgsConstructor
@Validated @Validated
@Slf4j @Slf4j
public class TradeCartController { public class AppCartController {
@Resource @Resource
private TradeCartService cartService; private CartService cartService;
@PostMapping("/add") @PostMapping("/add")
@Operation(summary = "添加购物车商品") @Operation(summary = "添加购物车商品")
@PreAuthenticated @PreAuthenticated
public CommonResult<Long> addCart(@Valid @RequestBody AppTradeCartAddReqVO addCountReqVO) { public CommonResult<Long> addCart(@Valid @RequestBody AppCartAddReqVO addCountReqVO) {
return success(cartService.addCart(getLoginUserId(), addCountReqVO)); return success(cartService.addCart(getLoginUserId(), addCountReqVO));
} }
@PutMapping("/update") @PutMapping("/update-count")
@Operation(summary = "更新购物车商品") @Operation(summary = "更新购物车商品数量")
@PreAuthenticated @PreAuthenticated
public CommonResult<Boolean> updateCart(@Valid @RequestBody AppTradeCartUpdateReqVO updateReqVO) { public CommonResult<Boolean> updateCartCount(@Valid @RequestBody AppCartUpdateCountReqVO updateReqVO) {
cartService.updateCart(getLoginUserId(), updateReqVO); cartService.updateCartCount(getLoginUserId(), updateReqVO);
return success(true);
}
@PutMapping("/update-selected")
@Operation(summary = "更新购物车商品选中")
@PreAuthenticated
public CommonResult<Boolean> updateCartSelected(@Valid @RequestBody AppCartUpdateSelectedReqVO updateReqVO) {
cartService.updateCartSelected(getLoginUserId(), updateReqVO);
return success(true); return success(true);
} }
@PutMapping("/reset") @PutMapping("/reset")
@Operation(summary = "重置购物车商品") @Operation(summary = "重置购物车商品")
@PreAuthenticated @PreAuthenticated
public CommonResult<Boolean> resetCart(@Valid @RequestBody AppTradeCartResetReqVO updateReqVO) { public CommonResult<Boolean> resetCart(@Valid @RequestBody AppCartResetReqVO updateReqVO) {
cartService.resetCart(getLoginUserId(), updateReqVO); cartService.resetCart(getLoginUserId(), updateReqVO);
return success(true); return success(true);
} }
@ -83,7 +88,7 @@ public class TradeCartController {
@GetMapping("/list") @GetMapping("/list")
@Operation(summary = "查询用户的购物车列表") @Operation(summary = "查询用户的购物车列表")
@PreAuthenticated @PreAuthenticated
public CommonResult<AppTradeCartListRespVO> getCartList() { public CommonResult<AppCartListRespVO> getCartList() {
return success(cartService.getCartList(getLoginUserId())); return success(cartService.getCartList(getLoginUserId()));
} }

View File

@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 购物车添加购物项 Request VO") @Schema(description = "用户 App - 购物车添加购物项 Request VO")
@Data @Data
public class AppTradeCartAddReqVO { public class AppCartAddReqVO {
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024") @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED,example = "1024")
@NotNull(message = "商品 SKU 编号不能为空") @NotNull(message = "商品 SKU 编号不能为空")
@ -17,8 +17,4 @@ public class AppTradeCartAddReqVO {
@NotNull(message = "数量不能为空") @NotNull(message = "数量不能为空")
private Integer count; private Integer count;
@Schema(description = "是否添加到购物车", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否添加购物车不能为空")
private Boolean addStatus;
} }

View File

@ -8,7 +8,7 @@ import java.util.List;
@Schema(description = "用户 App - 用户的购物车明细 Response VO") @Schema(description = "用户 App - 用户的购物车明细 Response VO")
@Data @Data
public class AppTradeCartDetailRespVO { public class AppCartDetailRespVO {
/** /**
* 商品分组数组 * 商品分组数组

View File

@ -9,7 +9,7 @@ import java.util.List;
@Schema(description = "用户 App - 用户的购物列表 Response VO") @Schema(description = "用户 App - 用户的购物列表 Response VO")
@Data @Data
public class AppTradeCartListRespVO { public class AppCartListRespVO {
/** /**
* 有效的购物项数组 * 有效的购物项数组
@ -31,6 +31,9 @@ public class AppTradeCartListRespVO {
@Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "商品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer count; private Integer count;
@Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean selected;
/** /**
* 商品 SPU * 商品 SPU
*/ */

View File

@ -8,7 +8,7 @@ import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 购物车重置 Request VO") @Schema(description = "用户 App - 购物车重置 Request VO")
@Data @Data
public class AppTradeCartResetReqVO { public class AppCartResetReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空") @NotNull(message = "编号不能为空")

View File

@ -6,9 +6,9 @@ import lombok.Data;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - 购物车更新 Request VO") @Schema(description = "用户 App - 购物车更新数量 Request VO")
@Data @Data
public class AppTradeCartUpdateReqVO { public class AppCartUpdateCountReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "编号不能为空") @NotNull(message = "编号不能为空")

View File

@ -8,11 +8,11 @@ import java.util.Collection;
@Schema(description = "用户 App - 购物车更新是否选中 Request VO") @Schema(description = "用户 App - 购物车更新是否选中 Request VO")
@Data @Data
public class AppTradeCartItemUpdateSelectedReqVO { public class AppCartUpdateSelectedReqVO {
@Schema(description = "商品 SKU 编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048") @Schema(description = "编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024,2048")
@NotNull(message = "商品 SKU 编号列表不能为空") @NotNull(message = "编号列表不能为空")
private Collection<Long> skuIds; private Collection<Long> ids;
@Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @Schema(description = "是否选中", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否选中不能为空") @NotNull(message = "是否选中不能为空")

View File

@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.trade.controller.app.base.sku.AppProductSkuBaseRespVO; import cn.iocoder.yudao.module.trade.controller.app.base.sku.AppProductSkuBaseRespVO;
import cn.iocoder.yudao.module.trade.controller.app.base.spu.AppProductSpuBaseRespVO; import cn.iocoder.yudao.module.trade.controller.app.base.spu.AppProductSpuBaseRespVO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppCartListRespVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -21,16 +21,16 @@ public interface TradeCartConvert {
TradeCartConvert INSTANCE = Mappers.getMapper(TradeCartConvert.class); TradeCartConvert INSTANCE = Mappers.getMapper(TradeCartConvert.class);
default AppTradeCartListRespVO convertList(List<TradeCartDO> carts, default AppCartListRespVO convertList(List<CartDO> carts,
List<ProductSpuRespDTO> spus, List<ProductSkuRespDTO> skus) { List<ProductSpuRespDTO> spus, List<ProductSkuRespDTO> skus) {
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spus, ProductSpuRespDTO::getId); Map<Long, ProductSpuRespDTO> spuMap = convertMap(spus, ProductSpuRespDTO::getId);
Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId); Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
// 遍历开始转换 // 遍历开始转换
List<AppTradeCartListRespVO.Cart> validList = new ArrayList<>(carts.size()); List<AppCartListRespVO.Cart> validList = new ArrayList<>(carts.size());
List<AppTradeCartListRespVO.Cart> invalidList = new ArrayList<>(); List<AppCartListRespVO.Cart> invalidList = new ArrayList<>();
carts.forEach(cart -> { carts.forEach(cart -> {
AppTradeCartListRespVO.Cart cartVO = new AppTradeCartListRespVO.Cart(); AppCartListRespVO.Cart cartVO = new AppCartListRespVO.Cart();
cartVO.setId(cart.getId()).setCount(cart.getCount()); cartVO.setId(cart.getId()).setCount(cart.getCount()).setSelected(cart.getSelected());
ProductSpuRespDTO spu = spuMap.get(cart.getSpuId()); ProductSpuRespDTO spu = spuMap.get(cart.getSpuId());
ProductSkuRespDTO sku = skuMap.get(cart.getSkuId()); ProductSkuRespDTO sku = skuMap.get(cart.getSkuId());
cartVO.setSpu(convert(spu)).setSku(convert(sku)); cartVO.setSpu(convert(spu)).setSku(convert(sku));
@ -38,13 +38,14 @@ public interface TradeCartConvert {
if (spu == null if (spu == null
|| !ProductSpuStatusEnum.isEnable(spu.getStatus()) || !ProductSpuStatusEnum.isEnable(spu.getStatus())
|| spu.getStock() <= 0) { || spu.getStock() <= 0) {
cartVO.setSelected(false); // 强制设置成不可选中
invalidList.add(cartVO); invalidList.add(cartVO);
} else { } else {
// 虽然 SKU 可能也会不存在但是可以通过购物车重新选择 // 虽然 SKU 可能也会不存在但是可以通过购物车重新选择
validList.add(cartVO); validList.add(cartVO);
} }
}); });
return new AppTradeCartListRespVO().setValidList(validList).setInvalidList(invalidList); return new AppCartListRespVO().setValidList(validList).setInvalidList(invalidList);
} }
AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu); AppProductSpuBaseRespVO convert(ProductSpuRespDTO spu);
AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku); AppProductSkuBaseRespVO convert(ProductSkuRespDTO sku);

View File

@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductProp
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;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
@ -221,12 +221,12 @@ public interface TradeOrderConvert {
ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO); ProductCommentCreateReqDTO convert04(AppTradeOrderItemCommentCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItemDO);
default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO, default TradePriceCalculateReqBO convert(Long userId, AppTradeOrderSettlementReqVO settlementReqVO,
List<TradeCartDO> cartList) { List<CartDO> cartList) {
TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO(); TradePriceCalculateReqBO reqBO = new TradePriceCalculateReqBO();
reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId()) reqBO.setUserId(userId).setCouponId(settlementReqVO.getCouponId()).setAddressId(settlementReqVO.getAddressId())
.setItems(new ArrayList<>(settlementReqVO.getItems().size())); .setItems(new ArrayList<>(settlementReqVO.getItems().size()));
// 商品项的构建 // 商品项的构建
Map<Long, TradeCartDO> cartMap = convertMap(cartList, TradeCartDO::getId); Map<Long, CartDO> cartMap = convertMap(cartList, CartDO::getId);
for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) { for (AppTradeOrderSettlementReqVO.Item item : settlementReqVO.getItems()) {
// 情况一skuId + count // 情况一skuId + count
if (item.getSkuId() != null) { if (item.getSkuId() != null) {
@ -235,7 +235,7 @@ public interface TradeOrderConvert {
continue; continue;
} }
// 情况二cartId // 情况二cartId
TradeCartDO cart = cartMap.get(item.getCartId()); CartDO cart = cartMap.get(item.getCartId());
if (cart == null) { if (cart == null) {
continue; continue;
} }

View File

@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Accessors(chain = true)
public class TradeCartDO extends BaseDO { public class CartDO extends BaseDO {
// ========= 基础字段 BEGIN ========= // ========= 基础字段 BEGIN =========
@ -33,27 +33,7 @@ public class TradeCartDO extends BaseDO {
*/ */
private Long userId; private Long userId;
/** // ========= 商品信息 =========
* 是否添加到购物车
*
* false - 未添加用户点击立即购买
* true - 已添加用户点击添加购物车
*
* 为什么要设计这个字段
* 配合 orderStatus 字段可以知道有多少商品用户点击了立即购买最终多少确认下单
*/
private Boolean addStatus;
/**
* 是否提交订单
*
* false - 未下单立即购买或者添加到购物车此时设置为 false
* true - 已下单确认下单此时设置为 true
*/
private Boolean orderStatus;
// ========= 基础字段 END =========
// ========= 商品信息 BEGIN =========
/** /**
* 商品 SPU 编号 * 商品 SPU 编号
@ -71,16 +51,9 @@ public class TradeCartDO extends BaseDO {
* 商品购买数量 * 商品购买数量
*/ */
private Integer count; private Integer count;
/**
// ========= 商品信息 END ========= * 是否选中
*/
// ========= 优惠信息 BEGIN ========= private Boolean selected;
// TODO 芋艿combination_id 拼团 ID
// TODO 芋艿seckill_id 秒杀产品 ID
// TODO 芋艿bargain_id 砍价 ID
// TODO 芋艿pinkId 团长拼团 ID
// ========= 优惠信息 END =========
} }

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.dal.dataobject.order;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
@ -46,7 +46,7 @@ public class TradeOrderItemDO extends BaseDO {
/** /**
* 购物车项编号 * 购物车项编号
* *
* 关联 {@link TradeCartDO#getId()} * 关联 {@link CartDO#getId()}
*/ */
private Long cartId; private Long cartId;

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.trade.dal.mysql.cart;
import cn.hutool.core.collection.CollUtil;
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.module.trade.dal.dataobject.cart.CartDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Mapper
public interface CartMapper extends BaseMapperX<CartDO> {
default CartDO selectByUserIdAndSkuId(Long userId, Long skuId) {
return selectOne(CartDO::getUserId, userId,
CartDO::getSkuId, skuId);
}
default Integer selectSumByUserId(Long userId) {
// SQL sum 查询
List<Map<String, Object>> result = selectMaps(new QueryWrapper<CartDO>()
.select("SUM(count) AS sumCount")
.eq("user_id", userId)
.eq("add_status", true) // 只计算添加到购物车中的
.eq("order_status", false)); // 必须未下单
// 获得数量
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) {
return selectOne(CartDO::getId, id,
CartDO::getUserId, userId);
}
default List<CartDO> selectListByIds(Collection<Long> ids, Long userId) {
return selectList(new LambdaQueryWrapper<CartDO>()
.in(CartDO::getId, ids)
.eq(CartDO::getUserId, userId));
}
default List<CartDO> selectListByUserId(Long userId) {
return selectList(new LambdaQueryWrapper<CartDO>()
.eq(CartDO::getUserId, userId));
}
default List<CartDO> selectListByUserId(Long userId, Set<Long> ids) {
return selectList(new LambdaQueryWrapper<CartDO>()
.eq(CartDO::getUserId, userId)
.in(CartDO::getId, ids));
}
default void updateByIds(Collection<Long> ids, Long userId, CartDO updateObj) {
update(updateObj, new LambdaQueryWrapper<CartDO>()
.in(CartDO::getId, ids)
.eq(CartDO::getUserId, userId));
}
}

View File

@ -1,80 +0,0 @@
package cn.iocoder.yudao.module.trade.dal.mysql.cart;
import cn.hutool.core.collection.CollUtil;
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.module.trade.dal.dataobject.cart.TradeCartDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Mapper
public interface TradeCartMapper extends BaseMapperX<TradeCartDO> {
default TradeCartDO selectByUserIdAndSkuId(Long userId, Long skuId,
Boolean addStatus, Boolean orderStatus) {
return selectOne(new LambdaQueryWrapper<TradeCartDO>().eq(TradeCartDO::getUserId, userId)
.eq(TradeCartDO::getSkuId, skuId)
.eq(TradeCartDO::getAddStatus, addStatus)
.eq(TradeCartDO::getOrderStatus, orderStatus));
}
default Integer selectSumByUserId(Long userId) {
// SQL sum 查询
List<Map<String, Object>> result = selectMaps(new QueryWrapper<TradeCartDO>()
.select("SUM(count) AS sumCount")
.eq("user_id", userId)
.eq("add_status", true) // 只计算添加到购物车中的
.eq("order_status", false)); // 必须未下单
// 获得数量
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<TradeCartDO>()
.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 TradeCartDO selectById(Long id, Long userId) {
return selectOne(TradeCartDO::getId, id,
TradeCartDO::getUserId, userId);
}
default List<TradeCartDO> selectListByIds(Collection<Long> ids, Long userId) {
return selectList(new LambdaQueryWrapper<TradeCartDO>()
.in(TradeCartDO::getId, ids)
.eq(TradeCartDO::getUserId, userId));
}
default List<TradeCartDO> selectListByUserId(Long userId, Boolean addStatus, Boolean orderStatus) {
return selectList(new LambdaQueryWrapper<TradeCartDO>()
.eq(TradeCartDO::getUserId, userId)
.eq(TradeCartDO::getAddStatus, addStatus)
.eq(TradeCartDO::getOrderStatus, orderStatus));
}
default void updateByIds(Collection<Long> ids, TradeCartDO updateObject) {
update(updateObject, new LambdaQueryWrapper<TradeCartDO>().in(TradeCartDO::getId, ids));
}
default List<TradeCartDO> selectListByUserId(Long userId, Set<Long> ids) {
return selectList(new LambdaQueryWrapper<TradeCartDO>()
.eq(TradeCartDO::getUserId, userId)
.in(TradeCartDO::getId, ids));
}
}

View File

@ -1,10 +1,7 @@
package cn.iocoder.yudao.module.trade.service.cart; package cn.iocoder.yudao.module.trade.service.cart;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Collection; import java.util.Collection;
@ -17,7 +14,7 @@ import java.util.Set;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
public interface TradeCartService { public interface CartService {
/** /**
* 添加商品到购物车 * 添加商品到购物车
@ -26,7 +23,7 @@ public interface TradeCartService {
* @param addReqVO 添加信息 * @param addReqVO 添加信息
* @return 购物项的编号 * @return 购物项的编号
*/ */
Long addCart(Long userId, @Valid AppTradeCartAddReqVO addReqVO); Long addCart(Long userId, @Valid AppCartAddReqVO addReqVO);
/** /**
* 更新购物车商品数量 * 更新购物车商品数量
@ -34,7 +31,15 @@ public interface TradeCartService {
* @param userId 用户编号 * @param userId 用户编号
* @param updateCountReqVO 更新信息 * @param updateCountReqVO 更新信息
*/ */
void updateCart(Long userId, AppTradeCartUpdateReqVO updateCountReqVO); void updateCartCount(Long userId, AppCartUpdateCountReqVO updateCountReqVO);
/**
* 更新购物车选中状态
*
* @param userId 用户编号
* @param updateSelectedReqVO 更新信息
*/
void updateCartSelected(Long userId, @Valid AppCartUpdateSelectedReqVO updateSelectedReqVO);
/** /**
* 重置购物车商品 * 重置购物车商品
@ -44,7 +49,7 @@ public interface TradeCartService {
* @param userId 用户编号 * @param userId 用户编号
* @param updateReqVO 重置信息 * @param updateReqVO 重置信息
*/ */
void resetCart(Long userId, AppTradeCartResetReqVO updateReqVO); void resetCart(Long userId, AppCartResetReqVO updateReqVO);
/** /**
* 删除购物车商品 * 删除购物车商品
@ -68,7 +73,7 @@ public interface TradeCartService {
* @param userId 用户编号 * @param userId 用户编号
* @return 购物车列表 * @return 购物车列表
*/ */
AppTradeCartListRespVO getCartList(Long userId); AppCartListRespVO getCartList(Long userId);
/** /**
* 查询用户的购物车列表 * 查询用户的购物车列表
@ -77,7 +82,7 @@ public interface TradeCartService {
* @param ids 购物项的编号 * @param ids 购物项的编号
* @return 购物车列表 * @return 购物车列表
*/ */
List<TradeCartDO> getCartList(Long userId, Set<Long> ids); List<CartDO> getCartList(Long userId, Set<Long> ids);
/** /**
* 获得用户的购物车商品 SPU 数量的 Map * 获得用户的购物车商品 SPU 数量的 Map

View File

@ -5,13 +5,10 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartAddReqVO; import cn.iocoder.yudao.module.trade.controller.app.cart.vo.*;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartListRespVO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartResetReqVO;
import cn.iocoder.yudao.module.trade.controller.app.cart.vo.AppTradeCartUpdateReqVO;
import cn.iocoder.yudao.module.trade.convert.cart.TradeCartConvert; import cn.iocoder.yudao.module.trade.convert.cart.TradeCartConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import cn.iocoder.yudao.module.trade.dal.mysql.cart.TradeCartMapper; import cn.iocoder.yudao.module.trade.dal.mysql.cart.CartMapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -29,17 +26,16 @@ import static java.util.Collections.emptyList;
/** /**
* 购物车 Service 实现类 * 购物车 Service 实现类
* *
* // TODO 芋艿秒杀拼团砍价对购物车的影响 * // TODO 芋艿未来优化购物车的价格计算支持营销信息目前不支持的原因前端界面需要前端 pr 支持下
* // TODO 芋艿未来优化购物车的价格计算支持营销信息
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@Service @Service
@Validated @Validated
public class TradeCartServiceImpl implements TradeCartService { public class CartServiceImpl implements CartService {
@Resource @Resource
private TradeCartMapper cartMapper; private CartMapper cartMapper;
@Resource @Resource
private ProductSpuApi productSpuApi; private ProductSpuApi productSpuApi;
@ -47,13 +43,11 @@ public class TradeCartServiceImpl implements TradeCartService {
private ProductSkuApi productSkuApi; private ProductSkuApi productSkuApi;
@Override @Override
public Long addCart(Long userId, AppTradeCartAddReqVO addReqVO) { public Long addCart(Long userId, AppCartAddReqVO addReqVO) {
// 查询 TradeCartDO // 查询 TradeCartDO
TradeCartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId(), CartDO cart = cartMapper.selectByUserIdAndSkuId(userId, addReqVO.getSkuId());
addReqVO.getAddStatus(), false);
// 校验 SKU // 校验 SKU
Integer count = cart != null && addReqVO.getAddStatus() ? Integer count = addReqVO.getCount();
cart.getCount() + addReqVO.getCount() : addReqVO.getCount();
ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count); ProductSkuRespDTO sku = checkProductSku(addReqVO.getSkuId(), count);
// 情况零特殊count 小于等于 0说明前端项目删除 // 情况零特殊count 小于等于 0说明前端项目删除
@ -63,23 +57,22 @@ public class TradeCartServiceImpl implements TradeCartService {
if (count <= 0) { if (count <= 0) {
cartMapper.deleteById(cart.getId()); cartMapper.deleteById(cart.getId());
} else { } else {
cartMapper.updateById(new TradeCartDO().setId(cart.getId()).setCount(count)); cartMapper.updateById(new CartDO().setId(cart.getId()).setCount(count));
} }
return cart.getId(); return cart.getId();
// 情况二不存在则进行插入 // 情况二不存在则进行插入
} else { } else {
cart = new TradeCartDO().setUserId(userId) cart = new CartDO().setUserId(userId)
.setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count) .setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count);
.setAddStatus(addReqVO.getAddStatus()).setOrderStatus(false);
cartMapper.insert(cart); cartMapper.insert(cart);
} }
return cart.getId(); return cart.getId();
} }
@Override @Override
public void updateCart(Long userId, AppTradeCartUpdateReqVO updateReqVO) { public void updateCartCount(Long userId, AppCartUpdateCountReqVO updateReqVO) {
// 校验 TradeCartDO 存在 // 校验 TradeCartDO 存在
TradeCartDO cart = cartMapper.selectById(updateReqVO.getId(), userId); CartDO cart = cartMapper.selectById(updateReqVO.getId(), userId);
if (cart == null) { if (cart == null) {
throw exception(CARD_ITEM_NOT_FOUND); throw exception(CARD_ITEM_NOT_FOUND);
} }
@ -87,29 +80,35 @@ public class TradeCartServiceImpl implements TradeCartService {
checkProductSku(cart.getSkuId(), updateReqVO.getCount()); checkProductSku(cart.getSkuId(), updateReqVO.getCount());
// 更新数量 // 更新数量
cartMapper.updateById(new TradeCartDO().setId(cart.getId()) cartMapper.updateById(new CartDO().setId(cart.getId())
.setCount(updateReqVO.getCount())); .setCount(updateReqVO.getCount()));
} }
@Override
public void updateCartSelected(Long userId, AppCartUpdateSelectedReqVO updateSelectedReqVO) {
cartMapper.updateByIds(updateSelectedReqVO.getIds(), userId,
new CartDO().setSelected(updateSelectedReqVO.getSelected()));
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void resetCart(Long userId, AppTradeCartResetReqVO resetReqVO) { public void resetCart(Long userId, AppCartResetReqVO resetReqVO) {
// 第一步删除原本的购物项 // 第一步删除原本的购物项
TradeCartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId); CartDO oldCart = cartMapper.selectById(resetReqVO.getId(), userId);
if (oldCart == null) { if (oldCart == null) {
throw exception(CARD_ITEM_NOT_FOUND); throw exception(CARD_ITEM_NOT_FOUND);
} }
cartMapper.deleteById(oldCart.getId()); cartMapper.deleteById(oldCart.getId());
// 第二步添加新的购物项 // 第二步添加新的购物项
TradeCartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId(), // TODO 芋艿直接改成 addCart 貌似就行
true, false); CartDO newCart = cartMapper.selectByUserIdAndSkuId(userId, resetReqVO.getSkuId());
if (newCart != null) { if (newCart != null) {
updateCart(userId, new AppTradeCartUpdateReqVO() updateCartCount(userId, new AppCartUpdateCountReqVO()
.setId(newCart.getId()).setCount(resetReqVO.getCount())); .setId(newCart.getId()).setCount(resetReqVO.getCount()));
} else { } else {
addCart(userId, new AppTradeCartAddReqVO().setAddStatus(true) addCart(userId, new AppCartAddReqVO().setSkuId(resetReqVO.getSkuId())
.setSkuId(resetReqVO.getSkuId()).setCount(resetReqVO.getCount())); .setCount(resetReqVO.getCount()));
} }
} }
@ -122,7 +121,7 @@ public class TradeCartServiceImpl implements TradeCartService {
@Override @Override
public void deleteCart(Long userId, Collection<Long> ids) { public void deleteCart(Long userId, Collection<Long> ids) {
// 查询 TradeCartDO 列表 // 查询 TradeCartDO 列表
List<TradeCartDO> carts = cartMapper.selectListByIds(ids, userId); List<CartDO> carts = cartMapper.selectListByIds(ids, userId);
if (CollUtil.isEmpty(carts)) { if (CollUtil.isEmpty(carts)) {
return; return;
} }
@ -133,30 +132,33 @@ public class TradeCartServiceImpl implements TradeCartService {
@Override @Override
public Integer getCartCount(Long userId) { public Integer getCartCount(Long userId) {
// TODO 芋艿需要算上 selected
return cartMapper.selectSumByUserId(userId); return cartMapper.selectSumByUserId(userId);
} }
@Override @Override
public Map<Long, Integer> getCartCountMap(Long userId) { public Map<Long, Integer> getCartCountMap(Long userId) {
// TODO 芋艿需要算上 selected
return cartMapper.selectSumMapByUserId(userId); return cartMapper.selectSumMapByUserId(userId);
} }
@Override @Override
public AppTradeCartListRespVO getCartList(Long userId) { public AppCartListRespVO getCartList(Long userId) {
// 获得购物车的商品只查询未下单的 // 获得购物车的商品
List<TradeCartDO> carts = cartMapper.selectListByUserId(userId, true, false); List<CartDO> carts = cartMapper.selectListByUserId(userId);
carts.sort(Comparator.comparing(TradeCartDO::getId).reversed()); carts.sort(Comparator.comparing(CartDO::getId).reversed());
// 如果未空则返回空结果 // 如果未空则返回空结果
if (CollUtil.isEmpty(carts)) { if (CollUtil.isEmpty(carts)) {
return new AppTradeCartListRespVO().setValidList(emptyList()) return new AppCartListRespVO().setValidList(emptyList())
.setInvalidList(emptyList()); .setInvalidList(emptyList());
} }
// 查询 SPUSKU 列表 // 查询 SPUSKU 列表
List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(convertSet(carts, TradeCartDO::getSpuId)); List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(convertSet(carts, CartDO::getSpuId));
List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(carts, TradeCartDO::getSkuId)); List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(carts, CartDO::getSkuId));
// 如果 SPU 被删除则删除购物车对应的商品延迟删除 // 如果 SPU 被删除则删除购物车对应的商品延迟删除
// 为什么不是 SKU 被删除呢因为 SKU 被删除时还可以通过 SPU 选择其它 SKU
deleteCartIfSpuDeleted(carts, spus); deleteCartIfSpuDeleted(carts, spus);
// 拼接数据 // 拼接数据
@ -164,14 +166,14 @@ public class TradeCartServiceImpl implements TradeCartService {
} }
@Override @Override
public List<TradeCartDO> getCartList(Long userId, Set<Long> ids) { public List<CartDO> getCartList(Long userId, Set<Long> ids) {
if (CollUtil.isEmpty(ids)) { if (CollUtil.isEmpty(ids)) {
return Collections.emptyList(); return Collections.emptyList();
} }
return cartMapper.selectListByUserId(userId, ids); return cartMapper.selectListByUserId(userId, ids);
} }
private void deleteCartIfSpuDeleted(List<TradeCartDO> carts, List<ProductSpuRespDTO> spus) { private void deleteCartIfSpuDeleted(List<CartDO> carts, List<ProductSpuRespDTO> spus) {
// 如果 SPU 被删除则删除购物车对应的商品延迟删除 // 如果 SPU 被删除则删除购物车对应的商品延迟删除
carts.removeIf(cart -> { carts.removeIf(cart -> {
if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) { if (spus.stream().noneMatch(spu -> spu.getId().equals(cart.getSpuId()))) {

View File

@ -43,7 +43,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO;
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.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; import cn.iocoder.yudao.module.trade.dal.dataobject.cart.CartDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
@ -53,7 +53,7 @@ import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.*; import cn.iocoder.yudao.module.trade.enums.order.*;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; import cn.iocoder.yudao.module.trade.service.cart.CartService;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; import cn.iocoder.yudao.module.trade.service.message.TradeMessageService;
import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
@ -93,7 +93,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
private TradeOrderItemMapper tradeOrderItemMapper; private TradeOrderItemMapper tradeOrderItemMapper;
@Resource @Resource
private TradeCartService tradeCartService; private CartService tradeCartService;
@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<TradeCartDO> cartList = tradeCartService.getCartList(userId, List<CartDO> cartList = tradeCartService.getCartList(userId,
convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId)); convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId));
// 2. 计算价格 // 2. 计算价格

View File

@ -168,7 +168,7 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override @Override
public boolean isPasswordMatch(String rawPassword, String encodedPassword) { public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
if (true) { if(true) {
return true; return true;
} }
return passwordEncoder.matches(rawPassword, encodedPassword); return passwordEncoder.matches(rawPassword, encodedPassword);