| | |
| | | import com.xiaopeng.order.service.IXpOrderService; |
| | | import com.xiaopeng.order.utils.TaxiPricingDemoService; |
| | | import com.xiaopeng.order.utils.RegionCodeFilterUtil; |
| | | import com.xiaopeng.order.utils.XpPricingUtil; |
| | | import com.xiaopeng.order.utils.holiday.HolidayUtil; |
| | | import com.xiaopeng.order.vo.OrderDetailVo; |
| | | import lombok.RequiredArgsConstructor; |
| | |
| | | private final XpCruiseOrderMapper xpCruiseOrderMapper; |
| | | private final XpTaskRuleClient xpTaskRuleClient; |
| | | private final XpCruisePlanClient xpCruisePlanClient; |
| | | private final XpPricingUtil xpPricingUtil; |
| | | |
| | | |
| | | @Autowired |
| | |
| | | |
| | | for (XpHistoryStartPointsVo datum : data) { |
| | | |
| | | if(datum.getOperationStatus()==2){ |
| | | if (datum.getOperationStatus() == 2) { |
| | | datum.setOperationStatus(1); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | // 保留2位数小数 |
| | |
| | | break; |
| | | case 7: |
| | | // 查询自动结束行程时间 |
| | | if(xpOrder.getOpenTrunk() != 1){ |
| | | if (xpOrder.getOpenTrunk() != 1) { |
| | | Integer arriveTime = xpSystemSettingClient.getOrderFinishTime().getData(); |
| | | // 添加自动结束行程定时任务job |
| | | Map<String, ? extends Object> endTripJobMaps = |
| | |
| | | // 远途费价格明细 |
| | | List<FareBreakdownDetailVo> longDistance = new ArrayList<>(); |
| | | XpOrder order = this.getById(orderId); |
| | | |
| | | Long orderAppUserId = order.getAppUserId(); |
| | | if (order == null) { |
| | | throw new RuntimeException("订单不存在"); |
| | | } |
| | |
| | | Date date = DateUtils.localDateTimeToDate(boardingTime); |
| | | |
| | | |
| | | double paramNum4 =0.0; |
| | | double paramNum5 =0.0; |
| | | |
| | | |
| | | double paramNum4 = 0.0; |
| | | double paramNum5 = 0.0; |
| | | |
| | | |
| | | //一口价 |
| | | if(pricing.getPricingType() == 2){ |
| | | JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); |
| | | String num1 = "00:00"; |
| | | String num2 = "23:59"; |
| | | String num3 = basicPricingJson.getString("num1"); |
| | | String num4 = basicPricingJson.getString("num2"); |
| | | String num5 = basicPricingJson.getString("num3"); |
| | | String num6 = basicPricingJson.getString("num4"); |
| | | String num7 = basicPricingJson.getString("num5"); |
| | | config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); |
| | | paramNum4 = basicPricingJson.getDouble("num2"); |
| | | paramNum5 = basicPricingJson.getDouble("num3"); |
| | | } |
| | | if (pricing.getPricingType() == 2) { |
| | | Double mileageKilometers = order.getMileageKilometers(); |
| | | Double duration1 = order.getDuration(); |
| | | |
| | | |
| | | //动态计费 |
| | | if (pricing.getPricingType() == 1) { |
| | | |
| | | for (int i = 0; i < startingFareJsonArray.size(); i++) { |
| | | com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i); |
| | | String num1 = jsonObject.getString("num1"); |
| | | String num2 = jsonObject.getString("num2"); |
| | | String num3 = jsonObject.getString("num3"); |
| | | String num4 = jsonObject.getString("num4"); |
| | | String num5 = jsonObject.getString("num5"); |
| | | String num6 = jsonObject.getString("num6"); |
| | | String num7 = jsonObject.getString("num7"); |
| | | config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); |
| | | // 判断当前是那个时段 |
| | | |
| | | Calendar calendarStart = Calendar.getInstance(); |
| | | calendarStart.setTime(date); |
| | | calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0])); |
| | | calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1])); |
| | | |
| | | Calendar calendarEnd = Calendar.getInstance(); |
| | | calendarEnd.setTime(date); |
| | | calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0])); |
| | | calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1])); |
| | | // 找到符合条件的直接跳出循环 |
| | | if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) { |
| | | paramNum4 = jsonObject.getDouble("num4"); |
| | | paramNum5 = jsonObject.getDouble("num5"); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); |
| | | config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split(" - ")[0], basicPricingJson.getString("num21").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")),paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); |
| | | config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split(" - ")[0], basicPricingJson.getString("num22").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); |
| | | config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", basicPricingJson.getString("num14").split(" - ")[0], basicPricingJson.getString("num14").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num15")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num16")), Double.parseDouble(basicPricingJson.getString("num17"))); |
| | | config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "00:00", "23:59", Double.parseDouble(basicPricingJson.getString("num29")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num30")), Double.parseDouble(basicPricingJson.getString("num31"))); |
| | | // --- 远途加价区间配置 (关键修改) --- |
| | | // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2) |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num6")), Double.parseDouble(basicPricingJson.getString("num7")), Double.parseDouble(basicPricingJson.getString("num8")))); |
| | | // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0) |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num9")), Double.parseDouble(basicPricingJson.getString("num10")), Double.parseDouble(basicPricingJson.getString("num11")))); |
| | | // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值 |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num12")), 999999, Double.parseDouble(basicPricingJson.getString("num13")))); |
| | | } |
| | | |
| | | |
| | | TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService(); |
| | | Integer holidayToday = holidayUtil.isHolidayToday(); |
| | | Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getBoardingTime()), order.getMileageKilometers(), gpsPoints, config,holidayToday); |
| | | log.info("======= 订单计费账单 ======="); |
| | | bill.forEach((detail, price) -> log.info(detail + ": " + price + " 元")); |
| | | |
| | | BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | log.info("--------------------------"); |
| | | log.info("应付总额: " + totalAmount + " 元"); |
| | | BigDecimal startMoney = BigDecimal.ZERO; |
| | | // 默认费率1 |
| | | double priceRate = 1; |
| | | if (pricing.getIsDynamicPrice() == 1) { |
| | | // 先判断是否已经调价过了 |
| | | Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid); |
| | | if (userDynamicPriceObj != null) { |
| | | // 是否调价过了 |
| | | priceRate = Double.parseDouble(userDynamicPriceObj.toString()); |
| | | } else { |
| | | // 没有调过 |
| | | //是否触发动态调价 redis获取 |
| | | Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId()); |
| | | if (dynamicPriceObj != null) { |
| | | JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson()); |
| | | // 触发动态调价 |
| | | // value=时间 |
| | | String timeStr = dynamicPriceObj.toString(); |
| | | // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 |
| | | Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId())); |
| | | // 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_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | } |
| | | // 封装费用明细数据 |
| | | for (Map.Entry<String, BigDecimal> stringBigDecimalEntry : bill.entrySet()) { |
| | | // 封装起步价 |
| | | FareBreakdownDetailVo startDetail = new FareBreakdownDetailVo(); |
| | | String key = stringBigDecimalEntry.getKey(); |
| | | if (key.contains("起步价")) { |
| | | startDetail.setTime(key.split("\\|")[1]); |
| | | startDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | startMoney = startMoney.add(stringBigDecimalEntry.getValue()); |
| | | if (key.contains("普通时段")) { |
| | | startDetail.setType(1); |
| | | } else if (key.contains("夜间")) { |
| | | startDetail.setType(2); |
| | | } else if (key.contains("高峰")) { |
| | | startDetail.setType(3); |
| | | } else if (key.contains("节假")) { |
| | | startDetail.setType(4); |
| | | } |
| | | String durationAndMileage = key.split("\\|")[2]; |
| | | startDetail.setDuration(Double.valueOf(durationAndMileage.split("&")[0])); |
| | | startDetail.setMileage(new BigDecimal(durationAndMileage.split("&")[1])); |
| | | start.add(startDetail); |
| | | } |
| | | // 封装里程费 |
| | | if (!key.contains("起步") && !key.contains("时长") && !key.contains("远途") && !key.contains("distance")) { |
| | | FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("普通时段")) { |
| | | mileageDetail.setType(1); |
| | | String key1 = "distance普通时段|" + key.split("\\|")[1]; |
| | | String key2 = "普通时段|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("夜间行驶")) { |
| | | mileageDetail.setType(2); |
| | | String key1 = "distance夜间行驶|" + key.split("\\|")[1]; |
| | | String key2 = "夜间行驶|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("高峰期")) { |
| | | mileageDetail.setType(3); |
| | | String key1 = "distance高峰期|" + key.split("\\|")[1]; |
| | | String key2 = "高峰期|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("节假")) { |
| | | mileageDetail.setType(4); |
| | | String key1 = "distance节假日|" + key.split("\\|")[1]; |
| | | String key2 = "节假日|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } |
| | | mileage.add(mileageDetail); |
| | | } |
| | | // 封装时长费 |
| | | FareBreakdownDetailVo timeDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("时长费")) { |
| | | timeDetail.setType(startDetail.getType()); |
| | | timeDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | timeDetail.setDuration(Double.valueOf(key.split("&")[1])); |
| | | duration.add(timeDetail); |
| | | } |
| | | // 封装远途费 |
| | | FareBreakdownDetailVo longDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("远途费")) { |
| | | longDetail.setType(startDetail.getType()); |
| | | longDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | longDetail.setMileage(new BigDecimal(key.split("&")[1])); |
| | | longDistance.add(longDetail); |
| | | } |
| | | } |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : start) { |
| | | com.alibaba.fastjson.JSONObject basicPricingJson = com.alibaba.fastjson.JSONObject.parseObject(pricing.getBasicPricingJson()); |
| | | // String num1 = "00:00"; |
| | | // String num2 = "23:59"; |
| | | // String num3 = basicPricingJson.getString("num1"); |
| | | // String num4 = basicPricingJson.getString("num2"); |
| | | // String num5 = basicPricingJson.getString("num3"); |
| | | // String num6 = basicPricingJson.getString("num4"); |
| | | // String num7 = basicPricingJson.getString("num5"); |
| | | // config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); |
| | | // paramNum4 = basicPricingJson.getDouble("num2"); |
| | | // paramNum5 = basicPricingJson.getDouble("num3"); |
| | | XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationFixedPrice(orderAppUserId.toString(), basicPricingJson, null, mileageKilometers, duration1, 0, 0.0, pricing.getIsDynamicPrice(), order.getCityId(), pricing.getDynamicPricingJson()); |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(1); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | BigDecimal mileageMoney = BigDecimal.ZERO; |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : mileage) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setType(1); |
| | | xpOrderDetail.setMileage(new BigDecimal(mileageKilometers).setScale(2, RoundingMode.HALF_UP)); |
| | | xpOrderDetail.setDuration(duration1); |
| | | xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getStartPrice()).setScale(2, RoundingMode.HALF_UP)); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | xpOrderDetail = new XpOrderDetail(); |
| | | xpOrderDetail.setDetailType(2); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | order.setMileageMoney(mileageMoney); |
| | | |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : longDistance) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(4); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetail.setType(1); |
| | | xpOrderDetail.setMileage(new BigDecimal(mileageKilometers).setScale(2, RoundingMode.HALF_UP)); |
| | | xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDistancePrice()).setScale(2,RoundingMode.HALF_UP)); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail = new XpOrderDetail(); |
| | | xpOrderDetail.setDetailType(3); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setType(1); |
| | | xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDurationPrice()).setScale(2, RoundingMode.HALF_UP)); |
| | | xpOrderDetail.setDuration(duration1); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | |
| | | |
| | | |
| | | for (XpOrderDetail xpOrderDetail : xpOrderDetails) { |
| | | xpOrderDetailMapper.insert(xpOrderDetail); |
| | | } |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { |
| | | if(order.getDurationMoney()==null){ |
| | | order.setDurationMoney(BigDecimal.ZERO); |
| | | BigDecimal totalPrice =BigDecimal.ZERO; |
| | | for (XpOrderDetail xpOrderDetail1 : xpOrderDetails) { |
| | | totalPrice = totalPrice.add(xpOrderDetail1.getMoney()); |
| | | xpOrderDetailMapper.insert(xpOrderDetail1); |
| | | } |
| | | BigDecimal add = order.getDurationMoney().add(fareBreakdownDetailVo.getMoney()); |
| | | order.setDurationMoney(add); |
| | | } |
| | | order.setOrderMoney(totalPrice); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | |
| | | |
| | | } else { |
| | | |
| | | |
| | | //动态计费 |
| | | if (pricing.getPricingType() == 1) { |
| | | |
| | | for (int i = 0; i < startingFareJsonArray.size(); i++) { |
| | | com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i); |
| | | String num1 = jsonObject.getString("num1"); |
| | | String num2 = jsonObject.getString("num2"); |
| | | String num3 = jsonObject.getString("num3"); |
| | | String num4 = jsonObject.getString("num4"); |
| | | String num5 = jsonObject.getString("num5"); |
| | | String num6 = jsonObject.getString("num6"); |
| | | String num7 = jsonObject.getString("num7"); |
| | | config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); |
| | | // 判断当前是那个时段 |
| | | |
| | | Calendar calendarStart = Calendar.getInstance(); |
| | | calendarStart.setTime(date); |
| | | calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0])); |
| | | calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1])); |
| | | |
| | | Calendar calendarEnd = Calendar.getInstance(); |
| | | calendarEnd.setTime(date); |
| | | calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0])); |
| | | calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1])); |
| | | // 找到符合条件的直接跳出循环 |
| | | if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) { |
| | | paramNum4 = jsonObject.getDouble("num4"); |
| | | paramNum5 = jsonObject.getDouble("num5"); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | |
| | | JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); |
| | | config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split(" - ")[0], basicPricingJson.getString("num21").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); |
| | | config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split(" - ")[0], basicPricingJson.getString("num22").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")))); |
| | | config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", basicPricingJson.getString("num14").split(" - ")[0], basicPricingJson.getString("num14").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num15")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num16")), Double.parseDouble(basicPricingJson.getString("num17"))); |
| | | config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "00:00", "23:59", Double.parseDouble(basicPricingJson.getString("num29")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num30")), Double.parseDouble(basicPricingJson.getString("num31"))); |
| | | // --- 远途加价区间配置 (关键修改) --- |
| | | // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2) |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num6")), Double.parseDouble(basicPricingJson.getString("num7")), Double.parseDouble(basicPricingJson.getString("num8")))); |
| | | // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0) |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num9")), Double.parseDouble(basicPricingJson.getString("num10")), Double.parseDouble(basicPricingJson.getString("num11")))); |
| | | // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值 |
| | | config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num12")), 999999, Double.parseDouble(basicPricingJson.getString("num13")))); |
| | | } |
| | | |
| | | |
| | | TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService(); |
| | | Integer holidayToday = holidayUtil.isHolidayToday(); |
| | | Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getBoardingTime()), order.getMileageKilometers(), gpsPoints, config, holidayToday); |
| | | log.info("======= 订单计费账单 ======="); |
| | | bill.forEach((detail, price) -> log.info(detail + ": " + price + " 元")); |
| | | |
| | | BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | log.info("--------------------------"); |
| | | log.info("应付总额: " + totalAmount + " 元"); |
| | | BigDecimal startMoney = BigDecimal.ZERO; |
| | | // 默认费率1 |
| | | double priceRate = 1; |
| | | if (pricing.getIsDynamicPrice() == 1) { |
| | | // 先判断是否已经调价过了 |
| | | Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid); |
| | | if (userDynamicPriceObj != null) { |
| | | // 是否调价过了 |
| | | priceRate = Double.parseDouble(userDynamicPriceObj.toString()); |
| | | } else { |
| | | // 没有调过 |
| | | //是否触发动态调价 redis获取 |
| | | Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId()); |
| | | if (dynamicPriceObj != null) { |
| | | JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson()); |
| | | // 触发动态调价 |
| | | // value=时间 |
| | | String timeStr = dynamicPriceObj.toString(); |
| | | // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 |
| | | Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId())); |
| | | // 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_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES); |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | } |
| | | // 封装费用明细数据 |
| | | for (Map.Entry<String, BigDecimal> stringBigDecimalEntry : bill.entrySet()) { |
| | | // 封装起步价 |
| | | FareBreakdownDetailVo startDetail = new FareBreakdownDetailVo(); |
| | | String key = stringBigDecimalEntry.getKey(); |
| | | if (key.contains("起步价")) { |
| | | startDetail.setTime(key.split("\\|")[1]); |
| | | startDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | startMoney = startMoney.add(stringBigDecimalEntry.getValue()); |
| | | if (key.contains("普通时段")) { |
| | | startDetail.setType(1); |
| | | } else if (key.contains("夜间")) { |
| | | startDetail.setType(2); |
| | | } else if (key.contains("高峰")) { |
| | | startDetail.setType(3); |
| | | } else if (key.contains("节假")) { |
| | | startDetail.setType(4); |
| | | } |
| | | String durationAndMileage = key.split("\\|")[2]; |
| | | startDetail.setDuration(Double.valueOf(durationAndMileage.split("&")[0])); |
| | | startDetail.setMileage(new BigDecimal(durationAndMileage.split("&")[1])); |
| | | start.add(startDetail); |
| | | } |
| | | // 封装里程费 |
| | | if (!key.contains("起步") && !key.contains("时长") && !key.contains("远途") && !key.contains("distance")) { |
| | | FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("普通时段")) { |
| | | mileageDetail.setType(1); |
| | | String key1 = "distance普通时段|" + key.split("\\|")[1]; |
| | | String key2 = "普通时段|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("夜间行驶")) { |
| | | mileageDetail.setType(2); |
| | | String key1 = "distance夜间行驶|" + key.split("\\|")[1]; |
| | | String key2 = "夜间行驶|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("高峰期")) { |
| | | mileageDetail.setType(3); |
| | | String key1 = "distance高峰期|" + key.split("\\|")[1]; |
| | | String key2 = "高峰期|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } else if (key.contains("节假")) { |
| | | mileageDetail.setType(4); |
| | | String key1 = "distance节假日|" + key.split("\\|")[1]; |
| | | String key2 = "节假日|" + key.split("\\|")[1]; |
| | | BigDecimal distance = bill.get(key1); |
| | | BigDecimal money = bill.get(key2); |
| | | mileageDetail.setMileage(distance); |
| | | order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); |
| | | } |
| | | mileage.add(mileageDetail); |
| | | } |
| | | // 封装时长费 |
| | | FareBreakdownDetailVo timeDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("时长费")) { |
| | | timeDetail.setType(startDetail.getType()); |
| | | timeDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | timeDetail.setDuration(Double.valueOf(key.split("&")[1])); |
| | | duration.add(timeDetail); |
| | | } |
| | | // 封装远途费 |
| | | FareBreakdownDetailVo longDetail = new FareBreakdownDetailVo(); |
| | | if (key.contains("远途费")) { |
| | | longDetail.setType(startDetail.getType()); |
| | | longDetail.setMoney(stringBigDecimalEntry.getValue()); |
| | | longDetail.setMileage(new BigDecimal(key.split("&")[1])); |
| | | longDistance.add(longDetail); |
| | | } |
| | | } |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : start) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(1); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | BigDecimal mileageMoney = BigDecimal.ZERO; |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : mileage) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(2); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | order.setMileageMoney(mileageMoney); |
| | | |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : longDistance) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(4); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { |
| | | XpOrderDetail xpOrderDetail = new XpOrderDetail(); |
| | | BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); |
| | | xpOrderDetail.setOrderId(orderId); |
| | | xpOrderDetail.setDetailType(3); |
| | | xpOrderDetail.setCreateTime(LocalDateTime.now()); |
| | | mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); |
| | | xpOrderDetails.add(xpOrderDetail); |
| | | } |
| | | |
| | | |
| | | for (XpOrderDetail xpOrderDetail : xpOrderDetails) { |
| | | xpOrderDetailMapper.insert(xpOrderDetail); |
| | | } |
| | | |
| | | for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { |
| | | if (order.getDurationMoney() == null) { |
| | | order.setDurationMoney(BigDecimal.ZERO); |
| | | } |
| | | BigDecimal add = order.getDurationMoney().add(fareBreakdownDetailVo.getMoney()); |
| | | order.setDurationMoney(add); |
| | | } |
| | | // for (XpOrderDetail xpOrderDetail : xpOrderDetails) { |
| | | // if (xpOrderDetail.getDetailType() == 1) { |
| | | // order.setDurationType(xpOrderDetail.getType()); |
| | |
| | | // |
| | | // } |
| | | |
| | | BigDecimal orderMoney = startMoney.add(mileageMoney).add(order.getDurationMoney() != null ? order.getDurationMoney() : BigDecimal.ZERO) |
| | | .add(order.getLongDistancemoney() != null ? order.getLongDistancemoney() : BigDecimal.ZERO) |
| | | .add(order.getWaitMoney() != null ? order.getWaitMoney() : BigDecimal.ZERO); |
| | | order.setOrderMoney(orderMoney); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | BigDecimal orderMoney = startMoney.add(mileageMoney).add(order.getDurationMoney() != null ? order.getDurationMoney() : BigDecimal.ZERO) |
| | | .add(order.getLongDistancemoney() != null ? order.getLongDistancemoney() : BigDecimal.ZERO) |
| | | .add(order.getWaitMoney() != null ? order.getWaitMoney() : BigDecimal.ZERO); |
| | | order.setOrderMoney(orderMoney); |
| | | order.setAppUserId(null); |
| | | baseMapper.updateById(order); |
| | | |
| | | } |
| | | |
| | | |
| | | if (order.getCouponId() != null) { |
| | | UseUserCouponDto useUserCouponDto = new UseUserCouponDto(); |
| | | useUserCouponDto.setUserId(Long.valueOf(uid)); |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | private MileageDto mileageType(MileageDto param, JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) { |
| | | // 计算出是在哪个普通时间段内 |
| | | for (Object o : startingFareJsonArray) { |
| | |
| | | |
| | | List<FareBreakdownDetailVo> start = new ArrayList<>(); |
| | | List<FareBreakdownDetailVo> mileage = new ArrayList<>(); |
| | | List<FareBreakdownDetailVo> duration = new ArrayList<>(); |
| | | List<FareBreakdownDetailVo> longDistance = new ArrayList<>(); |
| | | |
| | | List<XpOrderDetail> xpOrderDetails = xpOrderDetailMapper.selectList(new LambdaQueryWrapper<XpOrderDetail>().eq(XpOrderDetail::getOrderId, orderId)); |
| | | for (XpOrderDetail xpOrderDetail : xpOrderDetails) { |
| | |
| | | detail.setMoney(xpOrderDetail.getMoney()); |
| | | if (xpOrderDetail.getDetailType() == 1) { |
| | | start.add(detail); |
| | | } else { |
| | | } else if(xpOrderDetail.getDetailType()==2){ |
| | | mileage.add(detail); |
| | | }else if(xpOrderDetail.getDetailType()==3){ |
| | | duration.add(detail); |
| | | }else if(xpOrderDetail.getDetailType()==4){ |
| | | longDistance.add(detail); |
| | | } |
| | | } |
| | | List<FareBreakdownDetailVo> duration = new ArrayList<>(); |
| | | if (order.getDuration() != null && order.getDuration() > 0) { |
| | | FareBreakdownDetailVo durationDetail = new FareBreakdownDetailVo(); |
| | | durationDetail.setType(order.getDurationType()); |
| | | durationDetail.setDuration(order.getDuration()); |
| | | durationDetail.setMoney(order.getDurationMoney()); |
| | | duration.add(durationDetail); |
| | | } |
| | | List<FareBreakdownDetailVo> longDistance = new ArrayList<>(); |
| | | |
| | | if (order.getLongDistance() != null && order.getLongDistance() > 0) { |
| | | FareBreakdownDetailVo longDistanceDetail = new FareBreakdownDetailVo(); |
| | | longDistanceDetail.setType(order.getLongDistanceType()); |
| | | longDistanceDetail.setMileage(BigDecimal.valueOf(order.getLongDistance())); |
| | | longDistanceDetail.setMoney(order.getLongDistancemoney()); |
| | | longDistance.add(longDistanceDetail); |
| | | } |
| | | // if (order.getDuration() != null && order.getDuration() > 0) { |
| | | // FareBreakdownDetailVo durationDetail = new FareBreakdownDetailVo(); |
| | | // durationDetail.setType(order.getDurationType()); |
| | | // durationDetail.setDuration(order.getDuration()); |
| | | // durationDetail.setMoney(order.getDurationMoney()); |
| | | // duration.add(durationDetail); |
| | | // } |
| | | |
| | | // |
| | | // if (order.getLongDistance() != null && order.getLongDistance() > 0) { |
| | | // FareBreakdownDetailVo longDistanceDetail = new FareBreakdownDetailVo(); |
| | | // longDistanceDetail.setType(order.getLongDistanceType()); |
| | | // longDistanceDetail.setMileage(BigDecimal.valueOf(order.getLongDistance())); |
| | | // longDistanceDetail.setMoney(order.getLongDistancemoney()); |
| | | // longDistance.add(longDistanceDetail); |
| | | // } |
| | | res.setStart(start); |
| | | res.setMileage(mileage); |
| | | res.setDuration(duration); |
| | |
| | | Duration durationBetween = Duration.between(createTime, tripEnd); |
| | | |
| | | // 转换为秒并保留一位小数 |
| | | BigDecimal minutes = BigDecimal.valueOf(durationBetween.getSeconds()) |
| | | ; |
| | | BigDecimal minutes = BigDecimal.valueOf(durationBetween.getSeconds()); |
| | | res.setTime(minutes); |
| | | return R.ok(res); |
| | | } |