|
|
|
@ -40,136 +40,195 @@ import java.util.Objects;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 购物车相关接口的控制器类
|
|
|
|
|
* 该类提供了多个与购物车操作相关的接口,包括获取购物车信息、删除购物车物品、清空购物车、添加/修改购物车物品、获取购物车商品数量、获取购物车失效商品信息、
|
|
|
|
|
* 清空失效商品以及获取选中购物项总计和商品数量等功能,通过调用不同的服务层方法来实现相应的业务逻辑,并借助`Swagger`注解对接口进行文档化描述,方便接口的查看与使用。
|
|
|
|
|
*
|
|
|
|
|
* @author lanhai
|
|
|
|
|
*/
|
|
|
|
|
@RestController
|
|
|
|
|
@RequestMapping("/p/shopCart")
|
|
|
|
|
@Tag(name = "购物车接口")
|
|
|
|
|
// 使用 @AllArgsConstructor 注解,由 lombok 自动生成包含所有成员变量的构造函数,用于依赖注入
|
|
|
|
|
@AllArgsConstructor
|
|
|
|
|
public class ShopCartController {
|
|
|
|
|
|
|
|
|
|
// 用于处理购物车相关业务逻辑的服务层对象,比如更新购物车、获取购物车商品项等操作
|
|
|
|
|
private final BasketService basketService;
|
|
|
|
|
|
|
|
|
|
// 用于处理商品相关业务逻辑的服务层对象,比如获取商品信息等操作
|
|
|
|
|
private final ProductService productService;
|
|
|
|
|
|
|
|
|
|
// 用于处理商品库存单元(SKU)相关业务逻辑的服务层对象,比如获取SKU信息等操作
|
|
|
|
|
private final SkuService skuService;
|
|
|
|
|
|
|
|
|
|
// Spring应用上下文对象,用于发布事件等操作,例如发布购物车相关事件
|
|
|
|
|
private final ApplicationContext applicationContext;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取用户购物车信息
|
|
|
|
|
* 获取用户购物车信息的接口方法
|
|
|
|
|
* 根据传入的以购物车ID为键的购物车参数对象映射表,先更新购物车信息(如果参数表不为空),然后获取购物车商品项列表,最后将其转换为购物车信息列表并返回给前端。
|
|
|
|
|
*
|
|
|
|
|
* @param basketIdShopCartParamMap 购物车参数对象列表
|
|
|
|
|
* @return
|
|
|
|
|
* @param basketIdShopCartParamMap 以购物车ID为键,对应的购物车参数对象为值的映射表,用于更新购物车相关信息,参数从请求体中获取。
|
|
|
|
|
* @return 返回一个ServerResponseEntity<List<ShopCartDto>>类型的响应,成功时包含用户购物车信息对应的DTO列表数据,若获取或处理数据出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/info")
|
|
|
|
|
@Operation(summary = "获取用户购物车信息" , description = "获取用户购物车信息,参数为用户选中的活动项数组,以购物车id为key")
|
|
|
|
|
@Operation(summary = "获取用户购物车信息", description = "获取用户购物车信息,参数为用户选中的活动项数组,以购物车id为key")
|
|
|
|
|
public ServerResponseEntity<List<ShopCartDto>> info(@RequestBody Map<Long, ShopCartParam> basketIdShopCartParamMap) {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
|
|
|
|
|
// 更新购物车信息,
|
|
|
|
|
// 如果传入的购物车参数映射表不为空,调用购物车服务层方法根据参数更新购物车信息
|
|
|
|
|
if (MapUtil.isNotEmpty(basketIdShopCartParamMap)) {
|
|
|
|
|
basketService.updateBasketByShopCartParam(userId, basketIdShopCartParamMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 拿到购物车的所有item
|
|
|
|
|
// 调用购物车服务层方法获取该用户的购物车商品项列表
|
|
|
|
|
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
|
|
|
|
|
return ServerResponseEntity.success(basketService.getShopCarts(shopCartItems));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 删除用户购物车物品的接口方法
|
|
|
|
|
* 根据传入的购物车ID列表,调用购物车服务层方法删除对应购物车中的物品,并返回表示操作成功的响应给前端。
|
|
|
|
|
*
|
|
|
|
|
* @param basketIds 要删除物品的购物车的ID列表,参数从请求体中获取。
|
|
|
|
|
* @return 返回一个ServerResponseEntity<Void>类型的响应,成功时表示删除购物车物品操作成功,无具体返回数据,若删除过程出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@DeleteMapping("/deleteItem")
|
|
|
|
|
@Operation(summary = "删除用户购物车物品" , description = "通过购物车id删除用户购物车物品")
|
|
|
|
|
@Operation(summary = "删除用户购物车物品", description = "通过购物车id删除用户购物车物品")
|
|
|
|
|
public ServerResponseEntity<Void> deleteItem(@RequestBody List<Long> basketIds) {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
basketService.deleteShopCartItemsByBasketIds(userId, basketIds);
|
|
|
|
|
return ServerResponseEntity.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 清空用户购物车所有物品的接口方法
|
|
|
|
|
* 调用购物车服务层方法清空当前登录用户购物车中的所有物品,并返回表示操作成功的响应给前端,响应中包含成功提示信息。
|
|
|
|
|
*
|
|
|
|
|
* @return 返回一个ServerResponseEntity<String>类型的响应,成功时表示清空购物车操作成功,返回的信息为"删除成功",若操作出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@DeleteMapping("/deleteAll")
|
|
|
|
|
@Operation(summary = "清空用户购物车所有物品" , description = "清空用户购物车所有物品")
|
|
|
|
|
@Operation(summary = "清空用户购物车所有物品", description = "清空用户购物车所有物品")
|
|
|
|
|
public ServerResponseEntity<String> deleteAll() {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
basketService.deleteAllShopCartItems(userId);
|
|
|
|
|
return ServerResponseEntity.success("删除成功");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 添加、修改用户购物车物品的接口方法
|
|
|
|
|
* 根据传入的更改购物车参数对象,进行一系列验证(如更改数量是否为0、商品是否下架、库存是否足够等)后,调用购物车服务层方法添加或修改购物车中的商品,
|
|
|
|
|
* 并根据不同情况返回相应的操作结果响应给前端。
|
|
|
|
|
*
|
|
|
|
|
* @param param 包含更改购物车商品相关信息的参数对象,如商品ID、SKU ID、店铺ID、更改的商品个数等信息,参数从请求体中获取且经过验证。
|
|
|
|
|
* @return 返回一个ServerResponseEntity<String>类型的响应,根据操作结果返回不同信息,如添加成功、库存不足、商品已下架等提示信息,若操作出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/changeItem")
|
|
|
|
|
@Operation(summary = "添加、修改用户购物车物品", description = "通过商品id(prodId)、skuId、店铺Id(shopId),添加/修改用户购物车商品,并传入改变的商品个数(count)," +
|
|
|
|
|
"当count为正值时,增加商品数量,当count为负值时,将减去商品的数量,当最终count值小于0时,会将商品从购物车里面删除")
|
|
|
|
|
public ServerResponseEntity<String> addItem(@Valid @RequestBody ChangeShopCartParam param) {
|
|
|
|
|
|
|
|
|
|
// 如果更改的商品数量为0,则返回提示输入更改数量的失败响应
|
|
|
|
|
if (param.getCount() == 0) {
|
|
|
|
|
return ServerResponseEntity.showFailMsg("输入更改数量");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
// 获取当前用户的购物车商品项列表,用于后续判断商品是否已在购物车中等操作
|
|
|
|
|
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
|
|
|
|
|
// 根据传入的商品ID获取商品信息
|
|
|
|
|
Product prodParam = productService.getProductByProdId(param.getProdId());
|
|
|
|
|
// 根据传入的SKU ID获取SKU信息
|
|
|
|
|
Sku skuParam = skuService.getSkuBySkuId(param.getSkuId());
|
|
|
|
|
|
|
|
|
|
// 当商品状态不正常时,不能添加到购物车
|
|
|
|
|
if (prodParam.getStatus() != 1 || skuParam.getStatus() != 1) {
|
|
|
|
|
// 当商品状态不正常(下架状态,状态值不为1)时,返回提示商品已下架的失败响应
|
|
|
|
|
if (prodParam.getStatus()!= 1 || skuParam.getStatus()!= 1) {
|
|
|
|
|
return ServerResponseEntity.showFailMsg("当前商品已下架");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 遍历购物车商品项列表,判断要操作的商品是否已在购物车中
|
|
|
|
|
for (ShopCartItemDto shopCartItemDto : shopCartItems) {
|
|
|
|
|
if (Objects.equals(param.getSkuId(), shopCartItemDto.getSkuId())) {
|
|
|
|
|
Basket basket = new Basket();
|
|
|
|
|
basket.setUserId(userId);
|
|
|
|
|
// 更新购物车中该商品的数量,为原数量加上传入的更改数量
|
|
|
|
|
basket.setBasketCount(param.getCount() + shopCartItemDto.getProdCount());
|
|
|
|
|
basket.setBasketId(shopCartItemDto.getBasketId());
|
|
|
|
|
|
|
|
|
|
// 防止购物车变成负数
|
|
|
|
|
// 防止购物车商品数量变成负数,如果数量小于等于0,则删除该购物车商品项
|
|
|
|
|
if (basket.getBasketCount() <= 0) {
|
|
|
|
|
basketService.deleteShopCartItemsByBasketIds(userId, Collections.singletonList(basket.getBasketId()));
|
|
|
|
|
return ServerResponseEntity.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 当sku实际库存不足时,不能添加到购物车
|
|
|
|
|
// 当SKU实际库存不足(当前库存小于购物车中要设置的数量,且原购物车商品数量大于0,说明是修改操作)时,返回提示库存不足的失败响应
|
|
|
|
|
if (skuParam.getStocks() < basket.getBasketCount() && shopCartItemDto.getProdCount() > 0) {
|
|
|
|
|
return ServerResponseEntity.showFailMsg("库存不足");
|
|
|
|
|
}
|
|
|
|
|
// 调用购物车服务层方法更新购物车商品项信息
|
|
|
|
|
basketService.updateShopCartItem(basket);
|
|
|
|
|
return ServerResponseEntity.success();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 防止购物车已被删除的情况下,添加了负数的商品
|
|
|
|
|
// 如果商品不在购物车中,且传入的更改数量为负数,说明商品已被删除,返回相应提示的失败响应
|
|
|
|
|
if (param.getCount() < 0) {
|
|
|
|
|
return ServerResponseEntity.showFailMsg("商品已从购物车移除");
|
|
|
|
|
}
|
|
|
|
|
// 当sku实际库存不足时,不能添加到购物车
|
|
|
|
|
|
|
|
|
|
// 当SKU实际库存不足(当前库存小于要添加的数量,说明是添加操作)时,返回提示库存不足的失败响应
|
|
|
|
|
if (skuParam.getStocks() < param.getCount()) {
|
|
|
|
|
return ServerResponseEntity.showFailMsg("库存不足");
|
|
|
|
|
}
|
|
|
|
|
// 所有都正常时
|
|
|
|
|
basketService.addShopCartItem(param,userId);
|
|
|
|
|
|
|
|
|
|
// 所有验证都通过时,调用购物车服务层方法添加购物车商品项,并返回添加成功的响应
|
|
|
|
|
basketService.addShopCartItem(param, userId);
|
|
|
|
|
return ServerResponseEntity.success("添加成功");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取购物车商品数量的接口方法
|
|
|
|
|
* 获取当前登录用户购物车中所有商品的数量总和,若购物车商品项列表为空则返回数量为0的成功响应,否则计算数量总和并返回相应的成功响应给前端。
|
|
|
|
|
*
|
|
|
|
|
* @return 返回一个ServerResponseEntity<Integer>类型的响应,成功时包含购物车商品数量总和,若获取数据出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@GetMapping("/prodCount")
|
|
|
|
|
@Operation(summary = "获取购物车商品数量" , description = "获取所有购物车商品数量")
|
|
|
|
|
@Operation(summary = "获取购物车商品数量", description = "获取所有购物车商品数量")
|
|
|
|
|
public ServerResponseEntity<Integer> prodCount() {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
// 获取当前用户的购物车商品项列表
|
|
|
|
|
List<ShopCartItemDto> shopCartItems = basketService.getShopCartItems(userId);
|
|
|
|
|
if (CollectionUtil.isEmpty(shopCartItems)) {
|
|
|
|
|
return ServerResponseEntity.success(0);
|
|
|
|
|
}
|
|
|
|
|
// 使用流操作计算购物车商品项列表中所有商品数量的总和
|
|
|
|
|
Integer totalCount = shopCartItems.stream().map(ShopCartItemDto::getProdCount).reduce(0, Integer::sum);
|
|
|
|
|
return ServerResponseEntity.success(totalCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取购物车失效商品信息的接口方法
|
|
|
|
|
* 获取当前登录用户购物车中的失效商品信息列表,先获取失效商品项列表,然后按照店铺ID进行分组整理,构建每个店铺对应的失效商品信息对象列表后返回给前端。
|
|
|
|
|
*
|
|
|
|
|
* @return 返回一个ServerResponseEntity<List<ShopCartExpiryItemDto>>类型的响应,成功时包含购物车失效商品信息对应的DTO列表数据,若获取数据出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@GetMapping("/expiryProdList")
|
|
|
|
|
@Operation(summary = "获取购物车失效商品信息" , description = "获取购物车失效商品列表")
|
|
|
|
|
@Operation(summary = "获取购物车失效商品信息", description = "获取购物车失效商品列表")
|
|
|
|
|
public ServerResponseEntity<List<ShopCartExpiryItemDto>> expiryProdList() {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
// 获取当前用户购物车中的失效商品项列表
|
|
|
|
|
List<ShopCartItemDto> shopCartItems = basketService.getShopCartExpiryItems(userId);
|
|
|
|
|
//根据店铺ID划分item
|
|
|
|
|
// 根据店铺ID对失效商品项列表进行分组,得到以店铺ID为键,对应商品项列表为值的映射表
|
|
|
|
|
Map<Long, List<ShopCartItemDto>> shopCartItemDtoMap = shopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDto::getShopId));
|
|
|
|
|
|
|
|
|
|
// 返回一个店铺对应的所有信息
|
|
|
|
|
// 用于存储构建好的每个店铺对应的购物车失效商品信息对象列表
|
|
|
|
|
List<ShopCartExpiryItemDto> shopcartExpiryitems = Lists.newArrayList();
|
|
|
|
|
|
|
|
|
|
// 遍历分组后的店铺ID集合,构建每个店铺对应的购物车失效商品信息对象,并添加到列表中
|
|
|
|
|
for (Long key : shopCartItemDtoMap.keySet()) {
|
|
|
|
|
ShopCartExpiryItemDto shopCartExpiryItemDto = new ShopCartExpiryItemDto();
|
|
|
|
|
shopCartExpiryItemDto.setShopId(key);
|
|
|
|
@ -185,66 +244,44 @@ public class ShopCartController {
|
|
|
|
|
return ServerResponseEntity.success(shopcartExpiryitems);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 清空用户失效商品的接口方法
|
|
|
|
|
* 调用购物车服务层方法清空当前登录用户购物车中的失效商品,并返回表示操作成功的响应给前端。
|
|
|
|
|
*
|
|
|
|
|
* @return 返回一个ServerResponseEntity<Void>类型的响应,成功时表示清空失效商品操作成功,无具体返回数据,若操作出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@DeleteMapping("/cleanExpiryProdList")
|
|
|
|
|
@Operation(summary = "清空用户失效商品" , description = "清空用户失效商品")
|
|
|
|
|
@Operation(summary = "清空用户失效商品", description = "清空用户失效商品")
|
|
|
|
|
public ServerResponseEntity<Void> cleanExpiryProdList() {
|
|
|
|
|
// 获取当前登录用户的ID,用于关联购物车与用户
|
|
|
|
|
String userId = SecurityUtils.getUser().getUserId();
|
|
|
|
|
basketService.cleanExpiryProdList(userId);
|
|
|
|
|
return ServerResponseEntity.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取选中购物项总计、选中的商品数量的接口方法
|
|
|
|
|
* 根据传入的购物车ID列表,筛选出对应的购物车商品项,按照店铺ID进行分组后,计算选中商品的总计金额、商品数量等信息,构建相应的DTO对象并返回给前端。
|
|
|
|
|
*
|
|
|
|
|
* @param basketIds 要获取总计信息的购物车的ID列表,参数从请求体中获取。
|
|
|
|
|
* @return 返回一个ServerResponseEntity<ShopCartAmountDto>类型的响应,成功时包含选中购物项总计、商品数量等信息对应的DTO对象,若获取或计算数据出现异常则返回相应的错误信息。
|
|
|
|
|
*/
|
|
|
|
|
@PostMapping("/totalPay")
|
|
|
|
|
@Operation(summary = "获取选中购物项总计、选中的商品数量" , description = "获取选中购物项总计、选中的商品数量,参数为购物车id数组")
|
|
|
|
|
@Operation(summary = "获取选中购物项总计、选中的商品数量", description = "获取选中购物项总计、选中的商品数量,参数为购物车id数组")
|
|
|
|
|
public ServerResponseEntity<ShopCartAmountDto> getTotalPay(@RequestBody List<Long> basketIds) {
|
|
|
|
|
|
|
|
|
|
// 拿到购物车的所有item
|
|
|
|
|
List<ShopCartItemDto> dbShopCartItems = basketService.getShopCartItems(SecurityUtils.getUser().getUserId());
|
|
|
|
|
|
|
|
|
|
// 从所有购物车商品项中筛选出传入的购物车ID列表对应的商品项
|
|
|
|
|
List<ShopCartItemDto> chooseShopCartItems = dbShopCartItems
|
|
|
|
|
.stream()
|
|
|
|
|
.filter(shopCartItemDto -> {
|
|
|
|
|
for (Long basketId : basketIds) {
|
|
|
|
|
if (Objects.equals(basketId,shopCartItemDto.getBasketId())) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
})
|
|
|
|
|
.toList();
|
|
|
|
|
|
|
|
|
|
// 根据店铺ID划分item
|
|
|
|
|
Map<Long, List<ShopCartItemDto>> shopCartMap = chooseShopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDto::getShopId));
|
|
|
|
|
|
|
|
|
|
double total = 0.0;
|
|
|
|
|
int count = 0;
|
|
|
|
|
double reduce = 0.0;
|
|
|
|
|
for (Long shopId : shopCartMap.keySet()) {
|
|
|
|
|
//获取店铺的所有商品项
|
|
|
|
|
List<ShopCartItemDto> shopCartItemDtoList = shopCartMap.get(shopId);
|
|
|
|
|
// 构建每个店铺的购物车信息
|
|
|
|
|
ShopCartDto shopCart = new ShopCartDto();
|
|
|
|
|
shopCart.setShopId(shopId);
|
|
|
|
|
|
|
|
|
|
applicationContext.publishEvent(new ShopCartEvent(shopCart, shopCartItemDtoList));
|
|
|
|
|
|
|
|
|
|
List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
|
|
|
|
|
|
|
|
|
|
for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
|
|
|
|
|
List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
|
|
|
|
|
|
|
|
|
|
for (ShopCartItemDto shopCartItem : shopCartItems) {
|
|
|
|
|
count = shopCartItem.getProdCount() + count;
|
|
|
|
|
total = Arith.add(shopCartItem.getProductTotalAmount(), total);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ShopCartAmountDto shopCartAmountDto = new ShopCartAmountDto();
|
|
|
|
|
shopCartAmountDto.setCount(count);
|
|
|
|
|
shopCartAmountDto.setTotalMoney(total);
|
|
|
|
|
shopCartAmountDto.setSubtractMoney(reduce);
|
|
|
|
|
shopCartAmountDto.setFinalMoney(Arith.sub(shopCartAmountDto.getTotalMoney(), shopCartAmountDto.getSubtractMoney()));
|
|
|
|
|
|
|
|
|
|
return ServerResponseEntity.success(shopCartAmountDto);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
.stream()
|
|
|
|
|
.filter(shopCartItemDto -> {
|
|
|
|
|
for (Long basketId : basketIds) {
|
|
|
|
|
if (Objects.equals(basketId, shopCartItemDto.getBasketId())) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
})
|
|
|
|
|
.toList();
|