OrderController
java
package com.sky.controller.user;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.vo.OrderSubmitVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
// 在一切类似电商系统的程序中,用户是通过下单的方式通知商家,用户已经购买了某商品,需要商家备货和发货,用户下单之后会产生
// 订单相关数据,订单数据必须包含以下信息:
// 1.购买了哪些商品 2.每一个商品的数量是多少 3.订单总金额是多少 4.下单的用户是谁 5.收货的地址是哪 6.用户的手机号
// 在本系统中,用户将菜品或套餐加入购物车之后,可以通过结算按钮,跳转到订单确认页面,然后进行支付操作
// 点餐业务逻辑:1.购物车 ------------ 2.提交订单 ------------ 3.支付订单 ------------ 4.下单成功
// 完成订单提交业务需要两个表,一个是order订单表;另一个是order_detail订单明细表。用户提交订单时,需要在order表中插入一条记录;需要在
// order_detail表中插入一条或多条记录,代表这次订单的明细
@RestController("userOrderController")
@RequestMapping("/user/order")
@Slf4j
@Api(tags = "用户端-订单接口")
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 提交订单
*
* @param ordersSubmitDTO
* @return
*/
@PostMapping("/submit")
@ApiOperation("用户下单")
public Result<OrderSubmitVO> submit(@RequestBody OrdersSubmitDTO ordersSubmitDTO) {
log.info("用户下单:{}", ordersSubmitDTO);
OrderSubmitVO orderSubmitVO = orderService.submitOrder(ordersSubmitDTO);
return Result.success(orderSubmitVO);
}
}
OrderService
java
package com.sky.service.impl;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.AddressBookMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.OrderService;
import com.sky.vo.OrderSubmitVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderDetailMapper orderDetailMapper;
@Autowired
private ShoppingCartMapper shoppingCartMapper;
@Autowired
private AddressBookMapper addressBookMapper;
/**
* 提交订单
*
* @param ordersSubmitDTO
* @return
*/
@Override
public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
// 先处理异常情况(收获地址为空、购物车为空),可以根据OrdersSubmitDTO对象传递的数据进行查询操作
AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
if (addressBook == null) {
// 此时根据OrdersSubmitDTO中的地址id查询,是查询不到该地址的,所以说抛出地址为空异常
throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
}
// 获取这次提交订单请求的用户id
Long userId = BaseContext.getCurrentId();
// 创建ShoppingCart对象并封装UserId,便于Mapper查询
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setUserId(userId);
// 查询当前提交用户的购物车数据
List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);
if (shoppingCartList == null || !shoppingCartList.isEmpty()) {
// 若当前提交订单的用户的购物车为null或没有商品,那么肯定是无法正常提交订单的,抛出购物车为空异常
throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
}
// 当异常处理完毕后,就可以正常进入业务了
// 首先需要将DTO对象封装为Order对象
Orders order = new Orders();
BeanUtils.copyProperties(ordersSubmitDTO, order);
// 拷贝之后的封装,必须特别小心,必须仔细对比二者的差异,然后进行封装
order.setPhone(addressBook.getPhone());
order.setAddress(addressBook.getDetail());
order.setConsignee(addressBook.getConsignee());
// TODO这种使用时间戳作为订单编号的方法理论上是有问题的(如果两个用户真的碰巧同一时间下单)则会出现重大业务问题
// 用当前时间的时间戳当作订单编号,需要把Long转换为String
order.setNumber(String.valueOf(System.currentTimeMillis()));
order.setUserId(userId);
// 设置该订单的支付状态
order.setStatus(Orders.PENDING_PAYMENT);
// 设置订单的支付方式
order.setPayStatus(Orders.UN_PAID);
// 设置下单时间
order.setOrderTime(LocalDateTime.now());
// 向订单表中插入这个订单,相当于提交成功
orderMapper.insert(order);
// 订单明细数据
// 一个订单中也许会有大量明细,所以说需要用一个集合封装
List<OrderDetail> orderDetailList = new ArrayList<>();
for (ShoppingCart cart : shoppingCartList) {
// 因为订单明细主要存储的是商品的明细,所以说可以直接将购物车拷贝到OrderDetail对象中
OrderDetail orderDetail = new OrderDetail();
BeanUtils.copyProperties(cart, orderDetail);
// 给订单明细对象封装订单id
orderDetail.setOrderId(order.getId());
orderDetailList.add(orderDetail);
}
// 直接向明细表中插入n条数据
orderDetailMapper.insertBatch(orderDetailList);
// 提交订单后,需要清空该用户的购物车数据
shoppingCartMapper.deleteByUerId(userId);
// 封装返回的VO
return OrderSubmitVO.builder()
.id(order.getId())
.orderNumber(order.getNumber())
.orderAmount(order.getAmount())
.orderTime(order.getOrderTime())
.build();
}
}