package com.xiaopeng.order.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.ImmutableMap; import com.xiaopeng.api.dto.account.GetUserCouponDto; import com.xiaopeng.api.dto.account.UseUserCouponDto; import com.xiaopeng.api.dto.account.UserResourcesDto; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; import com.xiaopeng.api.dto.order.HistoryStartPointsDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; import com.xiaopeng.api.feignClient.account.UserResourcesClient; import com.xiaopeng.api.feignClient.account.XpAppUserClient; import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.operation.XpPointClient; import com.xiaopeng.api.feignClient.operation.XpPricingClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.account.XpAppUser; import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.api.model.operation.XpGeoQueryEntity; import com.xiaopeng.api.model.operation.XpPoint; import com.xiaopeng.api.model.operation.XpPricing; import com.xiaopeng.api.model.order.*; import com.xiaopeng.api.model.vehicleConvoy.XpFleet; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.OrderType; import com.xiaopeng.api.vo.account.GetUserListByUidsVo; import com.xiaopeng.api.vo.account.UserCouponVo; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.order.*; import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.HttpStatus; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.core.enums.PushMessageTypeEnum; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.DateUtils; import com.xiaopeng.common.core.utils.GeodesyUtil; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.domain.BaseModel; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.common.security.utils.SecurityUtils; import com.xiaopeng.order.constant.I18nKeyConstant; import com.xiaopeng.order.dto.MileageDto; import com.xiaopeng.order.job.base.QuartzManager; import com.xiaopeng.order.job.base.TimeJobType; import com.xiaopeng.order.job.jobs.EndTripJob; import com.xiaopeng.order.job.jobs.OrderCancelJob; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.mangodb.service.OrderTrajectoryService; import com.xiaopeng.order.mapper.XpCruiseOrderMapper; import com.xiaopeng.order.mapper.XpOrderDetailMapper; import com.xiaopeng.order.mapper.XpOrderMapper; import com.xiaopeng.order.model.dto.XpOrderCommentDto; import com.xiaopeng.order.model.dto.XpOrderPayDto; import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; 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.utils.TaxiPricingDemoService; import com.xiaopeng.order.utils.TrajectoryGenerator; import com.xiaopeng.order.utils.holiday.HolidayUtil; import com.xiaopeng.order.vo.OrderDetailVo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType; import org.apache.shardingsphere.transaction.core.TransactionType; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.*; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; /** *

* 订单 服务实现类 *

* * @author mitao * @since 2026-02-03 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) public class XpOrderServiceImpl extends ServiceImpl implements IXpOrderService { private final UserResourcesClient userResourcesClient; private final XpPointClient xpPointClient; private final XpVehicleClient xpVehicleClient; private final XpAppUserCouponClient xpAppUserCouponClient; private final XpFleetClient xpFleetClient; private final XpFleetVehicleClient xpFleetVehicleClient; private final UserVehicleClient userVehicleClient; private final IXpOrderEvaluateService xpOrderEvaluateService; private final IXpOrderCancelService xpOrderCancelService; private final IXpOrderReassignService xpOrderReassignService; private final RedisService redisService; private final XpPricingClient xpPricingClient; private final XpSystemSettingClient xpSystemSettingClient; private final OrderTrajectoryService orderTrajectoryService; private final XpPushMessageClient xpPushMessageClient; private final OrderMissionClient orderMissionClient; private final XpOrderDetailMapper xpOrderDetailMapper; private final XpCruiseOrderMapper xpCruiseOrderMapper; @Autowired private MongoTemplate mongoTemplate; @Autowired private HolidayUtil holidayUtil; // @Autowired // private XpPricingUtil xpPricingUtil; @Override public OrderStatisticsDTO getOrderStatistics(StatisticsQueryDTO query) { OrderStatisticsDTO dto = new OrderStatisticsDTO(); // 1. 查询订单总数(状态为9=待评价或10=已完成) dto.setTotalCount(baseMapper.countCompletedOrders()); // 2. 查询时间范围内新增订单数 if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) { dto.setNewCount(baseMapper.countNewOrders(query.getStartDate(), query.getEndDate())); } else { dto.setNewCount(0L); } // 3. 查询总交易金额和总收入(pay_money累加) BigDecimal totalMoney = baseMapper.sumTotalMoney(); dto.setTotalMoney(Objects.nonNull(totalMoney) ? totalMoney : BigDecimal.ZERO); dto.setTotalIncome(Objects.nonNull(totalMoney) ? totalMoney : BigDecimal.ZERO); // 4. 查询近N天每日新增订单数(默认30天) Integer trendDays = Objects.nonNull(query.getTrendDays()) ? query.getTrendDays() : 30; LocalDate endDate = LocalDate.now(); LocalDate startDate = endDate.minusDays(trendDays - 1); List dailyCountList = baseMapper.getDailyOrderCount(startDate, endDate); dto.setDailyCountList(Objects.nonNull(dailyCountList) ? dailyCountList : new ArrayList<>()); return dto; } @Override public PageInfo pageList(XpOrderPageQuery query) { // 1. 构建查询条件 LambdaQueryWrapper wrapper = buildQueryWrapper(query); wrapper.orderByDesc(XpOrder::getCreateTime); // 2. 分页查询 Page page = new Page<>(query.getPageNum(), query.getPageSize()); Page pageResult = this.page(page, wrapper); if (CollectionUtils.isEmpty(pageResult.getRecords())) { PageInfo resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize()); resultPage.setTotal(0L); resultPage.setRecords(new ArrayList<>()); return resultPage; } // 3. 收集关联ID Set userIds = new HashSet<>(); Set vehicleIds = new HashSet<>(); Set fleetIds = new HashSet<>(); for (XpOrder order : pageResult.getRecords()) { if (Objects.nonNull(order.getAppUserId())) { userIds.add(order.getAppUserId()); } if (Objects.nonNull(order.getVehicleId())) { vehicleIds.add(order.getVehicleId()); } if (Objects.nonNull(order.getFleetId())) { fleetIds.add(order.getFleetId()); } } // 4. 批量查询关联数据 JSONObject jsonObject = batchGetUsers(userIds); Map vehicleMap = batchGetVehicles(vehicleIds); Map fleetMap = batchGetFleets(fleetIds); // 5. 组装 VO List voList = pageResult.getRecords().stream() .map(order -> convertToPageVO(order, jsonObject, vehicleMap, fleetMap)) .collect(Collectors.toList()); // 6. 返回分页结果 PageInfo resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize()); resultPage.setTotal(pageResult.getTotal()); resultPage.setRecords(voList); return resultPage; } @Override public XpOrderDetailVO getOrderDetail(Long id) { // 1. 查询订单基础信息 XpOrder order = this.getById(id); if (order == null) { throw new ServiceException("订单不存在"); } // 2. 转换为详情 VO XpOrderDetailVO vo = BeanUtil.toBean(order, XpOrderDetailVO.class); // 3. 获取用户信息 if (Objects.nonNull(order.getAppUserId())) { JSONObject jsonObject = batchGetUsers(Collections.singleton(order.getAppUserId())); JSONObject userInfo = jsonObject.getJSONObject(order.getAppUserId().toString()); if (Objects.nonNull(userInfo)) { vo.setNickName(userInfo.getString("nickName")); vo.setPhoneNumber(userInfo.getString("mobile")); } } // 4. 获取车辆信息 if (Objects.nonNull(order.getVehicleId())) { Map vehicleMap = batchGetVehicles(Collections.singleton(order.getVehicleId())); XpVehicle vehicle = vehicleMap.get(order.getVehicleId()); if (Objects.nonNull(vehicle)) { vo.setPlateNumber(vehicle.getPlateNumber()); vo.setVehicleModel(vehicle.getVehicleModel()); } } // 5. 获取车队信息 if (Objects.nonNull(order.getFleetId())) { Map fleetMap = batchGetFleets(Collections.singleton(order.getFleetId())); XpFleet fleet = fleetMap.get(order.getFleetId()); if (Objects.nonNull(fleet)) { vo.setFleetName(fleet.getFleetName()); } } // 6. 获取评价信息 LambdaQueryWrapper evaluateWrapper = new LambdaQueryWrapper<>(); evaluateWrapper.eq(XpOrderEvaluate::getOrderId, id); XpOrderEvaluate evaluate = xpOrderEvaluateService.getOne(evaluateWrapper); if (Objects.nonNull(evaluate)) { vo.setOrderRating(evaluate.getOrderRating()); } //TODO 7.查询mongodb 该订单上传的经纬度轨迹信息 vo.setOrderPositionList(new ArrayList<>()); return vo; } @Override public void deleteOrder(Long id) { // 1. 校验订单是否存在 XpOrder order = this.getById(id); if (Objects.isNull(order)) { throw new ServiceException("订单不存在", I18nKeyConstant.ORDER_NOT_EXISTS); } this.removeById(id); } @Override public List exportList(XpOrderPageQuery query) { // 1. 构建查询条件 LambdaQueryWrapper wrapper = buildQueryWrapper(query); // 2. 查询订单列表 List orderList = this.list(wrapper); if (CollectionUtils.isEmpty(orderList)) { return new ArrayList<>(); } // 3. 收集关联ID Set userIds = new HashSet<>(); Set vehicleIds = new HashSet<>(); Set fleetIds = new HashSet<>(); for (XpOrder order : orderList) { if (Objects.nonNull(order.getAppUserId())) { userIds.add(order.getAppUserId()); } if (Objects.nonNull(order.getVehicleId())) { vehicleIds.add(order.getVehicleId()); } if (Objects.nonNull(order.getFleetId())) { fleetIds.add(order.getFleetId()); } } // 4. 批量查询关联数据 JSONObject jsonObject = batchGetUsers(userIds); Map vehicleMap = batchGetVehicles(vehicleIds); Map fleetMap = batchGetFleets(fleetIds); // 5. 组装 VO return orderList.stream() .map(order -> convertToPageVO(order, jsonObject, vehicleMap, fleetMap)) .collect(Collectors.toList()); } /** * 构建查询条件 */ private LambdaQueryWrapper buildQueryWrapper(XpOrderPageQuery query) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(query.getOrderNumber()), XpOrder::getOrderNumber, query.getOrderNumber()) .eq(Objects.nonNull(query.getFleetId()), XpOrder::getFleetId, query.getFleetId()) .eq(Objects.nonNull(query.getOrderSource()), XpOrder::getOrderSource, query.getOrderSource()) .like(StringUtils.isNotBlank(query.getCityCode()), XpOrder::getCityCode, query.getCityCode()) .eq(Objects.nonNull(query.getStatus()), XpOrder::getStatus, query.getStatus()); if (Objects.nonNull(query.getStartTime())) { wrapper.ge(XpOrder::getCreateTime, LocalDateTime.of(query.getStartTime(), LocalTime.MIN)); } if (Objects.nonNull(query.getEndTime())) { wrapper.ge(XpOrder::getCreateTime, LocalDateTime.of(query.getEndTime(), LocalTime.MAX)); } wrapper.orderByDesc(XpOrder::getCreateTime); return wrapper; } /** * 批量获取用户信息 */ private JSONObject batchGetUsers(Set userIds) { if (CollectionUtils.isEmpty(userIds)) { return new JSONObject(); } try { GetUserListByUidsVo getUserListByUidsVo = new GetUserListByUidsVo(); getUserListByUidsVo.setUids(new ArrayList<>(userIds)); getUserListByUidsVo.setGetPreCarOwner(Boolean.TRUE); UserResourcesDto userListByUids = userResourcesClient.getUserListByUids(getUserListByUidsVo); if (userListByUids.getCode().equals(HttpStatus.SUCCESS)) { return JSONObject.parseObject(userListByUids.getData().toString()); } } catch (Exception e) { log.error("批量获取用户信息失败: {}", e.getMessage()); } return new JSONObject(); } /** * 批量获取车辆信息 */ private Map batchGetVehicles(Set vehicleIds) { if (CollectionUtils.isEmpty(vehicleIds)) { return new HashMap<>(); } try { R> result = xpVehicleClient.listByIds(new ArrayList<>(vehicleIds)); if (Objects.nonNull(result) && Objects.nonNull(result.getData())) { return result.getData().stream() .collect(Collectors.toMap(XpVehicle::getId, Function.identity(), (a, b) -> a)); } } catch (Exception e) { log.error("批量获取车辆信息失败: {}", e.getMessage()); } return new HashMap<>(); } /** * 批量获取车队信息 */ private Map batchGetFleets(Set fleetIds) { if (CollectionUtils.isEmpty(fleetIds)) { return new HashMap<>(); } try { R> result = xpFleetClient.listByIds(new ArrayList<>(fleetIds)); if (Objects.nonNull(result) && Objects.nonNull(result.getData())) { return result.getData().stream() .collect(Collectors.toMap(XpFleet::getId, Function.identity(), (a, b) -> a)); } } catch (Exception e) { log.error("批量获取车队信息失败: {}", e.getMessage()); } return new HashMap<>(); } @Transactional(rollbackFor = Exception.class) @Override public void cancelOrCloseOrder(Long orderId, Integer type) { // 1. 校验订单是否存在 XpOrder order = this.getById(orderId); if (Objects.isNull(order)) { throw new ServiceException("订单不存在"); } // 2. 校验操作类型 if (type != 1 && type != 2) { throw new ServiceException("操作类型错误,type只能为1或2"); } // 3. 校验订单状态是否允许操作 Integer currentStatus = order.getStatus(); //取消订单:在未接到乘客前都可以,关闭订单,在送达目的地可以操作关闭 if (type == 1) { // 取消订单:只有待接单(1)、待出发(2)、接驾中(3)状态可以取消 if (currentStatus != 1 && currentStatus != 2 && currentStatus != 3) { throw new ServiceException("当前订单状态不允许取消,只有待接单、待出发、接驾中状态的订单可以取消", I18nKeyConstant.ORDER_CANCEL_FAILED); } } else { // 关闭订单:只有待付款(8)、待评价(9)状态可以关闭 if (currentStatus != 7 && currentStatus != 8 && currentStatus != 9) { throw new ServiceException("当前订单状态不允许关闭,只有待付款、待评价状态的订单可以关闭", I18nKeyConstant.ORDER_CLOSE_FAILED); } } // 4. 执行操作 if (type == 1) { // 取消订单 cancelOrder(order); } else { // 关闭订单 closeOrder(order); } } /** * 转换为分页列表 VO */ private XpOrderPageVO convertToPageVO(XpOrder order, JSONObject jsonObject, Map vehicleMap, Map fleetMap) { XpOrderPageVO vo = new XpOrderPageVO(); vo.setId(order.getId()); vo.setOrderNumber(order.getOrderNumber()); vo.setCreateTime(order.getCreateTime()); vo.setOrderSource(order.getOrderSource()); vo.setRideTime(order.getRideTime()); vo.setStartAddress(order.getStartAddress()); vo.setEndAddress(order.getEndAddress()); vo.setOrderMoney(order.getOrderMoney()); vo.setStatus(order.getStatus()); // 用户信息 if (Objects.nonNull(order.getAppUserId()) && jsonObject.containsKey(order.getAppUserId().toString())) { JSONObject userInfo = jsonObject.getJSONObject(order.getAppUserId().toString()); vo.setNickName(userInfo.getString("nickName")); vo.setPhoneNumber(userInfo.getString("mobile")); } // 车辆信息 if (Objects.nonNull(order.getVehicleId()) && vehicleMap.containsKey(order.getVehicleId())) { XpVehicle vehicle = vehicleMap.get(order.getVehicleId()); vo.setPlateNumber(vehicle.getPlateNumber()); vo.setVehicleModel(vehicle.getVehicleModel()); } // 车队信息 if (Objects.nonNull(order.getFleetId()) && fleetMap.containsKey(order.getFleetId())) { XpFleet fleet = fleetMap.get(order.getFleetId()); vo.setFleetName(fleet.getFleetName()); } return vo; } /** * 取消订单 */ private void cancelOrder(XpOrder order) { // 1. 更新订单状态为已取消(0) order.setStatus(0); this.updateById(order); // 2. 保存取消记录 XpOrderCancel orderCancel = new XpOrderCancel(); orderCancel.setOrderId(order.getId()); orderCancel.setCancelSource(3); // 3=运营人员(后台管理接口固定为运营人员) orderCancel.setUserId(SecurityUtils.getUserId()); // 当前登录用户ID orderCancel.setCancelReason("运营人员取消订单"); orderCancel.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); xpOrderCancelService.save(orderCancel); log.info("订单取消成功,订单ID: {}, 操作人: {}", order.getId(), SecurityUtils.getUsername()); } /** * 关闭订单 */ private void closeOrder(XpOrder order) { // 更新订单状态为已完成(10) order.setStatus(10); this.updateById(order); log.info("订单关闭成功,订单ID: {}, 操作人: {}", order.getId(), SecurityUtils.getUsername()); } /** * 改派订单 */ @Transactional(rollbackFor = Exception.class) @Override public void reassignOrder(Long orderId, Long newVehicleId, String reassignReason) { // 1. 校验订单是否存在 XpOrder order = this.getById(orderId); if (Objects.isNull(order)) { throw new ServiceException("订单不存在"); } // 2. 校验订单状态(只有待接单、待出发、接驾中状态可以改派) Integer currentStatus = order.getStatus(); if (currentStatus != 1 && currentStatus != 2 && currentStatus != 3) { throw new ServiceException("当前订单状态不允许改派,只有待接单、待出发、接驾中状态的订单可以改派", I18nKeyConstant.ORDER_REASSIGN_FAILED); } // 3. 校验新旧车辆是否相同 if (Objects.equals(order.getVehicleId(), newVehicleId)) { throw new ServiceException("新车辆与原车辆相同,无需改派", I18nKeyConstant.ORDER_REASSIGN_VEHICLE_FAILED); } // 4. 查询新车辆信息并校验 R> vehicleResult = xpVehicleClient.listByIds(Collections.singletonList(newVehicleId)); if (Objects.isNull(vehicleResult) || Objects.isNull(vehicleResult.getData()) || vehicleResult.getData().isEmpty()) { throw new ServiceException("新车辆不存在", I18nKeyConstant.ORDER_REASSIGN_NEW_VEHICLE_NOT_EXISTS); } 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. 保存原车辆和车队信息 Long oldVehicleId = order.getVehicleId(); Long oldFleetId = order.getFleetId(); // 7. 查询新车辆关联的车队ID Long newFleetId = null; try { R fleetIdResult = xpFleetVehicleClient.getFleetIdByVehicleId(newVehicleId); if (Objects.nonNull(fleetIdResult) && Objects.nonNull(fleetIdResult.getData())) { newFleetId = fleetIdResult.getData(); log.info("查询到新车辆ID: {} 关联的车队ID: {}", newVehicleId, newFleetId); } else { log.warn("新车辆ID: {} 未关联任何车队,将使用原车队ID: {}", newVehicleId, oldFleetId); newFleetId = oldFleetId; } } catch (Exception e) { log.error("查询新车辆关联的车队ID失败,车辆ID: {},错误: {}", newVehicleId, e.getMessage()); newFleetId = oldFleetId; } // 8. 如果旧订单的车队ID为空,尝试查询旧车辆的车队ID if (Objects.isNull(oldFleetId) && Objects.nonNull(oldVehicleId)) { try { R oldFleetIdResult = xpFleetVehicleClient.getFleetIdByVehicleId(oldVehicleId); if (Objects.nonNull(oldFleetIdResult) && Objects.nonNull(oldFleetIdResult.getData())) { oldFleetId = oldFleetIdResult.getData(); log.info("补充查询到旧车辆ID: {} 关联的车队ID: {}", oldVehicleId, oldFleetId); } } catch (Exception e) { log.warn("查询旧车辆关联的车队ID失败,车辆ID: {},错误: {}", oldVehicleId, e.getMessage()); } } // 9. 更新订单的车辆和车队信息 order.setVehicleId(newVehicleId); if (Objects.nonNull(newFleetId)) { order.setFleetId(newFleetId); } this.updateById(order); // 10. 保存改派记录 XpOrderReassign orderReassign = new XpOrderReassign(); orderReassign.setOrderId(orderId); orderReassign.setUserId(SecurityUtils.getUserId()); orderReassign.setOperationTime(LocalDateTime.now()); orderReassign.setOldVehicleId(oldVehicleId); orderReassign.setNewVehicleId(newVehicleId); orderReassign.setOldFleetId(oldFleetId); orderReassign.setNewFleetId(newFleetId); orderReassign.setReassignReason( StringUtils.isNotBlank(reassignReason) ? reassignReason : "运营人员改派订单" ); orderReassign.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); xpOrderReassignService.save(orderReassign); log.info("订单改派成功,订单ID: {}, 原车辆ID: {}, 新车辆ID: {}, 原车队ID: {}, 新车队ID: {}, 操作人: {}", orderId, oldVehicleId, newVehicleId, oldFleetId, newFleetId, SecurityUtils.getUsername()); //推送消息 } @Override public XpPointInfoVo getUserQuickCapsule(String uid) { try { // 使用Redis的sorted set(排行榜)获取第一个元素 // 获取分数最高的元素(默认按分数从高到低排序) Set result = redisService.redisTemplate.opsForZSet().reverseRange("history_order_" + uid, 0, 0); if (result != null && !result.isEmpty()) { // 排行榜中存储的是JSON字符串 String jsonString = result.iterator().next().toString(); // 使用Hutool的JSON工具解析为XpPointInfoVo对象 return JSONUtil.toBean(jsonString, XpPointInfoVo.class); } } catch (Exception e) { log.error("获取用户快捷胶囊失败: {}", e.getMessage(), e); } return null; } @Override public List getHistoryStartPoints(String uid, double lon, double lat) { // List xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper().eq(XpOrder::getAppUserId, Long.parseLong(uid)).orderByDesc(BaseModel::getCreateTime).last("LIMIT 10")); if (xpOrders.isEmpty()) { return Collections.emptyList(); } // 获取点位信息 List startPointsIds = xpOrders.stream().map(XpOrder::getStartPointId).collect(Collectors.toList()); R> r = xpPointClient.getHistoryStartPoints(new HistoryStartPointsDto(startPointsIds, lon, lat)); return r.getData(); } @Override public List getHistoryEndPoints(String uid, double lon, double lat) { // List xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper().eq(XpOrder::getAppUserId, Long.parseLong(uid)).orderByDesc(BaseModel::getCreateTime).last("LIMIT 10")); if (xpOrders.isEmpty()) { return Collections.emptyList(); } // 获取点位信息 List endPointsIds = xpOrders.stream().map(XpOrder::getEndPointId).collect(Collectors.toList()); R> r = xpPointClient.getHistoryEndPoints(new HistoryEndPointsDto(endPointsIds, lon, lat)); return r.getData(); } /** * 获取历史订单列表 * * @param query * @param uid * @return */ @Override public XpOrderHistoryVO getHistoryOrderList(XpHistoryOrderListQuery query, String uid) { Page page = new Page<>(query.getPageNum(), query.getPageSize()); List list = this.baseMapper.getHistoryOrderList(page, query, Long.parseLong(uid)); XpOrderHistoryVO xpOrderHistoryVO = new XpOrderHistoryVO(); xpOrderHistoryVO.setTotal((int) page.getTotal()); // 根据time分组 Map> map = list.stream().collect(Collectors.groupingBy(XpOrderHistoryListVO::getOrderTime)); List dateVOS = map.entrySet().stream().map(entry -> { XpOrderHistoryDateVO xpOrderHistoryDateVO = new XpOrderHistoryDateVO(); xpOrderHistoryDateVO.setDateLabel(entry.getKey()); List value = entry.getValue(); value = value.stream().sorted(Comparator.comparing(XpOrderHistoryListVO::getTime).reversed()).collect(Collectors.toList()); xpOrderHistoryDateVO.setOrders(value); return xpOrderHistoryDateVO; }).collect(Collectors.toList()); xpOrderHistoryVO.setList(dateVOS); return xpOrderHistoryVO; } /** * 取消订单 * * @param orderId * @param uid */ @Override @Transactional public void cancelOrder(Long orderId, String uid) { XpOrder order = this.getById(orderId); if (order == null) { throw new ServiceException("订单不存在",I18nKeyConstant.ORDER_NOT_EXISTS); } if (!order.getAppUserId().toString().equals(uid)) { throw new ServiceException("订单不存在",I18nKeyConstant.ORDER_NOT_EXISTS); } if (order.getStatus() > 5 || order.getStatus() < 1) { throw new ServiceException("订单状态错误",I18nKeyConstant.ORDER_STATUS_ERROR); } order.setStatus(0); // 组装调用车机参数 CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); Long vehicleId = order.getVehicleId(); R xpVehicleR = xpVehicleClient.queryById(vehicleId); XpVehicle xpVehicle = xpVehicleR.getData(); if (xpVehicle == null) { throw new ServiceException("车辆不存在",I18nKeyConstant.VEHICLE_NOT_EXISTS); } cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(order.getAppUserId().toString()); cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(""); BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); if (baseVehicleUserDto==null) { // TODO 本地无法调通 // throw new RuntimeException("取消订单失败"); } order.setAppUserId(null); baseMapper.updateById(order); XpOrderCancel xpOrderCancel = new XpOrderCancel(); xpOrderCancel.setOrderId(orderId); xpOrderCancel.setUserId(Long.valueOf(uid)); xpOrderCancel.setCancelSource(1); 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); } // 下发命令 if(order.getStatus()>1){ PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.VEHICLE_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } } @Override @Transactional public void cancelOrder(String orderId) { XpOrder order = this.getById(orderId); if (order == null) { throw new ServiceException("订单不存在",I18nKeyConstant.ORDER_NOT_EXISTS); } order.setStatus(0); baseMapper.updateById(order); XpOrderCancel xpOrderCancel = new XpOrderCancel(); xpOrderCancel.setOrderId(Long.valueOf(orderId)); xpOrderCancel.setUserId(1l); xpOrderCancel.setCancelSource(4); xpOrderCancel.setCancelReason("系统取消订单"); xpOrderCancel.setCreateTime(LocalDateTime.now()); xpOrderCancelService.save(xpOrderCancel); R xpVehicleR = xpVehicleClient.queryById(order.getVehicleId()); XpVehicle xpVehicle = xpVehicleR.getData(); // 消息推送 Map params = new HashMap<>(); Map content = new HashMap<>(); content.put("orderId", order.getId()); content.put("status", OrderStatusEnum.CANCELED.getCode()); params.put("type", PushMessageTypeEnum.ORDER_STATUS.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); log.info("订单取消消息推送完毕"); // 下发命令 if(order.getStatus()>1){ PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } } /** * 评价订单 * * @param dto * @param uid */ @Override @Transactional public void comment(XpOrderCommentDto dto, String uid) { XpOrder xpOrder = this.getById(dto.getOrderId()); if (xpOrder == null) { throw new ServiceException("订单不存在",I18nKeyConstant.ORDER_NOT_EXISTS); } if (!xpOrder.getAppUserId().toString().equals(uid)) { throw new ServiceException("订单不存在",I18nKeyConstant.ORDER_NOT_EXISTS); } if (xpOrder.getStatus() != 9) { throw new ServiceException("订单状态错误",I18nKeyConstant.ORDER_STATUS_ERROR); } xpOrder.setAppUserId(null); xpOrder.setStatus(10); baseMapper.updateById(xpOrder); XpOrderEvaluate evaluate = new XpOrderEvaluate(); evaluate.setOrderId(xpOrder.getId()); evaluate.setVehicleId(xpOrder.getVehicleId()); evaluate.setAppUserId(Long.valueOf(uid)); evaluate.setOrderRating(dto.getOrderRating()); evaluate.setEvaluateTime(LocalDateTime.now()); evaluate.setFeedbackContent(dto.getFeedbackContent()); evaluate.setFeedbackPictures(dto.getFeedbackPictures()); evaluate.setFeedbackTypeId(dto.getFeedbackTypeId()); evaluate.setCreateTime(LocalDateTime.now()); xpOrderEvaluateService.save(evaluate); } @Override public R updateOrderStatus(Long orderId, Integer status) { XpOrder xpOrder = this.getById(orderId); if (Objects.isNull(xpOrder)) { return R.fail("订单不存在"); } if (xpOrder.getStatus() == 0) { return R.fail("订单已取消"); } xpOrder.setStatus(status); switch (status) { case 4: // 查询起点点位 Long startPointId = xpOrder.getStartPointId(); XpPoint xpPoint = xpPointClient.queryById(startPointId).getData(); // 添加取消订单定时任务job 时间为点位限停时长 Map cancelJobMaps = new ImmutableMap.Builder(). put("id", xpOrder.getId()) .build(); QuartzManager.addJob( OrderCancelJob.class, (OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpPoint.getParkingTimeLimit())), cancelJobMaps ); // 车辆到达上车点时间 xpOrder.setArrivalTime(LocalDateTime.now()); break; case 5: // 删除定时任务job QuartzManager.removeJob((OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL); break; case 6: // 行程开始时间 xpOrder.setTripBegin(LocalDateTime.now()); break; case 7: // 查询自动结束行程时间 Integer arriveTime = xpSystemSettingClient.getOrderFinishTime().getData(); // 添加自动结束行程定时任务job Map endTripJobMaps = new ImmutableMap.Builder(). put("id", xpOrder.getId()) .build(); QuartzManager.addJob( EndTripJob.class, (EndTripJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.END_TRIP, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(arriveTime)), endTripJobMaps ); break; } this.updateById(xpOrder); return R.ok(); } @Override public void endTrip(Long orderId, String uid) { List xpOrderDetails = new ArrayList<>(); // 起步价格明细 List start = new ArrayList<>(); // 里程费价格明细 List mileage = new ArrayList<>(); // 时长费价格明细 List duration = new ArrayList<>(); // 远途费价格明细 List longDistance = new ArrayList<>(); XpOrder order = this.getById(orderId); if (order == null) { throw new RuntimeException("订单不存在"); } if (order.getStatus() != 7) { throw new RuntimeException("订单状态错误"); } order.setStatus(8); // 计算完价格后 挑选优惠券 GetUserCouponDto getUserCouponDto = new GetUserCouponDto(); getUserCouponDto.setUserId(Long.valueOf(uid)); getUserCouponDto.setTotalAmount(order.getOrderMoney().doubleValue()); R userCouponVoR = xpAppUserCouponClient.getUserCoupon(getUserCouponDto); UserCouponVo userCouponVo = userCouponVoR.getData(); if (userCouponVo != null) { order.setCouponId(userCouponVo.getId()); order.setCouponMoney(BigDecimal.valueOf(userCouponVo.getMoney())); } order.setTripEnd(LocalDateTime.now()); baseMapper.updateById(order); // 解绑用户与车辆关系 CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo(); XpVehicle vehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); if (vehicle != null) { cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin()); cancelTaxiPassengerVo.setUid(uid); cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(""); userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); // 修改车辆接单状态 vehicle.setState(0); xpVehicleClient.updateVehicleById(vehicle); } // 根据订单所属开通城市id 查询定价 R pricingByCityId = xpPricingClient.getPricingByCid(order.getCityId()); XpPricing pricing = pricingByCityId.getData(); if (pricing == null) { throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS); } // 费用 // // 查询订单轨迹 // List trajectories = mongoTemplate.find( // new Query(Criteria.where("orderId").is(orderId)) // .with(Sort.by(Sort.Direction.ASC, "locatetime")), // OrderTrajectory.class // ); // List gpsPoints = new ArrayList<>(); // for (OrderTrajectory trajectory : trajectories) { // TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime()); // gpsPoints.add(point); // } // 补充临时轨迹数据 List gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime())); TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig(); JSONArray startingFareJsonArray = JSONArray.parseArray(pricing.getStartingFareJson()); if(pricing.getPricingType()==1){ JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson()); config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split("-")[0], basicPricingJson.getString("num21").split("-")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28")))); config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split("-")[0], basicPricingJson.getString("num22").split("-")[1], Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25")), Double.parseDouble(basicPricingJson.getString("num26")), Double.parseDouble(basicPricingJson.getString("num27")), Double.parseDouble(basicPricingJson.getString("num28")))); config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", basicPricingJson.getString("num14").split("-")[0], basicPricingJson.getString("num14").split("-")[1], Double.parseDouble(basicPricingJson.getString("num16")), Double.parseDouble(basicPricingJson.getString("num17")), Double.parseDouble(basicPricingJson.getString("num18")), Double.parseDouble(basicPricingJson.getString("num19")), Double.parseDouble(basicPricingJson.getString("num20"))); config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "00:00", "23:59", Double.parseDouble(basicPricingJson.getString("num30")), Double.parseDouble(basicPricingJson.getString("num31")), Double.parseDouble(basicPricingJson.getString("num32")), Double.parseDouble(basicPricingJson.getString("num33")), Double.parseDouble(basicPricingJson.getString("num234"))); // --- 远途加价区间配置 (关键修改) --- // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2) config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num6")), Double.parseDouble(basicPricingJson.getString("num7")), Double.parseDouble(basicPricingJson.getString("num8")))); // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0) config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num9")), Double.parseDouble(basicPricingJson.getString("num10")), Double.parseDouble(basicPricingJson.getString("num11")))); // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值 config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(Double.parseDouble(basicPricingJson.getString("num12")), 999999, Double.parseDouble(basicPricingJson.getString("num13")))); } for (Object o : startingFareJsonArray) { // 转化为jsonObject JSONObject jsonObject = (JSONObject) o; String num1 = jsonObject.getString("num1"); String num2 = jsonObject.getString("num2"); String num3 = jsonObject.getString("num3"); String num4 = jsonObject.getString("num4"); String num5 = jsonObject.getString("num5"); String num6 = jsonObject.getString("num6"); String num7 = jsonObject.getString("num7"); config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7))); } TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService(); Map bill = service.calculateOrderPrice(DateUtils.toDate(order.getCreateTime()), order.getMileageKilometers(), gpsPoints, config); System.err.println("======= 订单计费账单 ======="); bill.forEach((detail, price) -> System.err.println(detail + ": " + price + " 元")); BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add); System.err.println("--------------------------"); System.err.println("应付总额: " + totalAmount + " 元"); BigDecimal startMoney = BigDecimal.ZERO; // 默认费率1 double priceRate = 1; if (pricing.getIsDynamicPrice() == 1) { // 先判断是否已经调价过了 Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid); if (userDynamicPriceObj != null) { // 是否调价过了 priceRate = Double.parseDouble(userDynamicPriceObj.toString()); } else { // 没有调过 //是否触发动态调价 redis获取 Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId()); if (dynamicPriceObj != null) { JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson()); // 触发动态调价 // value=时间 String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId())); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); // 需要调价的次数 int count = num / orderNum; if (count > 0) { // 计算每次上升的费率 Integer upRate = getOrderNum(jsonObject, 5); BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); for (int i = count; i > 0; i--) { // 当前费率+(费率*上升百分比) priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue(); } // 冷却时间 Integer time = getOrderNum(jsonObject, 6); // 触发调价了 redisService.setCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES); } } } } // 封装费用明细数据 for (Map.Entry stringBigDecimalEntry : bill.entrySet()) { // 封装起步价 FareBreakdownDetailVo startDetail = new FareBreakdownDetailVo(); String key = stringBigDecimalEntry.getKey(); if (key.contains("起步价")) { startDetail.setTime(key.split("\\|")[1]); startDetail.setMoney(stringBigDecimalEntry.getValue()); startMoney = startMoney.add(stringBigDecimalEntry.getValue()); if (key.contains("普通时段")) { startDetail.setType(1); } else if (key.contains("夜间")) { startDetail.setType(2); } else if (key.contains("高峰")) { startDetail.setType(3); } else if (key.contains("节假")) { startDetail.setType(4); } startDetail.setDuration(Double.valueOf(key.split("=")[1])); startDetail.setMileage(new BigDecimal(key.split("&")[1])); start.add(startDetail); } // 封装里程费 if (!key.contains("起步") && !key.contains("时长") && !key.contains("远途") && !key.contains("distance")) { FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo(); if (key.contains("普通时段")) { mileageDetail.setType(1); String key1 = "distance普通时段" + key.split("\\|")[1]; String key2 = "普通时段" + key.split("\\|")[1]; BigDecimal distance = bill.get(key1); BigDecimal money = bill.get(key2); mileageDetail.setMileage(distance); order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); } else if (key.contains("夜间行驶")) { mileageDetail.setType(2); String key1 = "distance夜间行驶" + key.split("\\|")[1]; String key2 = "夜间行驶" + key.split("\\|")[1]; BigDecimal distance = bill.get(key1); BigDecimal money = bill.get(key2); mileageDetail.setMileage(distance); order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); } else if (key.contains("高峰期")) { mileageDetail.setType(3); String key1 = "distance高峰期" + key.split("\\|")[1]; String key2 = "高峰期" + key.split("\\|")[1]; BigDecimal distance = bill.get(key1); BigDecimal money = bill.get(key2); mileageDetail.setMileage(distance); order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); } else if (key.contains("节假")) { mileageDetail.setType(4); String key1 = "distance节假日" + key.split("\\|")[1]; String key2 = "节假日" + key.split("\\|")[1]; BigDecimal distance = bill.get(key1); BigDecimal money = bill.get(key2); mileageDetail.setMileage(distance); order.setStartMoney(money.multiply(BigDecimal.valueOf(priceRate))); mileageDetail.setMoney(money.multiply(BigDecimal.valueOf(priceRate))); } mileage.add(mileageDetail); } // 封装时长费 FareBreakdownDetailVo timeDetail = new FareBreakdownDetailVo(); if (key.contains("时长费")) { timeDetail.setType(startDetail.getType()); timeDetail.setMoney(stringBigDecimalEntry.getValue()); timeDetail.setDuration(Double.valueOf(key.split("&")[1])); duration.add(timeDetail); } // 封装远途费 FareBreakdownDetailVo longDetail = new FareBreakdownDetailVo(); if (key.contains("远途费")) { longDetail.setType(startDetail.getType()); longDetail.setMoney(stringBigDecimalEntry.getValue()); longDetail.setMileage(new BigDecimal(key.split("&")[1])); longDistance.add(longDetail); } } for (FareBreakdownDetailVo fareBreakdownDetailVo : start) { XpOrderDetail xpOrderDetail = new XpOrderDetail(); BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setDetailType(1); xpOrderDetail.setCreateTime(LocalDateTime.now()); xpOrderDetails.add(xpOrderDetail); } BigDecimal mileageMoney = BigDecimal.ZERO; for (FareBreakdownDetailVo fareBreakdownDetailVo : mileage) { XpOrderDetail xpOrderDetail = new XpOrderDetail(); BeanUtils.copyProperties(fareBreakdownDetailVo, xpOrderDetail); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setDetailType(2); xpOrderDetail.setCreateTime(LocalDateTime.now()); mileageMoney = mileageMoney.add(fareBreakdownDetailVo.getMoney()); xpOrderDetails.add(xpOrderDetail); } order.setMileageMoney(mileageMoney); for (XpOrderDetail xpOrderDetail : xpOrderDetails) { xpOrderDetailMapper.insert(xpOrderDetail); } for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) { order.setDurationType(fareBreakdownDetailVo.getType()); order.setDurationMoney(fareBreakdownDetailVo.getMoney()); order.setDuration(Double.parseDouble(fareBreakdownDetailVo.getDuration() + "")); } for (FareBreakdownDetailVo fareBreakdownDetailVo : longDistance) { order.setLongDistanceType(fareBreakdownDetailVo.getType()); order.setLongDistance(fareBreakdownDetailVo.getMileage().doubleValue()); order.setLongDistancemoney(fareBreakdownDetailVo.getMoney()); } BigDecimal orderMoney = startMoney.add(mileageMoney).add(order.getDurationMoney() != null ? order.getDurationMoney() : BigDecimal.ZERO) .add(order.getLongDistancemoney() != null ? order.getLongDistancemoney() : BigDecimal.ZERO) .add(order.getWaitMoney()!=null?order.getWaitMoney():BigDecimal.ZERO); order.setOrderMoney(orderMoney); baseMapper.updateById(order); if (order.getCouponId() != null) { UseUserCouponDto useUserCouponDto = new UseUserCouponDto(); useUserCouponDto.setUserId(Long.valueOf(uid)); useUserCouponDto.setTotalAmount(order.getOrderMoney().doubleValue()); useUserCouponDto.setOpenCityId(order.getCityId()); useUserCouponDto.setOrderId(orderId); useUserCouponDto.setUserCouponId(order.getCouponId()); xpAppUserCouponClient.useUserCoupon(useUserCouponDto); } // 结束后的车辆操作 if(vehicle!=null){ // 生成新的巡游单子 回到最新巡游的初始起点位置 XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1")); XpCruiseOrder xpCruiseOrder = new XpCruiseOrder(); xpCruiseOrder.setVehicleId(vehicle.getId()); xpCruiseOrder.setFleetId(vehicle.getFleetId()); xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin()); xpCruiseOrder.setOrderType(2); // 返程起点是当前正常订单的终点 xpCruiseOrder.setStartPointId(order.getEndPointId()); xpCruiseOrder.setStartPointName(order.getEndPointName()); xpCruiseOrder.setStartLon(order.getEndLon()); xpCruiseOrder.setStartLat(order.getEndLat()); xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat()); xpCruiseOrder.setStatus(1); xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId()); xpCruiseOrder.setCreateTime(LocalDateTime.now()); xpCruiseOrder.setId("XU"+ IdUtil.fastUUID()); xpCruiseOrderMapper.insert(xpCruiseOrder); //下发命令 orderMissionClient.pushOrder(new PushOrderDto(vehicle.getVehicleVin(),xpCruiseOrder.getId(),null)); } } private MileageDto mileageType(MileageDto param, JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) { // 计算出是在哪个普通时间段内 for (Object o : startingFareJsonArray) { JSONObject startingFare = (JSONObject) o; Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(mileageDate); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num1").split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num1").split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(mileageDate); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num2").split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num2").split(":")[1])); // 找到符合条件的直接跳出循环 if (mileageDate.getTime() > calendarStart.getTimeInMillis() && mileageDate.getTime() < calendarEnd.getTimeInMillis()) { param.setMileage(startingFare.getString("num6")); param.setTime(startingFare.getString("num7")); param.setMileageTypeTemp(1); break; } } // 根据时间确定是否使用基础信息配置 LocalDateTime createTime = begin; Date date = DateUtils.toDate(createTime); LocalDate localDate = DateUtils.toLocalDate(date); // 判断是否为夜间行驶 获取里程费用 Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(date); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[0].split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[0].split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(date); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[1].split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[1].split(":")[1])); if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis() ) { param.setMileage(num16); param.setTime(num17); param.setMileageTypeTemp(2); } // 判断是否为高峰期 获取里程费用 Calendar calendar1Start = Calendar.getInstance(); calendar1Start.setTime(date); calendar1Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[0].split(":")[0])); calendar1Start.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[0].split(":")[1])); Calendar calendar1End = Calendar.getInstance(); calendar1End.setTime(date); calendar1End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[1].split(":")[0])); calendar1End.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[1].split(":")[1])); Calendar calendar2Start = Calendar.getInstance(); calendar2Start.setTime(date); calendar2Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[0])); calendar2Start.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[1])); Calendar calendar2End = Calendar.getInstance(); calendar2End.setTime(date); calendar2End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[1].split(":")[0])); calendar2End.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[1].split(":")[1])); if ((date.getTime() > calendar1Start.getTimeInMillis() && date.getTime() < calendar1End.getTimeInMillis()) || (date.getTime() > calendar2Start.getTimeInMillis() && date.getTime() < calendar2End.getTimeInMillis())) { param.setMileage(num24); param.setTime(num25); param.setMileageTypeTemp(3); } // 判断当前是否属于节假日 获取里程费用 boolean holiday = holidayUtil.isHoliday(localDate); if (holiday) { // 判断是否为节假日 起步价修改 param.setMileage(num30); param.setTime(num31); param.setMileageTypeTemp(4); } return param; } private void calculateStartingFare(List trajectories, LocalDateTime tripBegin, boolean startFlag, Double startDistance, JSONArray startingFareJsonArray, String num3, String num4, String num5, Date endDate, XpOrder order, String num14, String num15, String num16, String num17, Integer startType, String num21, String num22, String num23, String num24, String num25, String num29, String num30, String num31, SimpleDateFormat timeFormat, Date startDate, List start) { String startTime; String num6; String num7; String endTime; // 根据订单创建时间确定是否使用基础信息配置 LocalDateTime createTime = order.getCreateTime(); Date date = DateUtils.toDate(createTime); LocalDate localDate = DateUtils.toLocalDate(date); for (Object o : startingFareJsonArray) { JSONObject startingFare = (JSONObject) o; Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(date); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num1").split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num1").split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(date); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num2").split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num2").split(":")[1])); // 找到符合条件的直接跳出循环 if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) { num3 = startingFare.getString("num3"); num4 = startingFare.getString("num4"); num5 = startingFare.getString("num5"); num6 = startingFare.getString("num6"); num7 = startingFare.getString("num7"); startTime = startingFare.getString("num1"); endTime = startingFare.getString("num2"); break; } } // 判断是否为夜间行驶 起步价修改 Calendar calendarStart = Calendar.getInstance(); calendarStart.setTime(date); calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[0].split(":")[0])); calendarStart.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[0].split(":")[1])); Calendar calendarEnd = Calendar.getInstance(); calendarEnd.setTime(date); calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num14.split("-")[1].split(":")[0])); calendarEnd.set(Calendar.MINUTE, Integer.valueOf(num14.split("-")[1].split(":")[1])); if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis() ) { num3 = num15; num6 = num16; num7 = num17; startType = 2; } // 判断是否为高峰期 Calendar calendar1Start = Calendar.getInstance(); calendar1Start.setTime(date); calendar1Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[0].split(":")[0])); calendar1Start.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[0].split(":")[1])); Calendar calendar1End = Calendar.getInstance(); calendar1End.setTime(date); calendar1End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num21.split("-")[1].split(":")[0])); calendar1End.set(Calendar.MINUTE, Integer.valueOf(num21.split("-")[1].split(":")[1])); Calendar calendar2Start = Calendar.getInstance(); calendar2Start.setTime(date); calendar2Start.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[0])); calendar2Start.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[0].split("-")[0].split(":")[1])); Calendar calendar2End = Calendar.getInstance(); calendar2End.setTime(date); calendar2End.set(Calendar.HOUR_OF_DAY, Integer.valueOf(num22.split("-")[1].split(":")[0])); calendar2End.set(Calendar.MINUTE, Integer.valueOf(num22.split("-")[1].split(":")[1])); // 判断是否为高峰期 起步价,里程费,时长费修改 if ((date.getTime() > calendar1Start.getTimeInMillis() && date.getTime() < calendar1End.getTimeInMillis()) || (date.getTime() > calendar2Start.getTimeInMillis() && date.getTime() < calendar2End.getTimeInMillis())) { num3 = num23; num6 = num24; num7 = num25; startType = 3; } // 判断当前是否属于节假日 boolean holiday = holidayUtil.isHoliday(localDate); if (holiday) { // 判断是否为节假日 起步价修改 num3 = num29; num6 = num30; num7 = num31; startType = 4; } // 起步价价格明细封装 FareBreakdownDetailVo fareBreakdownDetailVo = new FareBreakdownDetailVo(); fareBreakdownDetailVo.setType(startType); fareBreakdownDetailVo.setTime(timeFormat.format(startDate) + "-" + timeFormat.format(endDate)); fareBreakdownDetailVo.setMileage(new BigDecimal(startDistance / 1000).setScale(2, RoundingMode.HALF_UP)); // 计算startDate和endDate相差多少分钟 // 将 Date 转换为 LocalDateTime LocalDateTime startDateTime = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); LocalDateTime endDateTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); // 计算时间差(单位:分钟) long minutesDifference = Duration.between(startDateTime, endDateTime).toMinutes(); fareBreakdownDetailVo.setDuration((double) minutesDifference); fareBreakdownDetailVo.setMoney(new BigDecimal(num3)); start.add(fareBreakdownDetailVo); } /** * 获取配置 4每X单 5上升X% 6冷却 * * @param rule * @param num * @return */ private Integer getOrderNum(JSONObject rule, int num) { Integer param = rule.getInteger("num" + num); return param; } @Override public R fareBreakdown(Long orderId, String uid) { XpOrder order = this.getById(orderId); order.setAppUserId(null); // 查询订单轨迹 List trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(orderId)) .with(Sort.by(Sort.Direction.ASC, "locatetime")), OrderTrajectory.class ); FareBreakdownVo res = new FareBreakdownVo(); List start = new ArrayList<>(); List mileage = new ArrayList<>(); List xpOrderDetails = xpOrderDetailMapper.selectList(new LambdaQueryWrapper().eq(XpOrderDetail::getOrderId, orderId)); for (XpOrderDetail xpOrderDetail : xpOrderDetails) { FareBreakdownDetailVo detail = new FareBreakdownDetailVo(); detail.setType(xpOrderDetail.getType()); detail.setTime(xpOrderDetail.getTime()); detail.setMileage(xpOrderDetail.getMileage()); detail.setDuration(xpOrderDetail.getDuration()); if (xpOrderDetail.getType() == 1){ start.add(detail); }else{ mileage.add(detail); } } List duration = new ArrayList<>(); if (order.getDuration()!=null&&order.getDuration()>0){ FareBreakdownDetailVo durationDetail = new FareBreakdownDetailVo(); durationDetail.setType(order.getDurationType()); durationDetail.setDuration(order.getDuration()); durationDetail.setMoney(order.getDurationMoney()); } List longDistance = new ArrayList<>(); if (order.getLongDistance()!=null&&order.getLongDistance()>0){ FareBreakdownDetailVo longDistanceDetail = new FareBreakdownDetailVo(); longDistanceDetail.setType(order.getLongDistanceType()); longDistanceDetail.setMileage(BigDecimal.valueOf(order.getLongDistance())); longDistanceDetail.setMoney(order.getLongDistancemoney()); longDistance.add(longDistanceDetail); } res.setStart( start); res.setMileage( mileage); res.setDuration( duration); res.setLongDistance( longDistance); res.setRedPacketMoney(order.getRedPacketMoney()); res.setCouponMoney(order.getCouponMoney()); res.setOrderMoney(order.getOrderMoney()); res.setKilometer(order.getMileageKilometers()==null?BigDecimal.ZERO:BigDecimal.valueOf(order.getMileageKilometers())); LocalDateTime createTime = order.getCreateTime(); LocalDateTime tripEnd = order.getTripEnd(); if (tripEnd==null){ tripEnd = LocalDateTime.now(); order.setTripEnd(tripEnd); this.updateById(order); } // 计算行程时间 单位分钟 // 计算时间差 Duration durationBetween = Duration.between(createTime, tripEnd); // 转换为分钟并保留一位小数 BigDecimal minutes = BigDecimal.valueOf(durationBetween.getSeconds()) .divide(BigDecimal.valueOf(60), 1, RoundingMode.HALF_UP); res.setTime(minutes); return R.ok(res); } @Override public R payment(XpOrderPayDto dto, String uid) { // mvp版本不做支付 使用优惠券抵扣为0元订单处理 处理订单状态即可 XpOrder order = this.getById(dto.getOrderId()); order.setStatus(9); baseMapper.updateById(order); return R.ok(); } /** * 添加订单 * * @param xpOrder * @return */ @Override public boolean addOrder(XpOrder xpOrder) { int insert = this.baseMapper.insert(xpOrder); if (insert <= 0) { return false; } return true; } @Override public XpVehicle queryVehicleByOrderId(Long orderId, String uid) { XpOrder xpOrder = this.getById(orderId); XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); return xpVehicle; } /** * 获取订单数量 * * @param dto * @return */ @Override public Integer getOrderNum(GetOrderNumDto dto) { Long num = this.baseMapper.selectCount(new LambdaQueryWrapper().eq(XpOrder::getCityId, dto.getOpenCityId()).between(BaseModel::getCreateTime, dto.getTimeStr(), new Date())); return num.intValue(); } @Override public void saveVehicleLocation(OrderTrajectory orderTrajectory) { // 查询订单信息 XpOrder xpOrder = this.getById(orderTrajectory.getOrderId()); // 计算距离 // 获取上一次定位 String oldLocation = redisService.getCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId()); if (StringUtils.isEmpty(oldLocation)) { // 首次定位 xpOrder.setMileageKilometers(0D); this.updateById(xpOrder); orderTrajectory.setDistance(0D); // 存储mongo数据 orderTrajectoryService.create(orderTrajectory); // 存储首次定位 redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation()); } else { Map distance = GeodesyUtil.getDistance(orderTrajectory.getLocation(), oldLocation); if (null != distance) { Double distance1 = distance.get("WGS84"); if (distance1 > 50 && xpOrder.getStatus() == 6) {//大于50米表示在移动,且在服务中的时候记录里程 xpOrder.setMileageKilometers(BigDecimal.valueOf(xpOrder.getMileageKilometers()).add(new BigDecimal(distance1)).setScale(2, RoundingMode.HALF_EVEN).doubleValue()); this.updateById(xpOrder); // 存储本次距离 orderTrajectory.setDistance(distance1); // 存储mongo数据 orderTrajectoryService.create(orderTrajectory); } } else { log.error("调用高德计算距离出错"); } } } @Override public OrderDetailVo orderDetail(Long orderId, String uid) { OrderDetailVo orderDetailVo = new OrderDetailVo(); XpOrder order = this.getById(orderId); BeanUtils.copyProperties(order, orderDetailVo); // 查询车辆信息 XpVehicle vehicle = xpVehicleClient.queryById(order.getVehicleId()).getData(); if (vehicle != null) { orderDetailVo.setVehicleCode(vehicle.getVehicleCode()); orderDetailVo.setPlateNumber(vehicle.getPlateNumber()); orderDetailVo.setVehicleColor(vehicle.getVehicleColor()); orderDetailVo.setVehiclePictures(vehicle.getVehiclePictures()); } // 查询评价信息 XpOrderEvaluate evaluate = xpOrderEvaluateService.lambdaQuery().eq(XpOrderEvaluate::getOrderId, orderId) .last("limit 1").one(); if (evaluate != null) { orderDetailVo.setFeedbackPictures(evaluate.getFeedbackPictures()); orderDetailVo.setFeedbackContent(evaluate.getFeedbackContent()); orderDetailVo.setOrderRating(evaluate.getOrderRating()); if (evaluate.getFeedbackTypeId() != null) { XpFeedbackType feedbackType = xpSystemSettingClient.getFeedbackTypeById(evaluate.getFeedbackTypeId()).getData(); orderDetailVo.setFeedbackTypeName(feedbackType.getFeedbackType()); } } // List trajectories = mongoTemplate.find( // new Query(Criteria.where("orderId").is(orderId)) // .with(Sort.by(Sort.Direction.ASC, "locatetime")), // OrderTrajectory.class // ); List mockGpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime())); // 生成轨迹记录 List trajectories = TrajectoryGenerator.generateTrajectory(mockGpsPoints); orderDetailVo.setTrajectories(trajectories); if (order.getTripBegin() != null && order.getTripEnd() != null) { // 计算两个时间相差多少分钟 long minutesDifference = Duration.between(order.getTripBegin(), order.getTripEnd()).toMinutes(); orderDetailVo.setOrderTime(minutesDifference); } else { orderDetailVo.setOrderTime(0l); } if (order.getStartMileage() != null) { orderDetailVo.setTotalMileage(order.getStartMileage() + (order.getMileageKilometers() != null ? order.getMileageKilometers() : 0D)); } return orderDetailVo; } /** * 成功操作下发命令后调用 用于弹出redis队列的获取成功的数据 * * @param dto */ @Override @Transactional @ShardingSphereTransactionType(TransactionType.BASE) public void popOrder(PopOrderDto dto) { String orderType = dto.getOrderType(); Long orderId = dto.getOrderId(); //巡游单处理逻辑 if(OrderType.CRUISE_ORDER.equals(orderType)){ // todo 需要处理巡游的逻辑 } //乘客单处理逻辑 if(OrderType.USER_ORDER.equals(orderType)){ XpOrder order = this.getById(orderId); //订单为待接单状态 if(order.getStatus() == 1){ AddTaxiPassengerVo addTaxiPassengerVo = new AddTaxiPassengerVo(); order.setAcceptanceTime(LocalDateTime.now()); R byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin()); XpVehicle vehicle = null; if (byVehicleVin.getCode() == 200) { vehicle = byVehicleVin.getData(); order.setVehicleId(vehicle.getId()); order.setFleetId(vehicle.getFleetId()); addTaxiPassengerVo.setVin(vehicle.getVehicleVin()); } order.setStatus(2); // Redis弹出这个队列元素 // value 订单Id_经纬度_状态_用户id_订单编号_距离_时间 String popFirstElement = redisService.popFirstElement(order.getQueueName()); XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity(); String[] split = popFirstElement.split("_"); xpGeoQueryEntity.setOrderId(split[0]); // 存mongo数据 xpPricingClient.updateXpGeoQueryEntity(split[0]); this.updateById(order); // 修改车辆信息 vehicle.setState(1); xpVehicleClient.updateVehicleById(vehicle); //绑定用户和车辆关系 addTaxiPassengerVo.setUid(order.getAppUserId().toString()); addTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO appid addTaxiPassengerVo.setAppId(""); userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); //推送乘客车辆到达预约点的导航数据 sendRoute(order.getAppUserId().toString(), orderId, "ORDER_NAVIGATION_START_DATA"); }else{ //推送行起点到终点的驶轨迹给乘客端 sendRoute(order.getAppUserId().toString(), orderId, "ORDER_NAVIGATION_END_DATA"); } } } /** * 发送乘客导航路径数据 * @param appUserId * @param keyStr */ public void sendRoute(String appUserId, Long orderId, String keyStr){ Object cacheObject = redisService.getCacheObject(keyStr + ":" + appUserId); if(null != cacheObject){ RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class); JSONObject jsonObject = new JSONObject(); jsonObject.put("type", "ORDER_ROUTE"); jsonObject.put("timestamp", System.currentTimeMillis()); JSONObject content = new JSONObject(); content.put("orderId", orderId); content.put("routeType", "ORDER_NAVIGATION_START_DATA".equals(keyStr) ? 1 : 2); JSONObject route = new JSONObject(); route.put("distance", routeVo.getDistance()); route.put("duration", routeVo.getDuration()); route.put("routeID", routeVo.getRouteID()); List collect = routeVo.getPolyline().stream().map(item->{ JSONObject point = new JSONObject(); point.put("latitude", item.getLatitude()); point.put("longitude", item.getLongitude()); return point; }).collect(Collectors.toList()); route.put("polyline", collect); content.put("route", route); jsonObject.put("content", content); SendMessageDTO messageDTO = new SendMessageDTO(); messageDTO.setAppUserId(appUserId); messageDTO.setMessage(jsonObject.toJSONString()); xpPushMessageClient.sendRoute(messageDTO); } } /** * 获取当前用户正在执行的订单 * * @param uid * @return */ @Override public XpOrderDetailVO getActiveOrder(String uid) { XpOrderDetailVO xpOrderDetailVO = new XpOrderDetailVO(); XpOrder xpOrder = this.baseMapper.selectOne(new LambdaQueryWrapper().eq(XpOrder::getAppUserId, Long.parseLong(uid)).in(XpOrder::getStatus, Arrays.asList(1,2,3, 4, 5, 6, 7, 8)).orderByDesc(BaseModel::getCreateTime).last("LIMIT 1")); if (xpOrder == null) { return null; } BeanUtils.copyProperties(xpOrder, xpOrderDetailVO); R xpPointR = xpPointClient.queryById(xpOrder.getStartPointId()); if (xpPointR.getCode() == R.SUCCESS) { XpPoint startPoint = xpPointR.getData(); xpOrderDetailVO.setStartParkingTimeLimit(startPoint.getParkingTimeLimit()); } R xpPointR1 = xpPointClient.queryById(xpOrder.getEndPointId()); if (xpPointR1.getCode() == R.SUCCESS) { XpPoint endPoint = xpPointR1.getData(); xpOrderDetailVO.setEndParkingTimeLimit(endPoint.getParkingTimeLimit()); } // 算时间 if (xpOrder.getStatus() == 1) { R r = xpPricingClient.getWaitTime(new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat())); if (r.getCode() == R.SUCCESS) { xpOrderDetailVO.setEstimatedTime(r.getData()); } else { throw new RuntimeException(r.getMsg()); } } return xpOrderDetailVO; } }