liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/utils/XpPricingUtil.java
@@ -22,6 +22,9 @@
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -83,7 +86,7 @@
    public XpPricingCardVo calculationFixedPrice(String uid, JSONObject rule, JSONArray startingFareJson, double distance, long duration, long wait, Double waitMoney,
                                                 Integer isDynamicPriceStatus, Long openCityId, String dynamicPricingJson) {
        // 默认费率1
        double priceRate=1;
        double priceRate=100;
        if(isDynamicPriceStatus==1){
            // 先判断是否已经调价过了(供需调价)
            Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid);
@@ -91,66 +94,62 @@
                // 是否调价过了
                priceRate = Double.parseDouble(userDynamicPriceObj.toString());
            }else {
                //是否触发动态调价 redis获取
                Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + openCityId);
                if(dynamicPriceObj!=null){
                    JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                    // 触发动态调价
                    // value=时间
                    String timeStr = dynamicPriceObj.toString();
                    // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                    R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId));
                    if(r.getCode()==200){
                        int num = r.getData();
                        // X单上升一次调价
                        Integer orderNum = getOrderNum(jsonObject, 4);
                        // 需要调价的次数
                        int count = num / orderNum;
                        if(count>0){
                            // 计算每次上升的费率
                            Integer upRate = getOrderNum(jsonObject, 5);
                            BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                            for (int i = count; i > 0; i--) {
                                // 当前费率+(费率*上升百分比)
                                priceRate =  new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                            }
                JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                Integer num1 = jsonObject.getInteger("num1");
                String timeStr = LocalDateTime.now().minusMinutes(num1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                // 触发动态调价
                // value=时间
                // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId));
                if(r.getCode()==200){
                    int num = r.getData();
                    // X单上升一次调价
                    Integer orderNum = getOrderNum(jsonObject, 4);
                    // 需要调价的次数
                    int count = num / orderNum;
                    if(count>0){
                        // 计算每次上升的费率
                        Integer upRate = getOrderNum(jsonObject, 5);
                        BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                        for (int i = count; i > 0; i--) {
                            // 当前费率+(费率*上升百分比)
                            priceRate =  new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                        }
                    }
                    if(priceRate > 1){
                        // 冷却时间
                        Integer time = getOrderNum(jsonObject, 6);
                        // 触发调价了
                        redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES);
                    }
                }
                if(priceRate > 1){
                    // 冷却时间
                    Integer time = getOrderNum(jsonObject, 6);
                    // 触发调价了
                    redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES);
                }
            }
            log.info("供需后的费率 {}", priceRate);
            Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + openCityId);
            if(dynamicPriceObj!=null) {
                JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                // 天气预报动态调价
                JSONArray ws = jsonObject.getJSONArray("weatherRules");
                if (null != ws) {
                    XpOpenCity openCity = openCityClient.getXpOpenCityById(openCityId).getData();
                    WeatherDTO data = xpMapClient.wether(openCity.getCityCode()).getData();
                    List<WeatherDTO.Lives> lives = data.getLives();
                    if (lives != null && !lives.isEmpty()) {
                        String w = lives.get(0).getWeather();
                        for (Object o : ws) {
                            JSONObject ele = JSONObject.parseObject(o.toString());
                            if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                                double floatRate = ele.getDouble("ratio");
                                priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                break;
                            }
            JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
            // 天气预报动态调价
            JSONArray ws = jsonObject.getJSONArray("weatherRules");
            if (null != ws) {
                XpOpenCity openCity = openCityClient.getXpOpenCityById(openCityId).getData();
                WeatherDTO data = xpMapClient.wether(openCity.getCityCode()).getData();
                List<WeatherDTO.Lives> lives = data.getLives();
                if (lives != null && !lives.isEmpty()) {
                    String w = lives.get(0).getWeather();
                    for (Object o : ws) {
                        JSONObject ele = JSONObject.parseObject(o.toString());
                        if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                            double floatRate = ele.getDouble("ratio");
                            priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                            break;
                        }
                    }
                }
            }
        }
        priceRate = new BigDecimal(priceRate).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
        log.info("浮动费率 {}", priceRate);
        XpPricingCardVo xpPricingCardVo = new XpPricingCardVo();
        double amount = 0;
        double realDistance = distance / 1000;//实际公里
        double realTime = duration / 60;//实际时间
@@ -165,12 +164,9 @@
        // 超出时间价格
        Double durationPrice = new BigDecimal(rule.getDouble("num5") * exceedTime).setScale(2,RoundingMode.HALF_UP).doubleValue();
        startPrice = new BigDecimal(startPrice).multiply(BigDecimal.valueOf(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
        xpPricingCardVo.setStartPrice(startPrice);
        xpPricingCardVo.setDistancePrice(distancePrice);
        xpPricingCardVo.setDurationPrice(durationPrice);
        xpPricingCardVo.setStartPrice(new BigDecimal(startPrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
        xpPricingCardVo.setDistancePrice(new BigDecimal(distancePrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
        xpPricingCardVo.setDurationPrice(new BigDecimal(durationPrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
        xpPricingCardVo.setTotalPrice(new BigDecimal(startPrice + distancePrice + durationPrice).setScale(2,RoundingMode.HALF_UP).doubleValue());
        // 里程
        xpPricingCardVo.setDistance(realDistance*1000);
@@ -194,7 +190,7 @@
    public XpPricingCardVo calculationPrice(String uid,JSONObject rule, JSONArray startingFareJson, double distance, long duration,
                                            long wait, Double waitMoney,Integer isDynamicPriceStatus,Long openCityId,String dynamicPricingJson) {
        // 默认费率1
        double priceRate=1;
        double priceRate=100;
        if(isDynamicPriceStatus==1){
            // 先判断是否已经调价过了(供需调价)
            Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid);
@@ -202,66 +198,61 @@
                // 是否调价过了
                priceRate = Double.parseDouble(userDynamicPriceObj.toString());
            }else {
                //是否触发动态调价 redis获取
                Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + openCityId);
                if(dynamicPriceObj!=null){
                    JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                    // 触发动态调价
                    // value=时间
                    String timeStr = dynamicPriceObj.toString();
                    // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                    R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId));
                    if(r.getCode()==200){
                        int num = r.getData();
                        // X单上升一次调价
                        Integer orderNum = getOrderNum(jsonObject, 4);
                        // 需要调价的次数
                        int count = num / orderNum;
                        if(count>0){
                            // 计算每次上升的费率
                            Integer upRate = getOrderNum(jsonObject, 5);
                            BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                            for (int i = count; i > 0; i--) {
                                // 当前费率+(费率*上升百分比)
                                priceRate =  new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                            }
                JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                Integer num1 = jsonObject.getInteger("num1");
                String timeStr = LocalDateTime.now().minusMinutes(num1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                // 触发动态调价
                // value=时间
                // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId));
                if(r.getCode()==200){
                    int num = r.getData();
                    // X单上升一次调价
                    Integer orderNum = getOrderNum(jsonObject, 4);
                    // 需要调价的次数
                    int count = num / orderNum;
                    if(count>0){
                        // 计算每次上升的费率
                        Integer upRate = getOrderNum(jsonObject, 5);
                        BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                        for (int i = count; i > 0; i--) {
                            // 当前费率+(费率*上升百分比)
                            priceRate =  new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                        }
                    }
                    if(priceRate > 1){
                        // 冷却时间
                        Integer time = getOrderNum(jsonObject, 6);
                        // 触发调价了
                        redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES);
                    }
                }
                if(priceRate > 1){
                    // 冷却时间
                    Integer time = getOrderNum(jsonObject, 6);
                    // 触发调价了
                    redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES);
                }
            }
            log.info("供需后的费率 {}", priceRate);
            Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + openCityId);
            if(dynamicPriceObj!=null) {
                JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
                // 天气预报动态调价
                JSONArray ws = jsonObject.getJSONArray("weatherRules");
                if (null != ws) {
                    XpOpenCity openCity = openCityClient.getXpOpenCityById(openCityId).getData();
                    WeatherDTO data = xpMapClient.wether(openCity.getCityCode()).getData();
                    List<WeatherDTO.Lives> lives = data.getLives();
                    if (lives != null && !lives.isEmpty()) {
                        String w = lives.get(0).getWeather();
                        for (Object o : ws) {
                            JSONObject ele = JSONObject.parseObject(o.toString());
                            if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                                double floatRate = ele.getDouble("ratio");
                                priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                break;
                            }
            JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson);
            // 天气预报动态调价
            JSONArray ws = jsonObject.getJSONArray("weatherRules");
            if (null != ws) {
                XpOpenCity openCity = openCityClient.getXpOpenCityById(openCityId).getData();
                WeatherDTO data = xpMapClient.wether(openCity.getCityCode()).getData();
                List<WeatherDTO.Lives> lives = data.getLives();
                if (lives != null && !lives.isEmpty()) {
                    String w = lives.get(0).getWeather();
                    for (Object o : ws) {
                        JSONObject ele = JSONObject.parseObject(o.toString());
                        if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                            double floatRate = ele.getDouble("ratio");
                            priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                            break;
                        }
                    }
                }
            }
        }
        priceRate = new BigDecimal(priceRate).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
        log.info("浮动费率 {}", priceRate);
        XpPricingCardVo xpPricingCardVo = new XpPricingCardVo();
        double amount = 0;
        //等待费
        Date date = new Date();
        // 计算出是在那个时间段内
@@ -339,11 +330,10 @@
                longDistanceThree = rule.getDouble("num34") * (realDistance - rule.getDouble("num12"));
                longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
            }
            amount = rule.getDouble("num29") + new BigDecimal(exceedDistance * rule.getDouble("num30")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num31")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
            // 起步价
            xpPricingCardVo.setStartPrice(rule.getDouble("num29"));
            xpPricingCardVo.setStartPrice(new BigDecimal(rule.getDouble("num29")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
            // 时间段
            xpPricingCardVo.setTime("节假日");
@@ -354,13 +344,13 @@
            // 里程费
            double distancePrice = (exceedDistance * rule.getDouble("num30")) + longDistanceOne + longDistanceTwo + longDistanceThree;
            distancePrice = new BigDecimal(distancePrice).setScale(2,RoundingMode.HALF_UP).doubleValue();
            xpPricingCardVo.setDistancePrice(distancePrice);
            xpPricingCardVo.setDistancePrice(new BigDecimal(distancePrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
            // 时长
            xpPricingCardVo.setDuration(realTime);
            // 时长费
            xpPricingCardVo.setDurationPrice((exceedTime * rule.getDouble("num31")));
            xpPricingCardVo.setDurationPrice(new BigDecimal(exceedTime * rule.getDouble("num31")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
        } else {
@@ -390,11 +380,9 @@
                    longDistanceThree = rule.getDouble("num20") * (realDistance - rule.getDouble("num12"));
                    longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                }
                amount = rule.getDouble("num15") + new BigDecimal(exceedDistance * rule.getDouble("num16")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num17")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                // 起步价
                xpPricingCardVo.setStartPrice(rule.getDouble("num15"));
                xpPricingCardVo.setStartPrice(new BigDecimal(rule.getDouble("num15")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                // 时间段
                xpPricingCardVo.setTime(rule.getString("num14"));
@@ -404,13 +392,13 @@
                // 里程费
                double distancePrice = (exceedDistance * rule.getDouble("num16")) + longDistanceOne + longDistanceTwo + longDistanceThree;
                distancePrice = new BigDecimal(distancePrice).setScale(2,RoundingMode.HALF_UP).doubleValue();
                xpPricingCardVo.setDistancePrice(distancePrice);
                xpPricingCardVo.setDistancePrice(new BigDecimal(distancePrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                // 时长
                xpPricingCardVo.setDuration(realTime);
                // 时长费
                xpPricingCardVo.setDurationPrice((exceedTime * rule.getDouble("num17")));
                xpPricingCardVo.setDurationPrice(new BigDecimal(exceedTime * rule.getDouble("num17")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                xpPricingCardVo.setDistancePriceNormal(rule.getDouble("num2")*1000);
@@ -465,11 +453,9 @@
                        longDistanceThree = rule.getDouble("num28") * (realDistance - rule.getDouble("num12"));
                        longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    amount = rule.getDouble("num23") + new BigDecimal(exceedDistance * rule.getDouble("num24")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * rule.getDouble("num25")).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    // 起步价
                    xpPricingCardVo.setStartPrice(rule.getDouble("num23"));
                    xpPricingCardVo.setStartPrice(new BigDecimal(rule.getDouble("num23")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    // 时间段
                    if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) {
                        xpPricingCardVo.setTime(rule.getString("num21"));
@@ -487,13 +473,13 @@
                    // 里程费
                    double distancePrice = (exceedDistance * rule.getDouble("num24")) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    distancePrice = new BigDecimal(distancePrice).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    xpPricingCardVo.setDistancePrice(distancePrice);
                    xpPricingCardVo.setDistancePrice(new BigDecimal(distancePrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    // 时长
                    xpPricingCardVo.setDuration(realTime);
                    // 时长费
                    xpPricingCardVo.setDurationPrice((exceedTime * rule.getDouble("num25")));
                    xpPricingCardVo.setDurationPrice(new BigDecimal(exceedTime * rule.getDouble("num25")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                } else {
@@ -524,11 +510,9 @@
                        longDistanceThree = rule.getDouble("num13") * (realDistance - rule.getDouble("num12"));
                        longDistanceThree = new BigDecimal(longDistanceThree).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    }
                    amount = rule.getDouble("num1") + new BigDecimal(exceedDistance * rule.getDouble("num4")).setScale(2,RoundingMode.HALF_UP).doubleValue() + new BigDecimal(exceedTime * (null != rule.getDouble("num5") ? rule.getDouble("num5") : 0)).setScale(2,RoundingMode.HALF_UP).doubleValue() + (wait * waitMoney) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    // 起步价
                    xpPricingCardVo.setStartPrice(rule.getDouble("num1"));
                    xpPricingCardVo.setStartPrice(new BigDecimal(rule.getDouble("num1")).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    // 时间段
                    xpPricingCardVo.setTime(rule.getString("startTime") + " - " + rule.getString("endTime"));
@@ -542,36 +526,23 @@
                    // 里程费
                    double distancePrice = (exceedDistance * rule.getDouble("num4")) + longDistanceOne + longDistanceTwo + longDistanceThree;
                    distancePrice = new BigDecimal(distancePrice).setScale(2,RoundingMode.HALF_UP).doubleValue();
                    xpPricingCardVo.setDistancePrice(distancePrice);
                    xpPricingCardVo.setDistancePrice(new BigDecimal(distancePrice).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                    // 时长
                    xpPricingCardVo.setDuration(realTime);
                    // 时长费
                    xpPricingCardVo.setDurationPrice((exceedTime * (null != rule.getDouble("num5") ? rule.getDouble("num5") : 0)));
                    xpPricingCardVo.setDurationPrice(new BigDecimal(exceedTime * (null != rule.getDouble("num5") ? rule.getDouble("num5") : 0)).multiply(new BigDecimal(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue());
                }
            }
        }
        // 订单总额
        Double startPrice = xpPricingCardVo.getStartPrice();
        amount=new BigDecimal(amount).setScale(2,RoundingMode.HALF_UP).doubleValue();
        // 先减去起步价重新计算
        amount = amount - startPrice;
        // 动态计算费用
        startPrice= new BigDecimal(startPrice).multiply(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
        amount = amount+startPrice;
        double amount = xpPricingCardVo.getStartPrice() + xpPricingCardVo.getDistancePrice() + xpPricingCardVo.getDurationPrice();
        xpPricingCardVo.setTotalPrice(new BigDecimal(amount).setScale(2,RoundingMode.HALF_UP).doubleValue());
        xpPricingCardVo.setDistance(xpPricingCardVo.getDistance()*1000);
        xpPricingCardVo.setDuration(xpPricingCardVo.getDuration()*60);
        return xpPricingCardVo;
    }
    /**