苍穹外卖 订单提交接口

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();
    }
}
相关推荐
Mr. zhihao4 分钟前
享元模式在 JDK 中的应用解析
java·享元模式
茶馆大橘8 分钟前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
wrx繁星点点8 分钟前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
真的想不出名儿12 分钟前
Java基础——反射
java·开发语言
鱼跃鹰飞13 分钟前
大厂面试真题-简单说说线程池接到新任务之后的操作流程
java·jvm·面试
菜菜-plus21 分钟前
java设计模式之策略模式
java·设计模式·策略模式
努力编程的阿伟31 分钟前
【Java SE语法】抽象类(abstract class)和接口(interface)有什么异同?
java·开发语言
2401_8658548834 分钟前
iOS应用想要下载到手机上只能苹果签名吗?
后端·ios·iphone
包饭厅咸鱼1 小时前
QML----复制指定下标的ListModel数据
开发语言·数据库
bryant_meng1 小时前
【python】Distribution
开发语言·python·分布函数·常用分布