实习项目|苍穹外卖|day9

实战作业。

用户端新增功能

1. 查询历史订单

接口设计

在这里插入图片描述
返回的是order+orderdetails(那我这里就先查order,再根据order_id查)

分页

pageHelper的使用:

//controller相关函数
    @GetMapping("/historyOrders")
    @ApiOperation("历史订单查询")//query 不用@RequestBody 
    public Result<PageResult> historyOrders(OrdersPageQueryDTO ordersPageQueryDTO){
        log.info("历史订单查询:{}", ordersPageQueryDTO);
        PageResult pageResult = orderService.historyOrders(ordersPageQueryDTO);
        return Result.success(pageResult);
//service实现类相关函数
    public PageResult historyOrders(OrdersPageQueryDTO ordersPageQueryDTO) {
        Long userId = BaseContext.getCurrentId();
        ordersPageQueryDTO.setUserId(userId);

        // 原型就是select * from employee limit 0, 10
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Page<OrderVO> page = orderMapper.pageQuery(ordersPageQueryDTO);
        long total = page.getTotal();
        List<OrderVO> results = page.getResult();
        for (OrderVO result : results) {
            Long orderId = result.getId();
            List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orderId);
            result.setOrderDetailList(orderDetailList);
        }

        return new PageResult(total, results);
    }
// mapper.xml
    <select id="pageQuery" resultType="com.sky.vo.OrderVO">
        select * from orders
        <where>
            <if test="status != null and status != ''">
                and status = #{status}
            </if>
        </where>
        order by order_time desc
    </select>

2.查询历史订单详情

已知orderId查询,与上一个功能类似。

3.取消订单

在这里插入图片描述
非常简单的修改状态+修改时间?
是不是要有逻辑判断啊?(什么状态下是可以取消的?)

3.再来一单

在这里插入图片描述

这里有一个难点,就是如何插入新的订单(好多信息,比如预计送达时间等等要怎么处理?)

管理端

1.订单搜索

个人觉得难点就在于,啊啊啊,好多条件用来搜索,sql语言怎么写啊!!!
service的逻辑不太清楚是不是以下这样的:

PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Page<OrderVO> page = orderMapper.conditionSearch(ordersPageQueryDTO);

        long total = page.getTotal();
        List<OrderVO> result = page.getResult();

        for (OrderVO orderVO : result) {
            StringBuffer orderDishs = new StringBuffer();
            Long id = orderVO.getId();
            List<OrderDetail> orderDetails = orderDetailMapper.getByOrderId(id);
            for (OrderDetail orderDetail : orderDetails) {
                Long dishId = orderDetail.getDishId();//判断是不是菜品
                Dish dish;
                if(dishId != null){//是菜品,直接查询菜品表
                    dish = dishMapper.getById(dishId);
                    orderDishs.append(dish.toString());
                }else {//是套餐,查询套餐表//根据套餐ID,查下面的菜品ID,再查菜品信息
                    Long setmealId = orderDetail.getSetmealId();
                    List<SetmealDish> bySetmealId = setmealDishMapper.getBySetmealId(setmealId);
                    for (SetmealDish setmealDish : bySetmealId) {
                        dish = dishMapper.getById(setmealDish.getDishId());
                        orderDishs.append(dish.toString());
                    }
                }
                orderVO.setOrderDishes(orderDishs.toString());
            }

mapper

    <select id="conditionSearch" resultType="com.sky.vo.OrderVO">
        select * from orders
        <where>
            <if test="number != null and number != ''">
                and number = #{number}
            </if>
            <if test="phone != null and phone != ''">
                and phone = #{phone}
            </if>
            <if test="beginTime != null">
                and order_time &gt;= #{beginTime}
            </if>
            <if test="endTime != null">
                and order_time &lt;= #{endTime}
            </if>
            <if test="status != null and status != ''">
                and status = #{status}
            </if>
        </where>
        order by order_time desc
    </select>

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

    public OrderStatisticsVO statistics() {
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        Integer confirmed = orderMapper.countInStatus(Orders.CONFIRMED);
        Integer deliveryInProgress = orderMapper.countInStatus(Orders.DELIVERY_IN_PROGRESS);
        Integer  toBeConfirmed = orderMapper.countInStatus(Orders.TO_BE_CONFIRMED);
        orderStatisticsVO.setConfirmed(confirmed);
        orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
        orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
        
        return orderStatisticsVO;
    }

3.查询订单详情

与用户端共用一个service实现。

4.接单

改变订单状态。

5.拒单

这里面有逻辑我不是很清晰,拒单算作取消订单还是完成订单?

6.取消订单

和拒单几乎一样

7.派送订单

8.完成订单

在这里插入图片描述

        //这里自己设置一个状态检测吧,并不是任何状态都可以

        Orders order = orderMapper.getById(id);
        if (order.getStatus() != Orders.DELIVERY_IN_PROGRESS){
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }else{
            order.setStatus(Orders.COMPLETED);
            order.setDeliveryTime(LocalDateTime.now());
            orderMapper.update(order);
        }

已有功能优化

优化用户下单功能,加入校验逻辑,如果用户的收货地址距离商家门店超出配送范围(配送范围为5公里内),则下单失败。

提示:

​ 1. 基于百度地图开放平台实现(https://lbsyun.baidu.com/)

​ 2. 注册账号—>创建应用获取AK(服务端应用)—>调用接口

  1. 相关接口

    https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

    https://lbsyun.baidu.com/index.php?title=webapi/directionlite-v1

  2. 商家门店地址可以配置在配置文件中,例如:

    sky:
      shop:
        address: 北京市海淀区上地十街10号
    

自己的分析

我要知道我门店的位置(给的提示是写在配置里面,那应该是有对应的类了,那就可以直接依赖注入使用),要知道用户的位置(用户提交订单里面的地址提取出来!)。然后计算。

package com.sky.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "sky.shop")
@Data
public class ShopProperties {

    private String address;
    
}

API学习:地理编码+骑行路线规划

直接用百度的代码,感觉还是不行,这样代码风格不统一,自己阅读起来也很难受。

  1. 如何获取application.yam中的配置:@Value注解 更多方法
  2. 如何使用HttpClient:基于老师已给的HttpClientUtil进行的,直接doGet。
  3. 解析api调用返回的String报错。JSON.parseObject(str)。报错信息
    @Value("${sky.shop.address}")
    String shopAddress;

    @Value("${sky.baidumap.AK}")
    String Ak;

    @Value("${sky.baidumap.geocodingUrl}")
    String geocodingUrl;

    @Value("${sky.baidumap.distanceUrl}")
    String distanceUrl;
  1. 我现在纠结的点在于如何反馈,能够让客户端知道是距离问题导致的。

对答案

原本计划两天前就完成的,但是电脑出了些问题,如今重装了系统,一切恢复如常。还是一句话:有用的东西装D盘,所以基本上就是下下几个版本号错误的软件,重新安装一下mysql(数据都保存在D盘,简单恢复一下就好),就没多大事!!!

实战内容

完成用户端历史订单模块、商家端订单管理模块相关业务新功能开发和已有功能优化,具体任务列表如下:

1. 新功能开发

用户端历史订单模块:

  • 查询历史订单
  • 查询订单详情
  • 取消订单 //考虑不足,没有考虑到订单是否存在;没有理清状态改变。待接单状态下要退钱,退完钱要更新到取消状态。
// 校验订单是否存在
        if (ordersDB == null) {
            throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
        }

        //订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
        if (ordersDB.getStatus() > 2) {
            throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
        }

        Orders orders = new Orders();
        orders.setId(ordersDB.getId());

        // 订单处于待接单状态下取消,需要进行退款
        if (ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
            //调用微信支付退款接口
//            weChatPayUtil.refund(
//                    ordersDB.getNumber(), //商户订单号
//                    ordersDB.getNumber(), //商户退款单号
//                    new BigDecimal(0.01),//退款金额,单位 元
//                    new BigDecimal(0.01));//原订单金额

            //支付状态修改为 退款
            orders.setPayStatus(Orders.REFUND);
        }

        // 更新订单状态、取消原因、取消时间
        orders.setStatus(Orders.CANCELLED);
  • 再来一单 //答案思路是把数据库的数据转为购物车对象:
public void repetition(Long id) {
        // 查询当前用户id
        Long userId = BaseContext.getCurrentId();

        // 根据订单id查询当前订单详情
        List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);

        // 将订单详情对象转换为购物车对象
        List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(x -> {
            ShoppingCart shoppingCart = new ShoppingCart();

            // 将原订单详情里面的菜品信息重新复制到购物车对象中
            BeanUtils.copyProperties(x, shoppingCart, "id");
            shoppingCart.setUserId(userId);
            shoppingCart.setCreateTime(LocalDateTime.now());

            return shoppingCart;
        }).collect(Collectors.toList());

        // 将购物车对象批量添加到数据库
        shoppingCartMapper.insertBatch(shoppingCartList);
    }

商家端订单管理模块:(校验订单是否存在,和退款都是没有考虑到的。)

  • 订单搜索 (好奇怪,答案里的代码里没有考虑套餐的问题?答:直接套餐名*数量)
  • 各个状态的订单数量统计
  • 查询订单详情
  • 接单
  • 拒单 (没考虑已付款要退钱的问题。)
  • 取消订单
  • 派送订单
  • 完成订单
2. 已有功能优化

优化用户下单功能,加入校验逻辑,如果用户的收货地址距离商家门店超出配送范围(配送范围为5公里内),则下单失败。

提示:

​ 1. 基于百度地图开放平台实现(https://lbsyun.baidu.com/)

​ 2. 注册账号—>创建应用获取AK(服务端应用)—>调用接口

  1. 相关接口

    https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

    https://lbsyun.baidu.com/index.php?title=webapi/directionlite-v1

  2. 商家门店地址可以配置在配置文件中,例如:

    sky:
      shop:
        address: 北京市海淀区上地十街10号
    

实战要求

  1. 根据产品原型进行需求分析和接口设计
  2. 根据接口设计进行代码实现
  3. 分别通过swagger接口文档和前后端联调进行功能测试
  4. 分组实战(具体任务分工由组长分配)

主要的问题是:如何从配置中获取信息@value。如何访问接口(doGet,doPost,map)。如何解析得到的返回值(难,至今没搞懂,出了问题是照着答案抄的。)

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

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

    /**
     * 检查客户的收货地址是否超出配送范围
     * @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("超出配送范围");
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值