| | |
| | | import com.xiaopeng.api.dto.account.UseUserCouponDto; |
| | | import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; |
| | | import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO; |
| | | import com.xiaopeng.api.dto.map.OrderRouteAndFareDto; |
| | | import com.xiaopeng.api.dto.operation.CruisePointDto; |
| | | import com.xiaopeng.api.dto.operation.LonLatDto; |
| | | import com.xiaopeng.api.dto.order.GetOrderNumDto; |
| | |
| | | import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; |
| | | import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient; |
| | | import com.xiaopeng.api.feignClient.maintenance.XpTaskRuleClient; |
| | | import com.xiaopeng.api.feignClient.map.XpMapClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpPointClient; |
| | | import com.xiaopeng.api.feignClient.operation.XpPricingClient; |
| | |
| | | import com.xiaopeng.common.core.constant.Constants; |
| | | import com.xiaopeng.common.core.constant.HttpStatus; |
| | | import com.xiaopeng.common.core.domain.R; |
| | | 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.exception.ServiceException; |
| | |
| | | import com.xiaopeng.order.model.query.XpOrderExcelQuery; |
| | | import com.xiaopeng.order.model.query.XpOrderPageQuery; |
| | | import com.xiaopeng.order.model.vo.*; |
| | | import com.xiaopeng.order.service.IXpOrderCancelService; |
| | | import com.xiaopeng.order.service.IXpOrderEvaluateService; |
| | | import com.xiaopeng.order.service.IXpOrderReassignService; |
| | | import com.xiaopeng.order.service.IXpOrderService; |
| | | import com.xiaopeng.order.service.*; |
| | | import com.xiaopeng.order.utils.GDMapGeocodingUtil; |
| | | import com.xiaopeng.order.utils.TaxiPricingDemoService; |
| | | import com.xiaopeng.order.utils.RegionCodeFilterUtil; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.SimpleDateFormat; |
| | |
| | | @RequiredArgsConstructor(onConstructor_ = @Lazy) |
| | | public class XpOrderServiceImpl extends ServiceImpl<XpOrderMapper, XpOrder> implements IXpOrderService { |
| | | |
| | | private static final String REASSIGN_CANCEL_CONTEXT_PREFIX = "REASSIGN_CANCEL_CONTEXT:"; |
| | | private static final long REASSIGN_CANCEL_CONTEXT_TTL_MINUTES = 5L; |
| | | |
| | | private final UserResourcesClient userResourcesClient; |
| | | private final XpPointClient xpPointClient; |
| | | private final XpVehicleClient xpVehicleClient; |
| | |
| | | private final XpPricingUtil xpPricingUtil; |
| | | private final GDMapGeocodingUtil gdMapGeocodingUtil; |
| | | private final VehicleBuriedPointClient vehicleBuriedPointClient; |
| | | private final IXpTestOrderService xpTestOrderService; |
| | | private final XpMapClient xpMapClient; |
| | | |
| | | |
| | | @Autowired |
| | |
| | | vo.setEndAddress(order.getEndAddress()); |
| | | vo.setOrderMoney(order.getOrderMoney()); |
| | | vo.setStatus(order.getStatus()); |
| | | vo.setStartPointName(order.getStartPointName()); |
| | | vo.setEndPointName(order.getEndPointName()); |
| | | |
| | | // 用户信息 |
| | | if (Objects.nonNull(order.getAppUserId()) && userInfoMap != null && userInfoMap.containsKey(order.getAppUserId().toString())) { |
| | |
| | | vehicle1.setId(vehicle.getId()); |
| | | vehicle1.setState(0); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("管理后台取消订单,车辆状态修改0 {}", vehicle.getPlateNumber()); |
| | | } |
| | | } |
| | | } |
| | |
| | | // 1. 更新订单状态为已取消(0) |
| | | lambdaUpdate().set(XpOrder::getStatus, 0) |
| | | .eq(XpOrder::getId, order.getId()).update(); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 0, 24L, TimeUnit.HOURS); |
| | | |
| | | // 2. 保存取消记录 |
| | | XpOrderCancel orderCancel = new XpOrderCancel(); |
| | |
| | | vehicle1.setId(xpVehicle.getId()); |
| | | vehicle1.setState(0); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("管理后台取消订单,车辆状态修改0 {}", xpVehicle.getPlateNumber()); |
| | | } |
| | | |
| | | // 下发命令 |
| | |
| | | Long appUserId = order.getAppUserId(); |
| | | order.setAppUserId(null); |
| | | this.updateById(order); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 7, 24L, TimeUnit.HOURS); |
| | | |
| | | // 消息推送 |
| | | Map<String, Object> params1 = new HashMap<>(); |
| | |
| | | } |
| | | XpVehicle newVehicle = vehicleResult.getData().get(0); |
| | | |
| | | // 5. 校验新车辆的运营状态 |
| | | // 车辆状态:1=待完善 2=待运营 3=保险/年检过期 |
| | | // 运营状态:1=运营中 2=维修中 3=已收车 4=车辆异常 |
| | | // 当前模式:1=接单 2=测试 |
| | | // 模式状态:1=开始接单/开始测试 2=停止接单/停止测试 |
| | | if (Objects.isNull(newVehicle.getStatus()) || newVehicle.getStatus() == 3) { |
| | | throw new ServiceException("新车辆保险或年检已过期,无法接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_STATUS_INVALID); |
| | | } |
| | | if (Objects.isNull(newVehicle.getOperatingStatus()) || newVehicle.getOperatingStatus() != 1) { |
| | | throw new ServiceException("新车辆运营状态异常,无法接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_OPERATING_STATUS_INVALID); |
| | | } |
| | | if (Objects.isNull(newVehicle.getAcceptOrTest()) || newVehicle.getAcceptOrTest() != 1) { |
| | | throw new ServiceException("新车辆当前不在接单模式", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_NOT_IN_ACCEPT_MODE); |
| | | } |
| | | if (Objects.isNull(newVehicle.getAcceptOrTestStatus()) || newVehicle.getAcceptOrTestStatus() != 1) { |
| | | throw new ServiceException("新车辆未开始接单", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_NOT_START_ACCEPT); |
| | | } |
| | | if (Objects.isNull(newVehicle.getState()) || newVehicle.getState() != 0) { |
| | | throw new ServiceException("新车辆已接单,请重新选择", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_NOT_FREE); |
| | | } |
| | |
| | | |
| | | // 6.1.1 取消原订单指令 |
| | | PushOrderDto cancelDto = new PushOrderDto(); |
| | | cancelDto.setTaskId(IdUtil.getSnowflakeNextIdStr()); |
| | | cancelDto.setOrderId(order.getId().toString()); |
| | | cancelDto.setVin(oldVehicle.getVehicleVin()); |
| | | cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); |
| | | cancelDto.setCancelScene(CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode()); |
| | | orderMissionClient.cancelOrder(cancelDto); |
| | | log.info("已取消原车辆订单指令,订单ID: {}, VIN: {}", orderId, oldVehicle.getVehicleVin()); |
| | | cacheReassignCancelContext(orderId, oldVehicleId, newVehicleId, |
| | | oldVehicle.getVehicleVin(), currentStatus); |
| | | log.info("已取消原车辆订单指令,订单ID: {}, VIN: {}, taskId: {}, cancelScene: {}", |
| | | orderId, oldVehicle.getVehicleVin(), cancelDto.getTaskId(), cancelDto.getCancelScene()); |
| | | |
| | | // 6.1.2 解绑乘客与原车辆关系 |
| | | if (Objects.nonNull(order.getAppUserId())) { |
| | |
| | | vehicle1.setId(oldVehicle.getId()); |
| | | vehicle1.setState(0); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("管理后台改派订单,车辆状态修改0 {}", oldVehicle.getPlateNumber()); |
| | | log.info("已将原车辆状态设为空闲,车辆ID: {}", oldVehicleId); |
| | | |
| | | // 6.1.4 为原车辆创建返程巡游订单 |
| | |
| | | if (Objects.nonNull(newFleetId)) { |
| | | order.setFleetId(newFleetId); |
| | | } |
| | | //重置订单状态为【待接单】 |
| | | order.setStatus(1); |
| | | this.updateById(order); |
| | | |
| | | // 10. 保存改派记录 |
| | |
| | | vehicle1.setId(newVehicle.getId()); |
| | | vehicle1.setState(1); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("管理后台改派订单,车辆状态修改1 {}", newVehicle.getPlateNumber()); |
| | | log.info("已将新车辆状态设为已接单,车辆ID: {}", newVehicleId); |
| | | |
| | | //12.向小程序用户推送订单改派通知 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | Map<String, Object> content = new HashMap<>(); |
| | | content.put("orderId", order.getId().toString()); |
| | | content.put("status", order.getStatus()); |
| | | params.put("type", PushMessageTypeEnum.ORDER_REASSIGN.getDesc()); |
| | | params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content)); |
| | | params.put("timestamp", new Date().getTime() + ""); |
| | | String message = JSONObject.toJSONString(params); |
| | | SendMessageDTO sendMessageDTO = new SendMessageDTO(); |
| | | sendMessageDTO.setMessage(message); |
| | | sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId())); |
| | | xpPushMessageClient.sendStatus(sendMessageDTO); |
| | | } catch (Exception e) { |
| | | log.error("处理新车辆失败,车辆ID: {},错误: {}", newVehicleId, e.getMessage()); |
| | | } |
| | | |
| | | } |
| | | |
| | | private void cacheReassignCancelContext(Long orderId, Long oldVehicleId, Long newVehicleId, |
| | | String oldVehicleVin, Integer preReassignStatus) { |
| | | JSONObject context = new JSONObject(); |
| | | context.put("orderId", orderId); |
| | | context.put("oldVehicleId", oldVehicleId); |
| | | context.put("newVehicleId", newVehicleId); |
| | | context.put("oldVehicleVin", oldVehicleVin); |
| | | context.put("cancelScene", CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode()); |
| | | context.put("operationTime", System.currentTimeMillis()); |
| | | context.put("preReassignStatus", preReassignStatus); |
| | | redisService.setCacheObject(REASSIGN_CANCEL_CONTEXT_PREFIX + orderId, context.toJSONString(), |
| | | REASSIGN_CANCEL_CONTEXT_TTL_MINUTES, TimeUnit.MINUTES); |
| | | log.info("记录改派取消上下文成功,orderId: {}, oldVehicleId: {}, newVehicleId: {}, preReassignStatus: {}", |
| | | orderId, oldVehicleId, newVehicleId, preReassignStatus); |
| | | } |
| | | |
| | | /** |
| | |
| | | vehicle1.setId(vehicle.getId()); |
| | | vehicle1.setState(0); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("用户取消订单,车辆状态修改0 {}", vehicle.getPlateNumber()); |
| | | } |
| | | } |
| | | } |
| | |
| | | xpOrderCancel.setCancelReason("用户取消订单"); |
| | | xpOrderCancelService.save(xpOrderCancel); |
| | | |
| | | |
| | | // 设置当天的取消次数缓存 |
| | | Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + uid); |
| | | if (cacheObject == null) { |
| | | redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, 1); |
| | | } else { |
| | | Integer i = Integer.valueOf(cacheObject.toString()); |
| | | redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, i + 1); |
| | | } |
| | | |
| | | // 移除mongo数据 |
| | | xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString()); |
| | |
| | | vehicle1.setId(xpVehicle.getId()); |
| | | vehicle1.setState(0); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("用户取消订单,车辆状态修改0 {}", xpVehicle.getPlateNumber()); |
| | | } |
| | | |
| | | //下发XPU报文 |
| | |
| | | |
| | | // 移除mongo数据 |
| | | xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString()); |
| | | // 设置当天的取消次数缓存 |
| | | Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + appUserId); |
| | | if (cacheObject == null) { |
| | | redisService.setCacheCancelOrder("CANCEL_ORDER_" + appUserId, 1); |
| | | } else { |
| | | Integer i = Integer.valueOf(cacheObject.toString()); |
| | | redisService.setCacheCancelOrder("CANCEL_ORDER_" + appUserId, i + 1); |
| | | } |
| | | return order; |
| | | } |
| | | |
| | |
| | | case 6: |
| | | // 行程开始时间 |
| | | xpOrder.setTripBegin(LocalDateTime.now()); |
| | | redisService.deleteObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId()); |
| | | break; |
| | | case 7: |
| | | xpOrder.setGetoffTime(LocalDateTime.now()); |
| | |
| | | new ImmutableMap.Builder<String, String>() |
| | | .put("id", xpOrder.getId().toString()) |
| | | .put("appid", appid) |
| | | .put("orderType", OrderType.USER_ORDER) |
| | | .build(); |
| | | QuartzManager.addJob( |
| | | EndTripJob.class, |
| | |
| | | new ImmutableMap.Builder<String, String>() |
| | | .put("id", xpOrder.getId().toString()) |
| | | .put("appid", appid) |
| | | .put("orderType", OrderType.USER_ORDER) |
| | | .build(); |
| | | QuartzManager.addJob( |
| | | AddCruiseMissionJob.class, |
| | |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | //找到车辆的收车点位 更新终点点位 |
| | | R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder); |
| | | xpCruiseOrder = returnCruisePoint.getData(); |
| | | xpCruiseOrder.setOrderType(2); |
| | | xpCruiseOrder.setOrderReverse(1); |
| | | if(200 != returnCruisePoint.getCode()){ |
| | | xpCruiseOrder = returnCruisePoint.getData(); |
| | | xpCruiseOrder.setOrderType(2); |
| | | xpCruiseOrder.setOrderReverse(1); |
| | | } |
| | | } |
| | | } |
| | | xpCruiseOrderMapper.insert(xpCruiseOrder); |
| | |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | //找到车辆的收车点位 更新终点点位 |
| | | R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder); |
| | | xpCruiseOrder = returnCruisePoint.getData(); |
| | | xpCruiseOrder.setOrderType(2); |
| | | xpCruiseOrder.setOrderReverse(1); |
| | | if(200 != returnCruisePoint.getCode()){ |
| | | xpCruiseOrder = returnCruisePoint.getData(); |
| | | xpCruiseOrder.setOrderType(2); |
| | | xpCruiseOrder.setOrderReverse(1); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | public void saveVehicleLocation(OrderTrajectory orderTrajectory) { |
| | | // 查询订单信息 |
| | | Integer status = redisService.getCacheObject("ORDER_STATUS:" + orderTrajectory.getOrderId()); |
| | | if(status < 6){ |
| | | if(status < 6 || status > 8){ |
| | | return; |
| | | } |
| | | |
| | |
| | | vehicle1.setId(vehicle.getId()); |
| | | vehicle1.setState(1); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("推单成功后的处理逻辑,车辆状态修改1 {}", vehicle.getPlateNumber()); |
| | | |
| | | //绑定用户和车辆关系 |
| | | addTaxiPassengerVo.setUid(appUserId.toString()); |
| | | order.setAppUserId(null); |
| | | this.updateById(order); |
| | | redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 2, 24L, TimeUnit.HOURS); |
| | | |
| | | //构建推送消息 |
| | | Map<String, Object> params = new HashMap<>(); |
| | |
| | | addTaxiPassengerVo.setOrderNo(order.getOrderNumber()); |
| | | addTaxiPassengerVo.setAppId(appid); |
| | | userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); |
| | | |
| | | //生成前往上车点的导航数据 |
| | | //查询车辆位置 |
| | | VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(dto.getXpVehicleVin())), VehiclePosition.class); |
| | | if (Objects.isNull(vehiclePosition)) { |
| | | throw new RuntimeException("车辆位置信息不存在"); |
| | | } |
| | | |
| | | LonLatDto destination = new LonLatDto(); |
| | | LonLatDto origin = new LonLatDto(); |
| | | //查询司机当前位置到起点的线路 |
| | | origin.setLongitude(vehiclePosition.getPoint().getX()); |
| | | origin.setLatitude(vehiclePosition.getPoint().getY()); |
| | | destination.setLongitude(order.getStartLon()); |
| | | destination.setLatitude(order.getStartLat()); |
| | | |
| | | OrderRouteAndFareDto dto2 = new OrderRouteAndFareDto(); |
| | | dto2.setOrderId(orderId); |
| | | dto2.setOrigin(origin); |
| | | dto2.setDestination(destination); |
| | | dto2.setRouteType(1); |
| | | R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto2); |
| | | if (200 != routeVoR.getCode()) { |
| | | throw new RuntimeException("获取订单线路和运费失败"); |
| | | } |
| | | RouteVo routeVo = routeVoR.getData(); |
| | | //缓存数据,用于后续推给乘客导航线路 |
| | | redisService.setCacheObject("ORDER_NAVIGATION_START_DATA:" + appUserId, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS); |
| | | |
| | | //推送乘客车辆到达预约点的导航数据 |
| | | sendRoute(addTaxiPassengerVo.getUid(), orderId, "ORDER_NAVIGATION_START_DATA", dto.getXpVehicleVin()); |
| | | } |
| | |
| | | } |
| | | |
| | | } |
| | | //测试订单 |
| | | if (OrderType.TEST_ORDER.equals(orderType)) { |
| | | XpTestOrder xpTestOrder = xpTestOrderService.getById(orderId); |
| | | //订单为待接单状态 |
| | | if (xpTestOrder.getStatus() < 4) { |
| | | xpTestOrder.setAcceptanceTime(LocalDateTime.now()); |
| | | R<XpVehicle> byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin()); |
| | | XpVehicle vehicle = null; |
| | | if (byVehicleVin.getCode() == 200) { |
| | | vehicle = byVehicleVin.getData(); |
| | | xpTestOrder.setVehicleId(vehicle.getId()); |
| | | xpTestOrder.setFleetId(vehicle.getFleetId()); |
| | | } |
| | | xpTestOrder.setStatus(2); |
| | | |
| | | // 修改车辆信息 |
| | | XpVehicle vehicle1 = new XpVehicle(); |
| | | vehicle1.setId(vehicle.getId()); |
| | | vehicle1.setState(1); |
| | | xpVehicleClient.updateVehicleById(vehicle1); |
| | | log.info("推单成功后的处理逻辑,车辆状态修改1 {}", vehicle.getPlateNumber()); |
| | | |
| | | xpTestOrder.setStartTestPointId(null); |
| | | xpTestOrderService.updateById(xpTestOrder); |
| | | redisService.setCacheObject("TEST_ORDER_STATUS:" + xpTestOrder.getId(), 2, 24L, TimeUnit.HOURS); |
| | | } |
| | | } |
| | | if (OrderType.TEST_CRUISE_ORDER.equals(orderType)) { |
| | | XpTestOrder xpTestOrder = xpTestOrderService.getById(orderId); |
| | | //订单为待接单状态 |
| | | if (xpTestOrder.getStatus() < 4) { |
| | | xpTestOrder.setAcceptanceTime(LocalDateTime.now()); |
| | | R<XpVehicle> byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin()); |
| | | XpVehicle vehicle = null; |
| | | if (byVehicleVin.getCode() == 200) { |
| | | vehicle = byVehicleVin.getData(); |
| | | xpTestOrder.setVehicleId(vehicle.getId()); |
| | | xpTestOrder.setFleetId(vehicle.getFleetId()); |
| | | } |
| | | xpTestOrder.setStatus(6); |
| | | xpTestOrder.setStartTestPointId(null); |
| | | xpTestOrderService.updateById(xpTestOrder); |
| | | redisService.setCacheObject("TEST_ORDER_STATUS:" + xpTestOrder.getId(), 6, 24L, TimeUnit.HOURS); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |