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 | 242 ++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 202 insertions(+), 40 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 bcf439c..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,10 +1,13 @@
package com.xiaopeng.operation.service.impl;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-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;
@@ -12,9 +15,10 @@
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.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.vo.account.UserCouponVo;
@@ -26,14 +30,15 @@
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.PricingAddDTO;
-import com.xiaopeng.operation.dto.PricingSetPriceDTO;
-import com.xiaopeng.operation.dto.PricingSetRuleDTO;
-import com.xiaopeng.operation.dto.XpOrderDto;
+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;
@@ -42,7 +47,9 @@
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.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;
@@ -64,6 +71,7 @@
* @author liu
* @since 2026-02-03
*/
+@Slf4j
@Service
public class XpPricingServiceImpl extends ServiceImpl<XpPricingMapper, XpPricing> implements XpPricingService {
@@ -100,6 +108,8 @@
@Resource
+ private XpVehicleModelClient xpVehicleModelClient;
+ @Resource
private XpWhitelistMapper xpWhitelistMapper;
@Resource
@@ -116,6 +126,9 @@
@Autowired
private XpPointService xpPointService;
+
+ @Resource(name = "hutoolSnowflake")
+ private Snowflake snowflake;
// 自定义线程池用于并行执行任务
@@ -174,6 +187,7 @@
@Override
+ @Deprecated
public RouteAndFareVo getRouteAndFare(RouteAndFareDto routeAndFareDto, String userId) {
@@ -247,7 +261,7 @@
() -> {
// 优惠券
return xpAppUserCouponClient.getUserCoupon(
- new GetUserCouponDto(Long.valueOf(userId), finalXpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId())
+ new GetUserCouponDto(Long.valueOf(userId), finalXpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId(),null)
// new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId())
);
},
@@ -334,6 +348,7 @@
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 {
@@ -342,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并缓存
@@ -414,7 +429,6 @@
@Override
public Long saveOrder(XpOrderDto dto, String uid) {
-
// 是否在运营区域时间内
XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId());
XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(xpElectronicFenceArea.getElectronicId());
@@ -429,7 +443,7 @@
// 判断是否有进行的订单
R<Long> r = xpOrderClient.hasUnPaodOrder(uid);
if (r.getData() > 0) {
- throw new RuntimeException("有正在进行的订单");
+ throw new ServiceException("有正在进行的订单", I18nKeyConstant.HAS_UNPAID_ORDER);
}
// 获取起点经纬度
@@ -449,15 +463,11 @@
throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
}
- // 判断当天取消的次数 后台配置 redis 查询
- Object cancelOrder = redisService.getCacheObject("CANCEL_ORDER_" + uid);
// 静默处理
boolean isSilent = false;
- if (cancelOrder != null) {
- Integer num = Integer.valueOf(cancelOrder.toString());
- if (num >= cancelCount) {
- isSilent = true;
- }
+ Integer num = xpOrderClient.todayCancellationCount(Long.valueOf(uid)).getData();
+ if (num >= cancelCount) {
+ isSilent = true;
}
@@ -471,14 +481,14 @@
// 根据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();
@@ -488,7 +498,7 @@
// 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());
@@ -512,6 +522,8 @@
xpOrder.setEndPointId(dto.getEndPointId());
xpOrder.setStartPointName(xpPoint.getPointName());
xpOrder.setEndPointName(endXpPoint.getPointName());
+ xpOrder.setXpuStartTaskId(snowflake.nextId() + "");
+ xpOrder.setXpuEndTaskId(snowflake.nextId() + "");
// 当前时段
String currentTimeSlot = DateUtils.getCurrentTimeSlot();
@@ -613,7 +625,7 @@
// 计算2个时间的秒数
xpGeoQueryEntity.setTime(currentTimeSlot);
xpGeoQueryEntity.setStatus(0);
-
+ xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
geoQueryEntityService.save(xpGeoQueryEntity);
return orderId;
@@ -630,6 +642,11 @@
}
+
+ 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);
@@ -680,11 +697,28 @@
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 void add(PricingAddDTO dto) {
+ public Long add(PricingAddDTO dto) {
XpOpenCity openCity = xpOpenCityMapper.selectById(dto.getCityId());
if (openCity == null) {
throw new ServiceException("开通城市不存在");
@@ -702,7 +736,7 @@
XpPricing pricing = new XpPricing();
pricing.setVehicleModel(dto.getVehicleModel());
pricing.setChannel(dto.getChannel());
- pricing.setCityId(dto.getCityId().intValue());
+ pricing.setCityId(dto.getCityId());
pricing.setRemark(dto.getRemark());
pricing.setPricingType(dto.getPricingType());
pricing.setBasicPricingJson("{}");
@@ -710,6 +744,30 @@
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
@@ -718,11 +776,16 @@
if (pricing == null) {
throw new ServiceException("定价不存在", I18nKeyConstant.PRICING_NOT_EXIST);
}
-
try {
- JSONObject.parseObject(dto.getBasicPricingJson());
- JSONArray.parseArray(dto.getStartingFareJson());
- JSONObject.parseObject(dto.getDynamicPricingJson());
+ if (StringUtils.isNotBlank(dto.getBasicPricingJson())) {
+ JSONObject.parseObject(dto.getBasicPricingJson());
+ }
+ if (StringUtils.isNotBlank(dto.getStartingFareJson())) {
+ JSONArray.parseArray(dto.getStartingFareJson());
+ }
+ if (StringUtils.isNotBlank(dto.getDynamicPricingJson())) {
+ JSONObject.parseObject(dto.getDynamicPricingJson());
+ }
} catch (Exception e) {
throw new ServiceException("价格配置JSON格式不正确", I18nKeyConstant.PRICING_JSON_INVALID);
}
@@ -730,9 +793,32 @@
XpPricing update = new XpPricing();
update.setId(dto.getId());
update.setBasicPricingJson(dto.getBasicPricingJson());
- update.setStartingFareJson(dto.getStartingFareJson());
+ update.setStartingFareJson(StringUtils.isNotBlank(dto.getStartingFareJson()) ? dto.getStartingFareJson() : null);
update.setDynamicPricingJson(dto.getDynamicPricingJson());
+ update.setIsDynamicPrice(dto.getIsDynamicPrice());
this.updateById(update);
+
+ // 动态调价 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
@@ -748,4 +834,80 @@
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