package com.xiaopeng.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
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.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.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.XpAppUserClient;
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient;
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.feignClient.operation.XpPointClient;
import com.xiaopeng.api.feignClient.operation.XpPricingClient;
import com.xiaopeng.api.model.account.XpAppUser;
import com.xiaopeng.api.model.operation.XpPricing;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpOrderCancel;
import com.xiaopeng.api.model.order.XpOrderEvaluate;
import com.xiaopeng.api.model.order.XpOrderReassign;
import com.xiaopeng.api.vo.account.UserCouponVo;
import com.xiaopeng.api.vo.order.FareBreakdownVo;
import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo;
import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo;
import com.xiaopeng.api.vo.order.XpPointInfoVo;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.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.job.jobs.EndTripJob;
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.job.base.QuartzManager;
import com.xiaopeng.order.job.base.TimeJobType;
import com.xiaopeng.order.job.jobs.OrderCancelJob;
import io.swagger.annotations.ApiModelProperty;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
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.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
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 XpAppUserClient xpAppUserClient;
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;
@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. 分页查询
PageInfo pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
PageInfo orderPage = this.page(pageInfo, wrapper);
if (CollectionUtils.isEmpty(orderPage.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 : orderPage.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. 批量查询关联数据
Map userMap = batchGetUsers(userIds);
Map vehicleMap = batchGetVehicles(vehicleIds);
Map fleetMap = batchGetFleets(fleetIds);
// 5. 组装 VO
List voList = orderPage.getRecords().stream()
.map(order -> convertToPageVO(order, userMap, vehicleMap, fleetMap))
.collect(Collectors.toList());
// 6. 返回分页结果
PageInfo resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize());
resultPage.setTotal(orderPage.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())) {
Map userMap = batchGetUsers(Collections.singleton(order.getAppUserId()));
XpAppUser user = userMap.get(order.getAppUserId());
if (Objects.nonNull(user)) {
vo.setNickName(user.getNickName());
vo.setPhoneNumber(user.getPhoneNumber());
}
}
// 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. 批量查询关联数据
Map userMap = batchGetUsers(userIds);
Map vehicleMap = batchGetVehicles(vehicleIds);
Map fleetMap = batchGetFleets(fleetIds);
// 5. 组装 VO
return orderList.stream()
.map(order -> convertToPageVO(order, userMap, 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 Map batchGetUsers(Set userIds) {
if (CollectionUtils.isEmpty(userIds)) {
return new HashMap<>();
}
try {
R> result = xpAppUserClient.listByIds(new ArrayList<>(userIds));
if (Objects.nonNull(result) && Objects.nonNull(result.getData())) {
return result.getData().stream()
.collect(Collectors.toMap(XpAppUser::getId, Function.identity(), (a, b) -> a));
}
} catch (Exception e) {
log.error("批量获取用户信息失败: {}", e.getMessage());
}
return new HashMap<>();
}
/**
* 批量获取车辆信息
*/
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,
Map userMap,
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()) && userMap.containsKey(order.getAppUserId())) {
XpAppUser user = userMap.get(order.getAppUserId());
vo.setNickName(user.getNickName());
vo.setPhoneNumber(user.getPhoneNumber());
}
// 车辆信息
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);
}
// 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