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;
@@ -29,7 +30,6 @@
import com.xiaopeng.api.model.order.*;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.service.BootCommonService;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperationType;
@@ -39,9 +39,11 @@
import com.xiaopeng.common.core.constant.CacheConstants;
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;
@@ -51,8 +53,8 @@
import com.xiaopeng.order.job.base.QuartzManager;
import com.xiaopeng.order.job.base.TimeJobType;
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;
@@ -60,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;
@@ -73,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;
@@ -116,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;
@@ -141,6 +143,12 @@
    @Resource
    private BootCommonService bootCommonService;
    @Resource
    private XpTradingStrategyClient tradingStrategyClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
@@ -221,7 +229,7 @@
        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());
@@ -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();
@@ -258,6 +268,7 @@
        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);
@@ -266,8 +277,12 @@
            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());
@@ -279,6 +294,12 @@
            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);
@@ -411,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());
            }
        }
@@ -620,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();
@@ -631,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());
@@ -647,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)){
@@ -672,14 +696,77 @@
        //给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);
    }
    /**
     * 改派订单
@@ -743,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();
@@ -825,10 +913,15 @@
        // 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());
@@ -839,7 +932,7 @@
            // 调用推送服务  orderId + carVin
            orderMissionClient.pushOrder(pushOrderDto);
            log.info("已下发订单到新车辆,订单ID: {}, VIN: {}", orderId, newVehicle.getVehicleVin());
            log.info("已下发订单到新车辆,订单ID: {}, VIN: {}", orderId, vin);
            // 11.3 更新新车辆状态为已接单
            XpVehicle vehicle1 = new XpVehicle();
@@ -890,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
                    );
@@ -904,17 +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)){
@@ -1511,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);