liujie
2026-02-25 a9b378f9e7b1a72f9e50227ca445d5135c71020a
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -1,6 +1,7 @@
package com.xiaopeng.operation.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -25,6 +26,7 @@
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.uuid.UUID;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
@@ -200,18 +202,37 @@
        }
        XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, routeAndFareDto.getOpenCityId()));
//        if (xpPricing == null) {
//            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
//        }
        if (xpPricing == null) {
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        // 2. 计算价格(需要在并行任务前完成,因为优惠券查询需要价格) TODO 判断是动态还是一口价
//        XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationPrice(
//                JSON.parseObject(xpPricing.getBasicPricingJson()),
//                JSON.parseArray(xpPricing.getStartingFareJson()),
//                1, 1, 0, 0.0
//        );
        XpPricingCardVo xpPricingCardVo = new XpPricingCardVo();
//        // 算距离
        R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
        if(distanceAndDuration.getCode()!=200){
            throw new ServiceException("未找到路径", I18nKeyConstant.PATH_NOT_FOUND);
        }
        RouteVo routeVo = distanceAndDuration.getData();
        // 2. 计算价格(需要在并行任务前完成,因为优惠券查询需要价格)
        XpPricingCardVo xpPricingCardVo;
        if (xpPricing.getPricingType() == 1) {
            xpPricingCardVo = xpPricingUtil.calculationPrice(userId,
                    JSON.parseObject(xpPricing.getBasicPricingJson()),
                    JSON.parseArray(xpPricing.getStartingFareJson()),
                    routeVo.getDistance(), routeVo.getDuration(), 0, 0.0, xpPricing.getIsDynamicPrice(), routeAndFareDto.getOpenCityId(), xpPricing.getDynamicPricingJson()
            );
        } else {
            xpPricingCardVo = xpPricingUtil.calculationFixedPrice(userId,
                    JSON.parseObject(xpPricing.getBasicPricingJson()),
                    JSON.parseArray(xpPricing.getStartingFareJson()),
                    routeVo.getDistance(), routeVo.getDuration(),0, 0.0, xpPricing.getIsDynamicPrice(), routeAndFareDto.getOpenCityId(), xpPricing.getDynamicPricingJson()
            );
        }
        // 3. 并行执行远程服务调用 判断是否同一经营区域
@@ -220,19 +241,15 @@
                executorService
        );
//        // 算距离
//        CompletableFuture<R<RouteVo>> routeFuture = CompletableFuture.supplyAsync(
//                () -> xpMapClient.getDistanceAndDuration(routeAndFareDto),
//                executorService
//        );
        // 优惠券
        XpPricingCardVo finalXpPricingCardVo = xpPricingCardVo;
        CompletableFuture<R<UserCouponVo>> couponFuture = CompletableFuture.supplyAsync(
                () -> {
                    // 优惠券
                    return xpAppUserCouponClient.getUserCoupon(
//                                new GetUserCouponDto(Long.valueOf(userId), xpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId())
                            new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId())
                                new GetUserCouponDto(Long.valueOf(userId), finalXpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId())
//                            new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId())
                    );
                },
                executorService
@@ -240,7 +257,6 @@
        // 4. 等待所有并行任务完成并获取结果
        R<Boolean> diagnosisResult = diagnosisAreaFuture.join();
//        R<RouteVo> routeResult = routeFuture.join();
        R<UserCouponVo> couponResult = couponFuture.join();
        // 5. 处理诊断结果
@@ -251,7 +267,7 @@
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        // 6. 处理路线结果
//        // 6. 处理路线结果
//        if (routeResult.getCode() != 200) {
//            throw new RuntimeException(routeResult.getMsg());
//        }
@@ -265,9 +281,9 @@
        } else {
            minOrderDistance = systemSettingMapper.selectOne(null).getMinOrderDistance();
        }
//        if (routeVo.getDistance() < Integer.valueOf(minOrderDistance)) {
//            throw new ServiceException("当前上下车点距离过近,建议步行前往", I18nKeyConstant.TO_WORK);
//        }
        if (routeVo.getDistance() < Integer.valueOf(minOrderDistance)) {
            throw new ServiceException("当前上下车点距离过近,建议步行前往", I18nKeyConstant.TO_WORK);
        }
        // 7. 处理优惠券结果
        if (couponResult.getCode() != R.SUCCESS) {
@@ -282,38 +298,38 @@
        RouteAndFareVo routeAndFareVo = new RouteAndFareVo();
        // MOCK数据
        RouteVo routeVo = new RouteVo();
        routeVo.setDistance(3000);
        routeVo.setDuration(5);
        routeVo.setRouteID("1");
        List<LonLatDto> routePolyline = Arrays.asList(
                // 起点:天府新谷
                new LonLatDto(104.05363, 30.58937),
                // 途经点1:府城大道与交子北二路交叉口附近
                new LonLatDto(104.05821, 30.58745),
                // 途经点2:交子大道与成汉南路交叉口
                new LonLatDto(104.06418, 30.58492),
                // 途经点3:交子大道与万象南路交叉口
                new LonLatDto(104.06975, 30.58321),
                // 途经点4:交子大道与益州大道交叉口
                new LonLatDto(104.07366, 30.58198),
                // 终点:金融城(地铁站附近)
                new LonLatDto(104.076544, 30.581039)
        );
        routeVo.setPolyline(routePolyline);
//        RouteVo routeVo = new RouteVo();
//        routeVo.setDistance(3000);
//        routeVo.setDuration(5);
//        routeVo.setRouteID("1");
//        List<LonLatDto> routePolyline = Arrays.asList(
//                // 起点:天府新谷
//                new LonLatDto(104.05363, 30.58937),
//
//                // 途经点1:府城大道与交子北二路交叉口附近
//                new LonLatDto(104.05821, 30.58745),
//
//                // 途经点2:交子大道与成汉南路交叉口
//                new LonLatDto(104.06418, 30.58492),
//
//                // 途经点3:交子大道与万象南路交叉口
//                new LonLatDto(104.06975, 30.58321),
//
//                // 途经点4:交子大道与益州大道交叉口
//                new LonLatDto(104.07366, 30.58198),
//
//                // 终点:金融城(地铁站附近)
//                new LonLatDto(104.076544, 30.581039)
//        );
//        routeVo.setPolyline(routePolyline);
        routeAndFareVo.setRoute(routeVo);
        routeAndFareVo.setXpPricingCard(xpPricingCardVo);
        FareVo fareVo = new FareVo();
//        fareVo.setEstimatedDistanceKm(routeVo.getDistance().doubleValue() / 1000);
//        fareVo.setEstimatedDurationMin(routeVo.getDuration() / 60);
        fareVo.setEstimatedDistanceKm(routeVo.getDistance().doubleValue() / 1000);
        fareVo.setEstimatedDurationMin(routeVo.getDuration() / 60);
        // 9. 设置费用信息
        fareVo.setOriginalFare(xpPricingCardVo.getTotalPrice());
@@ -384,7 +400,7 @@
                    double waitMinutes = (average * count) / 60;
                    if (waitMinutes > 3) {
                        throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
                    }else if(waitMinutes==0){
                    } else if (waitMinutes == 0) {
                        return 1;
                    }
                    return (int) waitMinutes;
@@ -398,8 +414,6 @@
    @Override
    public Long saveOrder(XpOrderDto dto, String uid) {
        // 是否在运营区域时间内
        XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId());
@@ -415,7 +429,7 @@
        // 判断是否有进行的订单
        R<Long> r = xpOrderClient.hasUnPaodOrder(uid);
        if (r.getData() > 0) {
            throw new RuntimeException("有正在进行的订单");
            throw new ServiceException("有正在进行的订单", I18nKeyConstant.HAS_UNPAID_ORDER);
        }
        // 获取起点经纬度
@@ -427,11 +441,11 @@
        // 判断点位是否在运营区域内
        LocalTime now = LocalTime.now();
        boolean inTime = xpPointService.getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod());
        if(!inTime){
        if (!inTime) {
            throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        inTime = xpPointService.getInTime(now, endXpPoint.getEffectivePeriod(), endXpPoint.getEffectiveTimePeriod());
        if(!inTime){
        if (!inTime) {
            throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
@@ -442,7 +456,7 @@
        if (cancelOrder != null) {
            Integer num = Integer.valueOf(cancelOrder.toString());
            if (num >= cancelCount) {
                isSilent =true;
                isSilent = true;
            }
        }
@@ -541,7 +555,7 @@
        Long orderId = addOrderR.getData();
        // 静默处理 不推单
        if(isSilent){
        if (isSilent) {
            return orderId;
        }
@@ -575,7 +589,7 @@
                // 存储mongodb 数据
                XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
                xpGeoQueryEntity.setOrderId(orderId.toString());
                xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(),xpPoint.getPointLat()));
                xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
                // 计算2个时间的秒数
                xpGeoQueryEntity.setTime(currentTimeSlot);
                xpGeoQueryEntity.setStatus(0);
@@ -595,7 +609,7 @@
        // 存储mongodb 数据
        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
        xpGeoQueryEntity.setOrderId(orderId.toString());
        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(),xpPoint.getPointLat()));
        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
        // 计算2个时间的秒数
        xpGeoQueryEntity.setTime(currentTimeSlot);
        xpGeoQueryEntity.setStatus(0);
@@ -615,7 +629,6 @@
//        return null;
    }
    private Boolean isInOperationTime(String operationStrategy) {
@@ -705,11 +718,16 @@
        if (pricing == null) {
            throw new ServiceException("定价不存在", I18nKeyConstant.PRICING_NOT_EXIST);
        }
        try {
            JSONObject.parseObject(dto.getBasicPricingJson());
            JSONArray.parseArray(dto.getStartingFareJson());
            JSONObject.parseObject(dto.getDynamicPricingJson());
            if (StringUtils.isNotBlank(dto.getBasicPricingJson())) {
                JSONObject.parseObject(dto.getBasicPricingJson());
            }
            if (StringUtils.isNotBlank(dto.getStartingFareJson())) {
                JSONArray.parseArray(dto.getStartingFareJson());
            }
            if (StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
                JSONObject.parseObject(dto.getDynamicPricingJson());
            }
        } catch (Exception e) {
            throw new ServiceException("价格配置JSON格式不正确", I18nKeyConstant.PRICING_JSON_INVALID);
        }
@@ -717,8 +735,9 @@
        XpPricing update = new XpPricing();
        update.setId(dto.getId());
        update.setBasicPricingJson(dto.getBasicPricingJson());
        update.setStartingFareJson(dto.getStartingFareJson());
        update.setStartingFareJson(StringUtils.isNotBlank(dto.getStartingFareJson()) ? dto.getStartingFareJson() : null);
        update.setDynamicPricingJson(dto.getDynamicPricingJson());
        update.setIsDynamicPrice(dto.getIsDynamicPrice());
        this.updateById(update);
    }