From c96fbe6b0aeb413a17c429133ee6d81d138144b9 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期二, 09 六月 2026 10:58:52 +0800
Subject: [PATCH] Merge branch '1.0' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi into 1.0
---
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java | 610 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 523 insertions(+), 87 deletions(-)
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
index 9acc169..4a37637 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -1,45 +1,63 @@
package com.xiaopeng.operation.service.impl;
-import com.alibaba.fastjson.JSONObject;
+import cn.hutool.core.lang.Snowflake;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.account.GetUserCouponDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
+import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.feignClient.account.XpAppUserClient;
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
+import com.xiaopeng.api.feignClient.maintenance.XpVehicleModelClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
-import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
-import com.xiaopeng.api.model.account.XpAppUser;
+import com.xiaopeng.api.model.maintenance.XpVehicleModel;
import com.xiaopeng.api.model.operation.*;
import com.xiaopeng.api.model.order.XpOrder;
-import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.account.UserCouponVo;
import com.xiaopeng.api.vo.operation.FareVo;
import com.xiaopeng.api.vo.operation.RouteAndFareVo;
import com.xiaopeng.api.vo.operation.RouteVo;
+import com.xiaopeng.api.vo.order.XpPricingCardVo;
import com.xiaopeng.common.core.constant.CacheConstants;
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;
import com.xiaopeng.operation.constant.I18nKeyConstant;
-import com.xiaopeng.operation.dto.XpOrderDto;
-import com.xiaopeng.operation.entity.XpGeoQueryEntity;
+import com.xiaopeng.operation.dto.*;
+import com.xiaopeng.operation.job.base.QuartzManager;
+import com.xiaopeng.operation.job.base.TimeJobType;
+import com.xiaopeng.operation.job.jobs.DynamicPricingCheckJob;
import com.xiaopeng.operation.mapper.*;
+import com.xiaopeng.operation.query.PricingPageListQuery;
import com.xiaopeng.operation.service.IXpGeoQueryEntityService;
+import com.xiaopeng.operation.service.XpPointService;
import com.xiaopeng.operation.service.XpPricingService;
import com.xiaopeng.operation.utils.XpPricingUtil;
+import com.xiaopeng.operation.utils.holiday.HolidayUtil;
import com.xiaopeng.operation.utils.map.FastDistanceCalculator;
-import com.xiaopeng.operation.vo.XpPricingCardVo;
+import com.xiaopeng.operation.vo.PricingInfoVo;
+import com.xiaopeng.operation.vo.PricingPageListVO;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.stereotype.Service;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
@@ -53,6 +71,7 @@
* @author liu
* @since 2026-02-03
*/
+@Slf4j
@Service
public class XpPricingServiceImpl extends ServiceImpl<XpPricingMapper, XpPricing> implements XpPricingService {
@@ -87,26 +106,34 @@
@Resource
private XpElectronicFenceAreaMapper xpElectronicFenceAreaMapper;
- @Resource
- private XpVehicleClient xpVehicleClient;
@Resource
- private XpPointMapper xpPointMapper;
-
+ private XpVehicleModelClient xpVehicleModelClient;
@Resource
private XpWhitelistMapper xpWhitelistMapper;
@Resource
private XpAppUserClient xpAppUserClient;
+ @Resource
+ private HolidayUtil holidayUtil;
@Autowired
private IXpGeoQueryEntityService geoQueryEntityService;
+ @Autowired
+ private XpElectronicFenceMapper xpElectronicFenceMapper;
+
+ @Autowired
+ private XpPointService xpPointService;
+
+ @Resource(name = "hutoolSnowflake")
+ private Snowflake snowflake;
// 自定义线程池用于并行执行任务
private final ExecutorService executorService;
+
// 初始化自定义线程池
public XpPricingServiceImpl() {
@@ -160,6 +187,7 @@
@Override
+ @Deprecated
public RouteAndFareVo getRouteAndFare(RouteAndFareDto routeAndFareDto, String userId) {
@@ -169,7 +197,7 @@
+ "-" + routeAndFareDto.getDestination().getLongitude() + "-" + routeAndFareDto.getDestination().getLatitude() + "-" + getCurrentTimeSlot() + "-" + userId;
if (redisService.hasKey(key)) {
- String jsonStr = Objects.requireNonNull(redisService.getCacheObject( key)).toString();
+ String jsonStr = Objects.requireNonNull(redisService.getCacheObject(key)).toString();
RouteAndFareVo RouteAndFareVo = JSONObject.parseObject(jsonStr, RouteAndFareVo.class);
return (RouteAndFareVo);
}
@@ -186,18 +214,39 @@
routeAndFareDto.setRoutePlanRule(xpRoutePlan.getRoutePlanRule());
}
-// XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, routeAndFareDto.getOpenCityId()));
-// if (xpPricing == null) {
-// throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
-// }
+ XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, routeAndFareDto.getOpenCityId()));
+ if (xpPricing == null) {
+ throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
+ }
+
+
+
+// // 算距离
+ R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
+ if(distanceAndDuration.getCode()!=200){
+ throw new ServiceException("未找到路径", I18nKeyConstant.PATH_NOT_FOUND);
+ }
+
+
+ RouteVo routeVo = distanceAndDuration.getData();
// 2. 计算价格(需要在并行任务前完成,因为优惠券查询需要价格)
-// XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationPrice(
-// JSON.parseObject(xpPricing.getBasicPricingJson()),
-// JSON.parseArray(xpPricing.getStartingFareJson()),
-// 1, 1, 0, 0.0
-// );
- XpPricingCardVo xpPricingCardVo = new XpPricingCardVo();
+
+ 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. 并行执行远程服务调用 判断是否同一经营区域
CompletableFuture<R<Boolean>> diagnosisAreaFuture = CompletableFuture.supplyAsync(
@@ -205,27 +254,22 @@
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())
- new GetUserCouponDto(Long.valueOf(userId), 1d)
- );
+ // 优惠券
+ return xpAppUserCouponClient.getUserCoupon(
+ new GetUserCouponDto(Long.valueOf(userId), finalXpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId(),null)
+// new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId())
+ );
},
executorService
);
// 4. 等待所有并行任务完成并获取结果
R<Boolean> diagnosisResult = diagnosisAreaFuture.join();
-// R<RouteVo> routeResult = routeFuture.join();
R<UserCouponVo> couponResult = couponFuture.join();
// 5. 处理诊断结果
@@ -236,7 +280,7 @@
throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
}
- // 6. 处理路线结果
+// // 6. 处理路线结果
// if (routeResult.getCode() != 200) {
// throw new RuntimeException(routeResult.getMsg());
// }
@@ -250,9 +294,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) {
@@ -265,16 +309,46 @@
// 8. 构建响应对象
RouteAndFareVo routeAndFareVo = new RouteAndFareVo();
-// routeAndFareVo.setRoute(routeVo);
+
+ // 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);
+ 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());
if (userCouponVo != null) {
fareVo.setDiscountAmount(userCouponVo.getMoney());
+ fareVo.setCouponType(userCouponVo.getCouponType());
fareVo.setFinalFare(fareVo.getOriginalFare() - fareVo.getDiscountAmount());
fareVo.setCouponId(userCouponVo.getId());
} else {
@@ -283,11 +357,11 @@
}
// 10. 检查等待时间
- Integer waitTime = getWaitTime(routeAndFareDto.getOrigin().getLongitude(), routeAndFareDto.getOrigin().getLatitude());
- if(waitTime>3){
- throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
- }
- fareVo.setWaitingTime(waitTime);
+// Integer waitTime = getWaitTime(routeAndFareDto.getOrigin().getLongitude(), routeAndFareDto.getOrigin().getLatitude());
+// if (waitTime > 3) {
+// throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
+// }
+// fareVo.setWaitingTime(waitTime);
// 11. 生成订单ID并缓存
@@ -314,7 +388,7 @@
* @return
*/
@Override
- public Integer getWaitTime(double lon,double lat) {
+ public Integer getWaitTime(double lon, double lat) {
List<XpGeoQueryEntity> entities = geoQueryEntityService.findByLocationWithin500MetersAndLastWeekAndStatusGreater(
lon,
lat,
@@ -323,10 +397,10 @@
if (entities.isEmpty()) {
- return 1;
+ return 1;
} else {
// 已完成接单的数据
- List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() > 1).collect(Collectors.toList());
+ List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() == 1).collect(Collectors.toList());
// 计算平均等待时间
OptionalDouble averageOptional = validEntities.stream().mapToDouble(XpGeoQueryEntity::getSeconds).average();
@@ -335,63 +409,96 @@
// 未完成接单的数量
int count = entities.size() - validEntities.size();
if (count == 0) {
- return 1;
+ return 1;
} else {
double waitMinutes = (average * count) / 60;
if (waitMinutes > 3) {
throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
+ } else if (waitMinutes == 0) {
+ return 1;
}
return (int) waitMinutes;
}
} else {
- return 1;
+ return 1;
}
}
}
-
@Override
public Long saveOrder(XpOrderDto dto, String uid) {
+
+ // 是否在运营区域时间内
+ XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId());
+ XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(xpElectronicFenceArea.getElectronicId());
+ String operationStrategy = xpElectronicFence.getOperationStrategy();
+ Boolean inOperationTime = isInOperationTime(operationStrategy);
+ if (!inOperationTime) {
+ throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
+ }
+
+
Integer cancelCount = xpTradingStrategyMapper.selectOne(null).getCancleCount();
// 判断是否有进行的订单
R<Long> r = xpOrderClient.hasUnPaodOrder(uid);
- if(r.getData()>0){
- throw new RuntimeException("有正在进行的订单");
+ if (r.getData() > 0) {
+ throw new ServiceException("有正在进行的订单", I18nKeyConstant.HAS_UNPAID_ORDER);
}
// 获取起点经纬度
- XpPoint xpPoint = xpPointMapper.selectById(dto.getStartPointId());
+ XpPoint xpPoint = xpPointService.getById(dto.getStartPointId());
// 终点
- XpPoint endXpPoint = xpPointMapper.selectById(dto.getStartPointId());
+ XpPoint endXpPoint = xpPointService.getById(dto.getStartPointId());
- // 判断当天取消的次数 后台配置 redis 查询
- Object cancelOrder = redisService.getCacheObject("CANCEL_ORDER_" + uid);
- if(cancelOrder!=null){
- Integer num = Integer.valueOf(cancelOrder.toString());
- if(num>=cancelCount){
- return 0l;
- }
+ // 判断点位是否在运营区域内
+ LocalTime now = LocalTime.now();
+ boolean inTime = xpPointService.getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod());
+ if (!inTime) {
+ throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
+ }
+ inTime = xpPointService.getInTime(now, endXpPoint.getEffectivePeriod(), endXpPoint.getEffectiveTimePeriod());
+ if (!inTime) {
+ throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
}
+ // 静默处理
+ boolean isSilent = false;
+ Integer num = xpOrderClient.todayCancellationCount(Long.valueOf(uid)).getData();
+ if (num >= cancelCount) {
+ isSilent = true;
+ }
+
+
+ // 获取起步里程
+// XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, dto.getOpenCityId()));
+// Integer startMileage = XpPricingUtil.getStartMileage(xpPricing.getStartingFareJson());
+// if (startMileage == null) {
+// throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
+// }
// 根据id获取手机号
- Boolean isPriorityDispatch=false;
- R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
- if(xpAppUserR.getCode()==R.SUCCESS){
- Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
- if(count>0){
- isPriorityDispatch=true;
- }
- }
+ Boolean isPriorityDispatch = true;
+// R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
+// if (xpAppUserR.getCode() == R.SUCCESS) {
+// Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
+// if (count > 0) {
+// isPriorityDispatch = true;
+// }
+// }
// 生成订单数据
XpOrder xpOrder = new XpOrder();
+
+ xpOrder.setVehicleId(1l);
+
+// xpOrder.setStartMileage(Double.valueOf(startMileage));
+
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());
@@ -415,25 +522,62 @@
xpOrder.setEndPointId(dto.getEndPointId());
xpOrder.setStartPointName(xpPoint.getPointName());
xpOrder.setEndPointName(endXpPoint.getPointName());
+ xpOrder.setXpuStartTaskId(snowflake.nextId() + "");
+ xpOrder.setXpuEndTaskId(snowflake.nextId() + "");
// 当前时段
String currentTimeSlot = DateUtils.getCurrentTimeSlot();
xpOrder.setTimeSlot(currentTimeSlot);
xpOrder.setCreateTime(LocalDateTime.now());
+
+ // 计算距离 和 时间
+ RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
+ LonLatDto lonLatDto = new LonLatDto();
+ lonLatDto.setLongitude(xpPoint.getPointLon());
+ lonLatDto.setLatitude(xpPoint.getPointLat());
+ routeAndFareDto.setOrigin(lonLatDto);
+
+ LonLatDto lonLatDto1 = new LonLatDto();
+ lonLatDto1.setLongitude(endXpPoint.getPointLon());
+ lonLatDto1.setLatitude(endXpPoint.getPointLat());
+ routeAndFareDto.setDestination(lonLatDto1);
+
+
+ XpOpenCity xpOpenCity = xpOpenCityMapper.selectById(dto.getOpenCityId());
+ XpRoutePlan xpRoutePlan = xpRoutePlanMapper.selectOne(new LambdaQueryWrapper<XpRoutePlan>().eq(XpRoutePlan::getAuditStatus, 2).eq(XpRoutePlan::getCityCode, xpOpenCity.getCityCode()));
+ if (xpRoutePlan != null) {
+ routeAndFareDto.setRoutePlanRule(xpRoutePlan.getRoutePlanRule());
+ }
+ R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
+ Integer distance = 0;
+ Integer duration = 0;
+ if (distanceAndDuration.getCode() != 200) {
+// throw new ServiceException("订单生成失败", I18nKeyConstant.ORDER_CREATE_FAIL);
+ }
+// distance = distanceAndDuration.getData().getDistance();
+// duration = distanceAndDuration.getData().getDuration();
+
+
// 产生订单
R<Long> addOrderR = xpOrderClient.addOrder(xpOrder);
- if(addOrderR.getCode()!=R.SUCCESS){
+ if (addOrderR.getCode() != R.SUCCESS) {
throw new ServiceException("订单生成失败", I18nKeyConstant.ORDER_CREATE_FAIL);
}
Long orderId = addOrderR.getData();
+
+ // 静默处理 不推单
+ if (isSilent) {
+ return orderId;
+ }
+
// 最大距离
Object maxPushDistanceObj = redisService.getCacheObject(CacheConstants.MAX_PUSH_DISTANCE);
- Double maxPushDistance= 0.0;
- if(maxPushDistanceObj!=null){
- maxPushDistance = Double.valueOf(maxPushDistanceObj.toString());
- }else {
- maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance();
+ Double maxPushDistance = 0.0;
+ if (maxPushDistanceObj != null) {
+ maxPushDistance = Double.valueOf(maxPushDistanceObj.toString());
+ } else {
+ maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance();
}
// 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列 如果没有符合的新增一个队列 符合后看是否白名单账号 是则直接放在队列前端
@@ -443,20 +587,47 @@
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){
- if(isPriorityDispatch){
- // 头部 value 订单_经纬度_状态_用户id_订单编号
- redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber());
- }else {
+ if (v < maxPushDistance) {
+ if (isPriorityDispatch) {
+ // 头部 value 订单_经纬度_状态_用户id_订单编号_距离_时间
+ redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule());
+ } else {
// 尾部
- redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber());
+ redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule());
}
+ xpOrder.setQueueName(s);
+ 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;
}
}
- String key = CacheConstants.QUEUE_POINT_ID+"-"+ xpPoint.getId()+"-"+xpPoint.getPointLon()+","+xpPoint.getPointLat();
- redisService.setCacheList(key,Arrays.asList(orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()));
+ String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
+ redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule()));
+ 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;
//
@@ -466,12 +637,277 @@
//
-
-
// 产生订单 存订单数据 // 下发指令 消息推送用户端
// return null;
}
+ private String getOrderNumber(){
+ int random = Double.valueOf(Math.random() * 1000).intValue();
+ return "XP" + random + System.currentTimeMillis();
+ }
+
+ private Boolean isInOperationTime(String operationStrategy) {
+ JSONArray jsonArray = JSONArray.parseArray(operationStrategy);
+ Integer holidayToday = holidayUtil.isHolidayToday();
+ for (Object o : jsonArray) {
+ JSONObject jsonObject = JSONObject.parseObject(o.toString());
+ String type = jsonObject.getString("type");
+ if (type.equals(holidayToday.toString())) {
+ JSONArray time = jsonObject.getJSONArray("time");
+ // 判断当前时间 是否在time时间段中
+ for (Object object : time) {
+ String[] timeArray = object.toString().split("-");
+ String startTime = timeArray[0];
+ String endTime = timeArray[1];
+ boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
+ if (currentTimeInRange) {
+ return true;
+ }
+ }
+ } else if (type.equals("3")) {
+ // 判断是什么类型 0每天 1-7 想起
+ String typeStr = jsonObject.getString("typeStr");
+ // 查看今天周几
+ Integer week = DateUtils.getWeek();
+ // 包含每天 或者 包含当天
+ if (typeStr.contains("0") || typeStr.contains(week.toString())) {
+ JSONArray time = jsonObject.getJSONArray("time");
+ // 判断当前时间 是否在time时间段中
+ for (Object object : time) {
+ String[] timeArray = object.toString().split("-");
+ String startTime = timeArray[0];
+ String endTime = timeArray[1];
+ boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
+ if (currentTimeInRange) {
+ return true;
+ }
+ }
+ }
+
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public PageInfo<PricingPageListVO> pageList(PricingPageListQuery query) {
+ PageInfo<PricingPageListVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
+ Page<PricingPageListVO> page = this.baseMapper.pageList(pageInfo, query);
+ pageInfo.setRecords(page.getRecords());
+ pageInfo.setTotal(page.getTotal());
+ if(page.getRecords() != null){
+ Set<String> vehicleModelIds = page.getRecords().stream().map(PricingPageListVO::getVehicleModel).collect(Collectors.toSet());
+ R<List<XpVehicleModel>> listR = xpVehicleModelClient.listByIds(vehicleModelIds);
+ if(listR != null && listR.getData() != null){
+ List<XpVehicleModel> vehicleModels = listR.getData();
+ Map<String, XpVehicleModel> vehicleModelMap = new HashMap<>();
+ for (XpVehicleModel vehicleModel : vehicleModels) {
+ vehicleModelMap.put(vehicleModel.getId().toString(), vehicleModel);
+ }
+ for (PricingPageListVO record : page.getRecords()) {
+ XpVehicleModel xpVehicleModel = vehicleModelMap.get(record.getVehicleModel());
+ if(xpVehicleModel != null){
+ record.setVehicleModelName(xpVehicleModel.getName());
+ }
+ }
+ }
+ }
+ return pageInfo;
+ }
+
+ @Override
+ public Long add(PricingAddDTO dto) {
+ XpOpenCity openCity = xpOpenCityMapper.selectById(dto.getCityId());
+ if (openCity == null) {
+ throw new ServiceException("开通城市不存在");
+ }
+
+ Long count = this.lambdaQuery()
+ .eq(XpPricing::getVehicleModel, dto.getVehicleModel())
+ .eq(XpPricing::getChannel, dto.getChannel())
+ .eq(XpPricing::getCityId, dto.getCityId().intValue())
+ .count();
+ if (count != null && count > 0) {
+ throw new ServiceException("该车型/渠道/城市的定价已存在", I18nKeyConstant.PRICING_EXISTS);
+ }
+
+ XpPricing pricing = new XpPricing();
+ pricing.setVehicleModel(dto.getVehicleModel());
+ pricing.setChannel(dto.getChannel());
+ pricing.setCityId(dto.getCityId());
+ pricing.setRemark(dto.getRemark());
+ pricing.setPricingType(dto.getPricingType());
+ pricing.setBasicPricingJson("{}");
+ pricing.setStartingFareJson("[]");
+ pricing.setDynamicPricingJson("{}");
+ pricing.setIsDynamicPrice(0);
+ this.save(pricing);
+ return pricing.getId();
+ }
+
+ @Override
+ public Long edit(PricingEditDTO dto) {
+ //1.查询定价
+ XpPricing pricing = getById(dto.getId());
+ if (Objects.nonNull(pricing)) {
+ LambdaUpdateWrapper<XpPricing> updateWrapper = new LambdaUpdateWrapper<>();
+ //2.判断定价类型是否改变
+ if (!pricing.getPricingType().equals(dto.getPricingType())) {
+ updateWrapper.set(XpPricing::getBasicPricingJson, null);
+ updateWrapper.set(XpPricing::getStartingFareJson, null);
+ updateWrapper.set(XpPricing::getDynamicPricingJson, null);
+ }
+ updateWrapper.set(XpPricing::getVehicleModel, dto.getVehicleModel());
+ updateWrapper.set(XpPricing::getChannel, dto.getChannel());
+ updateWrapper.set(XpPricing::getCityId, dto.getCityId());
+ updateWrapper.set(StringUtils.isNotBlank(dto.getRemark()), XpPricing::getRemark, dto.getRemark());
+ updateWrapper.set(XpPricing::getPricingType, dto.getPricingType());
+ updateWrapper.eq(XpPricing::getId, dto.getId());
+ update(updateWrapper);
+ }
+ return dto.getId();
+ }
+
+ @Override
+ public void setPrice(PricingSetPriceDTO dto) {
+ XpPricing pricing = this.getById(dto.getId());
+ if (pricing == null) {
+ throw new ServiceException("定价不存在", I18nKeyConstant.PRICING_NOT_EXIST);
+ }
+ try {
+ 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);
+ }
+
+ XpPricing update = new XpPricing();
+ update.setId(dto.getId());
+ update.setBasicPricingJson(dto.getBasicPricingJson());
+ update.setStartingFareJson(StringUtils.isNotBlank(dto.getStartingFareJson()) ? dto.getStartingFareJson() : null);
+ update.setDynamicPricingJson(dto.getDynamicPricingJson());
+ update.setIsDynamicPrice(dto.getIsDynamicPrice());
+ this.updateById(update);
+
+ // 动态调价 Quartz 任务调度
+ String jobName = DynamicPricingCheckJob.JOB_PREFIX + dto.getId();
+ if (Integer.valueOf(1).equals(dto.getIsDynamicPrice())
+ && StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
+ JSONObject dynamicJson = JSONObject.parseObject(dto.getDynamicPricingJson());
+ Integer periodMinutes = dynamicJson.getInteger("num1");
+ if (periodMinutes != null && periodMinutes > 0) {
+ // 先移除可能存在的旧任务,再注册新任务(num1 分钟后首次执行)
+ QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
+ Date triggerTime = new Date(System.currentTimeMillis() + periodMinutes * 60_000L);
+ Map<String, Object> jobData = new HashMap<>();
+ jobData.put("pricingId", dto.getId());
+ QuartzManager.addJob(DynamicPricingCheckJob.class, jobName,
+ TimeJobType.DYNAMIC_PRICING_CHECK, triggerTime, jobData);
+ log.info("动态调价任务已注册 pricingId={}, 供需计算周期={}分钟", dto.getId(), periodMinutes);
+ }
+ } else {
+ // 关闭动态调价时,移除已存在的任务
+ QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
+ log.info("动态调价任务已移除 pricingId={}", dto.getId());
+ }
+ }
+
+ @Override
+ public void setRule(PricingSetRuleDTO dto) {
+ XpPricing pricing = this.getById(dto.getId());
+ if (pricing == null) {
+ throw new ServiceException("定价不存在", I18nKeyConstant.PRICING_NOT_EXIST);
+ }
+
+ XpPricing update = new XpPricing();
+ update.setId(dto.getId());
+ update.setPriceRule(dto.getPriceRule());
+ this.updateById(update);
+ }
+
+
+ @Override
+ public void savePrice(PricingInfoVo dto, XpOfficialPartner officialPartner) {
+ XpOpenCity openCity = xpOpenCityMapper.selectOne(new QueryWrapper<XpOpenCity>().eq("city_code", dto.getCityCode()));
+ if (openCity == null) {
+ throw new ServiceException("城市未开通");
+ }
+
+ XpPricing pricing = this.lambdaQuery()
+ .eq(XpPricing::getVehicleModel, dto.getVehicleModel())
+ .eq(XpPricing::getChannel, officialPartner.getBrandName())
+ .eq(XpPricing::getCityId, openCity.getId().intValue())
+ .eq(XpPricing::getOfficialPartnerId, officialPartner.getId())
+ .one();
+
+ if(null == pricing){
+ pricing = new XpPricing();
+ pricing.setOfficialPartnerId(officialPartner.getId());
+ pricing.setVehicleModel(dto.getVehicleModel());
+ pricing.setChannel(officialPartner.getBrandName());
+ pricing.setCityId(openCity.getId());
+ pricing.setRemark(dto.getRemark());
+ pricing.setPricingType(dto.getPricingType());
+ pricing.setBasicPricingJson("{}");
+ pricing.setStartingFareJson("[]");
+ pricing.setDynamicPricingJson("{}");
+ pricing.setIsDynamicPrice(0);
+ this.save(pricing);
+ }
+
+ try {
+ 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);
+ }
+
+ XpPricing update = new XpPricing();
+ update.setId(pricing.getId());
+ update.setBasicPricingJson(dto.getBasicPricingJson());
+ update.setStartingFareJson(StringUtils.isNotBlank(dto.getStartingFareJson()) ? dto.getStartingFareJson() : null);
+ update.setDynamicPricingJson(dto.getDynamicPricingJson());
+ update.setIsDynamicPrice(dto.getIsDynamicPrice());
+ update.setPriceRule(dto.getPriceRule());
+ this.updateById(update);
+
+ // 动态调价 Quartz 任务调度
+ String jobName = DynamicPricingCheckJob.JOB_PREFIX + pricing.getId();
+ if (Integer.valueOf(1).equals(dto.getIsDynamicPrice())
+ && StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
+ JSONObject dynamicJson = JSONObject.parseObject(dto.getDynamicPricingJson());
+ Integer periodMinutes = dynamicJson.getInteger("num1");
+ if (periodMinutes != null && periodMinutes > 0) {
+ // 先移除可能存在的旧任务,再注册新任务(num1 分钟后首次执行)
+ QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
+ Date triggerTime = new Date(System.currentTimeMillis() + periodMinutes * 60_000L);
+ Map<String, Object> jobData = new HashMap<>();
+ jobData.put("pricingId", pricing.getId());
+ QuartzManager.addJob(DynamicPricingCheckJob.class, jobName,
+ TimeJobType.DYNAMIC_PRICING_CHECK, triggerTime, jobData);
+ log.info("动态调价任务已注册 pricingId={}, 供需计算周期={}分钟", pricing.getId(), periodMinutes);
+ }
+ } else {
+ // 关闭动态调价时,移除已存在的任务
+ QuartzManager.removeJob(jobName, TimeJobType.DYNAMIC_PRICING_CHECK);
+ log.info("动态调价任务已移除 pricingId={}", pricing.getId());
+ }
+
+ }
}
--
Gitblit v1.7.1