🐛 未配载运次的计划时间取运单自身的值,详情与列表同源

运次读服务拼未配载运次时从不给 estimatedStartDate/estimatedEndDate 赋值,
而配载运次取配载单、是有值的。于是所有按运次读的出口里,普通运输一律没有计划时间:
调度端详情页「计划时间」显示 —,司机端列表卡片同理,而同一张运单在列表卡片上有值。

- 段一 select 补 estimated_start_time/estimated_end_time(不取这两列则仍为空)
- waybillTrip 从运单补计划时间,与 loadingTrip 取配载单同一口径
- 调度端、司机端卡片改为直接取运次字段,删掉未配载运单独走一次批量补查的分叉
- 司机端卡片的计划时间不再以「有配载单」为前提;运次级为空时不覆盖卡片已有值

库里本就为空的配载单(如未填日期的草稿)仍不显示,不编造值。
This commit is contained in:
2026-10-18 19:40:19 +08:00
parent d3705efa70
commit 04389cd9d5
5 changed files with 50 additions and 36 deletions
@@ -1086,10 +1086,16 @@ public class DriverWaybillServiceImpl implements IDriverWaybillService {
card.setVehicleNo(Func.toStr(trip.getVehicleNo(), ""));
card.setCreateTime(formatDateTime(trip.getSortTime()));
card.setPublishTime(card.getCreateTime());
// 计划时间与备注:配载运次取配载单,未配载的照运单卡片自己的值,不回填空
if (Func.isNotEmpty(card.getLoadingNo())) {
// 计划时间两条路同源:配载运次取配载单,未配载运次取那张运单自己的。
// 未配载详情进来时卡片已照运单填过,运次级为空就保留它,不覆盖成空
if (trip.getEstimatedStartDate() != null) {
card.setPlanShipTime(formatLocalDateYmd(trip.getEstimatedStartDate()));
}
if (trip.getEstimatedEndDate() != null) {
card.setPlanFinishTime(formatLocalDateYmd(trip.getEstimatedEndDate()));
}
// 备注只有配载运次有运次级的值,未配载的保留运单卡片自己带来的备注
if (Func.isNotEmpty(card.getLoadingNo())) {
card.setRemark(Func.toStr(trip.getTaskRemark(), ""));
}
card.setFromName(Func.toStrWithEmpty(trip.getDepartureName(), Func.toStr(trip.getDepartureAddress(), "")));
@@ -246,7 +246,7 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
}
/**
* 运次卡片页:一次算清这一页的重派标记、异常与未配载运次的计划时间,再逐条拼卡片
* 运次卡片页:一次算清这一页的重派标记与异常,再逐条拼卡片
*/
private Page<AdminWaybillCardVO> tripCardPage(List<TripVO> trips, int pageNo, int pageSize, long total,
Set<Long> exceptionWaybillIds) {
@@ -254,9 +254,8 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
if (!trips.isEmpty()) {
Set<String> reassignKeys = loadReassignTripKeys(
trips.stream().map(this::tripKeyOf).collect(Collectors.toCollection(LinkedHashSet::new)));
Map<Long, Waybill> loneWaybills = loadLoneWaybills(trips);
for (TripVO trip : trips) {
cards.add(toTripCard(trip, exceptionWaybillIds, reassignKeys, loneWaybills));
cards.add(toTripCard(trip, exceptionWaybillIds, reassignKeys));
}
}
Page<AdminWaybillCardVO> page = new Page<>(pageNo, pageSize, total);
@@ -265,12 +264,12 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
}
/**
* 运次卡片:展示单号、整趟车起/经/终与站点数、货物汇总都取运次字段。
* 运次卡片:展示单号、整趟车起/经/终与站点数、货物汇总、计划时间都取运次字段。
* 旧字段 id / waybillNo 保留运单语义(未配载就是这张运单,配载取第一张可见子运单),
* 打卡订正、重新派单等按运单进入的入口仍靠它们。
*/
private AdminWaybillCardVO toTripCard(TripVO trip, Set<Long> exceptionWaybillIds,
Set<String> reassignTripIds, Map<Long, Waybill> loneWaybills) {
Set<String> reassignTripIds) {
AdminWaybillCardVO card = new AdminWaybillCardVO();
List<TripVO.TripWaybillVO> children = trip.getWaybills() == null ? List.of() : trip.getWaybills();
Long firstChildId = children.isEmpty() ? null : parseId(children.get(0).getId());
@@ -293,15 +292,9 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
String weight = formatWeight(trip.getTotalQuantity(), trip.getQuantityUnit());
card.setWeight(weight);
card.setTotalWeight(weight);
if (loaded) {
card.setPlanTime(formatLocalDate(trip.getEstimatedStartDate()));
card.setPlanTimeEnd(formatLocalDate(trip.getEstimatedEndDate()));
} else {
// 未配载运次不带计划时间,按运单主键补一次;缺失时留空,不与其他运次串值
Waybill waybill = loneWaybills.get(parseId(trip.getId()));
card.setPlanTime(formatLocalDate(waybill == null ? null : waybill.getEstimatedStartTime()));
card.setPlanTimeEnd(formatLocalDate(waybill == null ? null : waybill.getEstimatedEndTime()));
}
// 计划时间两条路同源:配载运次取配载单,未配载运次取那张运单自己的
card.setPlanTime(formatLocalDate(trip.getEstimatedStartDate()));
card.setPlanTimeEnd(formatLocalDate(trip.getEstimatedEndDate()));
card.setStatus(trip.getStatus());
card.setDriverName(Func.toStr(trip.getDriverName(), ""));
card.setVehicleNo(Func.toStr(trip.getVehicleNo(), ""));
@@ -312,25 +305,6 @@ public class ManageWaybillServiceImpl implements IManageWaybillService {
return card;
}
/**
* 未配载运次(每张运单自成运次)的计划时间:运次读服务不下发它,一页一次批量补查
*/
private Map<Long, Waybill> loadLoneWaybills(List<TripVO> trips) {
Set<Long> loneIds = trips.stream()
.filter(trip -> Func.isEmpty(trip.getLoadingNo()))
.map(trip -> parseId(trip.getId()))
.filter(Objects::nonNull)
.collect(Collectors.toCollection(LinkedHashSet::new));
if (loneIds.isEmpty()) {
return Map.of();
}
return waybillService.list(Wrappers.<Waybill>lambdaQuery()
.select(Waybill::getId, Waybill::getEstimatedStartTime, Waybill::getEstimatedEndTime)
.in(Waybill::getId, loneIds))
.stream()
.collect(Collectors.toMap(Waybill::getId, Function.identity(), (first, ignored) -> first));
}
/** 这一页里带「子单被拒」标记的运次主键:判据与重派待办一致(已拒单 + 未取消未完成) */
private Set<String> loadReassignTripKeys(Set<String> tripIds) {
if (Func.isEmpty(tripIds)) {
@@ -231,7 +231,9 @@ public class TripQueryServiceImpl implements ITripQueryService {
Waybill::getCargoName, Waybill::getCargoType, Waybill::getQuantity, Waybill::getQuantityUnit,
Waybill::getDepartureName, Waybill::getDepartureAddress, Waybill::getArrivalName,
Waybill::getArrivalAddress, Waybill::getDriverName, Waybill::getDriverPhone, Waybill::getVehicleNo,
Waybill::getCustomerName, Waybill::getTransportType, Waybill::getTaskRemark, Waybill::getCreateTime)
Waybill::getCustomerName, Waybill::getTransportType, Waybill::getTaskRemark,
// 未配载运次没有配载单可依,计划时间要取运单自己的,故必须随行取回
Waybill::getEstimatedStartTime, Waybill::getEstimatedEndTime, Waybill::getCreateTime)
.in(Waybill::getBusinessStatus, TripAggregation.CHILD_STATUSES)
.and(visible -> visible.isNull(Waybill::getDriverAcceptStatus)
.or().ne(Waybill::getDriverAcceptStatus, WaybillProcessSupport.ACCEPT_REJECTED));
@@ -545,6 +547,9 @@ public class TripQueryServiceImpl implements ITripQueryService {
trip.setCargoType(Func.toStr(waybill.getCargoType(), ""));
trip.setDepartureAddress(Func.toStr(waybill.getDepartureAddress(), ""));
trip.setArrivalAddress(Func.toStr(waybill.getArrivalAddress(), ""));
// 未配载没有配载单可依,计划时间只能取这张运单自己的
trip.setEstimatedStartDate(waybill.getEstimatedStartTime());
trip.setEstimatedEndDate(waybill.getEstimatedEndTime());
trip.setTaskRemark(Func.toStr(waybill.getTaskRemark(), ""));
if (withPayload) {
trip.setRouteJson(waybill.getRouteJson());