liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpTestOrderServiceImpl.java
@@ -2,6 +2,7 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -9,12 +10,10 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.ImmutableMap;
import com.xiaopeng.api.dto.account.GetUserCouponDto;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
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.pushMessage.SendMessageDTO;
import com.xiaopeng.api.feignClient.account.UserResourcesClient;
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
@@ -32,20 +31,19 @@
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.SystemEventType;
import com.xiaopeng.api.vo.account.UserCouponVo;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperationType;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.FareBreakdownDetailVo;
import com.xiaopeng.api.vo.order.XpPricingCardVo;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.constant.HttpStatus;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.GeodesyUtil;
import com.xiaopeng.common.core.utils.SensitiveDataCryptoUtil;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.web.domain.BaseModel;
import com.xiaopeng.common.core.web.page.PageInfo;
@@ -54,10 +52,9 @@
import com.xiaopeng.order.constant.I18nKeyConstant;
import com.xiaopeng.order.job.base.QuartzManager;
import com.xiaopeng.order.job.base.TimeJobType;
import com.xiaopeng.order.job.jobs.AddCruiseMissionJob;
import com.xiaopeng.order.job.jobs.EndTripJob;
import com.xiaopeng.order.job.jobs.OrderCancelJob;
import com.xiaopeng.order.mangodb.model.OrderTrajectory;
import com.xiaopeng.order.job.jobs.TestOrderCancelJob;
import com.xiaopeng.api.model.order.OrderTrajectory;
import com.xiaopeng.order.mapper.XpCruiseOrderMapper;
import com.xiaopeng.order.mapper.XpTestOrderDetailMapper;
import com.xiaopeng.order.mapper.XpTestOrderMapper;
@@ -65,10 +62,7 @@
import com.xiaopeng.order.model.vo.AddTestOrderVo;
import com.xiaopeng.order.model.vo.XpTestOrderDetailVO;
import com.xiaopeng.order.model.vo.XpTestOrderPageVO;
import com.xiaopeng.order.service.IXpOrderEvaluateService;
import com.xiaopeng.order.service.IXpOrderReassignService;
import com.xiaopeng.order.service.IXpTestOrderCancelService;
import com.xiaopeng.order.service.IXpTestOrderService;
import com.xiaopeng.order.service.*;
import com.xiaopeng.order.utils.GDMapGeocodingUtil;
import com.xiaopeng.order.utils.TaxiPricingDemoService;
import com.xiaopeng.order.utils.XpPricingUtil;
@@ -78,6 +72,7 @@
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
@@ -88,14 +83,13 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -122,7 +116,9 @@
    private final UserVehicleClient userVehicleClient;
    private final IXpOrderEvaluateService xpOrderEvaluateService;
    private final IXpTestOrderCancelService xpTestOrderCancelService;
    private final IXpOrderReassignService xpOrderReassignService;
    @Lazy
    @Autowired
    private IXpOrderReassignService xpOrderReassignService;
    private final RedisService redisService;
    private final XpPricingClient xpPricingClient;
    private final XpSystemSettingClient xpSystemSettingClient;
@@ -142,8 +138,17 @@
    private final MongoTemplate mongoTemplate;
    private final XpElectronicFenceClient xpElectronicFenceClient;
    private final XpElectronicClient xpElectronicClient;
    private final XpTestPointClient testPointClient;
    @Resource
    private BootCommonService bootCommonService;
    @Resource
    private XpTradingStrategyClient tradingStrategyClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
@@ -156,8 +161,8 @@
    public void addTestOrder(AddTestOrderVo query) {
        Long startTestPointId = query.getStartTestPointId();
        Long endTestPointId = query.getEndTestPointId();
        XpTestPoint xpPoint = xpTestPlanClient.getXpTestPointById(startTestPointId).getData();
        XpTestPoint endXpPoint = xpTestPlanClient.getXpTestPointById(endTestPointId).getData();
        XpTestPoint xpPoint = testPointClient.queryById(startTestPointId).getData();
        XpTestPoint endXpPoint = testPointClient.queryById(endTestPointId).getData();
        if(xpPoint ==null || xpPoint.getOperationStatus()!=2){
            throw new ServiceException("起站点已停止运营", 200,I18nKeyConstant.NO_CURRENT_POINT);
        }
@@ -191,7 +196,7 @@
        if (openCity == null) {
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        XpPricing xpPricing = xpPricingClient.getPricingByCid(openCity.getId()).getData();
        XpPricing xpPricing = bootCommonService.getXpPricing(openCity.getId(),null);
        if (xpPricing == null) {
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
@@ -224,8 +229,11 @@
        xpOrder.setTestPlanId(query.getTestPlanId());
        xpOrder.setOrderType(query.getOrderType());
        xpOrder.setMileageKilometers(0.0);
        xpOrder.setOrderNumber("XP" + System.currentTimeMillis());
        xpOrder.setOrderNumber(getOrderNumber());
        xpOrder.setCityId(openCity.getId());
        xpOrder.setPlacementLat(xpPoint.getPointLat());
        xpOrder.setPlacementLon(xpPoint.getPointLon());
        xpOrder.setPlacementAddress(xpPoint.getPointAddress());
        xpOrder.setStartLon(xpPoint.getPointLon());
        xpOrder.setStartLat(xpPoint.getPointLat());
        xpOrder.setBoardingLon(xpPoint.getPointLon());
@@ -246,6 +254,8 @@
        xpOrder.setStatus(1);
        xpOrder.setOrderSource(1);
        xpOrder.setOpenTrunk(2);
        xpOrder.setXpuStartTaskId(snowflake.nextId() + "");
        xpOrder.setXpuEndTaskId(snowflake.nextId() + "");
        // 当前时段
        String currentTimeSlot = DateUtils.getCurrentTimeSlot();
@@ -256,27 +266,40 @@
        List<Long> vehicleIds = query.getVehicleIds();
        for (Long vehicleId : vehicleIds) {
            xpOrder.setId(null);
            XpVehicle xpVehicle = xpVehicleClient.queryById(vehicleId).getData();
            String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
            xpOrder.setVehicleId(vehicleId);
            xpOrder.setFleetId(xpVehicle.getFleetId());
            this.save(xpOrder);
            redisService.setCacheObject("ORDER_STATUS:" + xpOrder.getId(), 1, 24L, TimeUnit.HOURS);
            redisService.setCacheObject("TEST_ORDER_STATUS:" + xpOrder.getId(), 1, 24L, TimeUnit.HOURS);
            //缓存导航数据,用于下单后推送导航给车端和乘客端
            redisService.setCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + vehicleId, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
            //下发XPU消息
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId());
            pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId());
            pushOrderDto.setVin(vin);
            pushOrderDto.setOrderId("TEST" + xpOrder.getId());
            pushOrderDto.setStartWaypointId(xpOrder.getStartTestPointId());
            pushOrderDto.setEndWaypointId(xpOrder.getEndTestPointId());
            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
            pushOrderDto.setEndLatitude(xpOrder.getEndLat());
            pushOrderDto.setEndLongitude(xpOrder.getEndLon());
            pushOrderDto.setEndPoiName(xpOrder.getEndTestPointName());
            pushOrderDto.setOrderType(xpOrder.getOrderType() == 1 ? OrderType.TEST_ORDER : OrderType.TEST_CRUISE_ORDER);
            pushOrderDto.setStage(1);
            // 调用推送服务  orderId + carVin
            orderMissionClient.pushOrder(pushOrderDto);
        }
    }
    private String getOrderNumber(){
        int random = Double.valueOf(Math.random() * 1000).intValue();
        return "XP" + random + System.currentTimeMillis();
    }
    private Boolean isInOperationTime(String operationStrategy) {
        JSONArray jsonArray = JSONArray.parseArray(operationStrategy);
@@ -343,6 +366,7 @@
        }
        // 1. 构建查询条件
        LambdaQueryWrapper<XpTestOrder> wrapper = buildQueryWrapper(query);
        wrapper.eq(XpTestOrder::getTestPlanId, query.getTestPlanId());
        if (CollUtil.isNotEmpty(vehicleIdsFilter)) {
            wrapper.in(XpTestOrder::getVehicleId, vehicleIdsFilter);
        }
@@ -408,7 +432,7 @@
            XpVehicle vehicle = vehicleMap.get(order.getVehicleId());
            if (Objects.nonNull(vehicle)) {
                vo.setPlateNumber(vehicle.getPlateNumber());
                vo.setVehicleModel(vehicle.getVehicleModel());
                vo.setVehicleModel(vehicle.getVehicleModelName());
            }
        }
@@ -558,6 +582,7 @@
                                          Map<Long, XpFleet> fleetMap) {
        XpTestOrderPageVO vo = new XpTestOrderPageVO();
        vo.setId(order.getId());
        vo.setOrderType(order.getOrderType());
        vo.setOrderNumber(order.getOrderNumber());
        vo.setCreateTime(order.getCreateTime());
        vo.setOrderSource(order.getOrderSource());
@@ -584,7 +609,6 @@
     * 取消订单
     */
    private void cancelOrder(XpTestOrder order) {
        redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        //判断还原车辆状态
        if (null == order.getVehicleId()) {
            Object cacheObject1 = redisService.getCacheObject("CREATE_ORDER:" + order.getId().toString());
@@ -617,6 +641,7 @@
        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
        if (xpVehicleR.getCode() == HttpStatus.SUCCESS && Objects.nonNull(xpVehicleR.getData())) {
            XpVehicle xpVehicle = xpVehicleR.getData();
            String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
            //还原车辆状态
            if(1 == xpVehicle.getState()){
                XpVehicle vehicle1 = new XpVehicle();
@@ -628,8 +653,9 @@
            // 下发命令
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setEndTaskId(order.getStatus() < 6 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
            pushOrderDto.setOrderId("TEST" + order.getId().toString());
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setVin(vin);
            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            orderMissionClient.cancelOrder(pushOrderDto);
            log.info("运营人员取消订单成功,开始执行巡游订单 {}", order.getId());
@@ -644,10 +670,11 @@
     */
    private void closeOrder(XpTestOrder order) {
        XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
        String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
        order.setStatus(7);
        order.setGetoffTime(LocalDateTime.now());
        // 解析下车地点
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
        if(Objects.nonNull(vehiclePosition)){
            GeoJsonPoint point = vehiclePosition.getPoint();
            if(Objects.nonNull(point)){
@@ -665,18 +692,81 @@
        order.setDuration(new BigDecimal(duration).divide(new BigDecimal(60), 2, RoundingMode.HALF_EVEN).doubleValue());
        order.setStartTestPointId(null);
        this.updateById(order);
        redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 7, 24L, TimeUnit.HOURS);
        redisService.setCacheObject("TEST_ORDER_STATUS:" + order.getId(), 7, 24L, TimeUnit.HOURS);
        //给XPU推送订单取消的报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setEndTaskId(order.getStatus() < 6 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
        pushOrderDto.setOrderId("TEST" + order.getId().toString());
        pushOrderDto.setVin(xpVehicle.getVehicleVin());
        pushOrderDto.setVin(vin);
        pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
        orderMissionClient.cancelOrder(pushOrderDto);
        //结束行程,修改状态和计算费用
        endTrip(order.getId());
    }
    public void carAbnormalUpdateOrderStatus(Long orderId) {
        XpTestOrder order = this.getById(orderId);
        XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
        String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
        order.setStatus(7);
        order.setGetoffTime(LocalDateTime.now());
        // 解析下车地点
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
        if(Objects.nonNull(vehiclePosition)){
            GeoJsonPoint point = vehiclePosition.getPoint();
            if(Objects.nonNull(point)){
                double x = point.getX();
                double y = point.getY();
                Map<String, String> geocode = gdMapGeocodingUtil.geocode(String.valueOf(x), String.valueOf(y));
                order.setGetoffAddress(geocode.get("address"));
            }
        }
        //计算行驶总距离和时长
        List<OrderTrajectory> orderTrajectoryList = mongoTemplate.find(new Query().addCriteria(Criteria.where("orderId").is(order.getId())), OrderTrajectory.class);
        Double reduce = orderTrajectoryList.stream().map(OrderTrajectory::getDistance).reduce(0.0, Double::sum);
        order.setMileageKilometers(new BigDecimal(reduce).divide(new BigDecimal(1000)).setScale(4, RoundingMode.HALF_EVEN).doubleValue());
        long duration = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - order.getTripBegin().toEpochSecond(ZoneOffset.of("+8"));
        order.setDuration(new BigDecimal(duration).divide(new BigDecimal(60), 2, RoundingMode.HALF_EVEN).doubleValue());
        order.setStartTestPointId(null);
        this.updateById(order);
        redisService.setCacheObject("TEST_ORDER_STATUS:" + order.getId(), 7, 24L, TimeUnit.HOURS);
        //给XPU推送订单取消的报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setEndTaskId(order.getStatus() < 6 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
        pushOrderDto.setOrderId("TEST" + order.getId().toString());
        pushOrderDto.setVin(vin);
        pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
        orderMissionClient.cancelOrder(pushOrderDto);
        //结束行程,修改状态和计算费用
        endTrip(order.getId());
        //将支付金额修改成0 并将状态修改成 订单状态9
        setFree(order.getId());
    }
    /**
     * 豁免
     */
    public void setFree(Long id) {
        //将支付金额修改成0 并将状态修改成 订单状态9
        XpTestOrder xpOrder1 = new XpTestOrder();
        xpOrder1.setId(id);
        xpOrder1.setIsFree(true);//豁免
        xpOrder1.setPayMoney(BigDecimal.ZERO);
        xpOrder1.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode());
        xpOrder1.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(xpOrder1);
    }
    /**
     * 改派订单
@@ -714,9 +804,9 @@
        // 运营状态:1=运营中 2=维修中 3=已收车 4=车辆异常
        // 当前模式:1=接单 2=测试
        // 模式状态:1=开始接单/开始测试 2=停止接单/停止测试
        if (Objects.isNull(newVehicle.getStatus()) || newVehicle.getStatus() == 3) {
            throw new ServiceException("新车辆保险或年检已过期,无法接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_STATUS_INVALID);
        }
//        if (Objects.isNull(newVehicle.getStatus()) || newVehicle.getStatus() == 3) {
//            throw new ServiceException("新车辆保险或年检已过期,无法接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_STATUS_INVALID);
//        }
        if (Objects.isNull(newVehicle.getOperatingStatus()) || newVehicle.getOperatingStatus() != 1) {
            throw new ServiceException("新车辆运营状态异常,无法接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_OPERATING_STATUS_INVALID);
        }
@@ -740,14 +830,15 @@
                R<XpVehicle> oldVehicleResult = xpVehicleClient.queryById(oldVehicleId);
                if (oldVehicleResult != null && oldVehicleResult.getCode() == HttpStatus.SUCCESS && oldVehicleResult.getData() != null) {
                    XpVehicle oldVehicle = oldVehicleResult.getData();
                    String vin = SensitiveDataCryptoUtil.decryptIfPossible(oldVehicle.getVehicleVin());
                    // 6.1.1 取消原订单指令
                    PushOrderDto cancelDto = new PushOrderDto();
                    cancelDto.setOrderId("TEST" + order.getId().toString());
                    cancelDto.setVin(oldVehicle.getVehicleVin());
                    cancelDto.setVin(vin);
                    cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                    orderMissionClient.cancelOrder(cancelDto);
                    log.info("已取消原车辆订单指令,订单ID: {}, VIN: {}", orderId, oldVehicle.getVehicleVin());
                    log.info("已取消原车辆订单指令,订单ID: {}, VIN: {}", orderId, vin);
                    // 6.1.3 修改原车辆状态为空闲
                    XpVehicle vehicle1 = new XpVehicle();
@@ -822,20 +913,26 @@
        // 11. 处理新车辆:绑定乘客、下发订单、更新状态
        try {
            String vin = SensitiveDataCryptoUtil.decryptIfPossible(newVehicle.getVehicleVin());
            // 11.2 下发订单到新车辆
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setVin(newVehicle.getVehicleVin());
            pushOrderDto.setStartTaskId(order.getXpuStartTaskId());
            pushOrderDto.setEndTaskId(order.getXpuEndTaskId());
            pushOrderDto.setVin(vin);
            pushOrderDto.setOrderId("TEST" + order.getId());
            pushOrderDto.setStartWaypointId(order.getStartTestPointId());
            pushOrderDto.setEndWaypointId(order.getEndTestPointId());
            pushOrderDto.setStartLatitude(order.getStartLat());
            pushOrderDto.setStartLongitude(order.getStartLon());
            pushOrderDto.setEndLatitude(order.getEndLat());
            pushOrderDto.setEndLongitude(order.getEndLon());
            pushOrderDto.setEndPoiName(order.getEndTestPointName());
            pushOrderDto.setOrderType(OrderType.USER_ORDER);
            pushOrderDto.setStage(1);
            // 调用推送服务  orderId + carVin
            orderMissionClient.pushOrder(pushOrderDto);
            log.info("已下发订单到新车辆,订单ID: {}, VIN: {}", orderId, newVehicle.getVehicleVin());
            log.info("已下发订单到新车辆,订单ID: {}, VIN: {}", orderId, vin);
            // 11.3 更新新车辆状态为已接单
            XpVehicle vehicle1 = new XpVehicle();
@@ -886,9 +983,9 @@
                                    put("id", xpOrder.getId())
                                    .build();
                    QuartzManager.addJob(
                            OrderCancelJob.class,
                            (OrderCancelJob.name + xpOrder.getId()).toUpperCase(),
                            TimeJobType.ORDER_CANCEL,
                            TestOrderCancelJob.class,
                            (TestOrderCancelJob.name + xpOrder.getId()).toUpperCase(),
                            TimeJobType.TEST_ORDER_CANCEL,
                            DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpPoint.getParkingTimeLimit())),
                            cancelJobMaps
                    );
@@ -900,16 +997,44 @@
                    xpOrder.setBoardingTime(now);
                    xpOrder.setRideTime(now);
                    // 删除定时任务job
                    QuartzManager.removeJob((OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL);
                    QuartzManager.removeJob((TestOrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.TEST_ORDER_CANCEL);
                    //乘客已上车,重新倒计时不开始行程取消订单
                    XpTestPoint xpPoint1 = xpTestPointClient.queryById(xpOrder.getStartTestPointId()).getData();
                    if(StringUtils.isEmpty(xpPoint1.getCityCode())){
                        Map<String, String> geocode = gdMapGeocodingUtil.geocode(xpPoint1.getPointLon().toString(), xpPoint1.getPointLat().toString());
                        if(null != geocode){
                            xpPoint1.setCityCode(geocode.get("cityCode"));
                            xpPoint1.setCityName(geocode.get("address"));
                            xpTestPointClient.editXpPoint(xpPoint1);
                        }
                    }
                    XpTradingStrategy tradingStrategy = tradingStrategyClient.getTradingStrategyByCityCode(xpPoint1.getCityCode()).getData();
                    if(null != tradingStrategy){
                        Map<String, ? extends Object> cancelJobMaps1 =
                                new ImmutableMap.Builder<String, Long>()
                                        .put("id", xpOrder.getId())
                                        .build();
                        QuartzManager.addJob(
                                TestOrderCancelJob.class,
                                (TestOrderCancelJob.name + xpOrder.getId()).toUpperCase(),
                                TimeJobType.TEST_ORDER_CANCEL,
                                DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(tradingStrategy.getBdNotBoardedTime())),
                                cancelJobMaps1
                        );
                    }
                    break;
                case 6:
                    // 删除定时任务job
                    QuartzManager.removeJob((TestOrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.TEST_ORDER_CANCEL);
                    // 行程开始时间
                    xpOrder.setTripBegin(LocalDateTime.now());
                    redisService.deleteObject("TEST_ORDER_NAVIGATION_START_DATA:" + xpOrder.getVehicleId());
                    break;
                case 7:
                    String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                    xpOrder.setGetoffTime(LocalDateTime.now());
                    // 解析下车地点
                    VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
                    VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
                    if(Objects.nonNull(vehiclePosition)){
                        GeoJsonPoint point = vehiclePosition.getPoint();
                        if(Objects.nonNull(point)){
@@ -925,19 +1050,36 @@
                    xpOrder.setMileageKilometers(new BigDecimal(reduce).divide(new BigDecimal(1000)).setScale(4, RoundingMode.HALF_EVEN).doubleValue());
                    long duration = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - xpOrder.getTripBegin().toEpochSecond(ZoneOffset.of("+8"));
                    xpOrder.setDuration(new BigDecimal(duration).divide(new BigDecimal(60), 2, RoundingMode.HALF_EVEN).doubleValue());
                    //创建定时结束订单和等待结束后下发巡游单的定时任务
                    Integer arriveTime = xpSystemSettingClient.getOrderFinishTime().getData();
                    // 添加自动结束行程定时任务job
                    Map<String, ? extends Object> endTripJobMaps =
                            new ImmutableMap.Builder<String, String>()
                                    .put("id", xpOrder.getId().toString())
                                    .put("orderType", OrderType.TEST_ORDER)
                                    .build();
                    QuartzManager.addJob(
                            EndTripJob.class,
                            (EndTripJob.name + xpOrder.getId()).toUpperCase(),
                            TimeJobType.END_TRIP,
                            DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(arriveTime)),
                            endTripJobMaps
                    );
                    break;
            }
            xpOrder.setStatus(status);
            xpOrder.setStartTestPointId(null);
            this.updateById(xpOrder);
            redisService.setCacheObject("ORDER_STATUS:" + xpOrder.getId(), status, 24L, TimeUnit.HOURS);
            redisService.setCacheObject("TEST_ORDER_STATUS:" + xpOrder.getId(), status, 24L, TimeUnit.HOURS);
        }else{
            //测试巡游单,只需要修改状态
            if(status == 10){
                xpOrder.setStatus(status);
                xpOrder.setStartTestPointId(null);
                this.updateById(xpOrder);
                redisService.setCacheObject("ORDER_STATUS:" + xpOrder.getId(), status, 24L, TimeUnit.HOURS);
                redisService.setCacheObject("TEST_ORDER_STATUS:" + xpOrder.getId(), status, 24L, TimeUnit.HOURS);
            }
        }
        return R.ok();
@@ -966,11 +1108,10 @@
        order.setStartTestPointId(null);
        order.setTripEnd(LocalDateTime.now());
        baseMapper.updateById(order);
        redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 8, 24L, TimeUnit.HOURS);
        redisService.setCacheObject("TEST_ORDER_STATUS:" + order.getId(), 8, 24L, TimeUnit.HOURS);
        // 根据订单所属开通城市id 查询定价
        R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCid(order.getCityId());
        XpPricing pricing = pricingByCityId.getData();
        XpPricing pricing = bootCommonService.getXpPricing(order.getCityId(),order.getVehicleId());
        if (pricing == null) {
            throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS);
        }
@@ -1334,7 +1475,7 @@
    @Override
    public void saveVehicleLocation(OrderTrajectory orderTrajectory) {
        // 查询订单信息
        Integer status = redisService.getCacheObject("ORDER_STATUS:" + orderTrajectory.getOrderId());
        Integer status = redisService.getCacheObject("TEST_ORDER_STATUS:" + orderTrajectory.getOrderId());
        if(status < 6 || status > 8){
            return;
        }
@@ -1490,8 +1631,10 @@
            xpTestOrder.setStartTestPointId(null);
            this.updateById(xpTestOrder);
            XpVehicle xpVehicle = xpVehicleClient.queryById(xpTestOrder.getVehicleId()).getData();
            String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setEndTaskId(xpTestOrder.getStatus() < 6 ? xpTestOrder.getXpuStartTaskId() : xpTestOrder.getXpuEndTaskId());
            pushOrderDto.setVin(vin);
            pushOrderDto.setOrderId("TEST" + xpTestOrder.getId());
            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            R<Boolean> booleanR = orderMissionClient.cancelOrder(pushOrderDto);