购物车相关代码
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
package com.aida.buyer.module.cart.controller;
|
||||||
|
|
||||||
|
import com.aida.buyer.common.context.UserContext;
|
||||||
|
import com.aida.buyer.module.cart.dto.AddCartRequest;
|
||||||
|
import com.aida.buyer.module.cart.dto.CartItemDTO;
|
||||||
|
import com.aida.buyer.module.cart.service.ICartService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/buyer/cart")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Tag(name = "Shopping Cart", description = "Buyer shopping cart management")
|
||||||
|
public class CartController {
|
||||||
|
|
||||||
|
private final ICartService cartService;
|
||||||
|
|
||||||
|
@Operation(summary = "加购", description = "支持单个 listingId 或批量 listingIds")
|
||||||
|
@PostMapping("/add")
|
||||||
|
public void addItem(@Valid @RequestBody AddCartRequest request) {
|
||||||
|
Long buyerId = UserContext.getBuyerId();
|
||||||
|
cartService.addItem(buyerId, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "移除单个商品")
|
||||||
|
@DeleteMapping("/remove")
|
||||||
|
public void removeItem(
|
||||||
|
@Parameter(description = "商品ID") @RequestParam Long listingId) {
|
||||||
|
Long buyerId = UserContext.getBuyerId();
|
||||||
|
cartService.removeItem(buyerId, listingId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "清空购物车")
|
||||||
|
@DeleteMapping("/clear")
|
||||||
|
public void clearCart() {
|
||||||
|
Long buyerId = UserContext.getBuyerId();
|
||||||
|
cartService.clearCart(buyerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询购物车列表", description = "返回含商品详情的购物车项列表")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public List<CartItemDTO> getCartItems() {
|
||||||
|
Long buyerId = UserContext.getBuyerId();
|
||||||
|
return cartService.getCartItems(buyerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.aida.buyer.module.cart.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "加购请求")
|
||||||
|
public class AddCartRequest implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "商品ID(单个加购)")
|
||||||
|
private Long listingId;
|
||||||
|
|
||||||
|
@Schema(description = "商品ID列表(批量加购)")
|
||||||
|
private List<Long> listingIds;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.aida.buyer.module.cart.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "购物车项(含商品详情)")
|
||||||
|
public class CartItemDTO implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "购物车记录ID")
|
||||||
|
private Long cartId;
|
||||||
|
|
||||||
|
@Schema(description = "商品ID")
|
||||||
|
private Long listingId;
|
||||||
|
|
||||||
|
@Schema(description = "商品标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description = "商品封面图")
|
||||||
|
private String cover;
|
||||||
|
|
||||||
|
@Schema(description = "商品价格")
|
||||||
|
private BigDecimal price;
|
||||||
|
|
||||||
|
@Schema(description = "商品状态")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@Schema(description = "加入购物车时间")
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.aida.buyer.module.cart.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "buyer_cart", autoResultMap = true)
|
||||||
|
public class CartEntity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Long buyerId;
|
||||||
|
|
||||||
|
private Long listingId;
|
||||||
|
|
||||||
|
private LocalDateTime addTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.aida.buyer.module.cart.mapper;
|
||||||
|
|
||||||
|
import com.aida.buyer.module.cart.entity.CartEntity;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CartMapper extends BaseMapper<CartEntity> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.aida.buyer.module.cart.service;
|
||||||
|
|
||||||
|
import com.aida.buyer.module.cart.dto.AddCartRequest;
|
||||||
|
import com.aida.buyer.module.cart.dto.CartItemDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ICartService {
|
||||||
|
|
||||||
|
void addItem(Long buyerId, AddCartRequest request);
|
||||||
|
|
||||||
|
void removeItem(Long buyerId, Long listingId);
|
||||||
|
|
||||||
|
void clearCart(Long buyerId);
|
||||||
|
|
||||||
|
List<CartItemDTO> getCartItems(Long buyerId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package com.aida.buyer.module.cart.service.impl;
|
||||||
|
|
||||||
|
import com.aida.buyer.common.result.Response;
|
||||||
|
import com.aida.buyer.module.cart.dto.AddCartRequest;
|
||||||
|
import com.aida.buyer.module.cart.dto.CartItemDTO;
|
||||||
|
import com.aida.buyer.module.cart.entity.CartEntity;
|
||||||
|
import com.aida.buyer.module.cart.mapper.CartMapper;
|
||||||
|
import com.aida.buyer.module.cart.service.ICartService;
|
||||||
|
import com.aida.buyer.module.listing.feign.ListingFeignClient;
|
||||||
|
import com.aida.buyer.module.listing.vo.ListingMallVO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CartServiceImpl implements ICartService {
|
||||||
|
|
||||||
|
private final CartMapper cartMapper;
|
||||||
|
private final ListingFeignClient listingFeignClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addItem(Long buyerId, AddCartRequest request) {
|
||||||
|
List<Long> listingIds = resolveListingIds(request);
|
||||||
|
if (CollectionUtils.isEmpty(listingIds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Long listingId : listingIds) {
|
||||||
|
CartEntity existing = cartMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<CartEntity>()
|
||||||
|
.eq(CartEntity::getBuyerId, buyerId)
|
||||||
|
.eq(CartEntity::getListingId, listingId));
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
existing.setAddTime(LocalDateTime.now());
|
||||||
|
cartMapper.updateById(existing);
|
||||||
|
} else {
|
||||||
|
CartEntity entity = new CartEntity();
|
||||||
|
entity.setBuyerId(buyerId);
|
||||||
|
entity.setListingId(listingId);
|
||||||
|
entity.setAddTime(LocalDateTime.now());
|
||||||
|
cartMapper.insert(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeItem(Long buyerId, Long listingId) {
|
||||||
|
cartMapper.delete(new LambdaQueryWrapper<CartEntity>()
|
||||||
|
.eq(CartEntity::getBuyerId, buyerId)
|
||||||
|
.eq(CartEntity::getListingId, listingId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearCart(Long buyerId) {
|
||||||
|
cartMapper.delete(new LambdaQueryWrapper<CartEntity>()
|
||||||
|
.eq(CartEntity::getBuyerId, buyerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CartItemDTO> getCartItems(Long buyerId) {
|
||||||
|
List<CartEntity> cartItems = cartMapper.selectList(
|
||||||
|
new LambdaQueryWrapper<CartEntity>()
|
||||||
|
.eq(CartEntity::getBuyerId, buyerId)
|
||||||
|
.orderByDesc(CartEntity::getAddTime));
|
||||||
|
if (CollectionUtils.isEmpty(cartItems)) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Long> listingIds = cartItems.stream()
|
||||||
|
.map(CartEntity::getListingId)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
Response<List<ListingMallVO>> response = listingFeignClient.getListingSummaries(listingIds);
|
||||||
|
List<ListingMallVO> listings = response != null && response.getData() != null
|
||||||
|
? response.getData()
|
||||||
|
: List.of();
|
||||||
|
|
||||||
|
Map<Long, ListingMallVO> listingMap = listings.stream()
|
||||||
|
.collect(Collectors.toMap(ListingMallVO::getId, Function.identity()));
|
||||||
|
|
||||||
|
return cartItems.stream()
|
||||||
|
.filter(item -> listingMap.containsKey(item.getListingId()))
|
||||||
|
.map(item -> {
|
||||||
|
ListingMallVO listing = listingMap.get(item.getListingId());
|
||||||
|
CartItemDTO dto = new CartItemDTO();
|
||||||
|
dto.setCartId(item.getId());
|
||||||
|
dto.setListingId(item.getListingId());
|
||||||
|
dto.setTitle(listing.getTitle());
|
||||||
|
dto.setCover(listing.getCover());
|
||||||
|
dto.setPrice(listing.getPrice());
|
||||||
|
dto.setStatus(listing.getStatus());
|
||||||
|
dto.setAddTime(item.getAddTime());
|
||||||
|
return dto;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Long> resolveListingIds(AddCartRequest request) {
|
||||||
|
List<Long> ids = new ArrayList<>();
|
||||||
|
if (request.getListingId() != null) {
|
||||||
|
ids.add(request.getListingId());
|
||||||
|
}
|
||||||
|
if (!CollectionUtils.isEmpty(request.getListingIds())) {
|
||||||
|
ids.addAll(request.getListingIds());
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,8 +9,11 @@ import com.aida.buyer.module.listing.vo.ListingPageVO;
|
|||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品服务 Feign Client
|
* 商品服务 Feign Client
|
||||||
*/
|
*/
|
||||||
@@ -29,4 +32,7 @@ public interface ListingFeignClient {
|
|||||||
@RequestParam String designFor,
|
@RequestParam String designFor,
|
||||||
@RequestParam(defaultValue = "1") int pageNum,
|
@RequestParam(defaultValue = "1") int pageNum,
|
||||||
@RequestParam(defaultValue = "10") int pageSize);
|
@RequestParam(defaultValue = "10") int pageSize);
|
||||||
|
|
||||||
|
@PostMapping("/mall/batch")
|
||||||
|
Response<List<ListingMallVO>> getListingSummaries(@RequestBody List<Long> listingIds);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,4 +22,6 @@ public class ListingMallVO implements Serializable {
|
|||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
private BigDecimal price;
|
private BigDecimal price;
|
||||||
|
|
||||||
|
private Integer status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import com.aida.buyer.common.result.PageResponse;
|
|||||||
import com.aida.buyer.common.result.Response;
|
import com.aida.buyer.common.result.Response;
|
||||||
import com.aida.buyer.module.account.entity.BuyerAccount;
|
import com.aida.buyer.module.account.entity.BuyerAccount;
|
||||||
import com.aida.buyer.module.account.mapper.BuyerAccountMapper;
|
import com.aida.buyer.module.account.mapper.BuyerAccountMapper;
|
||||||
|
import com.aida.buyer.module.cart.entity.CartEntity;
|
||||||
|
import com.aida.buyer.module.cart.mapper.CartMapper;
|
||||||
import com.aida.buyer.module.order.dto.AssetsDTO;
|
import com.aida.buyer.module.order.dto.AssetsDTO;
|
||||||
import com.aida.buyer.module.order.dto.BuyerOrdersDTO;
|
import com.aida.buyer.module.order.dto.BuyerOrdersDTO;
|
||||||
import com.aida.buyer.module.order.dto.CreateOrderDTO;
|
import com.aida.buyer.module.order.dto.CreateOrderDTO;
|
||||||
@@ -14,6 +16,7 @@ import com.aida.buyer.module.order.service.IBuyerOrderService;
|
|||||||
import com.aida.buyer.module.order.vo.AssetsVO;
|
import com.aida.buyer.module.order.vo.AssetsVO;
|
||||||
import com.aida.buyer.module.order.vo.BuyerOrderVO;
|
import com.aida.buyer.module.order.vo.BuyerOrderVO;
|
||||||
import com.aida.buyer.module.order.vo.CreateOrderResultVO;
|
import com.aida.buyer.module.order.vo.CreateOrderResultVO;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -25,6 +28,7 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
|
|||||||
|
|
||||||
private final OrderFeignClient orderFeignClient;
|
private final OrderFeignClient orderFeignClient;
|
||||||
private final BuyerAccountMapper buyerAccountMapper;
|
private final BuyerAccountMapper buyerAccountMapper;
|
||||||
|
private final CartMapper cartMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response<PageResponse<BuyerOrderVO>> getMyOrders(BuyerOrdersDTO dto) {
|
public Response<PageResponse<BuyerOrderVO>> getMyOrders(BuyerOrdersDTO dto) {
|
||||||
@@ -48,6 +52,13 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
|
|||||||
|
|
||||||
CreateOrderResultVO result = orderResp.getData();
|
CreateOrderResultVO result = orderResp.getData();
|
||||||
// TODO:调用支付模块,传入buyerId,result.getOrderIds(),result.getTotalAmount()
|
// TODO:调用支付模块,传入buyerId,result.getOrderIds(),result.getTotalAmount()
|
||||||
|
|
||||||
|
if (listingIds != null && !listingIds.isEmpty()) {
|
||||||
|
cartMapper.delete(new LambdaQueryWrapper<CartEntity>()
|
||||||
|
.eq(CartEntity::getBuyerId, buyerId)
|
||||||
|
.in(CartEntity::getListingId, listingIds));
|
||||||
|
}
|
||||||
|
|
||||||
return Response.success();
|
return Response.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,4 +18,7 @@ public class CreateOrderResultVO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "所有订单总金额(HK$)")
|
@Schema(description = "所有订单总金额(HK$)")
|
||||||
private BigDecimal totalAmount;
|
private BigDecimal totalAmount;
|
||||||
|
|
||||||
|
@Schema(description = "本次成功下单的未购买商品ID列表")
|
||||||
|
private List<Long> unpurchasedListingIds;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,3 +24,15 @@ CREATE TABLE IF NOT EXISTS `buyer_account` (
|
|||||||
UNIQUE KEY `uk_username` (`username`),
|
UNIQUE KEY `uk_username` (`username`),
|
||||||
INDEX `idx_deleted` (`deleted`)
|
INDEX `idx_deleted` (`deleted`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='买家账号表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='买家账号表';
|
||||||
|
|
||||||
|
-- 创建 buyer_cart 表
|
||||||
|
CREATE TABLE IF NOT EXISTS `buyer_cart` (
|
||||||
|
`id` BIGINT NOT NULL COMMENT '主键ID' PRIMARY KEY,
|
||||||
|
`buyer_id` BIGINT NOT NULL COMMENT '买家ID',
|
||||||
|
`listing_id` BIGINT NOT NULL COMMENT '商品ID',
|
||||||
|
`add_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '加入购物车时间',
|
||||||
|
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
UNIQUE KEY `uk_buyer_listing` (`buyer_id`, `listing_id`),
|
||||||
|
INDEX `idx_buyer_id` (`buyer_id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='购物车表';
|
||||||
|
|||||||
Reference in New Issue
Block a user