| | |
| | | |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.xiaopeng.api.dto.WeatherDTO; |
| | | import com.xiaopeng.api.dto.order.GetOrderNumDto; |
| | | import com.xiaopeng.api.feignClient.map.XpMapClient; |
| | | import com.xiaopeng.api.feignClient.order.XpOrderClient; |
| | | import com.xiaopeng.api.model.operation.XpOpenCity; |
| | | import com.xiaopeng.api.vo.order.XpPricingCardVo; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | import com.xiaopeng.common.redis.service.RedisService; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | |
| | | |
| | | @Autowired |
| | | private XpOrderClient xpOrderClient; |
| | | |
| | | @Autowired |
| | | private XpMapClient xpMapClient; |
| | | |
| | | |
| | | /** |
| | |
| | | */ |
| | | public XpPricingCardVo calculationFixedPrice(String uid, JSONObject rule, JSONArray startingFareJson, double distance, double duration, long wait, Double waitMoney, Integer isDynamicPriceStatus, Long openCityId, String dynamicPricingJson) { |
| | | // 默认费率1 |
| | | double priceRate=1; |
| | | if(isDynamicPriceStatus==1){ |
| | | double priceRate = 100; |
| | | if (isDynamicPriceStatus == 1) { |
| | | // 先判断是否已经调价过了 |
| | | Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid); |
| | | if(userDynamicPriceObj!=null){ |
| | | if (userDynamicPriceObj != null) { |
| | | // 是否调价过了 |
| | | 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.getData()==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(); |
| | | } |
| | | |
| | | // 冷却时间 |
| | | Integer time = getOrderNum(jsonObject, 6); |
| | | // 触发调价了 |
| | | redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES); |
| | | } |
| | | } else { |
| | | 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")); |
| | | // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 |
| | | Integer num = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)).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); |
| | | } |
| | | } |
| | | } |
| | | log.info("供需后的费率 {}", priceRate); |
| | | |
| | | JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson); |
| | | // 天气预报动态调价 |
| | | JSONArray ws = jsonObject.getJSONArray("weatherRules"); |
| | | if (null != ws) { |
| | | WeatherDTO data = xpMapClient.wether(openCityId.toString()).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;//实际公里 |
| | | double realTime = duration ;//实际时间 |
| | | double exceedDistance = (realDistance - rule.getDouble("num2")) < 0 ? 0 : realDistance - rule.getDouble("num2");//超出起步里程的公里 |
| | | double exceedTime = (realTime - rule.getDouble("num3")) < 0 ? 0 : realTime - rule.getDouble("num3");//超过起步分钟数的时间 |
| | | |
| | | // 起步价 |
| | | Double startPrice = rule.getDouble("num1"); |
| | | Double startPrice = rule.getDouble("num1") * priceRate; |
| | | |
| | | // 超出公里数价格 |
| | | Double distancePrice = new BigDecimal(rule.getDouble("num4") * exceedDistance).setScale(2,RoundingMode.HALF_UP).doubleValue(); |
| | | Double distancePrice = new BigDecimal(rule.getDouble("num4") * exceedDistance).multiply(BigDecimal.valueOf(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue(); |
| | | |
| | | // 超出时间价格 |
| | | Double durationPrice = new BigDecimal(rule.getDouble("num5") * exceedTime).setScale(2,RoundingMode.HALF_UP).doubleValue(); |
| | | Double durationPrice = new BigDecimal(rule.getDouble("num5") * exceedTime).multiply(BigDecimal.valueOf(priceRate)).setScale(2,RoundingMode.HALF_UP).doubleValue(); |
| | | |
| | | startPrice = new BigDecimal(startPrice).multiply(BigDecimal.valueOf(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue(); |
| | | |
| | |
| | | |
| | | return xpPricingCardVo; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 计算基础价格 |
| | |
| | | // 是否调价过了 |
| | | 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.getData()==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(); |
| | | } |
| | | |
| | | // 冷却时间 |
| | | Integer time = getOrderNum(jsonObject, 6); |
| | | // 触发调价了 |
| | | redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES); |
| | | 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")); |
| | | // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 |
| | | 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(); |
| | | } |
| | | } |
| | | |
| | | // 冷却时间 |
| | | Integer time = getOrderNum(jsonObject, 6); |
| | | // 触发调价了 |
| | | redisService.setCacheObject("USER_DYNAMIC_PRICE_" + openCityId + "_" + uid, priceRate,time.longValue(), TimeUnit.MINUTES); |
| | | } |
| | | } |
| | | } |
| | | |
| | | log.info("供需后的费率 {}", priceRate); |
| | | JSONObject jsonObject = JSONObject.parseObject(dynamicPricingJson); |
| | | // 天气预报动态调价 |
| | | JSONArray ws = jsonObject.getJSONArray("weatherRules"); |
| | | if (null != ws) { |
| | | WeatherDTO data = xpMapClient.wether(openCityId.toString()).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; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | XpPricingCardVo xpPricingCardVo = new XpPricingCardVo(); |
| | | double amount = 0; |
| | | //等待费 |
| | | Date date = new Date(); |
| | | // 计算出是在那个时间段内 |
| | |
| | | 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("节假日"); |
| | | |
| | |
| | | // 里程费 |
| | | 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 { |
| | |
| | | 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")); |
| | | |
| | |
| | | |
| | | // 里程费 |
| | | 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()); |
| | | |
| | | |
| | | } else { |
| | |
| | | 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")); |
| | |
| | | |
| | | // 里程费 |
| | | 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 { |
| | | //其他时间段的计算 |
| | |
| | | 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 * rule.getDouble("num5")).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")); |
| | | |
| | |
| | | |
| | | // 里程费 |
| | | 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 * rule.getDouble("num5"))); |
| | | xpPricingCardVo.setDurationPrice(new BigDecimal(exceedTime * rule.getDouble("num5")).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; |
| | | xpPricingCardVo.setTotalPrice(amount); |
| | | |
| | | |
| | | |
| | | double amount = xpPricingCardVo.getStartPrice() + xpPricingCardVo.getDistancePrice() + xpPricingCardVo.getDurationPrice(); |
| | | xpPricingCardVo.setTotalPrice(new BigDecimal(amount).setScale(2,RoundingMode.HALF_UP).doubleValue()); |
| | | return xpPricingCardVo; |
| | | } |
| | | /** |