产品原型:
业务规则:
接口设计:参见接口文档
在admin包下创建OrderController
/** * 订单管理 */ @RestController("adminOrderController") @RequestMapping("/admin/order") @Slf4j @Api(tags = "订单管理接口") public class OrderController { @Autowired private OrderService orderService; /** * 订单搜索 * * @param ordersPageQueryDTO * @return */ @GetMapping("/conditionSearch") @ApiOperation("订单搜索") public ResultconditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) { PageResult pageResult = orderService.conditionSearch(ordersPageQueryDTO); return Result.success(pageResult); } }
/** * 条件搜索订单 * @param ordersPageQueryDTO * @return */ PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO);
/** * 订单搜索 * * @param ordersPageQueryDTO * @return */ public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) { PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize()); Pagepage = orderMapper.pageQuery(ordersPageQueryDTO); // 部分订单状态,需要额外返回订单菜品信息,将Orders转化为OrderVO List orderVOList = getOrderVOList(page); return new PageResult(page.getTotal(), orderVOList); } private List getOrderVOList(Page page) { // 需要返回订单菜品信息,自定义OrderVO响应结果 List orderVOList = new ArrayList<>(); List ordersList = page.getResult(); if (!CollectionUtils.isEmpty(ordersList)) { for (Orders orders : ordersList) { // 将共同字段复制到OrderVO OrderVO orderVO = new OrderVO(); BeanUtils.copyProperties(orders, orderVO); String orderDishes = getOrderDishesStr(orders); // 将订单菜品信息封装到orderVO中,并添加到orderVOList orderVO.setOrderDishes(orderDishes); orderVOList.add(orderVO); } } return orderVOList; } /** * 根据订单id获取菜品信息字符串 * * @param orders * @return */ private String getOrderDishesStr(Orders orders) { // 查询订单菜品详情信息(订单中的菜品和数量) List orderDetailList = orderDetailMapper.getByOrderId(orders.getId()); // 将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3;) List orderDishList = orderDetailList.stream().map(x -> { String orderDish = x.getName() + "*" + x.getNumber() + ";"; return orderDish; }).collect(Collectors.toList()); // 将该订单对应的所有菜品信息拼接在一起 return String.join("", orderDishList); }
接口设计:参见接口文档
/** * 各个状态的订单数量统计 * * @return */ @GetMapping("/statistics") @ApiOperation("各个状态的订单数量统计") public Resultstatistics() { OrderStatisticsVO orderStatisticsVO = orderService.statistics(); return Result.success(orderStatisticsVO); }
/** * 各个状态的订单数量统计 * @return */ OrderStatisticsVO statistics();
/** * 各个状态的订单数量统计 * * @return */ public OrderStatisticsVO statistics() { // 根据状态,分别查询出待接单、待派送、派送中的订单数量 Integer toBeConfirmed = orderMapper.countStatus(Orders.TO_BE_CONFIRMED); Integer confirmed = orderMapper.countStatus(Orders.CONFIRMED); Integer deliveryInProgress = orderMapper.countStatus(Orders.DELIVERY_IN_PROGRESS); // 将查询出的数据封装到orderStatisticsVO中响应 OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO(); orderStatisticsVO.setToBeConfirmed(toBeConfirmed); orderStatisticsVO.setConfirmed(confirmed); orderStatisticsVO.setDeliveryInProgress(deliveryInProgress); return orderStatisticsVO; }
/** * 根据状态统计订单数量 * @param status */ @Select("select count(id) from orders where status = #{status}") Integer countStatus(Integer status);
产品原型:
业务规则:
接口设计:参见接口文档
/** * 订单详情 * * @param id * @return */ @GetMapping("/details/{id}") @ApiOperation("查询订单详情") public Resultdetails(@PathVariable("id") Long id) { OrderVO orderVO = orderService.details(id); return Result.success(orderVO); }
产品原型:
业务规则:
接口设计:参见接口文档
/** * 接单 * * @return */ @PutMapping("/confirm") @ApiOperation("接单") public Result confirm(@RequestBody OrdersConfirmDTO ordersConfirmDTO) { orderService.confirm(ordersConfirmDTO); return Result.success(); }
/** * 接单 * * @param ordersConfirmDTO */ void confirm(OrdersConfirmDTO ordersConfirmDTO);
/** * 接单 * * @param ordersConfirmDTO */ public void confirm(OrdersConfirmDTO ordersConfirmDTO) { Orders orders = Orders.builder() .id(ordersConfirmDTO.getId()) .status(Orders.CONFIRMED) .build(); orderMapper.update(orders); }
业务规则:
接口设计:参见接口文档
/** * 拒单 * * @return */ @PutMapping("/rejection") @ApiOperation("拒单") public Result rejection(@RequestBody OrdersRejectionDTO ordersRejectionDTO) throws Exception { orderService.rejection(ordersRejectionDTO); return Result.success(); }
/** * 拒单 * * @param ordersRejectionDTO */ void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception;
/** * 拒单 * * @param ordersRejectionDTO */ public void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception { // 根据id查询订单 Orders ordersDB = orderMapper.getById(ordersRejectionDTO.getId()); // 订单只有存在且状态为2(待接单)才可以拒单 if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) { throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); } //支付状态 Integer payStatus = ordersDB.getPayStatus(); if (payStatus == Orders.PAID) { //用户已支付,需要退款 String refund = weChatPayUtil.refund( ordersDB.getNumber(), ordersDB.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01)); log.info("申请退款:{}", refund); } // 拒单需要退款,根据订单id更新订单状态、拒单原因、取消时间 Orders orders = new Orders(); orders.setId(ordersDB.getId()); orders.setStatus(Orders.CANCELLED); orders.setRejectionReason(ordersRejectionDTO.getRejectionReason()); orders.setCancelTime(LocalDateTime.now()); orderMapper.update(orders); }
业务规则:
接口设计:参见接口文档
/** * 取消订单 * * @return */ @PutMapping("/cancel") @ApiOperation("取消订单") public Result cancel(@RequestBody OrdersCancelDTO ordersCancelDTO) throws Exception { orderService.cancel(ordersCancelDTO); return Result.success(); }
/** * 商家取消订单 * * @param ordersCancelDTO */ void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception;
/** * 取消订单 * * @param ordersCancelDTO */ public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception { // 根据id查询订单 Orders ordersDB = orderMapper.getById(ordersCancelDTO.getId()); //支付状态 Integer payStatus = ordersDB.getPayStatus(); if (payStatus == 1) { //用户已支付,需要退款 String refund = weChatPayUtil.refund( ordersDB.getNumber(), ordersDB.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01)); log.info("申请退款:{}", refund); } // 管理端取消订单需要退款,根据订单id更新订单状态、取消原因、取消时间 Orders orders = new Orders(); orders.setId(ordersCancelDTO.getId()); orders.setStatus(Orders.CANCELLED); orders.setCancelReason(ordersCancelDTO.getCancelReason()); orders.setCancelTime(LocalDateTime.now()); orderMapper.update(orders); }
产品原型:
业务规则:
接口设计:参见接口文档
/** * 派送订单 * * @return */ @PutMapping("/delivery/{id}") @ApiOperation("派送订单") public Result delivery(@PathVariable("id") Long id) { orderService.delivery(id); return Result.success(); }
/** * 派送订单 * * @param id */ void delivery(Long id);
/** * 派送订单 * * @param id */ public void delivery(Long id) { // 根据id查询订单 Orders ordersDB = orderMapper.getById(id); // 校验订单是否存在,并且状态为3 if (ordersDB == null || !ordersDB.getStatus().equals(Orders.CONFIRMED)) { throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); } Orders orders = new Orders(); orders.setId(ordersDB.getId()); // 更新订单状态,状态转为派送中 orders.setStatus(Orders.DELIVERY_IN_PROGRESS); orderMapper.update(orders); }
业务规则:
接口设计:参见接口文档
/** * 完成订单 * * @return */ @PutMapping("/complete/{id}") @ApiOperation("完成订单") public Result complete(@PathVariable("id") Long id) { orderService.complete(id); return Result.success(); }
/** * 完成订单 * * @param id */ void complete(Long id);
/** * 完成订单 * * @param id */ public void complete(Long id) { // 根据id查询订单 Orders ordersDB = orderMapper.getById(id); // 校验订单是否存在,并且状态为4 if (ordersDB == null || !ordersDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) { throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); } Orders orders = new Orders(); orders.setId(ordersDB.getId()); // 更新订单状态,状态转为完成 orders.setStatus(Orders.COMPLETED); orders.setDeliveryTime(LocalDateTime.now()); orderMapper.update(orders); }
注册账号:https://passport.baidu.com/v2/?reg&tt=1671699340600&overseas=&gid=CF954C2-A3D2-417F-9FE6-B0F249ED7E33&tpl=pp&u=https%3A%2F%2Flbsyun.baidu.com%2Findex.php%3Ftitle%3D%E9%A6%96%E9%A1%B5
登录百度地图开放平台:https://lbsyun.baidu.com/
进入控制台,创建应用,获取AK:
相关接口:
https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
https://lbsyun.baidu.com/index.php?title=webapi/directionlite-v1
配置外卖商家店铺地址和百度地图的AK:
改造OrderServiceImpl,注入上面的配置项:
@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("超出配送范围"); } }
在OrderServiceImpl的submitOrder方法中调用上面的校验方法:
后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹