黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理

文章目录

  • 一.用户端历史订单
    • 1. 查询历史订单
    • 2. 查询订单详情
    • 3. 取消订单
    • 4. 再来一单
  • 二.商家端订单管理模块
    • 1. 订单搜索
    • 2. 各个状态的订单数量统计
    • 3. 查询订单详情
    • 4. 接单
    • 5. 拒单
    • 6. 取消订单
    • 7. 派送订单
    • 8. 完成订单
  • 三.重点:校验收货地址是否超出配送范围
    • 1.地址编码API
    • 2.轻量级路线规划服务


一.用户端历史订单

1. 查询历史订单

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第1张图片

业务规则:

  • 分页查询历史订单
  • 可以根据订单状态查询
  • 展示订单数据时,需要展示的数据包括:下单时间、订单状态、订单金额、订单明细(商品名称、图片)

接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第2张图片
url传参为:page,pageSize,status
返回数据为:PageResult

思路:
1.需要注意的是,返回给页面的数据为集合嵌套了集合(历史订单有多个订单数据,一个订单数据又有多个菜品或者套餐数据)

2.需要明确的是PageResult中的集合属性应为OrderVO集合,其中一个OrderVO中封装了OrderDetail集合,故只需要针对OrderVO集合中的每一个OrderVO对象封装每个订单的菜品或者套餐数据即可,明确了思路代码实现不难

2. 查询订单详情

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第3张图片
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第4张图片
路径参数为:id
返回数据为:OrderVO类

思路:

1.首先需要明确的是OrderVO其实是继承自Orders对象,故OrderVO类中也有Orders的属性,所以说只需要返回一个OrderVO对象即可拥有查询订单详情所需的数据

2.明白了继承关系后,其实通过id将Orders对象查询出来后进行对象属性拷贝到OrderVO对象,再通过id将orderDetail中的菜品或套餐数据查询出来赋值给OrderVO对象即可.

3. 取消订单

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第5张图片
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第6张图片
路径参数为:id
不需要返回数据,只需返回成功与否

业务规则:

  • 待支付和待接单状态下,用户可直接取消订单
  • 商家已接单状态下,用户取消订单需电话沟通商家
  • 派送中状态下,用户取消订单需电话沟通商家
  • 如果在待接单状态下取消订单,需要给用户退款
  • 取消订单后需要将订单状态修改为“已取消”

思路:

根据业务规则对应实现即可

4. 再来一单

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第7张图片
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第8张图片
路径参数为:id
不需要返回数据,只需返回成功与否

思路:
1.再来一单就是将原订单中的商品重新加入到购物车中

2.通过id将查询OrderDetail表,将相应的菜品或者套餐数据查询出来,重新通过用户id添加到购物车表中即可

3.通过订单id查询出来的肯定为集合数据,通过new一个购物车集合对象,然后对象属性拷贝到单个购物车对象即可,最后需要注意的是不能将orderDetail表中的菜品或者套餐的id拷贝到ShoppingCart对象中

二.商家端订单管理模块

1. 订单搜索

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第9张图片
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第10张图片
url传参为:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第11张图片

返回数据为:PageResult

业务规则:

  • 输入订单号/手机号进行搜索,支持模糊搜索
  • 根据订单状态进行筛选
  • 下单时间进行时间筛选
  • 搜索内容为空,提示未找到相关订单
  • 搜索结果页,展示包含搜索关键词的内容
  • 分页展示搜索到的订单数据

思路:

1.需要注意的是部分订单状态,需要额外返回订单菜品信息,即OrderVO中的订单菜品信息private String orderDishes属性,故传入PageResult中的为OrderVO集合

2.明确了第一点思路后,后面的实现和用户端的查询历史订单业务相似,首先对page对象中的Orders集合进行依次遍历,将其中的数据封装到OrderVO集合中,遍历过程中需要封装orderDishes属性的值.

3.接着第二点末尾,将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3;),则需要根据Orders中的id查询到OrderDetail集合,其中封装了菜品和套餐数据,然后将集合拼接成字符串返回即可

2. 各个状态的订单数量统计

产品原型:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第12张图片
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第13张图片
get方式不需要传参
返回数据为:OrderStatisticsVO类

思路:
使用count(id)和where status = #{status}"查询统计不同的status的id数量

3. 查询订单详情

此功能在用户端已经进行了实现,调用实现类的方法即可

4. 接单

产品原型:
商家端点击接单
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第14张图片
请求体传参:封装了id和status的OrdersConfirmDTO类(只有id有值)

业务规则:

  • 商家接单其实就是将订单的状态修改为“已接单”

思路:
修改状态即可

5. 拒单

产品原型:
商家端点击拒单
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第15张图片
请求体传参:封装了id和订单拒绝原因rejectionReason的OrdersRejectionDTO类

业务规则:

  • 商家拒单其实就是将订单状态修改为“已取消”
  • 只有订单处于“待接单”状态时可以执行拒单操作
  • 商家拒单时需要指定拒单原因
  • 商家拒单时,如果用户已经完成了支付,需要为用户退款

思路:
根据业务规则依次实现即可

6. 取消订单

产品原型:
商家端点击取消订单
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第16张图片
请求体传参:封装了id和订单取消原因cancelReason的OrdersCancelDTO类

业务规则:

  • 取消订单其实就是将订单状态修改为“已取消”
  • 商家取消订单时需要指定取消原因
  • 商家取消订单时,如果用户已经完成了支付,需要为用户退款

思路:
根据业务规则依次实现即可

7. 派送订单

产品原型:
商家端点击派送订单
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第17张图片
url传参:id

业务规则:

  • 派送订单其实就是将订单状态修改为“派送中”
  • 只有状态为“待派送”的订单可以执行派送订单操作

思路:
根据业务规则依次实现即可

8. 完成订单

产品原型:
商家端点击完成订单
接口设计:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第18张图片
url传参:id

业务规则:

  • 完成订单其实就是将订单状态修改为“已完成”
  • 只有状态为“派送中”的订单可以执行订单完成操作

思路:
根据业务规则依次实现即可

三.重点:校验收货地址是否超出配送范围

思路:调用百度地图的API,将商家的地址和用户的收货地址转换为经纬值,计算两者之间的距离,若小于某个距离则可以进行下单操作,反之抛出错误异常信息

实现思路:
1.地址连接:百度地图开发平台

2.找到Web服务API总览:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第19张图片
实现方式就是调用其中的两个API接口
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第20张图片

1.地址编码API

地址编码的开发文档中可以找到API服务地址,请求参数和返回参数
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第21张图片
请求参数和返回参数中重要的参数如下:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第22张图片
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第23张图片
通过观察文档可知,给地址编码的API一个地址就能返回这个地址所对应的经纬值

2.轻量级路线规划服务

轻量级路线规划服务的开发文档中可以找到API服务地址,请求参数和返回参数
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第24张图片
请求参数中重要的参数如下:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第25张图片
返回参数中重要的参数如下:
黑马苍穹外卖项目思路09_用户端历史订单、商家端订单管理_第26张图片
通过观察文档可知,通过传入起点和终点的经纬值就可以返回方案的距离,获得距离就可以判断是否满足配送距离要求

代码实现:
1.配置商家端的地址信息在配置文件(yml)中
2.在OrderServiceImpl中注入商家的地址和调用API所需的ak属性值

	@Value("${sky.shop.address}")
    private String shopAddress;

	@Value("${sky.baidu.ak}")
    private String ak;

在OrderServiceImpl中提供校验方法:

/**
     * 检查客户的收货地址是否超出配送范围
     * @param address
     */
    private void checkOutOfRange(String address) {
        Map map = new HashMap();
        map.put("address",shopAddress);
        map.put("output","json");
        map.put("ak",ak);

        //获取店铺的经纬度坐标
        String shopCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);

        JSONObject jsonObject = JSON.parseObject(shopCoordinate);
        if(!jsonObject.getString("status").equals("0")){
            throw new OrderBusinessException("店铺地址解析失败");
        }

        //数据解析
        JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");
        String lat = location.getString("lat");
        String lng = location.getString("lng");
        //店铺经纬度坐标
        String shopLngLat = lat + "," + lng;

        map.put("address",address);
        //获取用户收货地址的经纬度坐标
        String userCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);

        jsonObject = JSON.parseObject(userCoordinate);
        if(!jsonObject.getString("status").equals("0")){
            throw new OrderBusinessException("收货地址解析失败");
        }

        //数据解析
        location = jsonObject.getJSONObject("result").getJSONObject("location");
        lat = location.getString("lat");
        lng = location.getString("lng");
        //用户收货地址经纬度坐标
        String userLngLat = lat + "," + lng;

        map.put("origin",shopLngLat);
        map.put("destination",userLngLat);
        map.put("steps_info","0");

        //路线规划
        String json = HttpClientUtil.doGet("https://api.map.baidu.com/directionlite/v1/driving", map);

        jsonObject = JSON.parseObject(json);
        if(!jsonObject.getString("status").equals("0")){
            throw new OrderBusinessException("配送路线规划失败");
        }

        //数据解析
        JSONObject result = jsonObject.getJSONObject("result");
        JSONArray jsonArray = (JSONArray) result.get("routes");
        Integer distance = (Integer) ((JSONObject) jsonArray.get(0)).get("distance");

        if(distance > 5000){
            //配送距离超过5000米
            throw new OrderBusinessException("超出配送范围");
        }
    }

前面的课程中使用HttpClient次数很多了,代码并不复杂,难点是自己能分析出请求参数和返回参数和逻辑方面的判断

在OrderServiceImpl的submitOrder方法中调用上面的校验方法完成校验:

checkOutOfRange(addressBook.getCityName()+addressBook.getDistrictName()+addressBook.getDetail());

你可能感兴趣的:(java,数据库,前端,maven,服务器,开发语言,github)