feat(新增): 下单

Signed-off-by: bunny <1319900154@qq.com>
This commit is contained in:
bunny 2024-03-29 09:57:15 +08:00
parent 74d59f47df
commit d352cd8dd2
19 changed files with 332 additions and 12 deletions

View File

@ -31,4 +31,6 @@ public class MessageConstant {
public static final String VERIFICATION_CODE_IS_EMPTY = "请先发送验证码";
public static final String LOGIN_DTO_IS_EMPTY = "登录参数不能为空";
public static final String TOKEN_IS_EMPTY = "token为空";
public static final String DATA_IS_EMPTY = "数据为空";
public static final String STOCK_LESS = "库存不足";
}

View File

@ -9,6 +9,9 @@ import java.util.List;
@FeignClient(value = "service-cart", path = "/api/order/cart")
public interface CartFeignClient {
@GetMapping(value = "/auth/getAllCkecked")
@GetMapping("/auth/getAllCkecked")
Result<List<CartInfo>> getAllChecked();
@GetMapping("/auth/deleteChecked")
Result<String> deleteChecked();
}

View File

@ -6,7 +6,7 @@ import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "service-product", path = "/api/product/")
@FeignClient(value = "service-product", path = "/api/product/")
public interface ProductFeignClient {
@GetMapping("getBySkuId/{skuId}")
Result<ProductSku> getBySkuId(@PathVariable Long skuId);

View File

@ -0,0 +1,13 @@
package com.atguigu.feign.user;
import com.atguigu.spzx.model.entity.user.UserAddress;
import com.atguigu.spzx.model.vo.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "service-user", path = "/api/user/userAddress")
public interface UserFeignClient {
@GetMapping("getUserAddress/{id}")
Result<UserAddress> getUserAddress(@PathVariable Long id);
}

View File

@ -43,15 +43,15 @@ public class CartController {
@Operation(summary = "更新购物车商品选中状态")
@GetMapping("/auth/checkCart/{skuId}/{isChecked}")
public Result<String> checkCart(@Parameter(name = "skuId", description = "商品skuId", required = true) @PathVariable(value = "skuId") Long skuId,
@Parameter(name = "isChecked", description = "是否选中 1:选中 0:取消选中", required = true) @PathVariable(value = "isChecked") Integer isChecked) {
public Result<String> checkCart(@Parameter(name = "skuId", description = "商品skuId", required = true) @PathVariable("skuId") Long skuId,
@Parameter(name = "isChecked", description = "是否选中 1:选中 0:取消选中", required = true) @PathVariable("isChecked") Integer isChecked) {
cartService.checkCart(skuId, isChecked);
return Result.success();
}
@Operation(summary = "更新购物车商品全部选中状态")
@GetMapping("/auth/allCheckCart/{isChecked}")
public Result<String> allCheckCart(@Parameter(name = "isChecked", description = "是否选中 1:选中 0:取消选中", required = true) @PathVariable(value = "isChecked") Integer isChecked) {
public Result<String> allCheckCart(@Parameter(name = "isChecked", description = "是否选中 1:选中 0:取消选中", required = true) @PathVariable("isChecked") Integer isChecked) {
cartService.allCheckCart(isChecked);
return Result.success();
}
@ -64,9 +64,16 @@ public class CartController {
}
@Operation(summary = "选中的购物车")
@GetMapping(value = "/auth/getAllCkecked")
@GetMapping("/auth/getAllCkecked")
public Result<List<CartInfo>> getAllChecked() {
List<CartInfo> cartInfoList = cartService.getAllChecked();
return Result.success(cartInfoList);
}
@Operation(summary = "清空提交过的购物车")
@GetMapping("/auth/deleteChecked")
public Result<String> deleteChecked() {
cartService.deleteChecked();
return Result.success();
}
}

View File

@ -53,4 +53,9 @@ public interface CartService {
* @return CartInfo列表
*/
List<CartInfo> getAllChecked();
/**
* 清空提交过的购物车
*/
void deleteChecked();
}

View File

@ -180,4 +180,19 @@ public class CartServiceImpl implements CartService {
}
return new ArrayList<>();
}
/**
* 清空提交过的购物车
*/
@Override
public void deleteChecked() {
Long userId = BaseContext.getUserInfo().getId();
String cartKey = RedisUtils.getCartKey(userId);
List<Object> objectList = redisTemplate.opsForHash().values(cartKey); // 删除选中的购物项数据
if (!CollectionUtils.isEmpty(objectList)) {
objectList.stream().map(cartInfoJSON -> JSON.parseObject(cartInfoJSON.toString(), CartInfo.class))
.filter(cartInfo -> cartInfo.getIsChecked() == 1)
.forEach(cartInfo -> redisTemplate.opsForHash().delete(cartKey, String.valueOf(cartInfo.getSkuId())));
}
}
}

View File

@ -23,5 +23,15 @@
<artifactId>service-cart-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-user-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-product-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -7,7 +7,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients(basePackages = {"com.atguigu.feign.cart"})
@EnableFeignClients(basePackages = {"com.atguigu.feign.cart", "com.atguigu.feign.user"})
@EnableUserTokenFeignInterceptor
@Slf4j
public class OrderApplication {

View File

@ -1,14 +1,14 @@
package com.atguigu.order.controller;
import com.atguigu.order.service.OrderInfoService;
import com.atguigu.spzx.model.dto.h5.OrderInfoDto;
import com.atguigu.spzx.model.vo.h5.TradeVo;
import com.atguigu.spzx.model.vo.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Tag(name = "订单管理")
@RestController
@ -23,4 +23,11 @@ public class OrderInfoController {
TradeVo tradeVo = orderInfoService.getTrade();
return Result.success(tradeVo);
}
@Operation(summary = "提交订单")
@PostMapping("auth/submitOrder")
public Result<Long> submitOrder(@Parameter(name = "orderInfoDto", description = "请求参数实体类", required = true) @RequestBody OrderInfoDto orderInfoDto) {
Long orderId = orderInfoService.submitOrder(orderInfoDto);
return Result.success(orderId);
}
}

View File

@ -1,7 +1,14 @@
package com.atguigu.order.mapper;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderInfoMapper {
/**
* 添加数据到order_info中
*
* @param orderInfo orderInfo
*/
void save(OrderInfo orderInfo);
}

View File

@ -0,0 +1,14 @@
package com.atguigu.order.mapper;
import com.atguigu.spzx.model.entity.order.OrderItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderItemMapper {
/**
* 保存订单明细
*
* @param orderItem orderItem
*/
void save(OrderItem orderItem);
}

View File

@ -0,0 +1,14 @@
package com.atguigu.order.mapper;
import com.atguigu.spzx.model.entity.order.OrderLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderLogMapper {
/**
* 记录日志
*
* @param orderLog orderLog
*/
void save(OrderLog orderLog);
}

View File

@ -1,5 +1,6 @@
package com.atguigu.order.service;
import com.atguigu.spzx.model.dto.h5.OrderInfoDto;
import com.atguigu.spzx.model.vo.h5.TradeVo;
public interface OrderInfoService {
@ -9,4 +10,12 @@ public interface OrderInfoService {
* @return 结算实体类
*/
TradeVo getTrade();
/**
* 提交订单
*
* @param orderInfoDto OrderInfoDto
* @return Long
*/
Long submitOrder(OrderInfoDto orderInfoDto);
}

View File

@ -1,21 +1,55 @@
package com.atguigu.order.service.impl;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.atguigu.constant.MessageConstant;
import com.atguigu.context.BaseContext;
import com.atguigu.exception.BunnyException;
import com.atguigu.feign.cart.CartFeignClient;
import com.atguigu.feign.product.ProductFeignClient;
import com.atguigu.feign.user.UserFeignClient;
import com.atguigu.order.mapper.OrderInfoMapper;
import com.atguigu.order.mapper.OrderItemMapper;
import com.atguigu.order.mapper.OrderLogMapper;
import com.atguigu.order.service.OrderInfoService;
import com.atguigu.order.service.module.OrderInfoServiceModule;
import com.atguigu.spzx.model.dto.h5.OrderInfoDto;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.order.OrderItem;
import com.atguigu.spzx.model.entity.order.OrderLog;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.entity.user.UserAddress;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.model.vo.h5.TradeVo;
import com.atguigu.spzx.model.vo.result.ResultCodeEnum;
import com.atguigu.utils.EmptyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class OrderInfoServiceImpl implements OrderInfoService {
@Autowired
private OrderInfoServiceModule orderInfoServiceModule;
@Autowired
private CartFeignClient cartFeignClient;
@Autowired
private ProductFeignClient productFeignClient;
@Autowired
private UserFeignClient userFeignClient;
@Autowired
private OrderInfoMapper orderInfoMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private OrderLogMapper orderLogMapper;
@Autowired
private EmptyUtil emptyUtil;
/**
* 确认下单
@ -38,4 +72,81 @@ public class OrderInfoServiceImpl implements OrderInfoService {
return tradeVo;
}
/**
* 提交订单
*
* @param orderInfoDto OrderInfoDto
* @return Long
*/
@Override
public Long submitOrder(OrderInfoDto orderInfoDto) {
// 数据校验
List<OrderItem> orderItemList = orderInfoDto.getOrderItemList();
if (CollectionUtils.isEmpty(orderItemList)) {
throw new BunnyException(ResultCodeEnum.DATA_ERROR);
}
// 检验商品库存是否充足遍历list集合
orderItemList.forEach(orderItem -> {
ProductSku productSku = productFeignClient.getBySkuId(orderItem.getSkuId()).getData();
if (productSku == null) {
throw new BunnyException(MessageConstant.DATA_IS_EMPTY);
}
// 检验每个库存是否充足
if (productSku.getStockNum() < orderItem.getSkuNum()) {
throw new BunnyException(MessageConstant.STOCK_LESS);
}
});
// 添加数据到order_info表
// 构建订单数据保存订单
UserInfo userInfo = BaseContext.getUserInfo();
OrderInfo orderInfo = new OrderInfo();
// 订单编号
orderInfo.setOrderNo(String.valueOf(System.currentTimeMillis()));
// 用户id
orderInfo.setUserId(userInfo.getId());
// 用户昵称
orderInfo.setNickName(userInfo.getNickName());
// 用户收货地址信息
UserAddress userAddress = userFeignClient.getUserAddress(orderInfoDto.getUserAddressId()).getData();
orderInfo.setReceiverName(userAddress.getName());
orderInfo.setReceiverPhone(userAddress.getPhone());
orderInfo.setReceiverTagName(userAddress.getTagName());
orderInfo.setReceiverProvince(userAddress.getProvinceCode());
orderInfo.setReceiverCity(userAddress.getCityCode());
orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
orderInfo.setReceiverAddress(userAddress.getFullAddress());
// 订单金额
BigDecimal totalAmount = new BigDecimal(0);
for (OrderItem orderItem : orderItemList) {
totalAmount = totalAmount.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
}
orderInfo.setTotalAmount(totalAmount);
orderInfo.setCouponAmount(new BigDecimal(0));
orderInfo.setOriginalTotalAmount(totalAmount);
orderInfo.setFeightFee(orderInfoDto.getFeightFee());
orderInfo.setPayType(2);
orderInfo.setOrderStatus(0);
// 添加数据到order_info中
orderInfoMapper.save(orderInfo);
// 保存订单明细
for (OrderItem orderItem : orderItemList) {
orderItem.setOrderId(orderInfo.getId());
orderItemMapper.save(orderItem);
}
// 记录日志
OrderLog orderLog = new OrderLog();
orderLog.setOrderId(orderInfo.getId());
orderLog.setProcessStatus(0);
orderLog.setNote("提交订单");
orderLogMapper.save(orderLog);
// 5清空购物车数据
cartFeignClient.deleteChecked();
// 6返回订单id
return orderInfo.getId();
}
}

View File

@ -1,5 +1,60 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.order.mapper.OrderInfoMapper">
<!-- 用于select查询公用抽取的列 -->
<sql id="columns">
id,user_id,nick_name,order_no,coupon_id,total_amount,coupon_amount,original_total_amount,feight_fee,pay_type,order_status,receiver_name,receiver_phone,receiver_tag_name,receiver_province,receiver_city,receiver_district,receiver_address,payment_time,delivery_time,receive_time,remark,cancel_time,cancel_reason,create_time,update_time,is_deleted
</sql>
<!-- 添加数据到order_info中 -->
<insert id="save">
insert into order_info (id,
user_id,
nick_name,
order_no,
coupon_id,
total_amount,
coupon_amount,
original_total_amount,
feight_fee,
pay_type,
order_status,
receiver_name,
receiver_phone,
receiver_tag_name,
receiver_province,
receiver_city,
receiver_district,
receiver_address,
payment_time,
delivery_time,
receive_time,
remark,
cancel_time,
cancel_reason)
values (#{id},
#{userId},
#{nickName},
#{orderNo},
#{couponId},
#{totalAmount},
#{couponAmount},
#{originalTotalAmount},
#{feightFee},
#{payType},
#{orderStatus},
#{receiverName},
#{receiverPhone},
#{receiverTagName},
#{receiverProvince},
#{receiverCity},
#{receiverDistrict},
#{receiverAddress},
#{paymentTime},
#{deliveryTime},
#{receiveTime},
#{remark},
#{cancelTime},
#{cancelReason})
</insert>
</mapper>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.order.mapper.OrderItemMapper">
<!-- 用于select查询公用抽取的列 -->
<sql id="columns">
id,order_id,sku_id,sku_name,thumb_img,sku_price,sku_num,create_time,update_time,is_deleted
</sql>
<!-- 保存订单明细 -->
<insert id="save">
insert into order_item (id,
order_id,
sku_id,
sku_name,
thumb_img,
sku_price,
sku_num)
values (#{id},
#{orderId},
#{skuId},
#{skuName},
#{thumbImg},
#{skuPrice},
#{skuNum})
</insert>
</mapper>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.order.mapper.OrderLogMapper">
<!-- 用于select查询公用抽取的列 -->
<sql id="columns">
id,order_id,operate_user,process_status,note,create_time,update_time,is_deleted
</sql>
<!-- 记录日志 -->
<insert id="save">
insert into order_log (id,
order_id,
operate_user,
process_status,
note)
values (#{id},
#{orderId},
#{operateUser},
#{processStatus},
#{note})
</insert>
</mapper>

View File

@ -31,7 +31,7 @@ public class UserAddressController {
@Operation(summary = "获取地址信息")
@GetMapping("getUserAddress/{id}")
public UserAddress getUserAddress(@PathVariable Long id) {
return userAddressService.getById(id);
public Result<UserAddress> getUserAddress(@PathVariable Long id) {
return Result.success(userAddressService.getById(id));
}
}