From 81f11c9cc34e83adaf3dae5ec56fa7c80435cdbe Mon Sep 17 00:00:00 2001
From: zjk <852185829@qq.com>
Date: 星期四, 16 四月 2026 16:57:35 +0800
Subject: [PATCH] 1.行程中取消订单功能 2.修改目的地确认操作

---
 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java |  172 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 125 insertions(+), 47 deletions(-)

diff --git a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
index ceccd71..fabfcfb 100644
--- a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
+++ b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -16,7 +16,7 @@
 import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
 import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO;
 import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
-import com.xiaopeng.api.dto.operation.CruisePointDto;
+import com.xiaopeng.api.dto.map.RouteAndFareDto;
 import com.xiaopeng.api.dto.operation.LonLatDto;
 import com.xiaopeng.api.dto.order.GetOrderNumDto;
 import com.xiaopeng.api.dto.order.HistoryEndPointsDto;
@@ -27,18 +27,13 @@
 import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
 import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
 import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto;
-import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto;
-import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto;
 import com.xiaopeng.api.feignClient.account.UserResourcesClient;
 import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
 import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
 import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient;
 import com.xiaopeng.api.feignClient.maintenance.XpTaskRuleClient;
 import com.xiaopeng.api.feignClient.map.XpMapClient;
-import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
-import com.xiaopeng.api.feignClient.operation.XpPointClient;
-import com.xiaopeng.api.feignClient.operation.XpPricingClient;
-import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient;
+import com.xiaopeng.api.feignClient.operation.*;
 import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
 import com.xiaopeng.api.feignClient.vehicleConvoy.*;
 import com.xiaopeng.api.model.maintenance.XpTaskRule;
@@ -92,7 +87,6 @@
 import com.xiaopeng.order.utils.GDMapGeocodingUtil;
 import com.xiaopeng.order.utils.TaxiPricingDemoService;
 import com.xiaopeng.order.utils.RegionCodeFilterUtil;
-import com.xiaopeng.order.utils.TaxiPricingDemoService;
 import com.xiaopeng.order.utils.XpPricingUtil;
 import com.xiaopeng.order.utils.holiday.HolidayUtil;
 import com.xiaopeng.order.vo.OrderDetailVo;
@@ -163,6 +157,8 @@
     private final VehicleBuriedPointClient vehicleBuriedPointClient;
     private final IXpTestOrderService xpTestOrderService;
     private final XpMapClient xpMapClient;
+    @Resource
+    private  XpRoutePlanClient xpRoutePlanClient;
 
 
     @Autowired
@@ -1591,11 +1587,11 @@
     @ShardingSphereTransactionType(TransactionType.BASE)
     public void cancelOrder(Long orderId, String uid) {
         XpOrder order = this.getById(orderId);
-        if (order.getStatus() == 0) {
-            return;
-        }
         if (order == null) {
             throw new ServiceException("订单不存在", I18nKeyConstant.ORDER_NOT_EXISTS);
+        }
+        if (order.getStatus() == 0) {
+            return;
         }
         if (!order.getAppUserId().toString().equals(uid)) {
             throw new ServiceException("订单不存在", I18nKeyConstant.ORDER_NOT_EXISTS);
@@ -1603,7 +1599,6 @@
         if (order.getStatus() > 5 || order.getStatus() < 1) {
             throw new ServiceException("订单状态错误", I18nKeyConstant.ORDER_STATUS_ERROR);
         }
-
         try {
             redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
         } catch (Exception e) {
@@ -1625,39 +1620,20 @@
                 }
             }
         }
-
-        if (order.getStatus() == 1) {
-            order.setStatus(0);
-            order.setAppUserId(null);
-            baseMapper.updateById(order);
-            redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS);
-            return;
-        }
-        /*
-        order.setStatus(0);
-        order.setAppUserId(null);
-        baseMapper.updateById(order);
-        redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS);
-        XpOrderCancel xpOrderCancel = new XpOrderCancel();
-        xpOrderCancel.setOrderId(orderId);
-        xpOrderCancel.setUserId(Long.valueOf(uid));
-        xpOrderCancel.setCancelSource(1);
-        xpOrderCancel.setCancelReason("用户取消订单");
-        xpOrderCancelService.save(xpOrderCancel);
-        */
-
-        // 移除mongo数据
-        xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString());
-
-        // 下发命令
-        if (null != order.getVehicleId()) {
+        else{// 下发命令
             R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
-            // 组装调用车机参数
-            CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
             XpVehicle xpVehicle = xpVehicleR.getData();
             if (xpVehicle == null) {
                 throw new ServiceException("车辆不存在", I18nKeyConstant.VEHICLE_NOT_EXISTS);
             }
+            //是否能取消行程
+            boolean cancelShow = this.isCancelShow(order,xpVehicle.getVehicleVin());
+            if(cancelShow){
+                throw new ServiceException("当前订单状态不允许取消,行程即将完成", I18nKeyConstant.ORDER_CANCEL_FAILED);
+            }
+
+            // 组装调用车机参数
+            CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
             cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin());
             cancelTaxiPassengerVo.setUid(uid);
             cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
@@ -1688,7 +1664,19 @@
             //车辆继续巡游
             addCruiseMission(xpVehicle.getId());
         }
+        order.setStatus(0);
+        order.setAppUserId(null);
+        baseMapper.updateById(order);
+        redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS);
 
+        XpOrderCancel xpOrderCancel = new XpOrderCancel();
+        xpOrderCancel.setOrderId(orderId);
+        xpOrderCancel.setUserId(Long.valueOf(uid));
+        xpOrderCancel.setCancelSource(1);
+        xpOrderCancel.setCancelReason("用户取消订单");
+        xpOrderCancelService.save(xpOrderCancel);
+        // 移除mongo数据
+        xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString());
     }
 
     @Override
@@ -3478,6 +3466,7 @@
         if (xpOrder.getVehicleId() != null) {
             R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpOrder.getVehicleId());
             XpVehicle vehicle = xpVehicleR.getData();
+            xpOrderDetailVO.setVehicleVin(vehicle.getVehicleVin());
             xpOrderDetailVO.setPlateNumber(vehicle.getPlateNumber());
             xpOrderDetailVO.setVehiclePictures(vehicle.getVehiclePictures());
         }
@@ -3489,24 +3478,113 @@
             xpOrder.setAppUserId(null);
             this.updateById(xpOrder);
         }
-        Boolean cancelShow = true; //是否能取消行程
-        xpOrderDetailVO.setCancelShow(cancelShow);
-
-
-
         return xpOrderDetailVO;
     }
 
+    @Override
+    public XpOrderDetailVO getActiveOrder_itineraryManage(String uid){
+        XpOrderDetailVO xpOrderDetailVO = new XpOrderDetailVO();
+        XpOrder xpOrder = this.baseMapper.selectOne(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.parseLong(uid)).in(XpOrder::getStatus, Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)).orderByDesc(BaseModel::getCreateTime).last("LIMIT 1"));
+        if (xpOrder == null) {
+            return null;
+        }
+        BeanUtils.copyProperties(xpOrder, xpOrderDetailVO);
+        if (xpOrder.getVehicleId() != null) {
+            R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpOrder.getVehicleId());
+            XpVehicle vehicle = xpVehicleR.getData();
+            xpOrderDetailVO.setVehicleVin(vehicle.getVehicleVin());
+        }
+        Boolean cancelShow = isCancelShow(xpOrder,xpOrderDetailVO.getVehicleVin()); //是否能取消行程
+        xpOrderDetailVO.setCancelShow(cancelShow);
+        return xpOrderDetailVO;
+    }
     /**
      * 取消行程:若处于“送驾中”且离目的地小于10分钟路程(后台配置),【取消行程】按钮应置灰;
      * 修改行程:
      * 1. 当前剩余里程 < 800米 (后台配置)或 剩余时间 < 5分钟(后台配置)(以先到者为准),禁止修改,按钮置灰。
      * 2. 单次行程最多允许修改 2次 (后台配置)目的地,防恶意高频调用
+     * 特殊豁免:若系统检测到车辆在当前坐标时速 < 3km/h 且持续时间 > 3分钟(后台配置)(判定为极度拥堵或异常停滞),此时解除限制,允许用户修改目的地或新增途径点以寻找更近的下车位置。
      * @return
      */
-    private Boolean isCancelShow(){
+    private boolean isCancelShow(XpOrder xpOrder,String vehicleVin) {
+        boolean isCancel = false;
+        //获取配置文件
+        int sylc = 800;//单位米 todo yyy 需要读取后台配置文件
+        int sysj = 5;//单位分钟 todo yyy 需要读取后台配置文件
+        // 减少3分钟 获取3分账内的 行程数据
+        long minute =3;//todo yyy 需要读取后台配置文件
 
-        return true;
+
+        List<OrderTrajectory> orderTrajectories = queryOrderTrajectories(xpOrder.getId());
+        if(!orderTrajectories.isEmpty()){// 减少3分钟 获取3分账内的 行程数据
+            //3千米/小时 转换成分钟 50米/分钟
+            BigDecimal suduDefault = new BigDecimal("3");//3千米/小时
+            BigDecimal suduDefault1 = suduDefault.multiply(BigDecimal.valueOf(1000)) ;
+            BigDecimal suduDefaultNew =suduDefault1.divide(BigDecimal.valueOf(60),2,RoundingMode.HALF_EVEN);
+
+            LocalDateTime minutesBefore = LocalDateTime.now().minusMinutes(minute);
+            long milliseconds = DateUtils.getMilliseconds(minutesBefore);
+            List<OrderTrajectory> orderTrajectoriesNew = new ArrayList<>();
+            for (OrderTrajectory orderTrajectory : orderTrajectories) {
+                if(orderTrajectory.getLocatetime() > milliseconds){
+                    orderTrajectoriesNew.add(orderTrajectory);
+                }
+            }
+            /*
+            获取最近3分钟的 数据 速度、平均
+             */
+            //计算行驶总距离和时长
+            Double reduce = orderTrajectoriesNew.stream().map(OrderTrajectory::getDistance).reduce(0.0, Double::sum);
+            BigDecimal xcsudu = new BigDecimal(reduce).divide(new BigDecimal(minute),2, RoundingMode.HALF_EVEN);//米/分钟
+
+            //特殊豁免:若系统检测到车辆在当前坐标时速 < 3km/h 且持续时间 > 3分钟(后台配置)(判定为极度拥堵或异常停滞),此时解除限制,允许用户修改目的地或新增途径点以寻找更近的下车位置。
+            if(xcsudu.compareTo(suduDefaultNew)<0){
+                return true;
+            }
+        }
+        RouteVo routeVo = this.getRouteVo(xpOrder, vehicleVin);
+        if(routeVo.getDistance() <sylc){
+            isCancel = true;
+        }
+        if(routeVo.getDuration() < sysj){
+            isCancel = true;
+        }
+
+        return isCancel;
+    }
+
+    /**
+     * 获取两个点位车的距离 和时间
+     * @param xpOrder
+     * @param vehicleVin
+     * @return
+     */
+    private RouteVo getRouteVo(XpOrder xpOrder,String vehicleVin){
+
+        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vehicleVin)), VehiclePosition.class);
+        // 计算距离 和 时间
+        RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
+        LonLatDto lonLatDto = new LonLatDto();
+        lonLatDto.setLongitude(vehiclePosition.getPoint().getX());//经度
+        lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
+        routeAndFareDto.setOrigin(lonLatDto);
+
+        LonLatDto lonLatDto1 = new LonLatDto();
+        lonLatDto1.setLongitude(xpOrder.getEndLon());
+        lonLatDto1.setLatitude(xpOrder.getEndLat());
+        routeAndFareDto.setDestination(lonLatDto1);
+
+//        XpOpenCity xpOpenCity = xpOpenCityMapper.selectById(dto.getOpenCityId());
+//        xpRoutePlanClient.
+        XpRoutePlan xpRoutePlan = xpRoutePlanClient.getXpRoutePlanOpenCityId(xpOrder.getCityId()).getData();
+        if (xpRoutePlan != null) {
+            routeAndFareDto.setRoutePlanRule(xpRoutePlan.getRoutePlanRule());
+        }
+        R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
+        if(distanceAndDuration.getCode()!=200){
+            throw new ServiceException("未找到路径", I18nKeyConstant.PATH_NOT_FOUND);
+        }
+        return distanceAndDuration.getData();
     }
 
 

--
Gitblit v1.7.1