xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/XpActivityDto.java
@@ -29,8 +29,11 @@ @ApiModelProperty(value = "活动类型 如新人活动、媒体邀约活动、日常提频等") private Integer activityType; @ApiModelProperty(value = "活动类型 如新人活动、媒体邀约活动、日常提频等") private Integer acticityType; @ApiModelProperty(value = "是否开启活动总限额") private boolean enableTotalLimit; private Boolean enableTotalLimit; @ApiModelProperty(value = "是否开启活动总限额") private BigDecimal totalLimit; @@ -67,7 +70,59 @@ @ApiModelProperty(value = "发放用户") List<XpActicityUser> activityUser; @ApiModelProperty(value = "活动通知") XpActivityNotice notice; @ApiModelProperty("微信通知(0=否,1=是)") private Integer wechatNotification; @ApiModelProperty("微信通知到账提醒(0=否,1=是)") private Integer wechatReceivedReminder; @ApiModelProperty("微信通知即将过期提醒(0=否,1=是)") private Integer wechatAboutExpireReminder; @ApiModelProperty("微信通知即将过期天数") private Integer wechatAboutExpireDays; @ApiModelProperty("微信通知活动开始提醒(0=否,1=是)") private Integer wechatActicityStart; @ApiModelProperty("微信通知临近券生效前X分钟通知") private Integer wechatActicityStartMinutes; @ApiModelProperty("短信通知(0=否,1=是)") private Integer smsNotification; @ApiModelProperty("短信通知到账提醒(0=否,1=是)") private Integer smsReceivedReminder; @ApiModelProperty("短信通知即将过期提醒(0=否,1=是)") private Integer smsAboutExpireReminder; @ApiModelProperty("短信通知即将过期天数") private Integer smsAboutExpireDays; @ApiModelProperty("短信通知活动开始提醒(0=否,1=是)") private Integer smsActicityStart; @ApiModelProperty("短信通知临近券生效前X分钟通知") private Integer smsActicityStartMinutes; @ApiModelProperty("短信通知屏蔽开始时间") private String smsStartBlockingTime; @ApiModelProperty("短信通知屏蔽结束时间") private String smsEndBlockingTime; @ApiModelProperty("小程序弹窗通知(0=否,1=是)") private Integer miniProgramNotification; @ApiModelProperty("小程序弹窗标题") private String miniProgramPopupTitle; @ApiModelProperty("小程序弹窗按钮文案") private String miniProgramBtnText; @ApiModelProperty("小程序弹窗券到账提醒(0=否,1=是)") private String miniProgramReceivedReminder; @ApiModelProperty("小程序弹窗即将过期提醒(0=否,1=是)") private String miniProgramAboutExpireReminder; @ApiModelProperty("小程序弹窗临近券生效前X分钟") private Integer miniProgramAboutExpireMinutes; @ApiModelProperty("通知内容") private String expireMinutesNotificationContent; @ApiModelProperty("小程序弹窗临近到期时间前X天") private Integer aboutExpireDays; @ApiModelProperty("通知内容") private String expireDaysNotificationContent; @ApiModelProperty("是否开启浮窗(0=否,1=是)") private Integer enableFloatWindow; @ApiModelProperty("浮窗优先级权重") private Integer floatWindowPriority; @ApiModelProperty("浮窗跳转链接") private String floatWindowJumpUrl; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityStrategy.java
@@ -11,6 +11,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.Value; import lombok.experimental.Accessors; import java.time.LocalDate; @@ -44,6 +45,9 @@ @ApiModelProperty(value = "发放规则(1=每日循环发放,2=仅发放一次,3=使用后发放)") private Integer distributionRules; @ApiModelProperty(value = "每日循环发放时间") private String distributionTime; @ApiModelProperty(value = "发放规则json,[]=本券使用后循环发放, [1,2,3]=指定优惠券使用后发放(优惠券id数组)") @TableField(typeHandler = JacksonTypeHandler.class) @@ -87,4 +91,12 @@ @ApiModelProperty(value = "是否自动使用(0=不开启,1=冒泡发单时自动使用)") private Integer startUsing; @ApiModelProperty(value = "优惠券id数据") @TableField(exist = false) private List<Long> couponIds; @ApiModelProperty(value = "优惠券列表数据") @TableField(exist = false) private List<XpCoupon> couponList; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityUser.java
@@ -2,14 +2,18 @@ import com.alibaba.fastjson2.JSONArray; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.util.List; /** * <p> @@ -42,7 +46,8 @@ private Integer userType; @ApiModelProperty(value = "指定用户json数组") private JSONArray userList; @TableField(typeHandler = JacksonTypeHandler.class) private List<Long> userList; @ApiModelProperty(value = "策略组名称") private String strategyName; xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivity.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.fasterxml.jackson.annotation.JsonFormat; import com.xiaopeng.api.vo.account.CouponVo; import com.xiaopeng.common.core.web.domain.BaseModel; @@ -50,7 +51,7 @@ private BigDecimal limitation; @ApiModelProperty(value = "封面图片json") private JSONObject coverImage; private String coverImage; @ApiModelProperty(value = "开始时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @@ -98,9 +99,9 @@ @ApiModelProperty("短信通知临近券生效前X分钟通知") private Integer smsActicityStartMinutes; @ApiModelProperty("短信通知屏蔽开始时间") private LocalDateTime smsStartBlockingTime; private String smsStartBlockingTime; @ApiModelProperty("短信通知屏蔽结束时间") private LocalDateTime smsEndBlockingTime; private String smsEndBlockingTime; @ApiModelProperty("小程序弹窗通知(0=否,1=是)") private Integer miniProgramNotification; @ApiModelProperty("小程序弹窗标题") xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivityNotice.java
@@ -66,9 +66,9 @@ private List<String> blockTime; @ApiModelProperty(value = "miniProgram临近到期toast") private Integer toastBeforeExpiry; private String toastBeforeExpiry; @ApiModelProperty(value = "miniProgram临近生效toast") private Integer toastBeforeEffective; private String toastBeforeEffective; @ApiModelProperty(value = "是否开启浮窗") private Boolean enableFloatingWindow; @ApiModelProperty(value = "浮窗优先级权重1-100") xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpOfficialPartner.java
New file @@ -0,0 +1,42 @@ package com.xiaopeng.api.model.operation; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import lombok.Data; /** * 合作商 */ @Data @TableName("xp_official_partner") public class XpOfficialPartner extends BaseModel { /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 名称 */ private String name; /** * 品牌名称 */ private String brandName; /** * 品牌logo */ private String logoUrl; /** * 应用APPKey */ private String appKey; /** * 应用APPSecret */ private String appSecret; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPricing.java
@@ -81,15 +81,6 @@ private String dynamicPricingJson; // public XpPricingDynamicPricesVo getDynamicPricingJsonObj() { // if(StringUtils.isNotEmpty(dynamicPricingJson)){ // return JSONObject.parseObject(dynamicPricingJson, XpPricingDynamicPricesVo.class); // } // return null; // } @ApiModelProperty(value = "价格规则") @TableField("price_rule") private String priceRule; @@ -99,4 +90,9 @@ @TableField("is_dynamic_price") private Integer isDynamicPrice; @ApiModelProperty(value = "合作商id") @TableField("official_partner_id") private Integer officialPartnerId; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpTradingStrategyPush.java
New file @@ -0,0 +1,72 @@ package com.xiaopeng.api.model.operation; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.Min; @Data @TableName("xp_trading_strategy_push") public class XpTradingStrategyPush { /** * 主键 */ @TableId(value = "id", type = IdType.AUTO) private Integer id; /** * 交易策略id */ private Long tradingStrategyId; /** * 开始时段 */ @ApiModelProperty(value = "开始时段") private String starTime; /** * 结束时段 */ @ApiModelProperty(value = "结束时段") private String endTime; @ApiModelProperty(value = "一轮推单距离") @Min(0) private Double onePushDistance; @ApiModelProperty(value = "一轮推单时间") @Min(0) private Integer onePushTime; @ApiModelProperty(value = "二轮推单距离") @Min(0) private Double twoPushDistance; @ApiModelProperty(value = "二轮推单时间") @Min(0) private Integer twoPushTime; @ApiModelProperty(value = "三轮推单距离") @Min(0) private Double threePushDistance; @ApiModelProperty(value = "三轮推单时间") @Min(0) private Integer threePushTime; @ApiModelProperty(value = "四轮推单距离") @Min(0) private Double fourPushDistance; @ApiModelProperty(value = "四轮推单时间") @Min(0) private Integer fourPushTime; @ApiModelProperty(value = "五轮推单距离") private Double fivePushDistance; @ApiModelProperty(value = "五轮推单时间") private Integer fivePushTime; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/vehicleConvoy/XpVehicle.java
@@ -120,6 +120,9 @@ @ApiModelProperty(value = "车辆接单状态 1接单中 0空闲") private Integer state; @ApiModelProperty(value = "合作商ID") private Integer officialPartnerId; @ApiModelProperty(value = "运营区域") @TableField(exist = false) private String electronicName; xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/XpTradingStrategyDetailVO.java
@@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.xiaopeng.api.model.operation.XpTradingStrategyCity; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -125,7 +126,8 @@ @ApiModelProperty(value = "播单—乘客上车后x分钟内未点击出车,订单自动取消") private Integer bdNotBoardedTime; @ApiModelProperty("时段推单策略") private List<XpTradingStrategyPush> timePushStrategyList; //---------------播单策略------------------------------------ xp-robotaxi-automatic-pilot-boot/pom.xml
@@ -108,6 +108,10 @@ </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.2.1</version> xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -42,10 +42,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -330,9 +327,6 @@ && mqttPublishDto.getCode()== 200){ // 修改车子为接单状态 xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(dto.getVin(), 1)); // TODO[流量接入] 通过设置的URL发送订单和导航路线给运力 } if(null != mqttPublishDto && mqttPublishDto.getCode() == 200){ @@ -809,7 +803,7 @@ dto.setDistance(10.0); dto.setDirection(60); dto.setMessageType(PushMessageTypeEnum.ORDER_ROUTE.getDesc()); xpPushMessageClient.pushOrderRoute(dto); R<String> stringR = xpPushMessageClient.pushOrderRoute(dto); //存储历史轨迹 OrderTrajectoryVo orderTrajectory = new OrderTrajectoryVo(); xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/AbstractJob.java
New file @@ -0,0 +1,38 @@ package com.xiaopeng.automaticPilot.job.base; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.order.XpTestOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.automaticPilot.job.utils.SpringContextsUtil; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractJob implements Job { protected Logger logger = LoggerFactory.getLogger(getClass()); @Override public abstract void execute(JobExecutionContext context) throws JobExecutionException; protected XpPushMessageClient xpPushMessageClient; protected OrderMissionClient orderMissionClient; protected XpVehicleClient xpVehicleClient; protected UserVehicleClient userVehicleClient; protected XpOrderClient xpOrderClient; protected XpTestOrderClient xpTestOrderClient; public AbstractJob(){ this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class); this.orderMissionClient = SpringContextsUtil.getBean(OrderMissionClient.class); this.xpVehicleClient = SpringContextsUtil.getBean(XpVehicleClient.class); this.userVehicleClient = SpringContextsUtil.getBean(UserVehicleClient.class); this.xpOrderClient = SpringContextsUtil.getBean(XpOrderClient.class); this.xpTestOrderClient = SpringContextsUtil.getBean(XpTestOrderClient.class); } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/QuartzManager.java
New file @@ -0,0 +1,128 @@ package com.xiaopeng.automaticPilot.job.base; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.util.Date; import java.util.Map; public class QuartzManager { private static SchedulerFactory factory = new StdSchedulerFactory(); private static final String TRIGGER_NAME_PREFIX = "TRIGGER_PREFIX_"; private static final String JOB_NAME_PREFIX = "JOB_PREFIX_"; /** * 添加定时任务:具体某个时间点执行一次的任务,如:在某个2015-06-01 12:00发送一条消息 * * @param jobName * 具体的任务名+ID标识唯一 * @param jobType * @param date * @param jp */ public synchronized static void addJob(Class<? extends Job> jobClass, String jobName, TimeJobType jobType, Date date, Map<String, ? extends Object> jp) { //logger.debug("ADD JOB {},jobName={},jobTyep={},jobDate={},",jobClass.getName(),jobName,jobType,date); try { Scheduler sched = factory.getScheduler(); JobDetail job = JobBuilder.newJob(jobClass).withIdentity(JOB_NAME_PREFIX + jobName, jobType.getType()) .setJobData(new JobDataMap(jp)).build(); SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity(TRIGGER_NAME_PREFIX + jobName, jobType.getType()).startAt(date).build(); removeJob(jobName, jobType); sched.scheduleJob(job, trigger); if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { //logger.error("ADD JOB exception {},jobName={},jobTyep={},jobDate={},",jobClass.getName(),jobName,jobType,date); } } /** * 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名) * @param jobName * @param time */ public synchronized static void modifyJobTime(String jobName,TimeJobType jobType, Date time) { //logger.error("Update JOB exception,jobName={},jobTyep={},jobDate={}," ,jobName,jobType,time); try { JobKey jobKey = new JobKey(JOB_NAME_PREFIX + jobName, jobType.getType()); TriggerKey key = new TriggerKey(TRIGGER_NAME_PREFIX + jobName, jobType.getType()); Scheduler sched = factory.getScheduler(); SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(key); if(trigger == null) { return; } Date oldTime = trigger.getStartTime(); if (oldTime.getTime() != time.getTime()) { JobDetail jobDetail = sched.getJobDetail(jobKey); Class<? extends Job> objJobClass = jobDetail.getJobClass(); removeJob(jobName,jobType); Map<String, Object> jp = jobDetail.getJobDataMap(); addJob(objJobClass, jobName, jobType, time, jp); } } catch (Exception e) { // logger.error("Update JOB exception,jobName={},jobTyep={},jobDate={}," ,jobName,jobType,time); } } /** * 移除一个任务 * * @param jobName */ public synchronized static void removeJob(String jobName, TimeJobType jobType) { try { JobKey jobKey = new JobKey(JOB_NAME_PREFIX + jobName, jobType.getType()); TriggerKey key = new TriggerKey(TRIGGER_NAME_PREFIX + jobName, jobType.getType()); Scheduler sched = factory.getScheduler(); JobDetail detail = sched.getJobDetail(jobKey); if (detail != null) { sched.pauseJob(jobKey); sched.pauseTrigger(key);// 停止触发器 sched.unscheduleJob(key);// 移除触发器 sched.deleteJob(jobKey);// 删除任务 } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 启动所有定时任务 */ public synchronized static void startJobs() { try { Scheduler sched = factory.getScheduler(); sched.start(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 关闭所有定时任务 */ public synchronized static void shutdownJobs() { try { Scheduler sched = factory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/TimeJobType.java
New file @@ -0,0 +1,33 @@ package com.xiaopeng.automaticPilot.job.base; /** * @Description 按时间点发布的任务类型 * @date 2025年2月17日 下午7:22:28 */ public enum TimeJobType { ORDER_CANCEL("order_cancel","订单取消"), TEST_ORDER_CANCEL("test_order_cancel","测试订单取消"), ADD_CRUISE_MISSION("add_cruise_mission","添加巡游任务"), ADD_CHAIN_REACTION_ORDER_MISSION("add_cruise_mission","添加派送连环单任务"), END_TRIP("end_trip","自动结束行程"), ERROR_ORDER_CANCEL("error_order_cancel","行程中异常订单取消"); private String type; private String desc; private TimeJobType(String type, String desc) { this.type = type; this.desc = desc; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/exceptions/TimeException.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.automaticPilot.job.exceptions; /** * @文件说明:定时器任务执行异常 * @版权所有:成都喜来达 * @项目名称: fengsheng * @创建者: Leeyns * @创建日期: 2016年5月18日 * @最近修改者:Leeyns * @最近修改日期:2016年5月18日 */ public class TimeException extends Exception { /** * TODO */ private static final long serialVersionUID = 5703430073981692250L; private String message; public TimeException() { super(); } public TimeException(String message) { super(message); this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/jobs/OrderExceptionJob.java
New file @@ -0,0 +1,38 @@ package com.xiaopeng.automaticPilot.job.jobs; import com.xiaopeng.api.vo.OrderType; import com.xiaopeng.automaticPilot.job.base.AbstractJob; import com.xiaopeng.common.core.enums.OrderStatusEnum; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * 异常订单定时任务,创建客服工单 * @author Administrator * */ @Slf4j public class OrderExceptionJob extends AbstractJob { public static final String name = "orderException_"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); Long orderId = maps.getLong("id"); String orderType = maps.getString("orderType"); if(OrderType.USER_ORDER.equals(orderType)){ //修改订单状态 xpOrderClient.updateOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode(), true); } if(OrderType.TEST_ORDER.equals(orderType)){ xpTestOrderClient.updateOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode()); } //发起客服工单 } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/utils/SpringContextsUtil.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.automaticPilot.job.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextsUtil implements ApplicationContextAware{ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringContextsUtil.applicationContext == null) { SpringContextsUtil.applicationContext = applicationContext; } } // 获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } // 通过name获取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } // 通过class获取Bean. public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } // 通过name,以及Clazz返回指定的Bean public static <T> T getBean(String name, Class<T> clazz) { System.out.println(getApplicationContext().getBean(name, clazz)); return getApplicationContext().getBean(name, clazz); } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -3,6 +3,7 @@ import cn.hutool.core.lang.Snowflake; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.google.common.collect.ImmutableMap; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; @@ -20,12 +21,14 @@ import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.operation.ReassignOrderClient; import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.order.XpTestOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpSystemSetting; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpTestOrder; @@ -36,6 +39,9 @@ import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.order.OrderTrajectoryVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; import com.xiaopeng.automaticPilot.job.base.QuartzManager; import com.xiaopeng.automaticPilot.job.base.TimeJobType; import com.xiaopeng.automaticPilot.job.jobs.OrderExceptionJob; import com.xiaopeng.automaticPilot.util.XPUUtil; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.Constants; @@ -43,6 +49,7 @@ import com.xiaopeng.common.core.enums.CancelOrderSceneEnum; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.core.enums.PushMessageTypeEnum; 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.redis.service.RedisService; @@ -60,6 +67,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -134,6 +142,9 @@ @Resource private RedissonClient redissonClient; @Resource private XpSystemSettingClient systemSettingClient; private static final JsonFormat.Printer jsonPrinter = JsonFormat.printer() .printingEnumsAsInts() @@ -1672,5 +1683,23 @@ OrderPhase orderPhase = naviRequest.getOrderPhase(); log.info("订单ID:{}", orderId); log.info("任务ID:{}", taskId); //获取系统异常订单超时配置,创建定时任务取消订单 if(!orderId.contains("XU")){ XpSystemSetting xpSystemSetting = systemSettingClient.getSystemSettingOne().getData(); Map<String, ? extends Object> jobMaps = new ImmutableMap.Builder<String, String>() .put("id", orderId) .put("orderType", orderId.contains("TEST") ? OrderType.TEST_ORDER : OrderType.USER_ORDER) .build(); QuartzManager.addJob( OrderExceptionJob.class, (OrderExceptionJob.name + orderId).toUpperCase(), TimeJobType.ERROR_ORDER_CANCEL, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpSystemSetting.getOrderExceptionalTimeout())), jobMaps ); } } } xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java
@@ -111,6 +111,11 @@ public static final String QUEUE_POINT_ID = "QUEUE_POINT_ID"; /** * 定向服务队列编号 */ public static final String SP_QUEUE_POINT_ID = "SP_QUEUE_POINT_ID"; /** * 最大推单距离 */ public static final String MAX_PUSH_DISTANCE = "MAX_PUSH_DISTANCE"; xp-robotaxi-common/xp-common-redis/src/main/java/com/xiaopeng/common/redis/service/RedisService.java
@@ -438,6 +438,11 @@ return key; } public String redisKey_SP_QUEUE_POINT_ID(Long xpPointId,Double pointLon,Double pointLat){ String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPointId + "-" + pointLon + "," + pointLat; return key; } /** * * @param orderId 订单id @@ -448,12 +453,10 @@ * @param distance 距离 米 * @param duration 时间 * @param planRuleForQueue 选中路线对应的高德 * @param targetedVal 是否定向 0 不定向 ,1-100 定向 * @return */ public String redisValue_QUEUE_POINT_ID(String orderId,String pointLon,String pointLat,String uid,String orderNumber ,String distance,String duration,String planRuleForQueue,Integer targetedVal){ return orderId + "_" + pointLon + "," + pointLat + "_0" + "_" + uid + "_" + orderNumber + "_" + distance + "_" + duration + "_" + planRuleForQueue+"_" + targetedVal; public String redisValue_QUEUE_POINT_ID(String orderId,String pointLon,String pointLat,String uid,String orderNumber ,String distance,String duration,String planRuleForQueue){ return orderId + "_" + pointLon + "," + pointLat + "_0" + "_" + uid + "_" + orderNumber + "_" + distance + "_" + duration + "_" + planRuleForQueue; } } xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/mapper/XpTradingStrategyPushMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.itinerary.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; public interface XpTradingStrategyPushMapper extends BaseMapper<XpTradingStrategyPush> { } xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -64,6 +64,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; @@ -112,6 +113,9 @@ @Resource private XpTradingStrategyMapper xpTradingStrategyMapper; @Resource private XpTradingStrategyPushMapper xpTradingStrategyPushMapper; @Resource private XpElectronicFenceAreaMapper xpElectronicFenceAreaMapper; @@ -617,7 +621,6 @@ if (!inTime) { throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION); } // todo 需要判断用户是否白名单,且白名单当天最大订单量 // 判断当天取消的次数 后台配置 redis 查询 // 静默处理 @@ -636,15 +639,15 @@ // } // 根据id获取手机号 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; // } // } //判断是否在白名单且优先派单 boolean isPriorityDispatch = false; UcUserInfo ucUserInfo = userResourcesClient.getBaseUserByUid(uid); if (null != ucUserInfo) { Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, ucUserInfo.getMobile()).eq(XpWhitelist::getIsPriorityDispatch, 1)); if (count > 0) { isPriorityDispatch = true; } } // 生成订单数据 XpOrder xpOrder = new XpOrder(); @@ -752,77 +755,168 @@ if (maxPushDistanceObj != null) { maxPushDistance = Double.valueOf(maxPushDistanceObj.toString()); } else { maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance(); XpTradingStrategy xpTradingStrategy = xpTradingStrategyMapper.selectOne(null); List<XpTradingStrategyPush> xpTradingStrategyPushes = xpTradingStrategyPushMapper.selectList(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", xpTradingStrategy.getId())); long now = Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm"))); XpTradingStrategyPush xpTradingStrategyPush = xpTradingStrategyPushes.stream().filter(item -> { long start = Long.parseLong(item.getStarTime().replace(":", "")); long end = Long.parseLong(item.getEndTime().replace(":", "")); return now >= start && now < end; }).findFirst().orElse(null); maxPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushDistance() : xpTradingStrategy.getFivePushDistance(); } // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列 如果没有符合的新增一个队列 符合后看是否白名单账号 是则直接放在队列前端 Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); int targetedVal = 0; //获取定向服务配置 R<List<XpTargetedServiceVehicleVo>> targetedServiceUserR = xpTargetedServiceClient.findListByUserIdAndCityCode(xpOrder.getAppUserId(), xpOrder.getCityCode()); if(targetedServiceUserR.getCode() == R.SUCCESS && CollUtil.isNotEmpty(targetedServiceUserR.getData()) ){ targetedVal = targetedServiceUserR.getData().get(0).getWeight(); XpTargetedServiceVehicleVo xpTargetedServiceVehicleVo = targetedServiceUserR.getData().get(0); return addSpOrderPush(xpOrder, xpPoint, xpRoutePlan, maxPushDistance, xpTargetedServiceVehicleVo, orderId, currentTimeSlot, distance, duration, uid); }else{ return addOrderPush(xpOrder, xpPoint, xpRoutePlan, maxPushDistance, isPriorityDispatch, orderId, currentTimeSlot, distance, duration, uid); } //String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat(); String redis_key = redisService.redisKey_QUEUE_POINT_ID(xpPoint.getId(), xpPoint.getPointLon(), xpPoint.getPointLat()); //orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + planRuleForQueue+"_" + targetedVal; String redis_value = redisService.redisValue_QUEUE_POINT_ID(orderId.toString(), xpPoint.getPointLon().toString(), xpPoint.getPointLat().toString(), uid, xpOrder.getOrderNumber(), distance.toString(), duration.toString(), planRuleForQueue == null ? null : planRuleForQueue.toString(),targetedVal); } /** * 构建普通订单推送数据 * @param xpOrder * @param xpPoint * @param xpRoutePlan * @param maxPushDistance * @param isPriorityDispatch * @param orderId * @param currentTimeSlot * @param distance * @param duration * @param uid * @return */ private String addOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance, Boolean isPriorityDispatch, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){ // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列 如果没有符合的新增一个队列 符合后看是否白名单账号 是则直接放在队列前端 Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); log.info("当前队列:{}", quoteMatchName); RedisQueuePointIdVo redisQueuePointIdVo = null; for (String s : quoteMatchName) { // QUEUE_POINT_ID-1-30.233,120.233 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) { // String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + planRuleForQueue; if(targetedVal>0){ //todo yyy 这里添加数据需要优化 需要redis 加锁 List<String> cacheList = redisService.getCacheList(s); cacheList.add(redis_value); List<RedisQueuePointIdVo> ll = new ArrayList<>(); for (String string : cacheList) { String[] split = string.split("_"); redisQueuePointIdVo = new RedisQueuePointIdVo(); redisQueuePointIdVo.setOrderId(split[0]); redisQueuePointIdVo.setPointLon(split[1]); redisQueuePointIdVo.setPointLat(split[2]); redisQueuePointIdVo.setUid(split[3]); redisQueuePointIdVo.setOrderNumber(split[4]); redisQueuePointIdVo.setDistance(split[5]); redisQueuePointIdVo.setDuration(split[6]); redisQueuePointIdVo.setPlanRuleForQueue(split[7]); if(split.length>8){ redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8])); }else{ redisQueuePointIdVo.setTargetedVal(0); } ll.add(redisQueuePointIdVo); } ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal()); List<String> redis_values = new ArrayList<>(); for (RedisQueuePointIdVo vo : ll) { String redis_value2 = redisService.redisValue_QUEUE_POINT_ID(vo.getOrderId(), vo.getPointLon(), vo.getPointLat(), vo.getUid(), vo.getOrderNumber(), vo.getDistance(), vo.getDuration(), vo.getPlanRuleForQueue(),vo.getTargetedVal()); redis_values.add(redis_value2); } redisService.setCacheList(s, redis_values); }else{ if (isPriorityDispatch) { // 头部 value 订单_经纬度_状态_用户id_订单编号_距离_时间 redisService.addToHead(s, redis_value); log.info("添加到队列头部:{} {}", s, redis_value); } else { // 尾部 redisService.addToTail(s, redis_value); log.info("添加到队列尾部:{} {}", s, redis_value); } String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule(); if (isPriorityDispatch) { // 头部 value 订单_经纬度_状态_用户id_订单编号_距离_时间 redisService.addToHead(s, value); log.info("添加到队列头部:{} {}", s, value); } else { // 尾部 redisService.addToTail(s, value); log.info("添加到队列尾部:{} {}", s, value); } 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.toString(); } } String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat(); if(xpRoutePlan==null){ redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null)); }else { redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule())); } log.info("订单推单:{} {}", key, redisService.getCacheList(key)); 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.toString(); } /** * 构建定向服务订单推送数据 * @param xpOrder * @param xpPoint * @param xpRoutePlan * @param maxPushDistance * @param xpTargetedServiceVehicleVo * @param orderId * @param currentTimeSlot * @param distance * @param duration * @param uid * @return */ private String addSpOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance, XpTargetedServiceVehicleVo xpTargetedServiceVehicleVo, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){ // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列 如果没有符合的新增一个队列 符合后看是否白名单账号 是则直接放在队列前端 Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID); log.info("当前队列:{}", quoteMatchName); for (String s : quoteMatchName) { // QUEUE_POINT_ID-1-30.233,120.233 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) { //在范围内,将队列中的数据转换成对象进行排序 List<String> cacheList = redisService.getCacheList(s); List<RedisQueuePointIdVo> ll = new ArrayList<>(); for (String string : cacheList) { String[] split = string.split("_"); RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo(); redisQueuePointIdVo.setOrderId(split[0]); redisQueuePointIdVo.setPointLonLat(split[1]); redisQueuePointIdVo.setPushStatus(split[2]); redisQueuePointIdVo.setUid(split[3]); redisQueuePointIdVo.setOrderNumber(split[4]); redisQueuePointIdVo.setDistance(split[5]); redisQueuePointIdVo.setDuration(split[6]); redisQueuePointIdVo.setPlanRuleForQueue(split[7]); redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8])); ll.add(redisQueuePointIdVo); } RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo(); redisQueuePointIdVo.setOrderId(orderId.toString()); redisQueuePointIdVo.setPointLonLat(xpPoint.getPointLon() + "," + xpPoint.getPointLat()); redisQueuePointIdVo.setPushStatus("0"); redisQueuePointIdVo.setUid(uid); redisQueuePointIdVo.setOrderNumber(xpOrder.getOrderNumber()); redisQueuePointIdVo.setDistance(distance.toString()); redisQueuePointIdVo.setDuration(duration.toString()); redisQueuePointIdVo.setPlanRuleForQueue(xpRoutePlan.getRoutePlanRule().toString()); redisQueuePointIdVo.setTargetedVal(xpTargetedServiceVehicleVo.getWeight()); ll.add(redisQueuePointIdVo); //排序 ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal()); List<String> collect = ll.stream().map(item -> { String value = item.getOrderId() + "_" + item.getPointLonLat() + "_" + item.getPushStatus() + "_" + item.getUid() + "_" + item.getOrderNumber() + "_" + item.getDistance() + "_" + item.getDuration() + "_" + item.getPlanRuleForQueue() + "_" + item.getTargetedVal(); return value; }).collect(Collectors.toList()); redisService.setCacheList(s, cacheList); xpOrder.setQueueName(s); xpOrderClient.updateOrder(xpOrder); @@ -836,12 +930,19 @@ xpGeoQueryEntity.setStatus(0); xpGeoQueryEntity.setTimestamp(System.currentTimeMillis()); geoQueryEntityService.save(xpGeoQueryEntity); return orderId.toString(); } } redisService.setCacheList(redis_key, ListUtil.toList(redis_value) ); log.info("订单推单:{} {}", redis_key, redisService.getCacheList(redis_key)); xpOrder.setQueueName(redis_key); String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat(); if(xpRoutePlan==null){ redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null + "_" + xpTargetedServiceVehicleVo.getWeight())); }else { redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule() + "_" + xpTargetedServiceVehicleVo.getWeight())); } log.info("订单推单:{} {}", key, redisService.getCacheList(key)); xpOrder.setQueueName(key); xpOrderClient.updateOrder(xpOrder); @@ -854,9 +955,13 @@ xpGeoQueryEntity.setStatus(0); xpGeoQueryEntity.setTimestamp(System.currentTimeMillis()); geoQueryEntityService.save(xpGeoQueryEntity); return orderId.toString(); } @Override public Boolean isInOperationTime(String operationStrategy) { JSONArray jsonArray = JSONArray.parseArray(operationStrategy); xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/vo/RedisQueuePointIdVo.java
@@ -8,10 +8,10 @@ @ApiModelProperty(value = "订单id") private String orderId; @ApiModelProperty(value = "经度") private String pointLon; @ApiModelProperty(value = "纬度") private String pointLat; @ApiModelProperty(value = "经度维度") private String pointLonLat; @ApiModelProperty(value = "推送状态(0=还未推送,1=已推送)") private String pushStatus; @ApiModelProperty(value = "用户id") private String uid; @ApiModelProperty(value = "订单编码") xp-robotaxi-itinerary-boot/src/main/resources/mapper/itinerary/XpTradingStrategyPushMapper.xml
New file @@ -0,0 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.itinerary.mapper.XpTradingStrategyPushMapper"> </mapper> xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleModelController.java
@@ -8,6 +8,8 @@ import com.xiaopeng.maintenance.model.query.XpVehicleModelPageQuery; import com.xiaopeng.maintenance.service.IXpVehicleModelService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -138,8 +140,15 @@ @GetMapping("/drainage/v1/vehicleModel/list") @ApiOperation(value = "查询可使用的车型列表", notes = "流量接入-基础信息") @ApiImplicitParams({ @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") }) public R<List<XpVehicleModel>> getVehicleModelList() { List<XpVehicleModel> list = xpVehicleModelService.queryList(); return R.ok(list); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpActicityController.java
@@ -161,7 +161,6 @@ List<XpActicityStrategy> strategies = strategyService.lambdaQuery().eq(XpActicityStrategy::getActitcityId, dto.getId()).list(); dto.setStrategy(strategies); dto.setActivityUser(userService.lambdaQuery().eq(XpActicityUser::getActitcityId, dto.getId()).list()); dto.setNotice(noticeService.lambdaQuery().eq(XpActivityNotice::getActivityId, dto.getId()).one()); } return R.ok(pageList); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpOfficialPartnerController.java
New file @@ -0,0 +1,50 @@ package com.xiaopeng.operation.controller; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.operation.service.IXpOfficialPartnerService; import com.xiaopeng.operation.vo.OfficialPartnerVo; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * 引流接口 */ @RestController @RequestMapping("/drainage") public class XpOfficialPartnerController { @Resource private IXpOfficialPartnerService xpOfficialPartnerService; /** * 保存合作商信息 * @param vo * @return */ @PostMapping("/v1/officialPartner/save") @ApiOperation(value = "保存合作商信息", notes = "流量接入-基础信息") @ApiImplicitParams({ @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") }) public R<?> save(@RequestBody OfficialPartnerVo vo) { xpOfficialPartnerService.addOfficialPartner(vo); return R.ok(); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -20,10 +20,14 @@ import com.xiaopeng.operation.query.PricingPageListQuery; import com.xiaopeng.operation.service.*; import com.xiaopeng.operation.utils.ImageTagProcessor; import com.xiaopeng.operation.vo.OfficialPartnerVo; import com.xiaopeng.operation.vo.PricingInfoVo; import com.xiaopeng.operation.vo.PricingPageListVO; import com.xiaopeng.operation.vo.SaveOrderVo; import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; @@ -266,4 +270,18 @@ } // /** // * 合作商添加计费策略 todo 现在的版本不支持手动选择车型 // * @param vo // * @return // */ // @PostMapping("/v1/pricing/save") // @ApiOperation(value = "保存计价规则", notes = "流量接入-基础信息") // @ApiImplicitParams({ // @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") // }) // public R<?> save(@RequestBody PricingInfoVo vo) { // // return R.ok(); // } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTargetedServiceController.java
@@ -140,4 +140,6 @@ } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTradingStrategyController.java
@@ -42,8 +42,6 @@ @ApiOperation(value = "获取交易策略配置", tags = {"inner-交易策略配置"}) @GetMapping("/logan/inner/xpOperationStrategy/getOne") public R<XpTradingStrategyDetailVO> getOne() { // TODO[流量接入] 这里需要判断是哪个三方车队的,获取到对应的交易策略 XpTradingStrategyDetailVO detail = tradingStrategyService.queryDetail(); return R.ok(detail); } @@ -58,15 +56,6 @@ @PostMapping("/api/v1/tradingStrategy/edit") public R<?> edit(@Validated @RequestBody XpTradingStrategyEditDTO dto) { tradingStrategyService.editStrategy(dto); return R.ok(); } @ApiOperation(value = "三方车队的交易策略", tags = {"流量接入-信息录入-设置交易策略"}) @PostMapping("/api/v1/xp-rt/strategy") public R<?> add(@Validated @RequestBody XpTradingStrategy dto) {//创建只接收部分可设置的参数的dto // 通过key认证是哪个三方车队 tradingStrategyService.save(dto); return R.ok(); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpTradingStrategyEditDTO.java
@@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.xiaopeng.api.model.operation.XpTradingStrategyCity; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -126,7 +127,8 @@ @ApiModelProperty(value = "播单—乘客上车后x分钟内未点击出车,订单自动取消") private Integer bdNotBoardedTime; @ApiModelProperty(value = "分时段推单列表") private List<XpTradingStrategyPush> pushTimeList; //---------------播单策略------------------------------------ xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpOfficialPartnerMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.operation.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.operation.XpOfficialPartner; public interface XpOfficialPartnerMapper extends BaseMapper<XpOfficialPartner> { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpTradingStrategyPushMapper.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.operation.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; public interface XpTradingStrategyPushMapper extends BaseMapper<XpTradingStrategyPush> { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpOfficialPartnerService.java
New file @@ -0,0 +1,16 @@ package com.xiaopeng.operation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.operation.XpOfficialPartner; import com.xiaopeng.operation.vo.OfficialPartnerVo; import org.springframework.web.bind.annotation.RequestBody; public interface IXpOfficialPartnerService extends IService<XpOfficialPartner> { /** * 添加合作商 * @param vo */ void addOfficialPartner(OfficialPartnerVo vo); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpTradingStrategyPushService.java
New file @@ -0,0 +1,7 @@ package com.xiaopeng.operation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; public interface IXpTradingStrategyPushService extends IService<XpTradingStrategyPush> { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpTargetedServiceVehicleService.java
@@ -15,4 +15,11 @@ */ void deleteByTargetedServiceId(Long targetedServiceId); /** * 获取当前有效的所有定向服务车辆的VIN码 * @return */ List<String> getVehicleVinByTargetedService(String cityCode); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityServiceImpl.java
@@ -5,18 +5,12 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.operation.XpActivityDto; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.model.operation.XpActicityStrategy; import com.xiaopeng.api.model.operation.XpActicityUser; import com.xiaopeng.api.model.operation.XpActivity; import com.xiaopeng.api.model.operation.XpActivityNotice; import com.xiaopeng.api.model.operation.*; import com.xiaopeng.api.query.operation.XpActivityPageListQuery; import com.xiaopeng.common.core.utils.bean.BeanUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.operation.mapper.XpActicityMapper; import com.xiaopeng.operation.service.IXpActicityService; import com.xiaopeng.operation.service.IXpActicityStrategyService; import com.xiaopeng.operation.service.IXpActicityUserService; import com.xiaopeng.operation.service.IXpActivityNoticeService; import com.xiaopeng.operation.service.*; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,6 +43,9 @@ @Resource private XpOrderClient xpOrderClient; @Resource private IXpActicityCouponService xpActicityCouponService; @@ -92,29 +89,43 @@ } @Override @Transactional public void save(XpActivityDto dto) { XpActivity activity = new XpActivity(); BeanUtils.copyBeanProp(activity, dto); activity.setActicityType(dto.getActivityType()); activity.setAggregateLimit(dto.getEnableTotalLimit() ? 1 : 0); activity.setLimitation(dto.getTotalLimit()); activity.setCoverImage(dto.getImg()); activity.setRemarks(dto.getRichText()); save(activity); List<XpActicityStrategy> strategy = dto.getStrategy(); List<XpActicityUser> activityUser = dto.getActivityUser(); XpActivityNotice notice = dto.getNotice(); strategy.forEach(e -> e.setActitcityId(activity.getId().intValue())); strategyService.saveBatch(strategy); for (XpActicityStrategy xpActicityStrategy : strategy) { xpActicityStrategy.setActitcityId(activity.getId().intValue()); xpActicityStrategy.setDeleted(false); strategyService.save(xpActicityStrategy); List<Long> couponIds = xpActicityStrategy.getCouponIds(); for (Long couponId : couponIds) { XpActicityCoupon xpActicityCoupon = new XpActicityCoupon(); xpActicityCoupon.setActicityStrategyId(xpActicityStrategy.getId().longValue()); xpActicityCoupon.setCouponId(couponId); xpActicityCoupon.setActivityId(activity.getId()); xpActicityCouponService.save(xpActicityCoupon); } } Map<String, XpActicityStrategy> strategyMap = strategy.stream().collect(Collectors.toMap( XpActicityStrategy::getName, Function.identity() )); activityUser.forEach(item -> { item.setActitcityId(activity.getId().intValue()); item.setActitcityStrategeId(strategyMap.get(item.getStrategyName()).getId()); }); notice.setActivityId(activity.getId()); userService.saveBatch(activityUser); activityNotice.save(notice); for (XpActicityUser xpActicityUser : activityUser) { xpActicityUser.setActitcityId(activity.getId().intValue()); xpActicityUser.setActitcityStrategeId(strategyMap.get(xpActicityUser.getStrategyName()).getId()); userService.save(xpActicityUser); } } @Override @@ -122,6 +133,11 @@ XpActivity byId = getById(id); XpActivityDto ret = new XpActivityDto(); BeanUtils.copyBeanProp(ret, byId); ret.setActicityType(byId.getActicityType()); ret.setEnableTotalLimit(byId.getAggregateLimit() == 1); ret.setTotalLimit(byId.getLimitation()); ret.setImg(byId.getCoverImage()); ret.setRichText(byId.getRemarks()); ret.setStrategy(strategyService.listByActicityId(id)); ret.setActivityUser(userService.listByActicityId(id)); return ret; xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityStrategyServiceImpl.java
@@ -1,13 +1,20 @@ package com.xiaopeng.operation.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.operation.XpActicityCoupon; import com.xiaopeng.api.model.operation.XpActicityStrategy; import com.xiaopeng.api.model.operation.XpCoupon; import com.xiaopeng.operation.mapper.XpActicityStrategyMapper; import com.xiaopeng.operation.service.IXpActicityCouponService; import com.xiaopeng.operation.service.IXpActicityStrategyService; import com.xiaopeng.operation.service.IXpCouponService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; import java.util.stream.Collectors; /** * <p> @@ -20,8 +27,23 @@ @Service public class XpActicityStrategyServiceImpl extends ServiceImpl<XpActicityStrategyMapper, XpActicityStrategy> implements IXpActicityStrategyService { @Resource private IXpCouponService xpCouponService; @Resource private IXpActicityCouponService xpActicityCouponService; @Override public List<XpActicityStrategy> listByActicityId(Long id) { return baseMapper.selectList(new LambdaQueryWrapper<XpActicityStrategy>().eq(XpActicityStrategy::getActitcityId, id)); List<XpActicityStrategy> xpActicityStrategies = baseMapper.selectList(new LambdaQueryWrapper<XpActicityStrategy>().eq(XpActicityStrategy::getActitcityId, id)); for (XpActicityStrategy xpActicityStrategy : xpActicityStrategies) { List<XpActicityCoupon> list = xpActicityCouponService.list(new QueryWrapper<XpActicityCoupon>().eq("acticity_strategy_id", xpActicityStrategy.getId())); if(null != list && !list.isEmpty()){ List<Long> couponIds = list.stream().map(XpActicityCoupon::getCouponId).collect(Collectors.toList()); List<XpCoupon> xpCoupons = xpCouponService.list(new QueryWrapper<XpCoupon>().in("id", couponIds)); xpActicityStrategy.setCouponList(xpCoupons); } } return xpActicityStrategies; } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpOfficialPartnerServiceImpl.java
New file @@ -0,0 +1,35 @@ package com.xiaopeng.operation.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.operation.XpOfficialPartner; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.operation.mapper.XpOfficialPartnerMapper; import com.xiaopeng.operation.service.IXpOfficialPartnerService; import com.xiaopeng.operation.vo.OfficialPartnerVo; import org.springframework.stereotype.Service; @Service public class XpOfficialPartnerServiceImpl extends ServiceImpl<XpOfficialPartnerMapper, XpOfficialPartner> implements IXpOfficialPartnerService { /** * 添加合作商 * @param vo */ @Override public void addOfficialPartner(OfficialPartnerVo vo) { XpOfficialPartner officialPartner = this.getOne(new QueryWrapper<XpOfficialPartner>().eq("app_key", vo.getAppKey()).eq("is_deleted", 0)); if(null == officialPartner){ throw new ServiceException("权限校验失败"); } if(!officialPartner.getAppSecret().equals(vo.getAppSecret())){ throw new ServiceException("权限校验失败"); } XpOfficialPartner xpOfficialPartner = new XpOfficialPartner(); xpOfficialPartner.setName(vo.getName()); xpOfficialPartner.setBrandName(vo.getBrandName()); xpOfficialPartner.setLogoUrl(vo.getLogoUrl()); this.updateById(xpOfficialPartner); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
@@ -5,6 +5,7 @@ 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.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.operation.PointMapQuery; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; @@ -29,6 +30,7 @@ import com.xiaopeng.operation.query.PointByNameQuery; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.IXpElectronicFenceService; import com.xiaopeng.operation.service.IXpTradingStrategyService; import com.xiaopeng.operation.service.XpPointService; import com.xiaopeng.operation.utils.TimeRangeChecker; import com.xiaopeng.operation.utils.holiday.HolidayUtil; @@ -83,6 +85,9 @@ @Resource private AliOssService aliOssService; @Resource private IXpTradingStrategyService xpTradingStrategyService; /** * 如果站点是挂在场站下的 需要返回一个场站id stationId @@ -728,6 +733,13 @@ @Override public OrderDistanceVo getOrderDistance() { OrderDistanceVo orderDistanceVo = new OrderDistanceVo(); XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); if(null != xpTradingStrategy){ orderDistanceVo.setQueuePollingTime(xpTradingStrategy.getQueuePollingTime()); orderDistanceVo.setWalkingNavigationDistance(xpTradingStrategy.getWalkingNavigationDistance()); orderDistanceVo.setMaxStandingTiming(xpTradingStrategy.getMaxStandingTiming()); } XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null); if (xpSystemSetting != null) { orderDistanceVo.setMaxDistance(xpSystemSetting.getOrderDistance()); xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTargetedServiceVehicleServiceImpl.java
@@ -1,13 +1,16 @@ package com.xiaopeng.operation.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpTargetedService; import com.xiaopeng.api.model.operation.XpTargetedServiceVehicle; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.operation.mapper.XpTargetedServiceMapper; import com.xiaopeng.operation.mapper.XpTargetedServiceVehicleMapper; import com.xiaopeng.operation.service.XpTargetedServiceService; import com.xiaopeng.operation.service.XpTargetedServiceVehicleService; import org.springframework.stereotype.Service; @@ -21,6 +24,12 @@ @Service public class XpTargetedServiceVehicleServiceImpl extends ServiceImpl<XpTargetedServiceVehicleMapper, XpTargetedServiceVehicle> implements XpTargetedServiceVehicleService { @Resource private XpVehicleClient xpVehicleClient; @Resource private XpTargetedServiceService xpTargetedServiceService; @Override @@ -32,7 +41,23 @@ wrapper.eq(XpTargetedServiceVehicle::getTargetedServiceId, targetedServiceId); this.remove(wrapper); } @Override public List<String> getVehicleVinByTargetedService(String cityCode) { List<XpTargetedService> targetedServices = xpTargetedServiceService.list(new QueryWrapper<XpTargetedService>().eq("status", 1) .eq("city_code", cityCode).last(" and (is_long_valid = 1 or now() between start_time and end_time)")); List<Long> collect = targetedServices.stream().map(XpTargetedService::getId).collect(Collectors.toList()); if(collect.isEmpty()){ return Collections.emptyList(); } List<XpTargetedServiceVehicle> list = this.list(new QueryWrapper<XpTargetedServiceVehicle>().in("targeted_service_id", collect)); List<String> vinList = list.stream().map(item -> { XpVehicle xpVehicle = xpVehicleClient.queryById(item.getVehicleId()).getData(); return xpVehicle.getVehicleVin(); }).collect(Collectors.toList()); return vinList; } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyPushServiceImpl.java
New file @@ -0,0 +1,12 @@ package com.xiaopeng.operation.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; import com.xiaopeng.operation.mapper.XpTradingStrategyPushMapper; import com.xiaopeng.operation.service.IXpTradingStrategyPushService; import org.springframework.stereotype.Service; @Service public class XpTradingStrategyPushServiceImpl extends ServiceImpl<XpTradingStrategyPushMapper, XpTradingStrategyPush> implements IXpTradingStrategyPushService { } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyServiceImpl.java
@@ -2,13 +2,16 @@ import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.model.operation.XpTradingStrategy; import com.xiaopeng.api.model.operation.XpTradingStrategyCity; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.operation.dto.XpTradingStrategyEditDTO; import com.xiaopeng.operation.mapper.XpTradingStrategyMapper; import com.xiaopeng.operation.service.IXpTradingStrategyCityService; import com.xiaopeng.operation.service.IXpTradingStrategyPushService; import com.xiaopeng.operation.service.IXpTradingStrategyService; import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO; import lombok.RequiredArgsConstructor; @@ -18,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import javax.annotation.Resource; import java.util.List; import java.util.Objects; @@ -34,6 +38,9 @@ public class XpTradingStrategyServiceImpl extends ServiceImpl<XpTradingStrategyMapper, XpTradingStrategy> implements IXpTradingStrategyService { private final IXpTradingStrategyCityService tradingStrategyCityService; @Resource private IXpTradingStrategyPushService xpTradingStrategyPushService; @Override public XpTradingStrategyDetailVO queryDetail() { @@ -55,7 +62,8 @@ // 3. 组装 VO XpTradingStrategyDetailVO vo = BeanUtil.copyProperties(strategy, XpTradingStrategyDetailVO.class); vo.setCityList(cityList); List<XpTradingStrategyPush> tradingStrategyId = xpTradingStrategyPushService.list(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", strategy.getId()).orderByAsc("start_time")); vo.setTimePushStrategyList(tradingStrategyId); return vo; } @@ -73,6 +81,14 @@ XpTradingStrategy updateStrategy = BeanUtil.copyProperties(dto, XpTradingStrategy.class); this.updateById(updateStrategy); //更新分时段推单策略 xpTradingStrategyPushService.remove(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", dto.getId())); List<XpTradingStrategyPush> pushTimeList = dto.getPushTimeList(); for (XpTradingStrategyPush xpTradingStrategyPush : pushTimeList) { xpTradingStrategyPush.setTradingStrategyId(dto.getId()); xpTradingStrategyPushService.save(xpTradingStrategyPush); } // 3. 删除旧的城市关联 tradingStrategyCityService.remove( new LambdaQueryWrapper<XpTradingStrategyCity>() xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.map.RouteAndFareDto; import com.xiaopeng.api.dto.operation.LonLatDto; @@ -18,7 +19,9 @@ import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpTargetedServiceVehicle; import com.xiaopeng.api.model.operation.XpTradingStrategy; import com.xiaopeng.api.model.operation.XpTradingStrategyPush; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpOrderReassign; @@ -54,6 +57,7 @@ import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -63,10 +67,12 @@ @Slf4j @Component public class TaskOrderUtil { @Resource private XpTargetedServiceService xpTargetedServiceService; @Resource XpTargetedServiceService xpTargetedServiceService; private XpTargetedServiceVehicleService xpTargetedServiceVehicleService; @Resource private RedisService redisService; @@ -84,6 +90,9 @@ @Resource private IXpTradingStrategyService xpTradingStrategyService; @Resource private IXpTradingStrategyPushService xpTradingStrategyPushService; @Resource private XpCruiseOrderClient xpCruiseOrderClient; @@ -138,25 +147,19 @@ */ @Scheduled(cron = "0/5 * * * * ?") public void taskOrder() { // System.out.println("5秒执行一次"); System.out.println("5秒执行一次"); Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); for (String name : quoteMatchName) { String firstElement = redisService.getFirstElement(name); if (firstElement != null) { String[] split = firstElement.split("_"); if(split.length>8){ String targetedVal = split[8]; if (!"0".equals(targetedVal)) { continue; } } String[] split = firstElement.toString().split("_"); // 如果未处理 创建新任务 if ("0".equals(split[2])) { if (split[2].equals("0")) { String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { orderProcess(name, firstElement); orderProcess(name, firstElement.toString(), false); }); } } @@ -168,25 +171,20 @@ */ @Scheduled(cron = "0/5 * * * * ?") public void taskOrder_targeted() { // System.out.println("5秒执行一次"); Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID); System.out.println("5秒执行一次"); Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID); for (String name : quoteMatchName) { String firstElement = redisService.getFirstElement(name); if (firstElement != null) { String[] split = firstElement.split("_"); if(split.length>8){ String targetedVal = split[8]; if (!"0".equals(targetedVal)) { // 如果未处理 创建新任务 if ("0".equals(split[2])) { String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { orderProcess(name, firstElement); }); } } String[] split = firstElement.toString().split("_"); // 如果未处理 创建新任务 if (split[2].equals("0")) { String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7]; // 状态改为处理中 redisService.updateFirst(name, value); threadPoolTaskExecutor.submit(() -> { orderProcess(name, firstElement.toString(), true); }); } } } @@ -198,7 +196,7 @@ * @param quoteName 队列名称 * @param firstElement 队列第一个元素 */ private void orderProcess(String quoteName, String firstElement) { private void orderProcess(String quoteName, String firstElement, Boolean isTargetedService) { XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null); String orderId = firstElement.split("_")[0]; String lonLat = firstElement.split("_")[1]; @@ -214,58 +212,68 @@ // 经纬度 String[] split = lonLat.split(","); //查询当前时段是不是特殊推单时段 List<XpTradingStrategyPush> tradingStrategyId = xpTradingStrategyPushService.list(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", xpTradingStrategy)); long now = Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm"))); XpTradingStrategyPush xpTradingStrategyPush = tradingStrategyId.stream().filter(item -> { long start = Long.parseLong(item.getStarTime().replace(":", "")); long end = Long.parseLong(item.getEndTime().replace(":", "")); return now >= start && now < end; }).findFirst().orElse(null); // 5轮找车辆 //每次查找车辆推单后的等待秒数 int sleepTime = 3; Integer onePushTime = xpTradingStrategy.getOnePushTime(); Double onePushDistance = xpTradingStrategy.getOnePushDistance(); Integer onePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushTime() : xpTradingStrategy.getOnePushTime(); Double onePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushDistance() : xpTradingStrategy.getOnePushDistance(); int count = onePushTime / sleepTime; // 第一轮推单 log.info("开始第一轮推单 {}", orderNo); Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule); Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule, isTargetedService); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第二轮推单 Integer twoPushTime = xpTradingStrategy.getTwoPushTime(); Double twoPushDistance = xpTradingStrategy.getTwoPushDistance(); Integer twoPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushTime() : xpTradingStrategy.getTwoPushTime(); Double twoPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushDistance() : xpTradingStrategy.getTwoPushDistance(); count = twoPushTime / sleepTime; log.info("开始第二轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule, isTargetedService); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第三轮推单 Integer threePushTime = xpTradingStrategy.getThreePushTime(); Double threePushDistance = xpTradingStrategy.getThreePushDistance(); Integer threePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushTime() : xpTradingStrategy.getThreePushTime(); Double threePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushDistance() : xpTradingStrategy.getThreePushDistance(); count = threePushTime / sleepTime; log.info("开始第三轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule, isTargetedService); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第四轮推单 Integer fourPushTime = xpTradingStrategy.getFourPushTime(); Double fourPushDistance = xpTradingStrategy.getFourPushDistance(); Integer fourPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushTime() : xpTradingStrategy.getFourPushTime(); Double fourPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushDistance() : xpTradingStrategy.getFourPushDistance(); count = fourPushTime / sleepTime; log.info("开始第四轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule, isTargetedService); if(processed){ log.info("订单推送成功 {}", orderNo); return; } // 第五轮推单 Integer fivePushTime = xpTradingStrategy.getFivePushTime(); Double fivePushDistance = xpTradingStrategy.getFivePushDistance(); Integer fivePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushTime() : xpTradingStrategy.getFivePushTime(); Double fivePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushDistance() : xpTradingStrategy.getFivePushDistance(); count = fivePushTime / sleepTime; log.info("开始第五轮推单 {}", orderNo); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule); processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule, isTargetedService); if(processed){ log.info("订单推送成功 {}", orderNo); return; @@ -320,7 +328,863 @@ * @param xpTradingStrategy 规则 */ @SneakyThrows private Boolean processPushOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule) { private Boolean processPushOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule, Boolean isTargetedService) { log.info("进入推单环节 单号 {}", orderNo); if (count == 0) { count = 1; } // 订单状态 R<XpOrder> xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { return false; } if (xpOrderR.getData().getStatus() != 1) { return true; } XpOrder xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() == 0) { redisService.removeByPattern(quoteName, xpOrder.getOrderNumber()); } // 找出围栏id Long xpElectronicFenceAreaId = xpOrder.getXpElectronicFenceAreaId(); Long electronicId = xpElectronicFenceAreaService.getById(xpElectronicFenceAreaId).getElectronicId(); XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(electronicId); // ===== 新增:UID-VIN 优先匹配(仅 enabled=true 时生效)===== log.info("[人车订单绑定测试] >>>>>> 进入优先匹配判断, uid={}, orderNo={}, 围栏区域ID={}", uid, orderNo, xpElectronicFenceAreaId); if (uidVinBindingConfig.isEnabled()) { log.info("[人车订单绑定测试] 总开关已开启, 开始执行优先匹配逻辑, uid={}, orderNo={}", uid, orderNo); try { PriorityMatchResult priorityResult = uidVinPriorityMatcher.tryPriorityMatch(uid, orderNo, String.valueOf(xpElectronicFenceAreaId)); log.info("[人车订单绑定测试] 优先匹配结果: matched={}, vin={}, failReason={}, uid={}, orderNo={}", priorityResult != null ? priorityResult.isMatched() : "null", priorityResult != null ? priorityResult.getVin() : "null", priorityResult != null ? priorityResult.getFailReason() : "null", uid, orderNo); if (priorityResult != null && priorityResult.isMatched()) { String priorityVin = priorityResult.getVin(); log.info("[人车订单绑定测试] 匹配成功, 准备获取分布式锁, lockKey=FIND_CAR_{}, orderNo={}", priorityVin, orderNo); RLock priorityLock = redissonClient.getLock("FIND_CAR_" + priorityVin); priorityLock.lock(10, TimeUnit.SECONDS); log.info("[人车订单绑定测试] 分布式锁获取成功, vin={}, orderNo={}", priorityVin, orderNo); try { // 二次校验车辆状态 log.info("[人车订单绑定测试] 开始二次校验车辆状态, vin={}, orderNo={}", priorityVin, orderNo); R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(priorityVin); log.info("[人车订单绑定测试] 二次校验-车辆查询结果: code={}, hasData={}, vin={}", vehicleR.getCode(), vehicleR.getData() != null, priorityVin); if (vehicleR.getCode() == 200 && vehicleR.getData() != null) { XpVehicle vehicle = vehicleR.getData(); //判断当前车辆是否在禁派单车辆内 String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId()); List<String> strings = new ArrayList<>(); if(null != cacheList){ strings = JSON.parseArray(cacheList, String.class); } log.info("[人车订单绑定测试] 二次校验-车辆状态: operatingStatus={}, state={}, vehicleType={}, vin={}", vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType(), priorityVin); if (vehicle.getOperatingStatus() == 1 && vehicle.getState() == 0 && vehicle.getVehicleType() != 1 && !strings.contains(vehicle.getVehicleVin())) { log.info("[人车订单绑定测试] 二次校验-车辆状态通过(空闲), 开始校验订单状态, orderNo={}", orderNo); // 二次校验订单状态 R<XpOrder> orderCheck = xpOrderClient.queryOrderByOrderNo(orderNo); log.info("[人车订单绑定测试] 二次校验-订单查询结果: code={}, status={}, orderNo={}", orderCheck.getCode(), orderCheck.getData() != null ? orderCheck.getData().getStatus() : "null", orderNo); if (orderCheck.getCode() == 200 && orderCheck.getData() != null && orderCheck.getData().getStatus() == 1) { log.info("[人车订单绑定测试] 二次校验全部通过, 开始关闭巡游单, vin={}, orderNo={}", priorityVin, orderNo); // 关闭巡游单 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(priorityVin); log.info("[人车订单绑定测试] 关闭巡游单结果: code={}, vin={}, orderNo={}", stringR != null ? stringR.getCode() : "null", priorityVin, orderNo); if (stringR != null && stringR.getCode() == 200) { log.info("[人车订单绑定测试] 关闭巡游单成功, 开始下发XPU命令, vin={}, orderNo={}", priorityVin, orderNo); // 下发XPU命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(priorityVin); pushOrderDto.setOrderId(orderCheck.getData().getId().toString()); pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat()); pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon()); pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat()); pushOrderDto.setEndLongitude(orderCheck.getData().getEndLon()); pushOrderDto.setEndPoiName(orderCheck.getData().getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); log.info("[人车订单绑定测试] XPU推单参数: vin={}, orderId={}, startLat={}, startLon={}, endLat={}, endLon={}, orderNo={}", priorityVin, orderCheck.getData().getId(), orderCheck.getData().getStartLat(), orderCheck.getData().getStartLon(), orderCheck.getData().getEndLat(), orderCheck.getData().getEndLon(), orderNo); orderMissionClient.pushOrder(pushOrderDto); log.info("[人车订单绑定测试] ====== 派单成功! uid={}, vin={}, orderNo={}, 从队列移除订单 ======", uid, priorityVin, orderNo); redisService.removeByPattern(quoteName, orderNo); return true; } else { log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo); } } else { log.info("[人车订单绑定测试] 二次校验-订单状态不满足(非待派单), 回退常规流程, orderNo={}", orderNo); } } else { if (vehicle.getState() != 0) { log.info("[人车订单绑定测试] 二次校验-车辆已接单(state={}), 当前有未完成订单, 无法指派, vin={}, plateNumber={}, orderNo={}", vehicle.getState(), priorityVin, vehicle.getPlateNumber(), orderNo); } else { log.info("[人车订单绑定测试] 二次校验-车辆状态不满足, 回退常规流程, vin={}, operatingStatus={}, state={}, vehicleType={}", priorityVin, vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType()); } } } else { log.info("[人车订单绑定测试] 二次校验-车辆查询失败, 回退常规流程, vin={}, code={}", priorityVin, vehicleR.getCode()); } } catch (Exception e) { log.error("[人车订单绑定测试] 锁内执行异常,回退常规流程, uid={}, vin={}, orderNo={}", uid, priorityVin, orderNo, e); } finally { priorityLock.unlock(); log.info("[人车订单绑定测试] 分布式锁已释放, vin={}, orderNo={}", priorityVin, orderNo); } } else { log.info("[人车订单绑定测试] 优先匹配未命中, 进入常规流程, uid={}, orderNo={}", uid, orderNo); } } catch (Exception e) { log.error("[人车订单绑定测试] 优先匹配过程异常,回退常规流程, uid={}, orderNo={}", uid, orderNo, e); } } else { log.info("[人车订单绑定测试] 总开关未开启(enabled=false), 跳过优先匹配, uid={}, orderNo={}", uid, orderNo); } // ===== 新增结束 ===== for (int i = 0; i < count; i++) { //等到sleepTime秒钟 Thread.sleep(sleepTime * 1000); // 根据距离找车 // 车多则根据配置找具体车数量 根据距离最近 // 更改 暂不限制数量 List<VehiclePosition> positionList = vehiclePositionService.findAvailableVehiclesNearby(Double.parseDouble(split[0]), Double.parseDouble(split[1]), pushDistance, xpTradingStrategy.getSimultaneouslyOrderCount()); log.info("根据距离找车 {} 距离 {}KM 经度 {} 维度 {} 查找结果 {} 单号 {}", orderNo, pushDistance, split[0], split[1], JSON.toJSONString(positionList), orderNo); // 获取车辆的区域信息 if (positionList.isEmpty()) { continue; } Set<String> vinList = positionList.stream().map(VehiclePosition::getVin).collect(Collectors.toSet()); //判断当前车辆是否在禁派单车辆内 String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId()); if(Objects.nonNull(cacheList)){ List<String> strings = JSON.parseArray(cacheList, String.class); Set<String> vins = new HashSet<>(); for (String s : vinList) { if (!strings.contains(s)) { vins.add(s); } } vinList = vins; } // 获取车辆的信息 筛选出可用车辆,定向服务的车辆排除 R<List<String>> vehiclePositionVos = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount())); log.info("筛选可用车辆结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); List<String> vehicleVinByTargetedService = xpTargetedServiceVehicleService.getVehicleVinByTargetedService(xpOrderR.getData().getCityCode()); if(!isTargetedService){ vehiclePositionVos.getData().removeAll(vehicleVinByTargetedService); log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); }else{ vehicleVinByTargetedService.removeAll(vehiclePositionVos.getData()); vehiclePositionVos.setData(vehicleVinByTargetedService); log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo); } if (vehiclePositionVos.getCode() != 200) { continue; } List<VehiclePositionVo> availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class); List<String> data = vehiclePositionVos.getData(); // 找出符合条件的 availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> data.contains(e.getVin())).collect(Collectors.toList()); if (!availableVehiclesNearby.isEmpty()) { if (availableVehiclesNearby.size() > 1) { log.info("附近有 {} 辆车,进入权重判断流程 单号 {}", availableVehiclesNearby.size(), orderNo); // 走权重 // 订单价值 Integer tendencyOrderValue = xpTradingStrategy.getTendencyOrderValue(); // 距离价值 Integer tendencyDistance = xpTradingStrategy.getTendencyDistance(); // 时间价值 Integer tendencyTime = xpTradingStrategy.getTendencyTime(); try { // 电量价值 Integer tendencyElectricity = xpTradingStrategy.getTendencyElectricity(); // 找出最大的值是那个 Integer max = Math.max(tendencyOrderValue, Math.max(tendencyDistance, Math.max(tendencyTime, tendencyElectricity))); if (max.equals(tendencyOrderValue)) { // 订单价值 // 时间差权重 Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference(); // 距离差权重 Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference(); // 距离权重 Integer weightDistance = xpTradingStrategy.getWeightDistance(); // 时间权重 Integer weightTime = xpTradingStrategy.getWeightTime(); // 电量权重 Integer weightElectricity = xpTradingStrategy.getWeightElectricity(); // 找出最大的值是那个 Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity)))); // 时间差 if (max1.equals(weightTimeDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration(); vehiclePosition.setTimeDifference(durationDifference); } } } // 距离差 if (max1.equals(weightDistanceDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance(); vehiclePosition.setDistanceDifference(distanceDifference); } } } if (max1.equals(weightDistance)) { log.info("车子距离~~"); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo); vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); double score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistance(score); score--; } } if (max1.equals(weightTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setSecond(score); score--; } } if (max1.equals(weightElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size = tendencyElectricity; // 做比对的分数 int temp = availableVehiclesNearby.get(0).getCurrentElectricity(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size); if (temp != vehiclePosition.getCurrentElectricity()) { size--; } } } // 算出总分 再来排序计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue()); } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList()); int size = tendencyOrderValue; // 做比对的分数 double temp = availableVehiclesNearby.get(0).getOrderValueTotal(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size); if (temp != vehiclePosition.getOrderValueTotal()) { size--; } } } // 距离分数 if (max.equals(tendencyDistance)) { log.info("车子距离~~"); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo); vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } // availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); // int size = tendencyDistance; // // 做比对的分数 // double temp = availableVehiclesNearby.get(0).getDistance(); // for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { // vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size); // if (temp != vehiclePosition.getDistance()) { // size--; // } // } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistanceScore(score); score--; } } // 时间分数 if (max.equals(tendencyTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } // 分数计算 把时间短的分数调高 availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int score = 10; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setTimeScore(score); score--; } // availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); // int size = tendencyTime; // // 做比对的分数 // double temp = availableVehiclesNearby.get(0).getSecond(); // for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { // vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size); // if (temp != vehiclePosition.getSecond()) { // size--; // } // } } // 电量分数 if (max.equals(tendencyElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size = tendencyElectricity; // 做比对的分数 int temp = availableVehiclesNearby.get(0).getCurrentElectricity(); int maxTemp = 0; for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size); if (temp != vehiclePosition.getCurrentElectricity()) { size--; } else { maxTemp++; } } if (maxTemp > 1) { // 证明有最高相同电量的 找下一个 // 找出最第二大的值是那个 // 将四个值放入列表 List<Integer> values = Arrays.asList(tendencyOrderValue, tendencyDistance, tendencyTime); // 降序排序 values.sort(Collections.reverseOrder()); // 获取第二大值 Integer secondMax = values.get(1); // 判断第二大的是哪个 if (Objects.equals(secondMax, tendencyDistance)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList()); int size1 = tendencyDistance; // 做比对的分数 double temp1 = availableVehiclesNearby.get(0).getDistance(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size1); if (temp1 != vehiclePosition.getDistance()) { size1--; } } } if (Objects.equals(secondMax, tendencyTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList()); int size1 = tendencyTime; // 做比对的分数 double temp1 = availableVehiclesNearby.get(0).getSecond(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size1); if (temp1 != vehiclePosition.getSecond()) { size1--; } } } // 订单价值 if (Objects.equals(secondMax, tendencyOrderValue)) { // 订单价值 // 时间差权重 Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference(); // 距离差权重 Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference(); // 距离权重 Integer weightDistance = xpTradingStrategy.getWeightDistance(); // 时间权重 Integer weightTime = xpTradingStrategy.getWeightTime(); // 电量权重 Integer weightElectricity = xpTradingStrategy.getWeightElectricity(); // 找出最大的值是那个 Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity)))); // 时间差 if (max1.equals(weightTimeDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration(); vehiclePosition.setTimeDifference(durationDifference); } } } if (max1.equals(weightDistanceDifference)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.valueOf(split[0])); lonLatDto1.setLatitude(Double.valueOf(split[1])); routeAndFareDto.setDestination(lonLatDto1); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (distanceAndDuration.getCode() == 200) { // 送驾- 接驾 Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance(); vehiclePosition.setDistanceDifference(distanceDifference); } } } if (max1.equals(weightDistance)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance())); } else { vehiclePosition.setDistance(0.0); } } } if (max1.equals(weightTime)) { for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { RouteAndFareDto routeAndFareDto = new RouteAndFareDto(); LonLatDto lonLatDto = new LonLatDto(); lonLatDto.setLongitude(vehiclePosition.getPoint().getX()); lonLatDto.setLatitude(vehiclePosition.getPoint().getY()); routeAndFareDto.setOrigin(lonLatDto); LonLatDto lonLatDto1 = new LonLatDto(); lonLatDto1.setLongitude(Double.parseDouble(split[0])); lonLatDto1.setLatitude(Double.parseDouble(split[1])); if(planRule!=null&& !"null".equals(planRule)){ routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule)); } routeAndFareDto.setDestination(lonLatDto1); // 调用地图 获取时间 R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto); if (r.getCode() == 200) { vehiclePosition.setSecond(r.getData().getDuration()); } else { vehiclePosition.setSecond(0); } } } if (max1.equals(weightElectricity)) { // 计算车的分数 分数最大是车的size availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList()); int size1 = tendencyElectricity; // 做比对的分数 int temp1 = availableVehiclesNearby.get(0).getCurrentElectricity(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size1); if (temp1 != vehiclePosition.getCurrentElectricity()) { size1--; } } } } // 算出总分 再来排序计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue()); } availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList()); int size2 = tendencyOrderValue; // 做比对的分数 double temp2 = availableVehiclesNearby.get(0).getOrderValueTotal(); for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) { vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size2); if (temp2 != vehiclePosition.getOrderValueTotal()) { size2--; } } } } } catch (Exception e) { log.error("异常", e); } // 判断总分来计算 for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) { vehiclePositionVo.setTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getValueScore()); } VehiclePositionVo vehiclePositionVo = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getTotal).reversed()).collect(Collectors.toList()).get(0); // // VehiclePositionVo vehiclePositionVo1 = vehiclePositionVo; RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin()); lock.lock(10, TimeUnit.SECONDS); log.info("队列 {} 车辆 {} 单号 {}", quoteName, vehiclePositionVo.getVin(), orderNo); try { // VehiclePosition vehiclePosition = vehiclePositionService.findByVehicleId(vehiclePositionVo.getVehicle_id()); R<XpVehicle> vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin()); if (vehiclePositionR.getCode() != 200) { continue; } XpVehicle vehiclePosition = vehiclePositionR.getData(); log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo); log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getStatus(), orderNo); if (vehiclePosition.getOperatingStatus() != 1 || vehiclePosition.getState() != 0 || vehiclePosition.getVehicleType() == 1) { continue; } // 再次查询一下订单 看是否取消 xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { continue; } xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() != 1) { continue; } // 关闭巡游单子 R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin()); if (stringR == null || stringR.getCode() != 200) { log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber()); continue; } log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo); // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(vehiclePosition.getVehicleVin()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setStartLatitude(xpOrder.getStartLat()); pushOrderDto.setStartLongitude(xpOrder.getStartLon()); pushOrderDto.setEndLatitude(xpOrder.getEndLat()); pushOrderDto.setEndLongitude(xpOrder.getEndLon()); pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo); redisService.removeByPattern(quoteName,xpOrder.getOrderNumber()); log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); return true; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } else { // 直接派单 定义一个锁来锁定车辆 VehiclePositionVo vehiclePosition = availableVehiclesNearby.get(0); String vehicleVin = vehiclePosition.getVin(); RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePosition.getVin()); lock.lock(10, TimeUnit.SECONDS); try { // 查询车辆状态 R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin); if (vehicleR.getCode() != 200) { continue; } XpVehicle vehicleId1 = vehicleR.getData(); log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo); log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo); if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) { continue; } // 再次查询一下订单 看是否取消 xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo); if (xpOrderR.getCode() != 200) { continue; } xpOrder = xpOrderR.getData(); if (xpOrder.getStatus() != 1) { continue; } // 关闭巡游单子 R<?> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin()); if (stringR == null || stringR.getCode() != 200) { log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber()); continue; } log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(vehiclePosition.getVin()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setStartLatitude(xpOrder.getStartLat()); pushOrderDto.setStartLongitude(xpOrder.getStartLon()); pushOrderDto.setEndLatitude(xpOrder.getEndLat()); pushOrderDto.setEndLongitude(xpOrder.getEndLon()); pushOrderDto.setEndPoiName(xpOrder.getEndPointName()); pushOrderDto.setOrderType(OrderType.USER_ORDER); pushOrderDto.setStage(1); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber()); redisService.popFirstElement(quoteName); log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName); return true; } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } } return false; } /** * 定向服务订单处理 * @param quoteName 队列名称 * @param count 轮数 * @param uid * @param split 经纬度 * @param orderNo 订单号 * @param xpTradingStrategy 规则 */ @SneakyThrows private Boolean processPushSpOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule) { log.info("进入推单环节 单号 {}", orderNo); if (count == 0) { count = 1; @@ -1256,6 +2120,8 @@ return false; } private static PushOrderDto buildPushOrderDto(XpOrder xpOrder) { PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId().toString()); xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OfficialPartnerVo.java
New file @@ -0,0 +1,20 @@ package com.xiaopeng.operation.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("合作商信息") public class OfficialPartnerVo { @ApiModelProperty("合作商名称") private String name; @ApiModelProperty("合作商品牌名称") private String brandName; @ApiModelProperty("合作商品牌logo") private String logoUrl; @ApiModelProperty("应用APPKey") private String appKey; @ApiModelProperty("应用APPSecret") private String appSecret; } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OrderDistanceVo.java
@@ -23,4 +23,13 @@ @ApiModelProperty(value = "天气单位") private String temperatureUnit; @ApiModelProperty("首页轮询接口间隔 秒") private Integer queuePollingTime; @ApiModelProperty("步行图标控制距离 米") private Integer walkingNavigationDistance; @ApiModelProperty("下单页停留时长") private Integer maxStandingTiming; } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/PricingInfoVo.java
New file @@ -0,0 +1,10 @@ package com.xiaopeng.operation.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("定价信息") public class PricingInfoVo { } xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpOfficialPartnerMapper.xml
New file @@ -0,0 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.operation.mapper.XpOfficialPartnerMapper"> </mapper> xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpTradingStrategyPushMapper.xml
New file @@ -0,0 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.operation.mapper.XpTradingStrategyPushMapper"> </mapper> xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -500,7 +500,7 @@ * + * 获取行程费用明细 */ @PutMapping("/api/v1/mini-program/order/fare-breakdown") @PostMapping("/api/v1/mini-program/order/fare-breakdown") @ApiOperation(value = "获取行程费用明细", tags = {"小程序-获取行程费用明细"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R<FareBreakdownVo> fareBreakdown(@RequestBody com.xiaopeng.order.vo.FareBreakdownVo vo, HttpServletRequest request) { @@ -619,8 +619,8 @@ Object cacheObject = redisService.getCacheObject(key); RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class); XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); // VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); // routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90); Long vehicleId = xpOrder.getVehicleId(); XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("vehicle_id", vehicleId).in("status", Arrays.asList(6, 7)).eq("is_deleted", 0)); @@ -721,7 +721,7 @@ //判断流失用户 XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("app_user_id", userId).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1")); if(null != one){ long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("GMT+8")) - one.getCreateTime().toEpochSecond(ZoneOffset.of("GMT+8")); long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - one.getCreateTime().toEpochSecond(ZoneOffset.of("+8")); if(time >= 60 * 60 * 24 * 5){ return R.ok(4); } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/mapper/XpOrderMapper.java
@@ -74,7 +74,11 @@ List<XpOrder> listUserRecentValidOrders(@Param("uid") Long uid, @Param("startTime") LocalDateTime startTime); List<Long> timeSceneOrders(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDateTime endDate, @Param("startMoment") LocalTime startMoment, @Param("endMoment") LocalTime endMoment, @Param("userId") Long userId); List<Long> timeSceneOrders(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDateTime endDate, @Param("startMoment") LocalTime startMoment, @Param("endMoment") LocalTime endMoment, @Param("userId") Long userId); List<Long> frequencyOrders(LocalDate startDate, LocalDateTime endDate, LocalTime startMoment, LocalTime endMoment, Long userId); } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -2136,18 +2136,6 @@ .put("orderType", OrderType.USER_ORDER) .build(); //如果是异常订单,需要定时创建客服工单 if(orderException){ XpSystemSetting xpSystemSetting = xpSystemSettingClient.getSystemSettingOne().getData(); QuartzManager.addJob( OrderExceptionJob.class, (OrderExceptionJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ADD_CRUISE_MISSION, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpSystemSetting.getOrderExceptionalTimeout())), jobMaps ); } //判断是否有连环单 String json = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder.getId().toString())); if (StringUtils.isNotEmpty(json)){ @@ -2284,19 +2272,19 @@ order.setAppUserId(appUserId); bootCommonService.setCache_orderStatus(order.getId(),order,null); //删除蓝牙秘钥 String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId); if(StringUtils.isNotBlank(token)){ redisService.deleteObject("rt:bluetooth:unlock:" + token); redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId); XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); BluetoothDeliverVo vo = new BluetoothDeliverVo(); vo.setVim(xpVehicle.getVehicleVin()); vo.setPassengerUid(order.getAppUserId()); BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); if(null == delete || delete.getCode() != 0){ log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); } } // String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId); // if(StringUtils.isNotBlank(token)){ // redisService.deleteObject("rt:bluetooth:unlock:" + token); // redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId); // XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); // BluetoothDeliverVo vo = new BluetoothDeliverVo(); // vo.setVim(xpVehicle.getVehicleVin()); // vo.setPassengerUid(order.getAppUserId()); // BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo); // if(null == delete || delete.getCode() != 0){ // log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber()); // } // } // 根据订单所属开通城市id 查询定价 XpPricing pricing = bootCommonService.getXpPricing(order.getCityId(),order.getVehicleId()); @@ -2353,12 +2341,15 @@ xpOrderDetail.setType(1); xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDistancePrice()).setScale(2,RoundingMode.HALF_UP)); xpOrderDetails.add(xpOrderDetail); xpOrderDetail = new XpOrderDetail(); xpOrderDetail.setDetailType(3); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setType(1); xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDurationPrice()).setScale(2, RoundingMode.HALF_UP)); xpOrderDetails.add(xpOrderDetail); //时长费不是必填项 if(null != xpPricingCardVo.getDurationPrice() && xpPricingCardVo.getDurationPrice() > 0){ xpOrderDetail = new XpOrderDetail(); xpOrderDetail.setDetailType(3); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setType(1); xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDurationPrice()).setScale(2, RoundingMode.HALF_UP)); xpOrderDetails.add(xpOrderDetail); } BigDecimal totalPrice =BigDecimal.ZERO; for (XpOrderDetail xpOrderDetail1 : xpOrderDetails) { @@ -2372,7 +2363,6 @@ else { //动态计费 if (pricing.getPricingType() == 1) { for (int i = 0; i < startingFareJsonArray.size(); i++) { com.alibaba.fastjson2.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i); String num1 = jsonObject.getString("num1"); @@ -2464,6 +2454,8 @@ // 触发调价了 redisService.setCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES); } //天气预报动态调价 } } @@ -3579,34 +3571,34 @@ .plusMinutes(routeVo1.getDuration()).plusMinutes(endPoint.getParkingTimeLimit()).plusMinutes(30); long expirationTime = localDateTime.toEpochSecond(ZoneOffset.of("+8")); //生成token String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(), order.getId(), order.getVehicleId(), expirationTime); log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber()); //存储缓存 JSONObject jsonObject = new JSONObject(); jsonObject.put("userId", order.getAppUserId()); jsonObject.put("orderId", order.getId()); jsonObject.put("vehicleId", order.getVehicleId()); jsonObject.put("expirationTime", expirationTime); jsonObject.put("orderNumber", order.getOrderNumber()); jsonObject.put("vehicleVin", vehicle.getVehicleVin()); jsonObject.put("createTime", System.currentTimeMillis()); redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS); redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS); //开始下发蓝牙token BluetoothDeliverVo vo = new BluetoothDeliverVo(); vo.setCredential(token); vo.setVim(vehicle.getVehicleVin()); vo.setPassengerUid(order.getAppUserId()); BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo); if(null == deliver){ throw new ServiceException("下发蓝牙token失败"); } if(deliver.getCode() != 0){ log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber()); throw new ServiceException(deliver.getMsg()); } log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber()); // String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(), // order.getId(), order.getVehicleId(), expirationTime); // log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber()); // //存储缓存 // JSONObject jsonObject = new JSONObject(); // jsonObject.put("userId", order.getAppUserId()); // jsonObject.put("orderId", order.getId()); // jsonObject.put("vehicleId", order.getVehicleId()); // jsonObject.put("expirationTime", expirationTime); // jsonObject.put("orderNumber", order.getOrderNumber()); // jsonObject.put("vehicleVin", vehicle.getVehicleVin()); // jsonObject.put("createTime", System.currentTimeMillis()); // redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS); // redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS); // //开始下发蓝牙token // BluetoothDeliverVo vo = new BluetoothDeliverVo(); // vo.setCredential(token); // vo.setVim(vehicle.getVehicleVin()); // vo.setPassengerUid(order.getAppUserId()); // BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo); // if(null == deliver){ // throw new ServiceException("下发蓝牙token失败"); // } // if(deliver.getCode() != 0){ // log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber()); // throw new ServiceException(deliver.getMsg()); // } // log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber()); } if(order.getStatus() == 2){ @@ -3792,9 +3784,11 @@ } Integer status = xpOrder.getStatus(); if(status > 2 && status < 8){ Boolean data = xpVehicleClient.getVehicleTrunkOpenStatus(xpOrder.getAppUserId(), xpOrder.getVehicleId()).getData(); xpOrder.setOpenTrunk(data ? 1 : 2); xpOrderDetailVO.setOpenTrunk(data ? 1 : 2); // Boolean data = xpVehicleClient.getVehicleTrunkOpenStatus(xpOrder.getAppUserId(), xpOrder.getVehicleId()).getData(); // xpOrder.setOpenTrunk(data ? 1 : 2); // xpOrderDetailVO.setOpenTrunk(data ? 1 : 2); xpOrder.setOpenTrunk(2); xpOrderDetailVO.setOpenTrunk(2); xpOrder.setAppUserId(null); this.updateById(xpOrder); } xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml
@@ -108,7 +108,7 @@ AND is_deleted = 0 AND status IN (9, 10) AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} AND TIME(create_time) BETWEEN #{startTime} AND #{endTime} AND TIME(create_time) BETWEEN #{startMoment} AND #{endMoment} GROUP BY end_point_id ORDER BY COUNT(*) DESC </select> xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/controller/WebSocketController.java
@@ -46,7 +46,7 @@ * @return 操作结果 */ @ApiOperation(value = "发送订单状态") @PostMapping("/inner/websocket/order/sendStatus") @PostMapping("/logan/inner/websocket/order/sendStatus") public R<String> sendStatus(@RequestBody SendMessageDTO dto) { try { String message = dto.getMessage(); xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetController.java
@@ -240,28 +240,4 @@ return R.ok(xpFleetService.list()); } @ApiOperation(value = "品牌信息", tags = {"流量接入-信息录入-品牌展示信息"}) @PostMapping("/api/v1/xp-rt/brand-info") public R<?> JoinUs( @ApiParam(value = "车辆信息", required = true) @RequestBody BrandInfo brandInfo ) { //包含接收订单的URL XpFleet xpFleet = new XpFleet(); XpOperationsUser operationsUser = new XpOperationsUser(); operationsUser.setNickName(brandInfo.getOperationsUserName()); operationsUser.setPhoneNumber(brandInfo.getPhoneNumber()); operationsUser.setDeviceType(1); xpFleet.setFleetName(brandInfo.getBrandName()); // xpFleetService.save(fleet); return R.ok(); } XpOperationsUserClient xpOperationsUserClient; } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetVehicleController.java
@@ -60,29 +60,4 @@ List<Long> vehicleIds = xpFleetVehicleService.listVehicleIdsByFleetId(fleetId); return R.ok(vehicleIds); } @ApiOperation(value = "添加车辆", tags = {"流量接入-信息录入-车辆"}) @PostMapping("/api/v1/xp-rt/vehicle") public R<?> add( @ApiParam(value = "车辆信息", required = true) @RequestBody XpFleetVehicle fleetVehicle ) { xpFleetVehicleService.save(fleetVehicle); return R.ok(); } @Resource MongoTemplate mongoTemplate; @ApiOperation(value = "车辆", tags = {"流量接入-信息录入-车辆"}) @PostMapping("/api/v1/xp-rt/vehicle/info") public R<?> JoinUs( @ApiParam(value = "车辆位置信息", required = true) @RequestBody VehiclePosition vp ) { mongoTemplate.save(vp); return R.ok(); } } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -42,6 +42,7 @@ import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel; import com.xiaopeng.vehicleConvoy.model.query.*; import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO; import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto; import com.xiaopeng.vehicleConvoy.service.IXpFleetService; import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService; import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService; @@ -746,26 +747,7 @@ } public static void main(String[] args) { String inspectionAttachments = "[{\"id\": \"d57c4ac4-acb0-451b-8e94-70f226331e0c\", \"url\": \"https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png\", \"name\": \"测试.jpg\"}]"; if (StringUtils.isNotBlank(inspectionAttachments)) { JSONArray jsonArray = JSONArray.parseArray(inspectionAttachments); for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); if (Objects.isNull(jsonObject)) { continue; } jsonObject.put("url", "downloadUrl"); } String jsonString = JSONArray.toJSONString(jsonArray); System.out.println(jsonString); } } /** * 根据围栏id查询空闲车辆 @@ -1205,35 +1187,24 @@ return R.ok(xpVehicleList); } @ApiOperation(value = "上报车辆位置", notes = "", tags = {"流量接入-上报车辆位置"}) @PostMapping("/api/v1/xp-rt/vehicle/position") public R<List<XpVehicleVO>> pushVehiclePosition(@RequestBody VehiclePosition vp) { // 更新到mongodb,用于被分配订单 // 如果是接单中,更新导航路线 return R.ok(); } /** * {@Link OrderStatusEnum} * @param vp * 上报车辆实时位置信息 * @param dto * @return */ @ApiOperation(value = "更新车辆状态", notes = "", tags = {"流量接入-更新车辆状态"}) @PostMapping("/api/v1/xp-rt/vehicle/status") public R<List<XpVehicleVO>> pushVehicleStatus(@RequestBody VehiclePosition vp) { // 前往接驾,等待上车,前往终点,到达终点等待下车,结束订单 // 更新order状态 @PostMapping("/drainage/v1/vehicle/reportVehicleLocation") @ApiOperation(value = "上报车辆实时位置信息", notes = "流量接入-基础信息") @ApiImplicitParams({ @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header") }) public R<?> reportVehicleLocation(@RequestBody VehiclePositionDto dto){ xpVehicleService.reportVehicleLocation(dto); return R.ok(); } } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/VehiclePositionDto.java
New file @@ -0,0 +1,61 @@ package com.xiaopeng.vehicleConvoy.model.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; import org.springframework.data.mongodb.core.index.GeoSpatialIndexed; @Data @ApiModel("车辆位置信息") public class VehiclePositionDto { /** * 车辆VIN */ @ApiModelProperty(value = "车辆VIN") private String vin; /** * 车辆实时位置信息 */ @ApiModelProperty(value = "车辆经度") private Double longitude; @ApiModelProperty(value = "车辆纬度") private Double latitude; /** * 航向,单位:度,北零顺时针。范围:[0-360)。0 => 北, 90 => 东, 180 => 南, 270 => 西 */ @ApiModelProperty("车头北向夹角") private Double course; /** * 海拔 单位米 */ @ApiModelProperty("车辆海拔") private Float alt; /** * 当前速度 */ @ApiModelProperty("车辆速度") private Float speed; /** * 当前电量 */ @ApiModelProperty("车辆电量") private Integer currentElectricity; /** * 综合续航 */ @ApiModelProperty("车辆综合续航") private Float mileageRange; /** * 订单id */ @ApiModelProperty("订单id") private Long orderId; /** * 总里程 */ @ApiModelProperty("总里程") private Long totalOdometer; } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IXpVehicleService.java
@@ -5,12 +5,15 @@ import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.operation.VehiclePositionVo; import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.vehicleConvoy.model.dto.*; import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel; import com.xiaopeng.vehicleConvoy.model.query.*; import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO; import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @@ -243,4 +246,11 @@ * @return */ VehicleDoorStatusVo getVehicleDoorStatus(Long orderId); /** * 上报车辆实时位置 * @param dto */ void reportVehicleLocation(VehiclePositionDto dto); } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -38,6 +38,7 @@ import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.operation.VehiclePositionVo; import com.xiaopeng.api.vo.vehicleConvoy.*; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.domain.R; @@ -54,6 +55,7 @@ import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel; import com.xiaopeng.vehicleConvoy.model.query.*; import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO; import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto; import com.xiaopeng.vehicleConvoy.service.AsyncVehicleStateService; import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService; import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService; @@ -70,6 +72,7 @@ import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -1446,4 +1449,43 @@ vo.setTrunk(trunk_ajar_st_new == 5 ? 1 : 0); return vo; } /** * 上报车辆实时位置 * @param dto */ @Override public void reportVehicleLocation(VehiclePositionDto dto) { if(StringUtils.isEmpty(dto.getVin())){ throw new ServiceException("无效数据"); } if(null == dto.getLatitude() || null == dto.getLongitude()){ throw new ServiceException("无效数据"); } XpVehicle vehicle = this.getOne(new QueryWrapper<XpVehicle>().eq("vehicle_vin", dto.getVin()).eq("is_deleted", 0)); if(null == vehicle){ throw new ServiceException("无效数据"); } VehiclePosition vehiclePosition = mongoTemplate.findOne(Query.query(Criteria.where("vin").is(dto.getVin())), VehiclePosition.class); if(null == vehiclePosition){ BeanUtil.copyProperties(dto, vehiclePosition); vehiclePosition.setPoint(new GeoJsonPoint(dto.getLongitude(), dto.getLatitude())); vehiclePosition.setAddTime(System.currentTimeMillis()); mongoTemplate.save(vehiclePosition); }else{ Update update = new Update() .set("point", new GeoJsonPoint(dto.getLongitude(), dto.getLatitude())) .set("course", dto.getCourse()) .set("alt", dto.getAlt()) .set("speed", dto.getSpeed()) .set("currentElectricity", dto.getCurrentElectricity()) .set("mileageRange", dto.getMileageRange()) .set("orderId", dto.getOrderId()) .set("totalOdometer", dto.getTotalOdometer()) .set("addTime", System.currentTimeMillis()); mongoTemplate.updateFirst(new Query(Criteria.where("vin").is(dto.getVin())), update, VehiclePosition.class); } } }