package com.xiaopeng.order.service.impl;
|
|
import cn.hutool.core.bean.BeanUtil;
|
import com.alibaba.fastjson.JSONArray;
|
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.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.XpAppUserClient;
|
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
|
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.XpGeoQueryEntity;
|
import com.xiaopeng.api.model.operation.XpFeedbackType;
|
import com.xiaopeng.api.model.operation.XpPoint;
|
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.model.vehicleConvoy.XpFleet;
|
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
|
import com.xiaopeng.api.vo.account.UserCouponVo;
|
import com.xiaopeng.api.vo.order.*;
|
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
|
import com.xiaopeng.common.core.constant.CacheConstants;
|
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.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.holiday.HolidayUtil;
|
import com.xiaopeng.order.vo.OrderDetailVo;
|
import io.swagger.annotations.ApiModelProperty;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
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.geo.GeoJsonPoint;
|
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.function.Function;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 订单 服务实现类
|
* </p>
|
*
|
* @author mitao
|
* @since 2026-02-03
|
*/
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor(onConstructor_ = @Lazy)
|
public class XpOrderServiceImpl extends ServiceImpl<XpOrderMapper, XpOrder> 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;
|
private final OrderTrajectoryService orderTrajectoryService;
|
private final XpPushMessageClient xpPushMessageClient;
|
|
@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<DailyCountDTO> dailyCountList = baseMapper.getDailyOrderCount(startDate, endDate);
|
dto.setDailyCountList(Objects.nonNull(dailyCountList) ? dailyCountList : new ArrayList<>());
|
|
return dto;
|
}
|
|
@Override
|
public PageInfo<XpOrderPageVO> pageList(XpOrderPageQuery query) {
|
// 1. 构建查询条件
|
LambdaQueryWrapper<XpOrder> wrapper = buildQueryWrapper(query);
|
wrapper.orderByDesc(XpOrder::getCreateTime);
|
|
// 2. 分页查询
|
PageInfo<XpOrder> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
PageInfo<XpOrder> orderPage = this.page(pageInfo, wrapper);
|
|
if (CollectionUtils.isEmpty(orderPage.getRecords())) {
|
PageInfo<XpOrderPageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize());
|
resultPage.setTotal(0L);
|
resultPage.setRecords(new ArrayList<>());
|
return resultPage;
|
}
|
|
// 3. 收集关联ID
|
Set<Long> userIds = new HashSet<>();
|
Set<Long> vehicleIds = new HashSet<>();
|
Set<Long> 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<Long, XpAppUser> userMap = batchGetUsers(userIds);
|
Map<Long, XpVehicle> vehicleMap = batchGetVehicles(vehicleIds);
|
Map<Long, XpFleet> fleetMap = batchGetFleets(fleetIds);
|
|
// 5. 组装 VO
|
List<XpOrderPageVO> voList = orderPage.getRecords().stream()
|
.map(order -> convertToPageVO(order, userMap, vehicleMap, fleetMap))
|
.collect(Collectors.toList());
|
|
// 6. 返回分页结果
|
PageInfo<XpOrderPageVO> 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<Long, XpAppUser> 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<Long, XpVehicle> 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<Long, XpFleet> fleetMap = batchGetFleets(Collections.singleton(order.getFleetId()));
|
XpFleet fleet = fleetMap.get(order.getFleetId());
|
if (Objects.nonNull(fleet)) {
|
vo.setFleetName(fleet.getFleetName());
|
}
|
}
|
|
// 6. 获取评价信息
|
LambdaQueryWrapper<XpOrderEvaluate> 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<XpOrderPageVO> exportList(XpOrderPageQuery query) {
|
// 1. 构建查询条件
|
LambdaQueryWrapper<XpOrder> wrapper = buildQueryWrapper(query);
|
|
// 2. 查询订单列表
|
List<XpOrder> orderList = this.list(wrapper);
|
|
if (CollectionUtils.isEmpty(orderList)) {
|
return new ArrayList<>();
|
}
|
|
// 3. 收集关联ID
|
Set<Long> userIds = new HashSet<>();
|
Set<Long> vehicleIds = new HashSet<>();
|
Set<Long> 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<Long, XpAppUser> userMap = batchGetUsers(userIds);
|
Map<Long, XpVehicle> vehicleMap = batchGetVehicles(vehicleIds);
|
Map<Long, XpFleet> fleetMap = batchGetFleets(fleetIds);
|
|
// 5. 组装 VO
|
return orderList.stream()
|
.map(order -> convertToPageVO(order, userMap, vehicleMap, fleetMap))
|
.collect(Collectors.toList());
|
}
|
|
/**
|
* 构建查询条件
|
*/
|
private LambdaQueryWrapper<XpOrder> buildQueryWrapper(XpOrderPageQuery query) {
|
LambdaQueryWrapper<XpOrder> 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<Long, XpAppUser> batchGetUsers(Set<Long> userIds) {
|
if (CollectionUtils.isEmpty(userIds)) {
|
return new HashMap<>();
|
}
|
try {
|
R<List<XpAppUser>> 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<Long, XpVehicle> batchGetVehicles(Set<Long> vehicleIds) {
|
if (CollectionUtils.isEmpty(vehicleIds)) {
|
return new HashMap<>();
|
}
|
try {
|
R<List<XpVehicle>> 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<Long, XpFleet> batchGetFleets(Set<Long> fleetIds) {
|
if (CollectionUtils.isEmpty(fleetIds)) {
|
return new HashMap<>();
|
}
|
try {
|
R<List<XpFleet>> 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<Long, XpAppUser> userMap,
|
Map<Long, XpVehicle> vehicleMap,
|
Map<Long, XpFleet> 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<List<XpVehicle>> 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<Long> 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<Long> 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<Object> 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 cn.hutool.json.JSONUtil.toBean(jsonString, XpPointInfoVo.class);
|
}
|
} catch (Exception e) {
|
log.error("获取用户快捷胶囊失败: {}", e.getMessage(), e);
|
}
|
return null;
|
}
|
|
@Override
|
public List<XpHistoryStartPointsVo> getHistoryStartPoints(String uid, double lon, double lat) {
|
//
|
List<XpOrder> xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, uid).orderByDesc(BaseModel::getCreateTime).last("LIMIT 10"));
|
if (xpOrders.isEmpty()) {
|
return Collections.emptyList();
|
}
|
// 获取点位信息
|
List<Long> startPointsIds = xpOrders.stream().map(XpOrder::getStartPointId).collect(Collectors.toList());
|
|
R<List<XpHistoryStartPointsVo>> r = xpPointClient.getHistoryStartPoints(new HistoryStartPointsDto(startPointsIds, lon, lat));
|
return r.getData();
|
|
}
|
|
@Override
|
public List<XpHistoryEndPointsVo> getHistoryEndPoints(String uid, double lon, double lat) {
|
//
|
List<XpOrder> xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, uid).orderByDesc(BaseModel::getCreateTime).last("LIMIT 10"));
|
if (xpOrders.isEmpty()) {
|
return Collections.emptyList();
|
}
|
// 获取点位信息
|
List<Long> endPointsIds = xpOrders.stream().map(XpOrder::getEndPointId).collect(Collectors.toList());
|
|
R<List<XpHistoryEndPointsVo>> 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<XpOrderHistoryListVO> page = new Page<>(query.getPageNum(), query.getPageSize());
|
List<XpOrderHistoryListVO> list = this.baseMapper.getHistoryOrderList(page, query, uid);
|
|
|
XpOrderHistoryVO xpOrderHistoryVO = new XpOrderHistoryVO();
|
xpOrderHistoryVO.setTotal((int) page.getTotal());
|
|
// 根据time分组
|
Map<LocalDateTime, List<XpOrderHistoryListVO>> map = list.stream().collect(Collectors.groupingBy(XpOrderHistoryListVO::getTime));
|
List<XpOrderHistoryDateVO> dateVOS = map.entrySet().stream().map(entry -> {
|
XpOrderHistoryDateVO xpOrderHistoryDateVO = new XpOrderHistoryDateVO();
|
xpOrderHistoryDateVO.setDateLabel(entry.getKey().toString());
|
xpOrderHistoryDateVO.setOrders(entry.getValue());
|
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 RuntimeException("订单不存在");
|
}
|
if (!order.getAppUserId().toString().equals(uid)) {
|
throw new RuntimeException("无权限取消该订单");
|
}
|
if (order.getStatus() > 5 || order.getStatus() < 1) {
|
throw new RuntimeException("订单状态错误");
|
}
|
order.setStatus(0);
|
|
// 组装调用车机参数
|
CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
|
Long vehicleId = order.getVehicleId();
|
R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId);
|
XpVehicle xpVehicle = xpVehicleR.getData();
|
if (xpVehicle == null) {
|
throw new RuntimeException("车辆不存在");
|
}
|
cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin());
|
cancelTaxiPassengerVo.setUid(order.getAppUserId().toString());
|
cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
|
// TODO 加配置文件取
|
cancelTaxiPassengerVo.setAppId("");
|
|
|
BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
|
if (baseVehicleUserDto.getCode() != 200) {
|
throw new RuntimeException("取消订单失败");
|
}
|
|
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);
|
}
|
}
|
|
@Override
|
@Transactional
|
public void cancelOrder(String orderId) {
|
XpOrder order = this.getById(orderId);
|
if (order == null) {
|
throw new RuntimeException("订单不存在");
|
}
|
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);
|
|
|
// 推送消息
|
// 消息推送
|
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> 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("订单取消消息推送完毕");
|
}
|
|
/**
|
* 评价订单
|
*
|
* @param dto
|
* @param uid
|
*/
|
@Override
|
@Transactional
|
public void comment(XpOrderCommentDto dto, String uid) {
|
XpOrder xpOrder = this.getById(dto.getOrderId());
|
if (xpOrder == null) {
|
throw new RuntimeException("订单不存在");
|
}
|
if (!xpOrder.getAppUserId().toString().equals(uid)) {
|
throw new RuntimeException("无权限评价该订单");
|
}
|
if (xpOrder.getStatus() != 9) {
|
throw new RuntimeException("订单状态错误");
|
}
|
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());
|
xpOrderEvaluateService.save(evaluate);
|
|
}
|
|
@Override
|
public R<String> 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<String, ? extends Object> cancelJobMaps =
|
new ImmutableMap.Builder<String, Long>().
|
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<String, ? extends Object> endTripJobMaps =
|
new ImmutableMap.Builder<String, Long>().
|
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<FareBreakdownDetailVo> start = new ArrayList<>();
|
// 里程费价格明细
|
List<FareBreakdownDetailVo> mileage = new ArrayList<>();
|
// 时长费价格明细
|
List<FareBreakdownDetailVo> duration = new ArrayList<>();
|
// 远途费价格明细
|
List<FareBreakdownDetailVo> 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<UserCouponVo> 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());
|
// cancelTaxiPassengerVo.setAppId();
|
|
userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
|
}
|
// 费用
|
// 查询订单轨迹
|
List<OrderTrajectory> trajectories = mongoTemplate.find(
|
new Query(Criteria.where("orderId").is(orderId))
|
.with(Sort.by(Sort.Direction.ASC, "locatetime")),
|
OrderTrajectory.class
|
);
|
List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>();
|
for (OrderTrajectory trajectory : trajectories) {
|
TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(),trajectory.getLocatetime() );
|
gpsPoints.add(point);
|
}
|
TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig();
|
config.peak = new TaxiPricingDemoService.PricingRule("高峰期", "14:40", "14:46", 15.0, 3.0, 5.0, 3.0, 0.8);
|
config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", "14:47", "14:48", 18.0, 3.0, 5.0, 3.5, 1.0);
|
config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "18:47", "18:48", 18.0, 3.0, 5.0, 4, 2.0);
|
config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", "14:46", "14:47", 10.0, 3.0, 5.0, 2.4, 0.5));
|
config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", "14:48", "17:59", 10.0, 3.0, 5.0, 2.4, 0.5));
|
|
// --- 远途加价区间配置 (关键修改) ---
|
// 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2)
|
config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(5.0, 6.0, 1.2));
|
// 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0)
|
config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(6.0, 7.0, 2.0));
|
// 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值
|
config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(7.0, 8.0, 3.5));
|
|
TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService();
|
Map<String, BigDecimal> 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 + " 元");
|
|
// // 计算实际价格
|
// // 根据订单所属开通城市id 查询定价
|
// R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCityId(order.getCityId());
|
// XpPricing pricing = pricingByCityId.getData();
|
// if (pricing == null) {
|
// throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS);
|
// }
|
// // 查询订单轨迹
|
// List<OrderTrajectory> trajectories = mongoTemplate.find(
|
// new Query(Criteria.where("orderId").is(orderId))
|
// .with(Sort.by(Sort.Direction.ASC, "locatetime")),
|
// OrderTrajectory.class
|
// );
|
// // 计算等待时间
|
// LocalDateTime boardingTime = order.getBoardingTime();// 上车时间
|
// LocalDateTime arrivalTime = order.getArrivalTime();// 车辆到达上车点时间
|
// // 行程开始时间
|
// Integer waitTime = Math.abs((int) Duration.between(boardingTime, arrivalTime).getSeconds());
|
//
|
// // 行程总时间 秒
|
// LocalDateTime tripBegin = order.getTripBegin();
|
// LocalDateTime tripEnd = order.getTripEnd();
|
// long seconds = Duration.between(tripBegin, tripEnd).getSeconds();
|
// // 默认费率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);
|
// }
|
//
|
// }
|
// }
|
// }
|
// if (trajectories.isEmpty()) {
|
// return;
|
// }
|
// // 起步价规则
|
// String startingFareJson = pricing.getStartingFareJson();
|
// JSONArray startingFareJsonArray = JSONArray.parseArray(startingFareJson);
|
// // 基础信息规则
|
// String basicPricing = pricing.getBasicPricingJson();
|
// JSONObject basicPricingJson = JSONObject.parseObject(basicPricing);
|
//
|
// // 计算过后得到起步价
|
// String num3 = "";
|
// String num4 = "";
|
// String num5 = "";
|
// String num6 = "";
|
// String num7 = "";
|
// String startTime = "";
|
// String endTime = "";
|
// // 等待费设置
|
// String num4Wait = basicPricingJson.getString("num4");
|
// String num5Wait = basicPricingJson.getString("num5");
|
// // 远途费设置
|
// String numLong6 = basicPricingJson.getString("num6");
|
// String numLong7 = basicPricingJson.getString("num7");
|
// String numLong8 = basicPricingJson.getString("num8");
|
// String numLong9 = basicPricingJson.getString("num9");
|
// String numLong10 = basicPricingJson.getString("num10");
|
// String numLong11 = basicPricingJson.getString("num11");
|
// String numLong12 = basicPricingJson.getString("num12");
|
// String numLong13 = basicPricingJson.getString("num13");
|
// String numLong14 = basicPricingJson.getString("num14");
|
// String numLong15 = basicPricingJson.getString("num15");
|
// // 节假日基础价格规则
|
// String num29 = basicPricingJson.getString("num29");
|
// String num30 = basicPricingJson.getString("num30");
|
// String num31 = basicPricingJson.getString("num31");
|
// String num32 = basicPricingJson.getString("num32");
|
// String num33 = basicPricingJson.getString("num33");
|
// String num34 = basicPricingJson.getString("num34");
|
//
|
// // 高峰期基础价格规则
|
// String num21 = basicPricingJson.getString("num21");
|
// String num22 = basicPricingJson.getString("num22");
|
// String num23 = basicPricingJson.getString("num23");
|
// String num24 = basicPricingJson.getString("num24");
|
// String num25 = basicPricingJson.getString("num25");
|
// String num26 = basicPricingJson.getString("num26");
|
// String num27 = basicPricingJson.getString("num27");
|
// String num28 = basicPricingJson.getString("num28");
|
// // 夜间行驶基础价格规则
|
// String num14 = basicPricingJson.getString("num14");
|
// String num15 = basicPricingJson.getString("num15");
|
// String num16 = basicPricingJson.getString("num16");
|
// String num17 = basicPricingJson.getString("num17");
|
// String num18 = basicPricingJson.getString("num18");
|
// String num19 = basicPricingJson.getString("num19");
|
// String num20 = basicPricingJson.getString("num20");
|
// // 起步里程
|
// Double startDistance = 0.00D;
|
// // 临时超出起步里程的额外里程
|
// Double mileageDistance = 0.00D;
|
// // 起步价所属时段 type 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段
|
// Integer startType = 1;
|
// // 里程费所属时段 type 0默认临时 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段
|
// Integer mileageType = 0;
|
// // 里程费所属时段临时字段 用于区分时段是否变化 type 0默认临时 1 普通时段 2 夜间行驶时段 3 高峰时段 4 节假日时段
|
// Integer mileageTypeTemp = 0;
|
//
|
// // 起步价时段开始时间
|
// Date startDate = DateUtils.toDate(order.getTripBegin());
|
// // 根据订单创建时间确定使用哪个起步价规则
|
// Date createTime = DateUtils.toDate(order.getCreateTime());
|
// // 起步价时段结束时间
|
// Date endDate = new Date();
|
// // 计算订单总行驶距离,单位米
|
// Double totalDistance = 0.00D;
|
// // 起步价计算完成表示
|
// boolean startFlag = true;
|
// SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
|
// if (pricing.getPricingType() == 1) {
|
//
|
// // 计算起步价
|
// for (Object o : startingFareJsonArray) {
|
// JSONObject startingFare = (JSONObject) o;
|
// Calendar calendarStart = Calendar.getInstance();
|
// calendarStart.setTime(createTime);
|
// 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(createTime);
|
// 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 (createTime.getTime() > calendarStart.getTimeInMillis() && createTime.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(createTime);
|
// 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(createTime);
|
// 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 (createTime.getTime() > calendarStart.getTimeInMillis() && createTime.getTime() < calendarEnd.getTimeInMillis()
|
// ) {
|
// num3 = num15;
|
// num6 = num16;
|
// num7 = num17;
|
// startType = 2;
|
//
|
// }
|
// // 判断是否为高峰期
|
// Calendar calendar1Start = Calendar.getInstance();
|
// calendar1Start.setTime(createTime);
|
// 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(createTime);
|
// 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(createTime);
|
// 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(createTime);
|
// 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 ((createTime.getTime() > calendar1Start.getTimeInMillis() && createTime.getTime() < calendar1End.getTimeInMillis())
|
// || (createTime.getTime() > calendar2Start.getTimeInMillis() && createTime.getTime() < calendar2End.getTimeInMillis())) {
|
// num3 = num23;
|
// num6 = num24;
|
// num7 = num25;
|
// startType = 3;
|
// }
|
// // 判断当前是否属于节假日
|
// boolean holiday = holidayUtil.isHoliday(DateUtils.toLocalDate(createTime));
|
// if (holiday) {
|
// // 判断是否为节假日 起步价修改
|
// num3 = num29;
|
// num6 = num30;
|
// num7 = num31;
|
// startType = 4;
|
// }
|
// // 查询起步价结束时间段
|
// for (OrderTrajectory trajectory : trajectories) {
|
// Long locatetime = trajectory.getLocatetime();
|
// endDate = new Date(locatetime);
|
// LocalDateTime end = DateUtils.dateToLocalDateTime(endDate);
|
// if (end.isAfter(tripBegin)) {
|
// // 行程开始 开始计算里程数
|
// if (startDistance >= Double.parseDouble(num4)) {
|
// // 行驶里程大于基础配置里程 那么起步价时段计算完成
|
// break;
|
// }
|
// startDistance += trajectory.getDistance();
|
// }
|
// }
|
// // 起步价价格明细封装
|
// FareBreakdownDetailVo startDetail = new FareBreakdownDetailVo();
|
// startDetail.setType(startType);
|
// startDetail.setTime(timeFormat.format(startDate) + "-" + timeFormat.format(endDate));
|
// startDetail.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();
|
// startDetail.setDuration(minutesDifference);
|
// startDetail.setMoney(new BigDecimal(num3));
|
// start.add(startDetail);
|
//
|
//
|
// // 计算起步价格、里程、时段、行驶时间
|
//// calculateStartingFare(trajectories, tripBegin, startFlag, startDistance, startingFareJsonArray, num3, num4, num5, endDate, order, num14, num15, num16, num17, startType, num21, num22, num23, num24, num25, num29, num30, num31, timeFormat, startDate, start);
|
//
|
// for (OrderTrajectory trajectory : trajectories) {
|
//// FareBreakdownDetailVo mileageDetail = new FareBreakdownDetailVo();
|
//// mileageDetail.setType();
|
//// mileageDetail.setTime();
|
//// mileageDetail.setMileage();
|
//// mileageDetail.setDuration();
|
//// mileageDetail.setMoney();
|
//
|
// Long locatetime = trajectory.getLocatetime();
|
// Date mileageDate = new Date(locatetime);
|
// LocalDateTime begin = DateUtils.dateToLocalDateTime(mileageDate);
|
// if (begin.isAfter(tripBegin)) {
|
// totalDistance += trajectory.getDistance();
|
// if (totalDistance >= startDistance) {
|
// // 开始累加起步里程
|
// mileageDistance += trajectory.getDistance();
|
// // 判断当前里程费属于什么时段
|
//// mileageTypeTemp
|
// MileageDto param = new MileageDto();
|
// param.setMileage(num6);
|
// param.setTime(num7);
|
// param.setMileageTypeTemp(mileageTypeTemp);
|
// MileageDto mileageDto = mileageType(param,startingFareJsonArray, mileageDate, begin, num14, num16, num17, num21, num22, num24, num25, num30, num31);
|
// if (mileageType==0){
|
// // 首次
|
// mileageType = mileageDto.getMileageTypeTemp();
|
// mileageTypeTemp= mileageDto.getMileageTypeTemp();
|
// } else if (mileageType!=mileageTypeTemp){
|
// // 新时段
|
// FareBreakdownDetailVo fareBreakdownDetailVo = new FareBreakdownDetailVo();
|
// fareBreakdownDetailVo.setType(mileageType);
|
// fareBreakdownDetailVo.setTime(timeFormat.format(endDate)+"-"+timeFormat.format(mileageDate));
|
// double md = mileageDistance / 1000;
|
// fareBreakdownDetailVo.setMileage(new BigDecimal(md).setScale(2, RoundingMode.HALF_UP));
|
// // 计算startDate和endDate相差多少分钟
|
// // 将 Date 转换为 LocalDateTime
|
// LocalDateTime startMileageTime = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
// LocalDateTime endMileageTime = mileageDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
//
|
// // 计算时间差(单位:分钟)
|
// long minutesDifferenceMileage = Duration.between(startMileageTime, endMileageTime).toMinutes();
|
// startDetail.setDuration(minutesDifference);
|
// fareBreakdownDetailVo.setDuration(minutesDifferenceMileage);
|
// // 如果md小数位是0 那么舍弃小数,如果小数位不为0 那么进1
|
// fareBreakdownDetailVo.setMileage(new BigDecimal(md).setScale(2, RoundingMode.HALF_UP));
|
// Integer temp = (int)md;
|
// if (md> temp){
|
// temp=temp+1;
|
// }
|
// // 超出的里程
|
// fareBreakdownDetailVo.setMoney(new BigDecimal(temp*6));
|
// mileage.add(fareBreakdownDetailVo);
|
// // 修改时段标识
|
// mileageType = mileageTypeTemp;
|
// // 修改新时段开始时间
|
// endDate = mileageDate;
|
// }else{
|
// // 时段未变化
|
// }
|
// }
|
// }
|
// }
|
// // 开始计算里程费用
|
// for (OrderTrajectory trajectory : trajectories) {
|
// Long locatetime = trajectory.getLocatetime();
|
// Date mileageDate = new Date(locatetime);
|
// LocalDateTime begin = DateUtils.dateToLocalDateTime(mileageDate);
|
// // 行驶里程大于起步里程配置 开始计算里程和里程费
|
// if (begin.isAfter(tripBegin)) {
|
// totalDistance += trajectory.getDistance();
|
// double v = totalDistance / 1000.0;
|
// if (v >= Double.parseDouble(num5)) {
|
// // 增加超出起步里程的里程数
|
// mileageDistance += trajectory.getDistance();
|
//
|
// }
|
// if (mileageType == 0) {
|
// // 第一次计算里程费
|
//
|
// }
|
// }
|
// }
|
// } else {
|
//
|
// }
|
//
|
//// XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationPrice(
|
//// order.getAppUserId().toString(),JSON.parseObject(pricing.getBasicPricingJson()),
|
//// JSON.parseArray(pricing.getStartingFareJson()),
|
//// pricing.getDynamicPricingJson(),
|
//// pricing.getIsDynamicPrice(),
|
//// totalDistance,
|
//// seconds,
|
//// order.getCityId()
|
//// );
|
|
|
}
|
|
|
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<OrderTrajectory> 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<FareBreakdownDetailVo> 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(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<FareBreakdownVo> fareBreakdown(Long orderId, String uid) {
|
XpOrder order = this.getById(orderId);
|
// 查询订单轨迹
|
List<OrderTrajectory> trajectories = mongoTemplate.find(
|
new Query(Criteria.where("orderId").is(orderId))
|
.with(Sort.by(Sort.Direction.ASC, "locatetime")),
|
OrderTrajectory.class
|
);
|
// 计算订单总行驶距离,单位米
|
Double totalDistance = 0.00D;
|
for (OrderTrajectory trajectory : trajectories) {
|
|
|
}
|
FareBreakdownVo fareBreakdownVo = new FareBreakdownVo();
|
// fareBreakdownVo.setStart();
|
// fareBreakdownVo.setMileage();
|
// fareBreakdownVo.setDuration();
|
// fareBreakdownVo.setLongDistance();
|
// fareBreakdownVo.setRedPacketMoney();
|
// fareBreakdownVo.setCouponMoney();
|
// fareBreakdownVo.setOrderMoney();
|
|
// BeanUtils.copyProperties(order, fareBreakdownVo);
|
// fareBreakdownVo.setTotalKilometers(
|
// BigDecimal.valueOf(order.getStartMileage() + order.getMileageKilometers() + order.getLongDistance())
|
// );
|
// LocalDateTime createTime = order.getCreateTime();
|
// LocalDateTime tripEnd = order.getTripEnd();
|
// // 计算行程时间 单位分钟
|
//
|
// // 计算时间差
|
// Duration duration = Duration.between(createTime, tripEnd);
|
//
|
// // 转换为分钟并保留一位小数
|
// BigDecimal minutes = BigDecimal.valueOf(duration.getSeconds())
|
// .divide(BigDecimal.valueOf(60), 1, RoundingMode.HALF_UP);
|
//
|
// fareBreakdownVo.setTotalTime(minutes);
|
return R.ok(fareBreakdownVo);
|
}
|
|
@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<XpOrder>().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<String, Double> 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());
|
XpFeedbackType feedbackType = xpSystemSettingClient.getFeedbackTypeById(evaluate.getFeedbackTypeId()).getData();
|
orderDetailVo.setFeedbackTypeName(feedbackType.getFeedbackType());
|
}
|
List<OrderTrajectory> trajectories = mongoTemplate.find(
|
new Query(Criteria.where("orderId").is(orderId))
|
.with(Sort.by(Sort.Direction.ASC, "locatetime")),
|
OrderTrajectory.class
|
);
|
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
|
// @ShardingTransactionType(TransactionType.BASE)
|
public void popOrder(PopOrderDto dto) {
|
|
XpOrder order = this.getById(dto.getOrderId());
|
order.setAcceptanceTime(LocalDateTime.now());
|
|
R<XpVehicle> byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin());
|
if (byVehicleVin.getCode()==200){
|
order.setVehicleId(byVehicleVin.getData().getId());
|
}
|
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);
|
|
}
|
|
|
/**
|
* 获取当前用户正在执行的订单
|
*
|
* @param uid
|
* @return
|
*/
|
@Override
|
public XpOrderDetailVO getActiveOrder(String uid) {
|
XpOrderDetailVO xpOrderDetailVO = new XpOrderDetailVO();
|
XpOrder xpOrder = this.baseMapper.selectOne(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, uid).in(XpOrder::getStatus, Arrays.asList(3, 4, 5, 6, 7, 8)).orderByDesc(BaseModel::getCreateTime).last("LIMIT 1"));
|
if (xpOrder == null) {
|
return xpOrderDetailVO;
|
}
|
BeanUtils.copyProperties(xpOrder, xpOrderDetailVO);
|
// 算时间
|
if (xpOrder.getStatus() == 1) {
|
R<Integer> 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;
|
}
|
}
|