liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -306,7 +306,7 @@
                        routeVo.getDistance(), routeVo.getDuration(), 0, 0.0, xpPricing.getIsDynamicPrice(), routeAndFareDto.getOpenCityId(), xpPricing.getDynamicPricingJson()
                );
            }
            log.info("计算费用明细 {}", JSON.toJSONString(xpPricingCardVo));
            // 优惠券:null=自动最佳;0=不使用;>0=指定券
            XpPricingCardVo finalXpPricingCardVo = xpPricingCardVo;
            R<UserCouponVo> coupon = null;
@@ -404,13 +404,15 @@
            // 9. 设置费用信息
            fareVo.setOriginalFare(xpPricingCardVo.getTotalPrice());
            fareVo.setOriginalFareStr(new BigDecimal(fareVo.getOriginalFare()).setScale(2, RoundingMode.HALF_UP).toString());
            fareVo.setOriginalFareStr(new BigDecimal(xpPricingCardVo.getTotalPrice()).setScale(2, RoundingMode.HALF_UP).toString());
            if (userCouponVo != null) {
                if(userCouponVo.getMoney()>fareVo.getOriginalFare()){
                    fareVo.setCouponType(userCouponVo.getCouponType());
                    fareVo.setDiscountAmount(fareVo.getOriginalFare());
                    fareVo.setFinalFare(0.00);
                }else {
                    fareVo.setDiscountAmount(userCouponVo.getMoney());
                    fareVo.setCouponType(userCouponVo.getCouponType());
                    fareVo.setFinalFare(fareVo.getOriginalFare() - fareVo.getDiscountAmount());
                }
//                if(fareVo.getFinalFare()>0){
@@ -654,7 +656,7 @@
        XpOrder xpOrder = new XpOrder();
        xpOrder.setMileageKilometers(0.0);
        xpOrder.setAppUserId(Long.valueOf(uid));
        xpOrder.setOrderNumber("XP" + System.currentTimeMillis());
        xpOrder.setOrderNumber(getOrderNumber());
        xpOrder.setPlacementLon(dto.getPlacementLon());
        xpOrder.setPlacementLat(dto.getPlacementLat());
        xpOrder.setPlacementAddress(dto.getPlacementAddress());
@@ -778,6 +780,11 @@
        }
    }
    private String getOrderNumber(){
        int random = Double.valueOf(Math.random() * 1000).intValue();
        return "XP" + random + System.currentTimeMillis();
    }
    /**
     * 构建普通订单推送数据
@@ -795,27 +802,57 @@
     */
    private String addOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance,
                                Boolean isPriorityDispatch, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
        log.info("当前队列:{}", quoteMatchName);
        for (String s : quoteMatchName) {
        RLock lock = redissonClient.getLock("ADD_ORDER_PUSH");
        try {
            if(lock.tryLock(2, 5, TimeUnit.SECONDS)){
                // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
                Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
                log.info("当前队列:{}", quoteMatchName);
                for (String s : quoteMatchName) {
//            QUEUE_POINT_ID-1-30.233,120.233
            String lonLat = s.split("-")[2];
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < maxPushDistance) {
                String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule();
                if (isPriorityDispatch) {
                    // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                    redisService.addToHead(s, value);
                    log.info("添加到队列头部:{} {}", s, value);
                } else {
                    // 尾部
                    redisService.addToTail(s, value);
                    log.info("添加到队列尾部:{} {}", s, value);
                    String lonLat = s.split("-")[2];
                    // 和上车点进行判断是否<maxPushDistance
                    double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
                    if (v < maxPushDistance) {
                        String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule();
                        if (isPriorityDispatch) {
                            // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                            redisService.addToHead(s, value);
                            log.info("添加到队列头部:{} {}", s, value);
                        } else {
                            // 尾部
                            redisService.addToTail(s, value);
                            log.info("添加到队列尾部:{} {}", s, value);
                        }
                        xpOrder.setQueueName(s);
                        xpOrder.setQueueValue(value);
                        xpOrderClient.updateOrder(xpOrder);
                        // 存储mongodb 数据
                        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
                        xpGeoQueryEntity.setOrderId(orderId.toString());
                        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
                        // 计算2个时间的秒数
                        xpGeoQueryEntity.setTime(currentTimeSlot);
                        xpGeoQueryEntity.setStatus(0);
                        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                        geoQueryEntityService.save(xpGeoQueryEntity);
                        return orderId.toString();
                    }
                }
                xpOrder.setQueueName(s);
                String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
                if(xpRoutePlan==null){
                    redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null));
                }else {
                    redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule()));
                }
                log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
                xpOrder.setQueueName(key);
                xpOrderClient.updateOrder(xpOrder);
                // 存储mongodb 数据
                XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
@@ -826,33 +863,12 @@
                xpGeoQueryEntity.setStatus(0);
                xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                geoQueryEntityService.save(xpGeoQueryEntity);
                return orderId.toString();
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        if(xpRoutePlan==null){
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null));
        }else {
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule()));
        }
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
        // 存储mongodb 数据
        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
        xpGeoQueryEntity.setOrderId(orderId.toString());
        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
        // 计算2个时间的秒数
        xpGeoQueryEntity.setTime(currentTimeSlot);
        xpGeoQueryEntity.setStatus(0);
        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
        geoQueryEntityService.save(xpGeoQueryEntity);
        return orderId.toString();
    }
@@ -872,56 +888,100 @@
     */
    private String addSpOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance,
                                  Integer weight, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID);
        log.info("当前队列(定向服务):{}", quoteMatchName);
        RLock lock = redissonClient.getLock("ADD_SP_ORDER_PUSH");
        try {
            if(lock.tryLock(2, 5, TimeUnit.SECONDS)){
                // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
                Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID);
                log.info("当前队列(定向服务):{}", quoteMatchName);
        for (String s : quoteMatchName) {
//            QUEUE_POINT_ID-1-30.233,120.233
            String lonLat = s.split("-")[2];
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < maxPushDistance) {
                //在范围内,将队列中的数据转换成对象进行排序
                List<String> cacheList = redisService.getCacheList(s);
                List<RedisQueuePointIdVo> ll = new ArrayList<>();
                for (String string : cacheList) {
                    String[] split = string.split("_");
                    RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                    redisQueuePointIdVo.setOrderId(split[0]);
                    redisQueuePointIdVo.setPointLonLat(split[1]);
                    redisQueuePointIdVo.setPushStatus(split[2]);
                    redisQueuePointIdVo.setUid(split[3]);
                    redisQueuePointIdVo.setOrderNumber(split[4]);
                    redisQueuePointIdVo.setDistance(split[5]);
                    redisQueuePointIdVo.setDuration(split[6]);
                    redisQueuePointIdVo.setPlanRuleForQueue(split[7]);
                    redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8]));
                    ll.add(redisQueuePointIdVo);
                for (String s : quoteMatchName) {
                    String lonLat = s.split("-")[2];
                    // 和上车点进行判断是否<maxPushDistance
                    double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
                    if (v < maxPushDistance) {
                        //在范围内,将队列中的数据转换成对象进行排序
                        List<String> cacheList = redisService.getCacheList(s);
                        List<RedisQueuePointIdVo> ll = new ArrayList<>();
                        //正在派单的数据,不参与权重排序
                        String pushOrder = null;
                        for (String string : cacheList) {
                            String[] split = string.split("_");
                            if(split[2].equals("0")){
                                RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                                redisQueuePointIdVo.setOrderId(split[0]);
                                redisQueuePointIdVo.setPointLonLat(split[1]);
                                redisQueuePointIdVo.setPushStatus(split[2]);
                                redisQueuePointIdVo.setUid(split[3]);
                                redisQueuePointIdVo.setOrderNumber(split[4]);
                                redisQueuePointIdVo.setDistance(split[5]);
                                redisQueuePointIdVo.setDuration(split[6]);
                                redisQueuePointIdVo.setPlanRuleForQueue(split[7]);
                                redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8]));
                                ll.add(redisQueuePointIdVo);
                            }else{
                                pushOrder = string;
                            }
                        }
                        RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                        redisQueuePointIdVo.setOrderId(orderId.toString());
                        redisQueuePointIdVo.setPointLonLat(xpPoint.getPointLon() + "," + xpPoint.getPointLat());
                        redisQueuePointIdVo.setPushStatus("0");
                        redisQueuePointIdVo.setUid(uid);
                        redisQueuePointIdVo.setOrderNumber(xpOrder.getOrderNumber());
                        redisQueuePointIdVo.setDistance(distance.toString());
                        redisQueuePointIdVo.setDuration(duration.toString());
                        redisQueuePointIdVo.setPlanRuleForQueue(xpRoutePlan.getRoutePlanRule().toString());
                        redisQueuePointIdVo.setTargetedVal(weight);
                        ll.add(redisQueuePointIdVo);
                        //排序
                        ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal());
                        List<String> collect = ll.stream().map(item -> {
                            String value = item.getOrderId() + "_" + item.getPointLonLat() + "_" + item.getPushStatus() + "_" + item.getUid() + "_" + item.getOrderNumber()
                                    + "_" + item.getDistance() + "_" + item.getDuration() + "_" + item.getPlanRuleForQueue() + "_" + item.getTargetedVal();
                            return value;
                        }).collect(Collectors.toList());
                        //如果有正在推单的数据,则放在第一位
                        if(StringUtils.isNotEmpty(pushOrder)){
                            collect.add(0, pushOrder);
                        }
                        //先清除key的缓存数据
                        redisService.deleteObject(s);
                        //再全部重新赋值
                        redisService.setCacheList(s, collect);
                        String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0_" + uid + "_" + xpOrder.getOrderNumber()
                                + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule() + "_" + weight;
                        xpOrder.setQueueName(s);
                        xpOrder.setQueueValue(value);
                        xpOrderClient.updateOrder(xpOrder);
                        // 存储mongodb 数据
                        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
                        xpGeoQueryEntity.setOrderId(orderId.toString());
                        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
                        // 计算2个时间的秒数
                        xpGeoQueryEntity.setTime(currentTimeSlot);
                        xpGeoQueryEntity.setStatus(0);
                        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                        geoQueryEntityService.save(xpGeoQueryEntity);
                        return orderId.toString();
                    }
                }
                RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                redisQueuePointIdVo.setOrderId(orderId.toString());
                redisQueuePointIdVo.setPointLonLat(xpPoint.getPointLon() + "," + xpPoint.getPointLat());
                redisQueuePointIdVo.setPushStatus("0");
                redisQueuePointIdVo.setUid(uid);
                redisQueuePointIdVo.setOrderNumber(xpOrder.getOrderNumber());
                redisQueuePointIdVo.setDistance(distance.toString());
                redisQueuePointIdVo.setDuration(duration.toString());
                redisQueuePointIdVo.setPlanRuleForQueue(xpRoutePlan.getRoutePlanRule().toString());
                redisQueuePointIdVo.setTargetedVal(weight);
                ll.add(redisQueuePointIdVo);
                //排序
                ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal());
                List<String> collect = ll.stream().map(item -> {
                    String value = item.getOrderId() + "_" + item.getPointLonLat() + "_" + item.getPushStatus() + "_" + item.getUid() + "_" + item.getOrderNumber()
                            + "_" + item.getDistance() + "_" + item.getDuration() + "_" + item.getPlanRuleForQueue() + "_" + item.getTargetedVal();
                    return value;
                }).collect(Collectors.toList());
                redisService.setCacheList(s, cacheList);
                xpOrder.setQueueName(s);
                String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
                if(xpRoutePlan==null){
                    redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null + "_" + weight));
                }else {
                    redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule() + "_" + weight));
                }
                log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
                xpOrder.setQueueName(key);
                xpOrderClient.updateOrder(xpOrder);
                // 存储mongodb 数据
                XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
@@ -932,32 +992,12 @@
                xpGeoQueryEntity.setStatus(0);
                xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                geoQueryEntityService.save(xpGeoQueryEntity);
                return orderId.toString();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        if(xpRoutePlan==null){
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null + "_" + weight));
        }else {
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule() + "_" + weight));
        }
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
        // 存储mongodb 数据
        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
        xpGeoQueryEntity.setOrderId(orderId.toString());
        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
        // 计算2个时间的秒数
        xpGeoQueryEntity.setTime(currentTimeSlot);
        xpGeoQueryEntity.setStatus(0);
        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
        geoQueryEntityService.save(xpGeoQueryEntity);
        return orderId.toString();
    }
@@ -1088,9 +1128,11 @@
        if (userCouponVo != null) {
            if (userCouponVo.getMoney() > fareVo.getOriginalFare()) {
                fareVo.setDiscountAmount(fareVo.getOriginalFare());
                fareVo.setCouponType(userCouponVo.getCouponType());
                fareVo.setFinalFare(0.00);
            } else {
                fareVo.setDiscountAmount(userCouponVo.getMoney());
                fareVo.setCouponType(userCouponVo.getCouponType());
                fareVo.setFinalFare(fareVo.getOriginalFare() - fareVo.getDiscountAmount());
            }
            fareVo.setCouponId(userCouponVo.getId());
@@ -1222,6 +1264,7 @@
        R<XpTradingStrategyDetailVO>  strategyDetailVOR = xpTradingStrategyClient.queryById();
        XpTradingStrategyDetailVO strategyDetailVO = strategyDetailVOR.getData();
        //将多线路数据缓存,用于后续确认操作
        redisService.setCacheObject(CacheConstants.ORDER_MULTI_ROUTE_SNAPSHOT + userId + ":" + snapshotId, JSON.toJSONString(payload), Long.valueOf(strategyDetailVO.getMaxStandingTiming()), TimeUnit.SECONDS);
@@ -1236,9 +1279,6 @@
        vo.setOperateFree(operateFree);
        //产品喊写死
        vo.setMaxPeopleNumber(5);
        RouteOptionVo first = options.get(0);
        redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + userId, JSON.toJSONString(first.getRoute()), 24L, TimeUnit.HOURS);
        return vo;
    }
    @Override
@@ -1473,18 +1513,20 @@
        RLock lock = redissonClient.getLock("queue_lock_" + queueName);
        try {
            if(lock.tryLock(2, 5, TimeUnit.SECONDS)){
                if (StringUtils.isBlank(queueName)) {
                if (StringUtils.isEmpty(queueName)) {
                    // 订单不在排队中
                    queueStatusVo.setStatus(1);
                    queueStatusVo.setCurrentPosition(0);
                    queueStatusVo.setTotalCount(0);
                    queueStatusVo.setEstimatedWaitTime(0);
                    log.info("订单不在排队中: {}", orderId);
                    return queueStatusVo;
                }
                // 从Redis获取队列数据
                List<String> queueItems = redisService.getCacheList(queueName);
                if (queueItems == null || queueItems.isEmpty()) {
                    log.error("列表为空: {}", orderId);
                    // 队列为空,说明已分配车辆
                    queueStatusVo.setStatus(1);
                    queueStatusVo.setCurrentPosition(0);
@@ -1492,7 +1534,7 @@
                    queueStatusVo.setEstimatedWaitTime(0);
                    return queueStatusVo;
                }
                log.info("排队队列数据 {}", JSON.toJSONString(queueItems));
                // 遍历队列,找到当前订单的位置
                int currentPosition = 0;
                int totalCount = queueItems.size();
@@ -1513,6 +1555,7 @@
                queueStatusVo.setEstimatedWaitTime((waitTimeTimeSlot*currentPosition)/60);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询排队状态失败: {}", e.getMessage(), e);
            // 异常情况下返回默认值
            queueStatusVo.setStatus(0);