|
@@ -3,12 +3,17 @@ package com.sckw.transport.service;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
+import com.google.common.collect.Lists;
|
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Maps;
|
|
|
|
|
+import com.google.common.collect.Sets;
|
|
|
import com.sckw.contract.api.RemoteContractService;
|
|
import com.sckw.contract.api.RemoteContractService;
|
|
|
import com.sckw.core.exception.BusinessException;
|
|
import com.sckw.core.exception.BusinessException;
|
|
|
import com.sckw.core.model.constant.UrlConstants;
|
|
import com.sckw.core.model.constant.UrlConstants;
|
|
|
import com.sckw.core.model.enums.AddressTypeEnum;
|
|
import com.sckw.core.model.enums.AddressTypeEnum;
|
|
|
import com.sckw.core.model.enums.CarWaybillEnum;
|
|
import com.sckw.core.model.enums.CarWaybillEnum;
|
|
|
|
|
+import com.sckw.core.model.enums.CarWaybillV1Enum;
|
|
|
import com.sckw.core.utils.DateUtils;
|
|
import com.sckw.core.utils.DateUtils;
|
|
|
import com.sckw.core.utils.HttpUtil;
|
|
import com.sckw.core.utils.HttpUtil;
|
|
|
import com.sckw.core.web.constant.CommonConstants;
|
|
import com.sckw.core.web.constant.CommonConstants;
|
|
@@ -19,6 +24,7 @@ import com.sckw.core.web.response.BaseResult;
|
|
|
import com.sckw.fleet.api.RemoteFleetService;
|
|
import com.sckw.fleet.api.RemoteFleetService;
|
|
|
import com.sckw.fleet.api.model.vo.RDriverVo;
|
|
import com.sckw.fleet.api.model.vo.RDriverVo;
|
|
|
import com.sckw.fleet.api.model.vo.RFleetDriverVo;
|
|
import com.sckw.fleet.api.model.vo.RFleetDriverVo;
|
|
|
|
|
+import com.sckw.fleet.api.model.vo.RFleetVo;
|
|
|
import com.sckw.fleet.api.model.vo.RTruckVo;
|
|
import com.sckw.fleet.api.model.vo.RTruckVo;
|
|
|
import com.sckw.manage.api.RemoteManageService;
|
|
import com.sckw.manage.api.RemoteManageService;
|
|
|
import com.sckw.order.api.dubbo.RemoteTradeOrderAmountService;
|
|
import com.sckw.order.api.dubbo.RemoteTradeOrderAmountService;
|
|
@@ -30,26 +36,22 @@ import com.sckw.system.api.RemoteSystemService;
|
|
|
import com.sckw.system.api.model.dto.res.EntCacheResDto;
|
|
import com.sckw.system.api.model.dto.res.EntCacheResDto;
|
|
|
import com.sckw.system.api.model.dto.res.KwsEnterpriseResDto;
|
|
import com.sckw.system.api.model.dto.res.KwsEnterpriseResDto;
|
|
|
import com.sckw.transport.common.config.UrlConfigProperties;
|
|
import com.sckw.transport.common.config.UrlConfigProperties;
|
|
|
-import com.sckw.transport.model.KwtLogisticsOrderUnit;
|
|
|
|
|
-import com.sckw.transport.model.KwtWaybillOrder;
|
|
|
|
|
-import com.sckw.transport.model.KwtWaybillOrderAddress;
|
|
|
|
|
-import com.sckw.transport.model.KwtWaybillOrderSubtask;
|
|
|
|
|
|
|
+import com.sckw.transport.model.*;
|
|
|
import com.sckw.transport.model.dto.TruckDto;
|
|
import com.sckw.transport.model.dto.TruckDto;
|
|
|
import com.sckw.transport.api.feign.VehicleTraceClient;
|
|
import com.sckw.transport.api.feign.VehicleTraceClient;
|
|
|
import com.sckw.transport.api.model.dto.VehicleDataDTO;
|
|
import com.sckw.transport.api.model.dto.VehicleDataDTO;
|
|
|
import com.sckw.transport.api.model.dto.VehicleReturnData;
|
|
import com.sckw.transport.api.model.dto.VehicleReturnData;
|
|
|
-import com.sckw.transport.api.model.vo.VehicleTraceResponse;
|
|
|
|
|
-import com.sckw.transport.model.param.CurrentTaskTraceReq;
|
|
|
|
|
-import com.sckw.transport.model.param.KwfTruckTraceReplayReq;
|
|
|
|
|
-import com.sckw.transport.model.param.TruckInfoReq;
|
|
|
|
|
-import com.sckw.transport.model.param.VehiclesTrajectoryReq;
|
|
|
|
|
|
|
+import com.sckw.transport.model.param.*;
|
|
|
|
|
+import com.sckw.transport.model.dto.GenerateTraceReq;
|
|
|
import com.sckw.transport.model.vo.CurrentTaskTraceReqVo;
|
|
import com.sckw.transport.model.vo.CurrentTaskTraceReqVo;
|
|
|
import com.sckw.transport.model.vo.KwfTruckTraceReplayVo;
|
|
import com.sckw.transport.model.vo.KwfTruckTraceReplayVo;
|
|
|
import com.sckw.transport.model.vo.TruckInfoVo;
|
|
import com.sckw.transport.model.vo.TruckInfoVo;
|
|
|
-import com.sckw.transport.repository.KwtLogisticsOrderUnitRepository;
|
|
|
|
|
-import com.sckw.transport.repository.KwtWaybillOrderAddressRepository;
|
|
|
|
|
-import com.sckw.transport.repository.KwtWaybillOrderRepository;
|
|
|
|
|
-import com.sckw.transport.repository.KwtWaybillOrderSubtaskRepository;
|
|
|
|
|
|
|
+import com.sckw.transport.model.vo.TruckSelectVo;
|
|
|
|
|
+import com.sckw.transport.model.dto.TruckSelectReq;
|
|
|
|
|
+import com.sckw.transport.model.dto.MapVehicleQueryReq;
|
|
|
|
|
+import com.sckw.transport.model.vo.MapVehicleVo;
|
|
|
|
|
+import com.sckw.transport.model.enuma.MapVehicleSortTypeEnum;
|
|
|
|
|
+import com.sckw.transport.repository.*;
|
|
|
import com.sckw.transport.response.CollectZjxlResponse;
|
|
import com.sckw.transport.response.CollectZjxlResponse;
|
|
|
import com.sckw.transport.service.zj.VehicleCollectService;
|
|
import com.sckw.transport.service.zj.VehicleCollectService;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
@@ -64,11 +66,14 @@ import java.time.Duration;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneOffset;
|
|
import java.time.ZoneOffset;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.function.Function;
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
+import lombok.Data;
|
|
|
|
|
+
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @author PC
|
|
* @author PC
|
|
@@ -84,6 +89,9 @@ public class kwfTruckTraceService {
|
|
|
private final VehicleCollectService vehicleCollectService;
|
|
private final VehicleCollectService vehicleCollectService;
|
|
|
private final KwtLogisticsOrderUnitRepository kwtLogisticsOrderUnitRepository;
|
|
private final KwtLogisticsOrderUnitRepository kwtLogisticsOrderUnitRepository;
|
|
|
private final VehicleTraceClient vehicleTraceClient;
|
|
private final VehicleTraceClient vehicleTraceClient;
|
|
|
|
|
+ private final KwtLogisticsOrderGoodsRepository kwtLogisticsOrderGoodsRepository;
|
|
|
|
|
+ private final KwtLogisticsOrderRepository kwtLogisticsOrderRepository;
|
|
|
|
|
+ private final KwtVehicleExceptionRepository kwtVehicleExceptionRepository;
|
|
|
@DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
|
|
@DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
|
|
|
RemoteSystemService remoteSystemService;
|
|
RemoteSystemService remoteSystemService;
|
|
|
|
|
|
|
@@ -536,14 +544,14 @@ public class kwfTruckTraceService {
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
// 使用 Feign 调用查询实时位置
|
|
// 使用 Feign 调用查询实时位置
|
|
|
- BaseResult<VehicleTraceResponse> result = vehicleTraceClient.queryRealTimeLocation(vehicleDataDTO);
|
|
|
|
|
|
|
+ BaseResult<VehicleReturnData> result = vehicleTraceClient.queryRealTimeLocation(vehicleDataDTO);
|
|
|
|
|
|
|
|
if (result == null || result.getCode() != HttpStatus.SUCCESS_CODE || result.getData() == null) {
|
|
if (result == null || result.getCode() != HttpStatus.SUCCESS_CODE || result.getData() == null) {
|
|
|
log.warn("查询实时轨迹返回空数据, 车牌号: {}", truckId);
|
|
log.warn("查询实时轨迹返回空数据, 车牌号: {}", truckId);
|
|
|
return null;
|
|
return null;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return result.getData().getData();
|
|
|
|
|
|
|
+ return result.getData();
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("查询任务轨迹异常, 车牌号: {}", truckId, e);
|
|
log.error("查询任务轨迹异常, 车牌号: {}", truckId, e);
|
|
|
return null;
|
|
return null;
|
|
@@ -668,4 +676,647 @@ public class kwfTruckTraceService {
|
|
|
truckDto.setTaskAddress(taskAddress);
|
|
truckDto.setTaskAddress(taskAddress);
|
|
|
return truckDto;
|
|
return truckDto;
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 查询车辆下拉列表(支持多选和输入匹配)
|
|
|
|
|
+ * @param req 查询请求
|
|
|
|
|
+ * @return 车辆下拉列表
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<TruckSelectVo> getTruckSelectList(TruckSelectReq req) {
|
|
|
|
|
+ log.info("查询车辆下拉列表参数:{}", JSON.toJSONString( req));
|
|
|
|
|
+
|
|
|
|
|
+ // 使用 Repository 查询车辆运单数据
|
|
|
|
|
+ List<KwtWaybillOrder> waybillOrders = kwtWaybillOrderRepository.selectTruckListForSelect(req.getTruckNo());
|
|
|
|
|
+
|
|
|
|
|
+ if (CollectionUtils.isEmpty(waybillOrders)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取所有车牌号列表,用于查询实时位置
|
|
|
|
|
+ List<String> truckNos = waybillOrders.stream()
|
|
|
|
|
+ .map(KwtWaybillOrder::getTruckNo)
|
|
|
|
|
+ .distinct()
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 批量查询实时位置状态(30分钟内有数据为在线)
|
|
|
|
|
+ Map<String, Integer> truckLocationStatusMap = getStringIntegerMap(truckNos);
|
|
|
|
|
+
|
|
|
|
|
+ // 转换为 VO 对象并根据状态筛选
|
|
|
|
|
+ return waybillOrders.stream()
|
|
|
|
|
+ .map(order -> getTruckSelectVo(order, truckLocationStatusMap))
|
|
|
|
|
+ // 根据请求参数筛选定位状态
|
|
|
|
|
+ .filter(vo -> req.getLocationStatus() == null || vo.getLocationStatus().equals(req.getLocationStatus()))
|
|
|
|
|
+ .sorted(Comparator.comparing(TruckSelectVo::getLocationStatus).reversed())
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private Map<String, Integer> getStringIntegerMap(List<String> truckNos) {
|
|
|
|
|
+ Map<String, Integer> truckLocationStatusMap = new HashMap<>();
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ LocalDateTime thirtyMinutesAgo = now.minusMinutes(30);
|
|
|
|
|
+
|
|
|
|
|
+ for (String truckNo : truckNos) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
|
|
|
|
|
+ vehicleDataDTO.setCarNo(truckNo);
|
|
|
|
|
+ BaseResult<VehicleReturnData> result = vehicleTraceClient.queryRealTimeLocation(vehicleDataDTO);
|
|
|
|
|
+
|
|
|
|
|
+ if (result == null || result.getCode() != HttpStatus.SUCCESS_CODE || result.getData() == null) {
|
|
|
|
|
+ // 无定位数据,设置为离线
|
|
|
|
|
+ truckLocationStatusMap.put(truckNo, 0);
|
|
|
|
|
+ return truckLocationStatusMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ VehicleReturnData vehicleData = result.getData();
|
|
|
|
|
+
|
|
|
|
|
+ // 判断定位时间是否在30分钟内
|
|
|
|
|
+ if (vehicleData.getTs() == null) {
|
|
|
|
|
+ // 无GPS时间,设置为离线
|
|
|
|
|
+ truckLocationStatusMap.put(truckNo, 0);
|
|
|
|
|
+ return truckLocationStatusMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 30分钟内为在线
|
|
|
|
|
+ if (vehicleData.getTs().isAfter(thirtyMinutesAgo)) {
|
|
|
|
|
+ truckLocationStatusMap.put(truckNo, 1);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ truckLocationStatusMap.put(truckNo, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("查询车辆实时位置异常, 车牌号: {}", truckNo, e);
|
|
|
|
|
+ truckLocationStatusMap.put(truckNo, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return truckLocationStatusMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private static TruckSelectVo getTruckSelectVo(KwtWaybillOrder order, Map<String, Integer> truckLocationStatusMap) {
|
|
|
|
|
+ TruckSelectVo vo = new TruckSelectVo();
|
|
|
|
|
+ vo.setTruckId(order.getTruckId());
|
|
|
|
|
+ vo.setTruckNo(order.getTruckNo());
|
|
|
|
|
+ vo.setDriverName(order.getDriverName());
|
|
|
|
|
+ vo.setDriverPhone(order.getDriverPhone());
|
|
|
|
|
+ vo.setStatus(order.getStatus());
|
|
|
|
|
+ vo.setStatusDesc(CarWaybillEnum.getName(order.getStatus()));
|
|
|
|
|
+
|
|
|
|
|
+ // 设置定位状态
|
|
|
|
|
+ Integer locationStatus = truckLocationStatusMap.getOrDefault(order.getTruckNo(), 0);
|
|
|
|
|
+ vo.setLocationStatus(locationStatus);
|
|
|
|
|
+ vo.setLocationStatusDesc(locationStatus == 1 ? "在线" : "离线");
|
|
|
|
|
+
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 分页查询地图车辆列表
|
|
|
|
|
+ * @param req 查询请求
|
|
|
|
|
+ * @return 分页结果
|
|
|
|
|
+ */
|
|
|
|
|
+ public PageDataResult<MapVehicleVo> queryMapVehicleList(MapVehicleQueryReq req) {
|
|
|
|
|
+ log.info("分页查询地图车辆列表参数:{}", req);
|
|
|
|
|
+ Set<Long> allEnt = getAllEnt();
|
|
|
|
|
+ // 处理日期参数,默认为当天
|
|
|
|
|
+ Date startDate = getDate(req.getStartDate());
|
|
|
|
|
+ Date endDate = getDate(req.getEndDate());
|
|
|
|
|
+
|
|
|
|
|
+ // 进行中任务状态:已接单(1)、到达装货点(5)、已装货(10)、已离场(15)
|
|
|
|
|
+ List<Integer> taskingStatus = Lists.newArrayList();
|
|
|
|
|
+ if (Objects.nonNull(req.getStatus())) {
|
|
|
|
|
+ taskingStatus.add(req.getStatus());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ taskingStatus.addAll(Arrays.asList(CarWaybillV1Enum.PENDING_VEHICLE.getCode(), CarWaybillV1Enum.REFUSE_TRAFFIC.getCode(),
|
|
|
|
|
+ CarWaybillV1Enum.EXIT_COMPLETED.getCode(), CarWaybillV1Enum.WAIT_LOADING.getCode()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 前置条件:根据承运单位和托运单位筛选出符合条件的运单ID
|
|
|
|
|
+ Set<Long> wayOrderIds = getWayOrderIds(req);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(wayOrderIds) && (StringUtils.isNotBlank(req.getLOrderNo()) || Objects.nonNull(req.getCarrierEntId()) || Objects.nonNull(req.getConsignEntId()))){
|
|
|
|
|
+ return PageDataResult.empty(req.getPageNum(), req.getPageSize());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 使用 MyBatis-Plus 分页查询(如果有前置筛选条件,则添加运单ID的IN条件)
|
|
|
|
|
+
|
|
|
|
|
+ IPage<KwtWaybillOrder> page = kwtWaybillOrderRepository.queryMapVehicleListPage(allEnt,startDate, endDate, taskingStatus, wayOrderIds, req.getPageNum(),req.getPageSize() );
|
|
|
|
|
+
|
|
|
|
|
+ List<KwtWaybillOrder> waybillOrders = page.getRecords();
|
|
|
|
|
+ if (CollectionUtils.isEmpty(waybillOrders)) {
|
|
|
|
|
+ return PageDataResult.empty(req.getPageNum(), req.getPageSize());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取运单ID列表
|
|
|
|
|
+ List<Long> wOrderIds = waybillOrders.stream()
|
|
|
|
|
+ .map(KwtWaybillOrder::getId)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 查询子运单信息
|
|
|
|
|
+ List<KwtWaybillOrderSubtask> subtasks = kwtWaybillOrderSubtaskRepository.queryByWOrderIds(wOrderIds);
|
|
|
|
|
+ final Map<Long, KwtWaybillOrderSubtask> wOrderIdSubtaskMap;
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(subtasks)) {
|
|
|
|
|
+ wOrderIdSubtaskMap = subtasks.stream()
|
|
|
|
|
+ .filter(subtask -> subtask.getWOrderId() != null)
|
|
|
|
|
+ .collect(Collectors.toMap(KwtWaybillOrderSubtask::getWOrderId, Function.identity(), (k1, k2) -> k1));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ wOrderIdSubtaskMap = new HashMap<>();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取物流订单ID
|
|
|
|
|
+ Set<Long> lOrderIds = new HashSet<>();
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(subtasks)) {
|
|
|
|
|
+ lOrderIds = subtasks.stream()
|
|
|
|
|
+ .map(KwtWaybillOrderSubtask::getLOrderId)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<KwtLogisticsOrderUnit> logisticsOrderUnits = Lists.newArrayList();
|
|
|
|
|
+ List<KwtLogisticsOrderGoods> goodsList = Lists.newArrayList();
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(lOrderIds)) {
|
|
|
|
|
+ // 查询托运企业和承运企业
|
|
|
|
|
+ logisticsOrderUnits = kwtLogisticsOrderUnitRepository.queryByLOrderIds(new ArrayList<>(lOrderIds));
|
|
|
|
|
+ // 查询商品信息
|
|
|
|
|
+ goodsList = kwtLogisticsOrderGoodsRepository.queryByLOrderIds(new ArrayList<>(lOrderIds));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 按物流订单ID和单位类型分组
|
|
|
|
|
+ Map<String, KwtLogisticsOrderUnit> unitMap =new HashMap<>();
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(logisticsOrderUnits)) {
|
|
|
|
|
+ unitMap = logisticsOrderUnits.stream()
|
|
|
|
|
+ .filter(unit -> unit.getLOrderId() != null && unit.getUnitType() != null)
|
|
|
|
|
+ .collect(Collectors.toMap(
|
|
|
|
|
+ unit -> unit.getLOrderId() + "_" + unit.getUnitType(),
|
|
|
|
|
+ Function.identity(),
|
|
|
|
|
+ (k1, k2) -> k1
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ Map<Long, KwtLogisticsOrderGoods> goodsMap =new HashMap<>();
|
|
|
|
|
+ if (CollectionUtils.isNotEmpty(goodsList)) {
|
|
|
|
|
+ goodsMap = goodsList.stream()
|
|
|
|
|
+ .filter(goods -> goods.getLOrderId() != null)
|
|
|
|
|
+ .collect(Collectors.toMap(KwtLogisticsOrderGoods::getLOrderId, Function.identity(), (k1, k2) -> k1));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取车牌号列表,查询定位信息
|
|
|
|
|
+ List<String> truckNos = waybillOrders.stream()
|
|
|
|
|
+ .map(KwtWaybillOrder::getTruckNo)
|
|
|
|
|
+ .distinct()
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 批量查询定位状态和位置信息
|
|
|
|
|
+ Map<String, VehicleLocationInfo> locationInfoMap = queryVehicleLocationBatch(truckNos);
|
|
|
|
|
+
|
|
|
|
|
+ // 批量查询运单轨迹数据,统计异常数量(通过alarmCode判断)
|
|
|
|
|
+ List<String> wOrderNos = waybillOrders.stream()
|
|
|
|
|
+ .map(KwtWaybillOrder::getWOrderNo)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .distinct()
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ Map<String, Integer> exceptionCountMap = countExceptionsByTraceData(wOrderNos);
|
|
|
|
|
+
|
|
|
|
|
+ // 根据定位状态筛选(这个筛选保留在内存中,因为涉及外部服务调用)
|
|
|
|
|
+ List<KwtWaybillOrder> filteredOrders = waybillOrders;
|
|
|
|
|
+ if (req.getLocationStatus() != null) {
|
|
|
|
|
+ filteredOrders = waybillOrders.stream()
|
|
|
|
|
+ .filter(order -> {
|
|
|
|
|
+ VehicleLocationInfo locationInfo = locationInfoMap.get(order.getTruckNo());
|
|
|
|
|
+ return locationInfo != null && req.getLocationStatus().equals(locationInfo.getLocationStatus());
|
|
|
|
|
+ })
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 转换为 VO
|
|
|
|
|
+ Map<String, KwtLogisticsOrderUnit> finalUnitMap = unitMap;
|
|
|
|
|
+ Map<Long, KwtLogisticsOrderGoods> finalGoodsMap = goodsMap;
|
|
|
|
|
+ List<MapVehicleVo> result = filteredOrders.stream()
|
|
|
|
|
+ .map(order -> buildMapVehicleVo(order, wOrderIdSubtaskMap, finalUnitMap, finalGoodsMap, locationInfoMap, exceptionCountMap))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 根据排序类型进行排序
|
|
|
|
|
+ MapVehicleSortTypeEnum sortType = MapVehicleSortTypeEnum.getByCode(req.getSortType());
|
|
|
|
|
+ result = switch (sortType) {
|
|
|
|
|
+ case TIME_DESC ->
|
|
|
|
|
+ // 按任务开始时间倒序
|
|
|
|
|
+ result.stream()
|
|
|
|
|
+ .sorted(Comparator.comparing(MapVehicleVo::getTaskStartTime,
|
|
|
|
|
+ Comparator.nullsLast(Comparator.reverseOrder())))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ case DURATION_DESC ->
|
|
|
|
|
+ // 按任务耗时倒序
|
|
|
|
|
+ result.stream()
|
|
|
|
|
+ .sorted(Comparator.comparing(MapVehicleVo::getTaskDuration,
|
|
|
|
|
+ Comparator.nullsLast(Comparator.reverseOrder())))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ case EXCEPTION_COUNT_DESC ->
|
|
|
|
|
+ // 按异常数量倒序
|
|
|
|
|
+ result.stream()
|
|
|
|
|
+ .sorted(Comparator.comparing(MapVehicleVo::getExceptionCount,
|
|
|
|
|
+ Comparator.nullsLast(Comparator.reverseOrder())))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 返回分页结果(使用数据库分页的总数)
|
|
|
|
|
+ return PageDataResult.of(page, result);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private Set<Long> getWayOrderIds(MapVehicleQueryReq req) {
|
|
|
|
|
+ Set<Long> wayOrderIds = Sets.newHashSet();
|
|
|
|
|
+ if (req.getConsignEntId() != null || req.getCarrierEntId() != null) {
|
|
|
|
|
+ // 第一步:从物流订单单位表查询符合条件的物流订单ID
|
|
|
|
|
+ // 同时有托运和承运单位条件,将企业ID和类型组合后批量查询
|
|
|
|
|
+ List<Long> entIds = Arrays.asList(req.getConsignEntId(), req.getCarrierEntId());
|
|
|
|
|
+
|
|
|
|
|
+ List<KwtLogisticsOrderUnit> allUnits = kwtLogisticsOrderUnitRepository.list(
|
|
|
|
|
+ Wrappers.<KwtLogisticsOrderUnit>lambdaQuery()
|
|
|
|
|
+ .eq(KwtLogisticsOrderUnit::getDelFlag, 0)
|
|
|
|
|
+ .in(KwtLogisticsOrderUnit::getEntId, entIds)
|
|
|
|
|
+ .in(KwtLogisticsOrderUnit::getUnitType, Arrays.asList(1, 2)));
|
|
|
|
|
+ if (CollectionUtils.isEmpty(allUnits)) {
|
|
|
|
|
+ return Set.of();
|
|
|
|
|
+ }
|
|
|
|
|
+ Set<Long> lOrderIds = allUnits.stream()
|
|
|
|
|
+ .map(KwtLogisticsOrderUnit::getLOrderId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+ if (CollectionUtils.isEmpty(lOrderIds)) {
|
|
|
|
|
+ return Set.of();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 第二步:根据物流订单ID查询子运单
|
|
|
|
|
+ List<KwtWaybillOrderSubtask> subtasks = kwtWaybillOrderSubtaskRepository.list(
|
|
|
|
|
+ Wrappers.<KwtWaybillOrderSubtask>lambdaQuery()
|
|
|
|
|
+ .eq(KwtWaybillOrderSubtask::getDelFlag, 0)
|
|
|
|
|
+ .in(KwtWaybillOrderSubtask::getLOrderId, lOrderIds));
|
|
|
|
|
+
|
|
|
|
|
+ if (CollectionUtils.isEmpty(subtasks)) {
|
|
|
|
|
+ return Set.of();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 第三步:获取运单ID
|
|
|
|
|
+ wayOrderIds = subtasks.stream()
|
|
|
|
|
+ .map(KwtWaybillOrderSubtask::getWOrderId)
|
|
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
+
|
|
|
|
|
+ if (CollectionUtils.isEmpty(wayOrderIds)) {
|
|
|
|
|
+ return Set.of();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isNotBlank(req.getLOrderNo())) {
|
|
|
|
|
+ // 获取物流订单ID
|
|
|
|
|
+ KwtLogisticsOrder logOrder = kwtLogisticsOrderRepository.queryByLogisticOrderNo(req.getLOrderNo());
|
|
|
|
|
+ if (Objects.isNull(logOrder)) {
|
|
|
|
|
+ return Set.of();
|
|
|
|
|
+ }
|
|
|
|
|
+ wayOrderIds.add(logOrder.getId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return wayOrderIds;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private static Date getDate(String date) {
|
|
|
|
|
+ Date startDate;
|
|
|
|
|
+ if (StringUtils.isBlank(date)) {
|
|
|
|
|
+ startDate = DateUtils.getStartOfDay(new Date());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ try {
|
|
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
|
|
+ startDate = sdf.parse(date);
|
|
|
|
|
+ startDate = DateUtils.getStartOfDay(startDate);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("解析开始日期失败", e);
|
|
|
|
|
+ startDate = DateUtils.getStartOfDay(new Date());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return startDate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 批量查询车辆定位信息
|
|
|
|
|
+ */
|
|
|
|
|
+ private Map<String, VehicleLocationInfo> queryVehicleLocationBatch(List<String> truckNos) {
|
|
|
|
|
+ Map<String, VehicleLocationInfo> locationInfoMap = new HashMap<>();
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+ LocalDateTime thirtyMinutesAgo = now.minusMinutes(30);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(truckNos)){
|
|
|
|
|
+ return locationInfoMap;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (String truckNo : truckNos) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
|
|
|
|
|
+ vehicleDataDTO.setCarNo(truckNo);
|
|
|
|
|
+ BaseResult<VehicleReturnData> result = vehicleTraceClient.queryRealTimeLocation(vehicleDataDTO);
|
|
|
|
|
+
|
|
|
|
|
+ VehicleLocationInfo locationInfo = new VehicleLocationInfo();
|
|
|
|
|
+
|
|
|
|
|
+ if (result != null && result.getCode() == 200 && result.getData() != null) {
|
|
|
|
|
+ VehicleReturnData vehicleData = result.getData();
|
|
|
|
|
+
|
|
|
|
|
+ // 判断定位状态
|
|
|
|
|
+ if (vehicleData.getTs() != null && vehicleData.getTs().isAfter(thirtyMinutesAgo)) {
|
|
|
|
|
+ locationInfo.setLocationStatus(1);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ locationInfo.setLocationStatus(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ locationInfo.setLongitude(vehicleData.getLongitude());
|
|
|
|
|
+ locationInfo.setLatitude(vehicleData.getLatitude());
|
|
|
|
|
+ if (vehicleData.getTs() != null) {
|
|
|
|
|
+ locationInfo.setLocationTime(vehicleData.getTs().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
|
|
|
|
+ }
|
|
|
|
|
+ locationInfo.setStatus(vehicleData.getStatus());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ locationInfo.setLocationStatus(0);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ locationInfoMap.put(truckNo, locationInfo);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("查询车辆定位信息异常, 车牌号: {}", truckNo, e);
|
|
|
|
|
+ VehicleLocationInfo locationInfo = new VehicleLocationInfo();
|
|
|
|
|
+ locationInfo.setLocationStatus(0);
|
|
|
|
|
+ locationInfoMap.put(truckNo, locationInfo);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return locationInfoMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 批量查询运单轨迹数据并统计异常数量
|
|
|
|
|
+ * 通过调用VehicleTraceClient#queryVehicleDataList查询轨迹,统计alarmCode不为空的数据为异常
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param wOrderNos 运单号列表
|
|
|
|
|
+ * @return 运单号对应的异常数量 Map
|
|
|
|
|
+ */
|
|
|
|
|
+ private Map<String, Integer> countExceptionsByTraceData(List<String> wOrderNos) {
|
|
|
|
|
+ Map<String, Integer> exceptionCountMap = new HashMap<>();
|
|
|
|
|
+
|
|
|
|
|
+ if (CollectionUtils.isEmpty(wOrderNos)) {
|
|
|
|
|
+ return exceptionCountMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 批量查询每个运单的轨迹数据
|
|
|
|
|
+ for (String wOrderNo : wOrderNos) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
|
|
|
|
|
+ vehicleDataDTO.setWOrderNo(wOrderNo);
|
|
|
|
|
+
|
|
|
|
|
+ // 调用Feign接口查询轨迹列表
|
|
|
|
|
+ BaseResult<List<com.sckw.transport.api.model.dto.VehicleReturnData>> result =
|
|
|
|
|
+ vehicleTraceClient.queryVehicleDataList(vehicleDataDTO);
|
|
|
|
|
+
|
|
|
|
|
+ if (result != null && result.getCode() == HttpStatus.SUCCESS_CODE && result.getData() != null) {
|
|
|
|
|
+ List<com.sckw.transport.api.model.dto.VehicleReturnData> traceDataList = result.getData();
|
|
|
|
|
+
|
|
|
|
|
+ // 统计alarmCode不为null且不为0的记录数量(表示有异常报警)
|
|
|
|
|
+ int exceptionCount = (int) traceDataList.stream()
|
|
|
|
|
+ .filter(data -> StringUtils.equals(data.getStatus(),"0"))
|
|
|
|
|
+ .count();
|
|
|
|
|
+
|
|
|
|
|
+ exceptionCountMap.put(wOrderNo, exceptionCount);
|
|
|
|
|
+ log.debug("运单号: {}, 异常数量: {}", wOrderNo, exceptionCount);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.warn("查询运单轨迹数据失败或返回空数据, 运单号: {}", wOrderNo);
|
|
|
|
|
+ exceptionCountMap.put(wOrderNo, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("查询运单轨迹数据异常, 运单号: {}", wOrderNo, e);
|
|
|
|
|
+ exceptionCountMap.put(wOrderNo, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return exceptionCountMap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 构建地图车辆VO
|
|
|
|
|
+ */
|
|
|
|
|
+ private MapVehicleVo buildMapVehicleVo(KwtWaybillOrder order,
|
|
|
|
|
+ Map<Long, KwtWaybillOrderSubtask> subtaskMap,
|
|
|
|
|
+ Map<String, KwtLogisticsOrderUnit> unitMap,
|
|
|
|
|
+ Map<Long, KwtLogisticsOrderGoods> goodsMap,
|
|
|
|
|
+ Map<String, VehicleLocationInfo> locationInfoMap,
|
|
|
|
|
+ Map<String, Integer> exceptionCountMap) {
|
|
|
|
|
+ MapVehicleVo vo = new MapVehicleVo();
|
|
|
|
|
+
|
|
|
|
|
+ // 车辆和司机信息
|
|
|
|
|
+ vo.setTruckNo(order.getTruckNo());
|
|
|
|
|
+ vo.setTruckId(order.getTruckId());
|
|
|
|
|
+ vo.setDriverName(order.getDriverName());
|
|
|
|
|
+ vo.setDriverPhone(order.getDriverPhone());
|
|
|
|
|
+ vo.setWOrderNo(order.getWOrderNo());
|
|
|
|
|
+ vo.setStatus(order.getStatus());
|
|
|
|
|
+ vo.setStatusDesc(CarWaybillEnum.getName(order.getStatus()));
|
|
|
|
|
+
|
|
|
|
|
+ // 子运单信息
|
|
|
|
|
+ KwtWaybillOrderSubtask subtask = subtaskMap.get(order.getId());
|
|
|
|
|
+ if (subtask != null) {
|
|
|
|
|
+ vo.setLOrderNo(String.valueOf(subtask.getLOrderId()));
|
|
|
|
|
+ vo.setLoadAmount(subtask.getLoadAmount());
|
|
|
|
|
+ vo.setEntrustAmount(subtask.getEntrustAmount());
|
|
|
|
|
+ vo.setUnit(subtask.getUnit());
|
|
|
|
|
+
|
|
|
|
|
+ // 装货重量/任务量
|
|
|
|
|
+ String loadWeight = String.format("%s%s / %s%s",
|
|
|
|
|
+ subtask.getLoadAmount() != null ? subtask.getLoadAmount() : "0",
|
|
|
|
|
+ subtask.getUnit() != null ? subtask.getUnit() : "",
|
|
|
|
|
+ subtask.getEntrustAmount() != null ? subtask.getEntrustAmount() : "0",
|
|
|
|
|
+ subtask.getUnit() != null ? subtask.getUnit() : "");
|
|
|
|
|
+ vo.setLoadWeight(loadWeight);
|
|
|
|
|
+
|
|
|
|
|
+ // 托运单位
|
|
|
|
|
+ KwtLogisticsOrderUnit consignUnit = unitMap.get(subtask.getLOrderId() + "_1");
|
|
|
|
|
+ if (consignUnit != null) {
|
|
|
|
|
+ vo.setConsignUnit(consignUnit.getFirmName());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 承运单位
|
|
|
|
|
+ KwtLogisticsOrderUnit carrierUnit = unitMap.get(subtask.getLOrderId() + "_2");
|
|
|
|
|
+ if (carrierUnit != null) {
|
|
|
|
|
+ vo.setCarrierUnit(carrierUnit.getFirmName());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 商品信息
|
|
|
|
|
+ KwtLogisticsOrderGoods goods = goodsMap.get(subtask.getLOrderId());
|
|
|
|
|
+ if (goods != null) {
|
|
|
|
|
+ vo.setGoodsInfo(goods.getGoodsName());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 定位信息
|
|
|
|
|
+ VehicleLocationInfo locationInfo = locationInfoMap.get(order.getTruckNo());
|
|
|
|
|
+ if (locationInfo != null) {
|
|
|
|
|
+ vo.setLocationStatus(locationInfo.getLocationStatus());
|
|
|
|
|
+ vo.setLocationStatusDesc(locationInfo.getLocationStatus() == 1 ? "在线" : "离线");
|
|
|
|
|
+ vo.setLongitude(locationInfo.getLongitude());
|
|
|
|
|
+ vo.setLatitude(locationInfo.getLatitude());
|
|
|
|
|
+ vo.setLocation(locationInfo.getLocation());
|
|
|
|
|
+ vo.setLocationTime(locationInfo.getLocationTime());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ vo.setLocationStatus(0);
|
|
|
|
|
+ vo.setLocationStatusDesc("离线");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 任务开始时间
|
|
|
|
|
+ vo.setTaskStartTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(order.getCreateTime()));
|
|
|
|
|
+
|
|
|
|
|
+ // 计算任务耗时(分钟)
|
|
|
|
|
+ Date startTime = order.getCreateTime();
|
|
|
|
|
+ Date endTime = new Date();
|
|
|
|
|
+ if (Objects.equals(order.getStatus(), CarWaybillV1Enum.WAIT_UNLOADING.getCode())){
|
|
|
|
|
+ endTime = order.getUpdateTime() != null ? order.getUpdateTime() : new Date();
|
|
|
|
|
+ }
|
|
|
|
|
+ long duration = (endTime.getTime() - startTime.getTime()) / (1000 * 60);
|
|
|
|
|
+ vo.setTaskDuration(duration);
|
|
|
|
|
+
|
|
|
|
|
+ // 从异常表查询该运单的异常数量
|
|
|
|
|
+ Integer exceptionCount = exceptionCountMap.getOrDefault(order.getWOrderNo(), 0);
|
|
|
|
|
+ vo.setExceptionCount(exceptionCount);
|
|
|
|
|
+
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 车辆定位信息内部类
|
|
|
|
|
+ */
|
|
|
|
|
+ @Data
|
|
|
|
|
+ private static class VehicleLocationInfo {
|
|
|
|
|
+ private Integer locationStatus;
|
|
|
|
|
+ private String longitude;
|
|
|
|
|
+ private String latitude;
|
|
|
|
|
+ private String location;
|
|
|
|
|
+ private String locationTime;
|
|
|
|
|
+ private String status;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private Set<Long> getAllEnt() {
|
|
|
|
|
+ Set<Long> allEnt = Sets.newHashSet();
|
|
|
|
|
+ //根据企业类型查询企业
|
|
|
|
|
+
|
|
|
|
|
+ allEnt.add( LoginUserHolder.getUserId());
|
|
|
|
|
+ EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(LoginUserHolder.getUserId());
|
|
|
|
|
+ if (Objects.nonNull(entCacheResDto)) {
|
|
|
|
|
+ EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
|
|
|
|
|
+ List<EntCacheResDto> child = entCacheResDto1.getChild();
|
|
|
|
|
+ if (com.sckw.core.utils.CollectionUtils.isNotEmpty(child)) {
|
|
|
|
|
+ allEnt.addAll(child.stream()
|
|
|
|
|
+ .map(EntCacheResDto::getId).toList());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return allEnt;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成车辆轨迹数据
|
|
|
|
|
+ * @param req 生成轨迹请求
|
|
|
|
|
+ */
|
|
|
|
|
+ public void generateTrace(GenerateTraceReq req) {
|
|
|
|
|
+ log.info("生成车辆轨迹参数:{}", JSON.toJSONString(req));
|
|
|
|
|
+
|
|
|
|
|
+ // 校验当前位置格式
|
|
|
|
|
+ String[] location = req.getCurrentLocation().split(",");
|
|
|
|
|
+ if (location.length != 2) {
|
|
|
|
|
+ throw new BusinessException("当前位置格式错误,应为:经度,纬度");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String longitude = location[0];
|
|
|
|
|
+ String latitude = location[1];
|
|
|
|
|
+
|
|
|
|
|
+ KwtWaybillOrder order = kwtWaybillOrderRepository.queryByWayOrderNo(req.getWOrderNo());
|
|
|
|
|
+ if (Objects.isNull(order)){
|
|
|
|
|
+ throw new BusinessException("运单不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ //查询子运单
|
|
|
|
|
+ KwtWaybillOrder subOrders = kwtWaybillOrderRepository.queryByBillOrderId(order.getLOrderId());
|
|
|
|
|
+ if (Objects.isNull(subOrders)){
|
|
|
|
|
+ throw new BusinessException("子运单不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ // 通过车牌id查询车队
|
|
|
|
|
+ RFleetVo fleetByTruckId = fleetService.findFleetByTruckId(order.getTruckId(), order.getEntId());
|
|
|
|
|
+ //查询物流订单号
|
|
|
|
|
+ KwtLogisticsOrder logisticsOrder = kwtLogisticsOrderRepository.queryByLogisticsOrderId(subOrders.getLOrderId());
|
|
|
|
|
+
|
|
|
|
|
+ // 构造轨迹数据
|
|
|
|
|
+ VehiclesTrajectoryReq vehiclesTrajectoryReq = getVehiclesTrajectoryReq(req, order, longitude, latitude, logisticsOrder, fleetByTruckId);
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 调用数据中台保存轨迹数据
|
|
|
|
|
+ BaseResult<Void> result = vehicleTraceClient.saveVehicleData(vehiclesTrajectoryReq);
|
|
|
|
|
+ if (result.getCode() != HttpStatus.SUCCESS_CODE) {
|
|
|
|
|
+ log.error("保存车辆轨迹数据失败:{}", result.getMessage());
|
|
|
|
|
+ throw new BusinessException("生成轨迹失败:" + result.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有异常类型,同时保存到本地车辆异常表
|
|
|
|
|
+ saveException(req, order, longitude, latitude);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("生成车辆轨迹成功,运单号:{},车牌号:{}", req.getWOrderNo(), req.getTruckNo());
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("生成车辆轨迹异常:", e);
|
|
|
|
|
+ throw new BusinessException("生成轨迹失败:" + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void saveException(GenerateTraceReq req, KwtWaybillOrder order, String longitude, String latitude) {
|
|
|
|
|
+ if (Objects.nonNull(req.getExceptionType())) {
|
|
|
|
|
+ // 保存到车辆异常表
|
|
|
|
|
+ KwtVehicleException vehicleException = new KwtVehicleException();
|
|
|
|
|
+ vehicleException.setEntId(order.getEntId());
|
|
|
|
|
+ vehicleException.setTruckId(order.getTruckId());
|
|
|
|
|
+ vehicleException.setTruckNo(req.getTruckNo());
|
|
|
|
|
+ vehicleException.setWOrderNo(req.getWOrderNo());
|
|
|
|
|
+ vehicleException.setDriverId(order.getDriverId());
|
|
|
|
|
+ vehicleException.setDriverName(order.getDriverName());
|
|
|
|
|
+ vehicleException.setDriverPhone(order.getDriverPhone());
|
|
|
|
|
+ vehicleException.setExceptionType(req.getExceptionType());
|
|
|
|
|
+ vehicleException.setLongitude(longitude);
|
|
|
|
|
+ vehicleException.setLatitude(latitude);
|
|
|
|
|
+ vehicleException.setExceptionTime(new Date());
|
|
|
|
|
+ vehicleException.setCreateBy(LoginUserHolder.getUserId());
|
|
|
|
|
+ vehicleException.setCreateTime(new Date());
|
|
|
|
|
+ vehicleException.setUpdateBy(LoginUserHolder.getUserId());
|
|
|
|
|
+ vehicleException.setUpdateTime(new Date());
|
|
|
|
|
+ vehicleException.setDelFlag(0);
|
|
|
|
|
+
|
|
|
|
|
+ // 保存异常信息
|
|
|
|
|
+ kwtVehicleExceptionRepository.save(vehicleException);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @NotNull
|
|
|
|
|
+ private static VehiclesTrajectoryReq getVehiclesTrajectoryReq(GenerateTraceReq req, KwtWaybillOrder order, String longitude, String latitude, KwtLogisticsOrder logisticsOrder, RFleetVo fleetByTruckId) {
|
|
|
|
|
+ VehiclesTrajectoryReq vehiclesTrajectoryReq = new VehiclesTrajectoryReq();
|
|
|
|
|
+ vehiclesTrajectoryReq.setTs(req.getDate() + " " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
|
|
|
|
+ vehiclesTrajectoryReq.setMobile(order.getDriverPhone());
|
|
|
|
|
+ vehiclesTrajectoryReq.setTruckNo(req.getTruckNo());
|
|
|
|
|
+ vehiclesTrajectoryReq.setLongitude(longitude);
|
|
|
|
|
+ vehiclesTrajectoryReq.setLatitude(latitude);
|
|
|
|
|
+ vehiclesTrajectoryReq.setSpeed(60.0f);
|
|
|
|
|
+ vehiclesTrajectoryReq.setGpsStatus("60");
|
|
|
|
|
+ vehiclesTrajectoryReq.setDirection(30.0f);
|
|
|
|
|
+ vehiclesTrajectoryReq.setFuelLevel(20.0f);
|
|
|
|
|
+ vehiclesTrajectoryReq.setMileage("60");
|
|
|
|
|
+ vehiclesTrajectoryReq.setEngineTemp(40.0f);
|
|
|
|
|
+ vehiclesTrajectoryReq.setBatteryVoltage(30.0f);
|
|
|
|
|
+ vehiclesTrajectoryReq.setStatus("0");
|
|
|
|
|
+ if (req.getExceptionType() != null){
|
|
|
|
|
+ vehiclesTrajectoryReq.setStatus(String.valueOf(req.getExceptionType()));
|
|
|
|
|
+ }
|
|
|
|
|
+ vehiclesTrajectoryReq.setWOrderNo(req.getWOrderNo());
|
|
|
|
|
+ vehiclesTrajectoryReq.setLOrderNo(Optional.ofNullable(logisticsOrder).map(KwtLogisticsOrder::getLOrderNo).orElse( ""));
|
|
|
|
|
+ VehiclesTrajectoryReq.VehicleDataVO vehicleDataVO = new VehiclesTrajectoryReq.VehicleDataVO();
|
|
|
|
|
+ vehicleDataVO.setCarNo(req.getTruckNo());
|
|
|
|
|
+ if (fleetByTruckId != null){
|
|
|
|
|
+ vehicleDataVO.setFleetId(fleetByTruckId.getId().toString());
|
|
|
|
|
+ vehicleDataVO.setFleetName(fleetByTruckId.getName());
|
|
|
|
|
+ }
|
|
|
|
|
+ vehiclesTrajectoryReq.setVehicleDataVO(vehicleDataVO);
|
|
|
|
|
+ return vehiclesTrajectoryReq;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|