Java-springboot生鲜电商项目(六)订单模块

订单开发思路

  1. 登录
  2. 浏览商品
  3. 加入购物车
  4. 下单,取消订单
  5. 扫描支付
  6. 发货
  7. 收货

涉及到的接口

  1. 前台:创建订单
  2. 前台:订单详情
  3. 前台:订单列表
  4. 前台:取消订单
  5. 生成支付二维码
  6. 前台:支付订单
  7. 后台:订单列表
  8. 后台:订单发货
  9. 订单完结

重难点

  1. VO的封装还裁剪
  2. 一个订单内包含多个商品
  3. 订单状态流转
  4. 二维码生成

(一)创建订单

新建一个创建订单的请求类

package com.hyb.mall.model.request;

import javax.validation.constraints.NotNull;

public class CreateOrderReq {

    @NotNull(message = "接收人名字不能不为空")
    private String receiverName;

    @NotNull(message = "接收人电话不能不为空")
    private String receiverMobile;

    @NotNull(message = "接收人地址不能不为空")
    private String receiverAddress;

    private Integer postage = 0;

    private Integer paymentType = 1;

    public String getReceiverName() {
        return receiverName;
    }

    public void setReceiverName(String receiverName) {
        this.receiverName = receiverName;
    }

    public String getReceiverMobile() {
        return receiverMobile;
    }

    public void setReceiverMobile(String receiverMobile) {
        this.receiverMobile = receiverMobile;
    }

    public String getReceiverAddress() {
        return receiverAddress;
    }

    public void setReceiverAddress(String receiverAddress) {
        this.receiverAddress = receiverAddress;
    }

    public Integer getPostage() {
        return postage;
    }

    public void setPostage(Integer postage) {
        this.postage = postage;
    }

    public Integer getPaymentType() {
        return paymentType;
    }

    public void setPaymentType(Integer paymentType) {
        this.paymentType = paymentType;
    }
}

添加异常

CART_EMPTY(10018,"购物车已勾选的商品为空"),
NO_ENUM(10019,"未找到对应的枚举类"),

在Constant添加

    /**
     * 订单状态
     */
    public enum OrderStatusEnum{
        CANCELED(0,"用户已取消"),
        NOT_PAID(10,"未付款"),
        PAID(20,"已付款"),
        DELIVERED(30,"已发货"),
        FINISHED(40,"交易完成");
        private String value;
        private int code;

        OrderStatusEnum(int code,String value) {
            this.value = value;
            this.code = code;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        //通过code返回意思
        public static OrderStatusEnum cedeOf(int code){
            for(OrderStatusEnum orderStatusEnum:values()){
                if (orderStatusEnum.getCode() == code){
                    return orderStatusEnum;
                }
            }
            throw new MallException(MallExceptionEnum.NO_ENUM);
        }
    }

在service添加创建订单方法

package com.hyb.mall.service.impl;

import com.hyb.mall.common.Constant;
import com.hyb.mall.exception.MallException;
import com.hyb.mall.exception.MallExceptionEnum;
import com.hyb.mall.filter.UserFilter;
import com.hyb.mall.model.dao.CartMapper;
import com.hyb.mall.model.dao.OrderItemMapper;
import com.hyb.mall.model.dao.OrderMapper;
import com.hyb.mall.model.dao.ProductMapper;
import com.hyb.mall.model.pojo.Order;
import com.hyb.mall.model.pojo.OrderItem;
import com.hyb.mall.model.pojo.Product;
import com.hyb.mall.model.request.CreateOrderReq;
import com.hyb.mall.model.vo.CartVO;
import com.hyb.mall.service.CartSrvice;
import com.hyb.mall.service.OrderSrvice;
import com.hyb.mall.util.OrderCodeFactory;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 描述:订单Service实现类
 */
@Service
public class OrderSrviceImpl implements OrderSrvice {
    @Autowired
    CartSrvice cartSrvice;

    @Autowired
    ProductMapper productMapper;

    @Autowired
    CartMapper cartMapper;

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Override
    //数据库事务
    @Transactional(rollbackFor = Exception.class)
    public String create(CreateOrderReq createOrderReq) {
        //拿到用户ID
        Integer userId = UserFilter.currentUser.getId();

        //从购物车查找已经勾选的商品
        List<CartVO> cartVOList = cartSrvice.list(userId);
        ArrayList<CartVO> cartVOListTemp = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            if (cartVO.getSelected().equals(Constant.Cart.CHCKED)) {
                cartVOListTemp.add(cartVO);
            }
        }
        cartVOList = cartVOListTemp;

        //如果购物车已勾选为空,报错
        if (CollectionUtils.isEmpty(cartVOList)) {
            throw new MallException(MallExceptionEnum.CART_EMPTY);
        }

        //判断商品是否存在,上下架状态,库存
        validSaleStatusAndStock(cartVOList);

        //把购物车对象转化为订单item对象
        List<OrderItem> orderItemList = cartVOListOrderItemList(cartVOList);

        //扣库存
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            Product product = productMapper.selectByPrimaryKey(orderItem.getProductId());
            int stock = product.getStock() - orderItem.getQuantity();
            if (stock < 0) {
                throw new MallException(MallExceptionEnum.NOT_ENOUGH);
            }
            product.setStock(stock);
            productMapper.updateByPrimaryKeySelective(product);
        }

        //把购物车中的已勾选商品删除
        cleanCart(cartVOList);

        //生成订单
        Order order = new Order();

        //生成订单号,有独立的规则
        String orderNo = OrderCodeFactory.getOrderCode(Long.valueOf(userId));
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setTotalPrice(totalPrice(orderItemList));
        order.setReceiverName(createOrderReq.getReceiverName());
        order.setReceiverMobile(createOrderReq.getReceiverMobile());
        order.setReceiverAddress(createOrderReq.getReceiverAddress());
        order.setOrderStatus(Constant.OrderStatusEnum.NOT_PAID.getCode());
        order.setPostage(0);
        order.setPaymentType(1);

        //插入到order表
        orderMapper.insertSelective(order);

        //循环保存每个商品到order_item表
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            orderItem.setOrderNo(order.getOrderNo());
            orderItemMapper.insertSelective(orderItem);
        }

        //把结果返回
        return orderNo;
    }

    private Integer totalPrice(List<OrderItem> orderItemList) {
        Integer totalPrice = 0;
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            totalPrice += orderItem.getTotalPrice();
        }
        return totalPrice;
    }

    private void cleanCart(List<CartVO> cartVOList) {
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            cartMapper.deleteByPrimaryKey(cartVO.getId());
        }
    }

    private List<OrderItem> cartVOListOrderItemList(List<CartVO> cartVOList) {
        List<OrderItem> orderItemList = new ArrayList<>();
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            OrderItem orderItem = new OrderItem();
            orderItem.setProductId(cartVO.getProductId());
            //记录商品快照信息
            orderItem.setProductName(cartVO.getProductName());
            orderItem.setProductImg(cartVO.getProductImage());
            orderItem.setUnitPrice(cartVO.getPrice());
            orderItem.setQuantity(cartVO.getQuantity());
            orderItem.setTotalPrice(cartVO.getTotalPrice());
            orderItemList.add(orderItem);

        }
        return orderItemList;
    }

    private void validSaleStatusAndStock(List<CartVO> cartVOList) {
        for (int i = 0; i < cartVOList.size(); i++) {
            CartVO cartVO = cartVOList.get(i);
            Product product = productMapper.selectByPrimaryKey(cartVO.getProductId());
            //判断商品是否存在,商品是否上架
            if (product == null || product.getStatus().equals(Constant.SaleStatus.NOT_SALE)) {
                throw new MallException(MallExceptionEnum.NOT_SALE);
            }
            //判断商品库存
            if (cartVO.getQuantity() > product.getStock()) {
                throw new MallException(MallExceptionEnum.NOT_ENOUGH);
            }
        }

    }
}

controller实现

package com.hyb.mall.controller;

import com.hyb.mall.common.ApiRestResponse;
import com.hyb.mall.model.request.CreateOrderReq;
import com.hyb.mall.service.OrderSrvice;
import io.swagger.annotations.ApiOperation;
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;

/**
 * 描述:订单控制器
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    OrderSrvice orderSrvice;

    @PostMapping("/create")
    @ApiOperation("创建订单")
    public ApiRestResponse create(@RequestBody CreateOrderReq createOrderReq){
        String orderNo = orderSrvice.create(createOrderReq);
        return ApiRestResponse.success(orderNo);
    }
}

在postman进行测试

在这里插入图片描述

(二)订单详情

定义异常

NO_ORDER(10020,"订单不存在"),
NO_YOU_ORDER(10020,"订单不属于你"),

先在dao创建接口

orderMpper

Order selectByOrderNo(String orderNo);

Mapper

  <select id="selectByOrderNo" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from imooc_mall_order
    where order_no = #{orderNo}
  </select>

先在dao创建接口

dao

List<OrderItem> selectByOrderNo(String orderNo);

Mapper

  <select id="selectByOrderNo" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from imooc_mall_order_item
    where order_no=#{orderNo}
  </select>

service,主要还是在拼接信息上

    //查询订单详情
    @Override
    public OrderVO detail(String orderNo){
        Order order = orderMapper.selectByOrderNo(orderNo);
        //订单不存在,则报错
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //订单存在,则判断所属
        Integer userId = UserFilter.currentUser.getId();
        if (!order.getUserId().equals(userId)){
            throw new MallException(MallExceptionEnum.NO_YOU_ORDER);
        }
        //拼接信息,将order转成orderVO
        OrderVO orderVO = getOrder(order);
        return orderVO;
    }

    private OrderVO getOrder(Order order) {
        OrderVO orderVO = new OrderVO();
        BeanUtils.copyProperties(order,orderVO);
        //获取订单对应的orderItemVOList
        List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());
        List<OrderItemVO> orderItemVOList = new ArrayList<>();
        for (int i = 0; i < orderItemList.size(); i++) {
            OrderItem orderItem = orderItemList.get(i);
            OrderItemVO orderItemVO = new OrderItemVO();
            BeanUtils.copyProperties(orderItem,orderItemVO);
            orderItemVOList.add(orderItemVO);
        }
        orderVO.setOrderItemVOList(orderItemVOList);
        orderVO.setOrderStatusName(Constant.OrderStatusEnum.cedeOf(orderVO.getOrderStatus()).getValue());
        return orderVO;
    }

controller

    @GetMapping("/detail")
    @ApiOperation("前台订单详情")
    public ApiRestResponse detail(@RequestParam String orderNo){
        OrderVO orderVO = orderSrvice.detail(orderNo);
        return ApiRestResponse.success(orderVO);
    }

(三)订单列表

dao

List<Order> selectForCustomer(Integer userId);

mapper

  <select id="selectForCustomer" resultMap="BaseResultMap" parameterType="integer">
    select
    <include refid="Base_Column_List"/>
    from imooc_mall_order
    where user_id = #{userId}
    order by create_time desc
  </select>

service

    @Override
    public PageInfo listForCustomer(Integer pageNum,Integer pageSize){
        Integer userId = UserFilter.currentUser.getId();
        PageHelper.startPage(pageNum,pageSize);
        List<Order> orderList = orderMapper.selectForCustomer(userId);
        //将order转化为orderVO
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        //包装成pageInfo进行返回
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

    private List<OrderVO> orderListToOrderVOList(List<Order> orderList) {
        List<OrderVO> orderVOList = new ArrayList<>();
        for (int i = 0; i < orderList.size(); i++) {
            Order order = orderList.get(i);
            OrderVO orderVO = getOrder(order);
            orderVOList.add(orderVO);
        }
        return orderVOList;
    }

controller

    @GetMapping("/list")
    @ApiOperation("前台订单列表")
    public ApiRestResponse list(@RequestParam Integer pageNum ,@RequestParam Integer pageSize){
        PageInfo pageInfo = orderSrvice.listForCustomer(pageNum, pageSize);
        return ApiRestResponse.success(pageInfo);
    }

postman测试

在这里插入图片描述

(四)取消订单

添加异常

WRONG_ORDER(10022,"订单状态不符"),

service

    @Override
    public void cancel(String orderNo){
        //查不到订单,报错
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //验证用户身份
        //订单存在,则判断所属
        Integer userId = UserFilter.currentUser.getId();
        if (!order.getUserId().equals(userId)){
            throw new MallException(MallExceptionEnum.NO_YOU_ORDER);
        }
        //没有付款才取消
        if (order.getOrderStatus().equals(Constant.OrderStatusEnum.NOT_PAID.getCode())) {
            //将订单状态设置成取消
            order.setOrderStatus(Constant.OrderStatusEnum.CANCELED.getCode());
            order.setEndTime(new Date());
            //将订单传到数据库,来更新数据库的状态
            orderMapper.updateByPrimaryKeySelective(order);
        }else{
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

controller

    @PostMapping("/cancel")
    @ApiOperation("前台取消订单")
    public ApiRestResponse cancel(@RequestParam String orderNo){
        orderSrvice.cancel(orderNo);
        return ApiRestResponse.success();
    }

postman

在这里插入图片描述

(五)后台管理员列表开发

dao

List<Order> selectForAdmin();

mapper

  <select id="selectForAdmin" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from imooc_mall_order
    order by create_time desc
  </select>

service

    @Override
    public PageInfo listForAdmin(Integer pageNum, Integer pageSize){
        PageHelper.startPage(pageNum,pageSize);
        List<Order> orderList = orderMapper.selectForAdmin();
        //将order转化为orderVO
        List<OrderVO> orderVOList = orderListToOrderVOList(orderList);
        //包装成pageInfo进行返回
        PageInfo pageInfo = new PageInfo<>(orderList);
        pageInfo.setList(orderVOList);
        return pageInfo;
    }

controller

package com.hyb.mall.controller;

import com.github.pagehelper.PageInfo;
import com.hyb.mall.common.ApiRestResponse;
import com.hyb.mall.service.OrderSrvice;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderAdminController {
    @Autowired
    OrderSrvice orderSrvice;
    @GetMapping("/admin/order/list")
    @ApiOperation("管理员订单列表")
    public ApiRestResponse listForAdmin(@RequestParam Integer pageNum,@RequestParam Integer pageSize){
        PageInfo pageInfo = orderSrvice.listForAdmin(pageNum, pageSize);
        return ApiRestResponse.success(pageInfo);
    }
}

(六)支付相关的二维码接口

引入生成二维码的依赖

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.0</version>
        </dependency>

在工具类中添加生成二维码的类

package com.hyb.mall.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.hyb.mall.common.Constant;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;

/**
 * 描述:     生成二维码工具
 */
public class QRCodeGenerator {


    public static void generateQRCodeImage(String text, int width, int height, String filePath)
            throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
        Path path = FileSystems.getDefault().getPath(filePath);
        MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
    }

    public static void main(String[] args) {
        try {
            generateQRCodeImage("Hello World", 350, 350, "/Users/hyb/Desktop/Pfile/二维码/QRTest.png");
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

生成后的图片

在这里插入图片描述

service

    @Value("${file.upload.ip}")
    String ip;
    @Override
    public String qrcode(String orderNo){
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String address = ip+":"+request.getLocalPort();
        //支付URL
        String payUrl = "http://"+address+"/pay?orderNo="+orderNo;
        try {
            QRCodeGenerator.generateQRCodeImage(payUrl,350,350,
                    Constant.FILE_UPLOAD_DIR+orderNo+".PNG");
        } catch (WriterException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String pngAddress= "http://"+address+"/images/"+orderNo+".png";
        return pngAddress;
    }

controller

    @PostMapping("/admin/qrcode")
    @ApiOperation("生成二维码")
    public ApiRestResponse listForAdmin(@RequestParam String orderNo){
        String pngAddress = orderSrvice.qrcode(orderNo);
        return ApiRestResponse.success(pngAddress);
    }

(七)支付接口

service

    @Override
    public void pay(String orderNo){
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单,报错
        if (order == null){
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        if (order.getOrderStatus() == Constant.OrderStatusEnum.NOT_PAID.getCode()){
            order.setOrderStatus(Constant.OrderStatusEnum.PAID.getCode());
            order.setPayTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        }else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

controller

    @GetMapping("/pay")
    @ApiOperation("前台:支付订单")
    public ApiRestResponse pay(@RequestParam String orderNo){
        orderSrvice.pay(orderNo);
        return ApiRestResponse.success();
    }

postman

在这里插入图片描述

(八)发货订单

service

    @Override
    public void delivered(String orderNo){
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单,报错
        if (order == null){
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //订单状态是不是付款的
        if (order.getOrderStatus() == Constant.OrderStatusEnum.NOT_PAID.getCode()){
            order.setOrderStatus(Constant.OrderStatusEnum.DELIVERED.getCode());
            order.setDeliveryTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        }else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

controller

    @PostMapping("/admin/order/delivered")
    @ApiOperation("后台:订单发货")
    public ApiRestResponse delivered(@RequestParam String orderNo){
        orderSrvice.delivered(orderNo);
        return ApiRestResponse.success();
    }

postman

在这里插入图片描述

(九)完结订单接口

service

    @Override
    public void finish(String orderNo){
        Order order = orderMapper.selectByOrderNo(orderNo);
        //查不到订单,报错
        if (order == null){
            throw new MallException(MallExceptionEnum.NO_ORDER);
        }
        //如果是普通用户,就要校验订单的所属
        if (!userService.checkAdminRole(UserFilter.currentUser) && !order.getUserId().equals(UserFilter.currentUser.getId())) {
            throw new MallException(MallExceptionEnum.NO_YOU_ORDER);
        }
        //发货后可以完结订单
        //订单状态是不是付款的
        if (order.getOrderStatus() == Constant.OrderStatusEnum.DELIVERED.getCode()){
            order.setOrderStatus(Constant.OrderStatusEnum.FINISHED.getCode());
            order.setEndTime(new Date());
            orderMapper.updateByPrimaryKeySelective(order);
        }else {
            throw new MallException(MallExceptionEnum.WRONG_ORDER_STATUS);
        }
    }

controller

    @PostMapping("/order/finish")
    @ApiOperation("订单完结")
    public ApiRestResponse finish(@RequestParam String orderNo){
        orderSrvice.finish(orderNo);
        return ApiRestResponse.success();
    }

postman

在这里插入图片描述

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值