业务规则:
接口设计:
url传参为:page,pageSize,status
返回数据为:PageResult
思路:
1.需要注意的是,返回给页面的数据为集合嵌套了集合(历史订单有多个订单数据,一个订单数据又有多个菜品或者套餐数据)
2.需要明确的是PageResult中的集合属性应为OrderVO集合,其中一个OrderVO中封装了OrderDetail集合,故只需要针对OrderVO集合中的每一个OrderVO对象封装每个订单的菜品或者套餐数据即可,明确了思路代码实现不难
产品原型:
接口设计:
路径参数为:id
返回数据为:OrderVO类
思路:
1.首先需要明确的是OrderVO其实是继承自Orders对象,故OrderVO类中也有Orders的属性,所以说只需要返回一个OrderVO对象即可拥有查询订单详情所需的数据
2.明白了继承关系后,其实通过id将Orders对象查询出来后进行对象属性拷贝到OrderVO对象,再通过id将orderDetail中的菜品或套餐数据查询出来赋值给OrderVO对象即可.
产品原型:
接口设计:
路径参数为:id
不需要返回数据,只需返回成功与否
业务规则:
思路:
根据业务规则对应实现即可
产品原型:
接口设计:
路径参数为:id
不需要返回数据,只需返回成功与否
思路:
1.再来一单就是将原订单中的商品重新加入到购物车中
2.通过id将查询OrderDetail表,将相应的菜品或者套餐数据查询出来,重新通过用户id添加到购物车表中即可
3.通过订单id查询出来的肯定为集合数据,通过new一个购物车集合对象,然后对象属性拷贝到单个购物车对象即可,最后需要注意的是不能将orderDetail表中的菜品或者套餐的id拷贝到ShoppingCart对象中
返回数据为:PageResult
业务规则:
思路:
1.需要注意的是部分订单状态,需要额外返回订单菜品信息,即OrderVO中的订单菜品信息private String orderDishes属性,故传入PageResult中的为OrderVO集合
2.明确了第一点思路后,后面的实现和用户端的查询历史订单业务相似,首先对page对象中的Orders集合进行依次遍历,将其中的数据封装到OrderVO集合中,遍历过程中需要封装orderDishes属性的值.
3.接着第二点末尾,将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3;),则需要根据Orders中的id查询到OrderDetail集合,其中封装了菜品和套餐数据,然后将集合拼接成字符串返回即可
产品原型:
接口设计:
get方式不需要传参
返回数据为:OrderStatisticsVO类
思路:
使用count(id)和where status = #{status}"查询统计不同的status的id数量
此功能在用户端已经进行了实现,调用实现类的方法即可
产品原型:
商家端点击接单
接口设计:
请求体传参:封装了id和status的OrdersConfirmDTO类(只有id有值)
业务规则:
思路:
修改状态即可
产品原型:
商家端点击拒单
接口设计:
请求体传参:封装了id和订单拒绝原因rejectionReason的OrdersRejectionDTO类
业务规则:
思路:
根据业务规则依次实现即可
产品原型:
商家端点击取消订单
接口设计:
请求体传参:封装了id和订单取消原因cancelReason的OrdersCancelDTO类
业务规则:
思路:
根据业务规则依次实现即可
产品原型:
商家端点击派送订单
接口设计:
url传参:id
业务规则:
思路:
根据业务规则依次实现即可
产品原型:
商家端点击完成订单
接口设计:
url传参:id
业务规则:
思路:
根据业务规则依次实现即可
思路:调用百度地图的API,将商家的地址和用户的收货地址转换为经纬值,计算两者之间的距离,若小于某个距离则可以进行下单操作,反之抛出错误异常信息
实现思路:
1.地址连接:百度地图开发平台
2.找到Web服务API总览:
实现方式就是调用其中的两个API接口
地址编码的开发文档中可以找到API服务地址,请求参数和返回参数
请求参数和返回参数中重要的参数如下:
通过观察文档可知,给地址编码的API一个地址就能返回这个地址所对应的经纬值
轻量级路线规划服务的开发文档中可以找到API服务地址,请求参数和返回参数
请求参数中重要的参数如下:
返回参数中重要的参数如下:
通过观察文档可知,通过传入起点和终点的经纬值就可以返回方案的距离,获得距离就可以判断是否满足配送距离要求
代码实现:
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());