From 04389cd9d5c9fc94f86af01f0c5932e354de5c5c Mon Sep 17 00:00:00 2001 From: weicw1996 Date: Sun, 18 Oct 2026 19:40:19 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E6=9C=AA=E9=85=8D=E8=BD=BD=E8=BF=90?= =?UTF-8?q?=E6=AC=A1=E7=9A=84=E8=AE=A1=E5=88=92=E6=97=B6=E9=97=B4=E5=8F=96?= =?UTF-8?q?=E8=BF=90=E5=8D=95=E8=87=AA=E8=BA=AB=E7=9A=84=E5=80=BC=EF=BC=8C?= =?UTF-8?q?=E8=AF=A6=E6=83=85=E4=B8=8E=E5=88=97=E8=A1=A8=E5=90=8C=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 运次读服务拼未配载运次时从不给 estimatedStartDate/estimatedEndDate 赋值, 而配载运次取配载单、是有值的。于是所有按运次读的出口里,普通运输一律没有计划时间: 调度端详情页「计划时间」显示 —,司机端列表卡片同理,而同一张运单在列表卡片上有值。 - 段一 select 补 estimated_start_time/estimated_end_time(不取这两列则仍为空) - waybillTrip 从运单补计划时间,与 loadingTrip 取配载单同一口径 - 调度端、司机端卡片改为直接取运次字段,删掉未配载运单独走一次批量补查的分叉 - 司机端卡片的计划时间不再以「有配载单」为前提;运次级为空时不覆盖卡片已有值 库里本就为空的配载单(如未填日期的草稿)仍不显示,不编造值。 --- .../impl/DriverWaybillServiceImpl.java | 10 ++++- .../impl/ManageWaybillServiceImpl.java | 40 ++++--------------- .../service/impl/TripQueryServiceImpl.java | 7 +++- .../service/impl/DriverTripCardTest.java | 4 ++ .../impl/TripQueryServiceImplTest.java | 25 ++++++++++++ 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverWaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverWaybillServiceImpl.java index e0f09fdf..350c0e92 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverWaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverWaybillServiceImpl.java @@ -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(), ""))); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ManageWaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ManageWaybillServiceImpl.java index 41ab9cc2..7cab655b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ManageWaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ManageWaybillServiceImpl.java @@ -246,7 +246,7 @@ public class ManageWaybillServiceImpl implements IManageWaybillService { } /** - * 运次卡片页:一次算清这一页的重派标记、异常与未配载运次的计划时间,再逐条拼卡片 + * 运次卡片页:一次算清这一页的重派标记与异常,再逐条拼卡片 */ private Page tripCardPage(List trips, int pageNo, int pageSize, long total, Set exceptionWaybillIds) { @@ -254,9 +254,8 @@ public class ManageWaybillServiceImpl implements IManageWaybillService { if (!trips.isEmpty()) { Set reassignKeys = loadReassignTripKeys( trips.stream().map(this::tripKeyOf).collect(Collectors.toCollection(LinkedHashSet::new))); - Map loneWaybills = loadLoneWaybills(trips); for (TripVO trip : trips) { - cards.add(toTripCard(trip, exceptionWaybillIds, reassignKeys, loneWaybills)); + cards.add(toTripCard(trip, exceptionWaybillIds, reassignKeys)); } } Page page = new Page<>(pageNo, pageSize, total); @@ -265,12 +264,12 @@ public class ManageWaybillServiceImpl implements IManageWaybillService { } /** - * 运次卡片:展示单号、整趟车起/经/终与站点数、货物汇总都取运次字段。 + * 运次卡片:展示单号、整趟车起/经/终与站点数、货物汇总、计划时间都取运次字段。 * 旧字段 id / waybillNo 保留运单语义(未配载就是这张运单,配载取第一张可见子运单), * 打卡订正、重新派单等按运单进入的入口仍靠它们。 */ private AdminWaybillCardVO toTripCard(TripVO trip, Set exceptionWaybillIds, - Set reassignTripIds, Map loneWaybills) { + Set reassignTripIds) { AdminWaybillCardVO card = new AdminWaybillCardVO(); List 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 loadLoneWaybills(List trips) { - Set 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.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 loadReassignTripKeys(Set tripIds) { if (Func.isEmpty(tripIds)) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TripQueryServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TripQueryServiceImpl.java index 7af9b79f..d4c45658 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TripQueryServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TripQueryServiceImpl.java @@ -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()); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverTripCardTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverTripCardTest.java index 612bb192..966ac370 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverTripCardTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverTripCardTest.java @@ -191,6 +191,8 @@ class DriverTripCardTest { assertEquals("", card.getLoadingNo()); assertEquals("YD-20260920-0003", card.getTripNo()); assertEquals("common", card.getTransportOrgType()); + assertEquals("2026-09-20", card.getPlanShipTime(), "未配载运次的卡片也要带计划时间"); + assertEquals("2026-09-22", card.getPlanFinishTime()); } @Test @@ -400,6 +402,8 @@ class DriverTripCardTest { trip.setRequireAccept(true); trip.setAcceptStatus("pending"); trip.setSortTime(new Date(1787629629000L)); + trip.setEstimatedStartDate(java.time.LocalDate.of(2026, 9, 20)); + trip.setEstimatedEndDate(java.time.LocalDate.of(2026, 9, 22)); trip.setDepartureName("南宁武鸣"); trip.setArrivalName("钦州港"); trip.setStationCount(2); diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/TripQueryServiceImplTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/TripQueryServiceImplTest.java index e981e71e..7c1a9420 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/TripQueryServiceImplTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/TripQueryServiceImplTest.java @@ -23,6 +23,7 @@ import org.springblade.transport.service.ILoadingManageService; import org.springblade.transport.service.IProcessConfigService; import org.springblade.transport.service.IWaybillService; +import java.time.LocalDate; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -112,6 +113,8 @@ class TripQueryServiceImplTest { String select = String.valueOf(capturedRowQuery().getSqlSelect()); assertTrue(select.contains("process_json"), "分档要按过程配置推导,必须取:" + select); assertTrue(select.contains("create_time"), "排序键要用:" + select); + assertTrue(select.contains("estimated_start_time"), "未配载运次的计划时间取自运单,必须取:" + select); + assertTrue(select.contains("estimated_end_time"), select); assertFalse(select.contains("route_json"), "运单表上的大 JSON 列不必拖回:" + select); assertFalse(select.contains("goods_json"), select); assertFalse(select.contains("task_info_json"), select); @@ -258,6 +261,28 @@ class TripQueryServiceImplTest { assertEquals("YD-20260920-0003", trip.getTripNo()); } + @Test + @DisplayName("未配载运次的计划时间取自这张运单:没有配载单可依,不能留空") + void unloadedTripPlanTimeComesFromWaybill() { + Waybill row = waybill(WAYBILL_ID, "YD-20260920-0003", null, "running", null, at(1000L), ACCEPT_NO); + row.setEstimatedStartTime(LocalDate.of(2026, 8, 7)); + row.setEstimatedEndTime(LocalDate.of(2026, 8, 24)); + stubRows(row); + + TripVO listed = service.page(TripQueryVO.forDriver(PHONE)).getRecords().get(0); + + assertEquals(LocalDate.of(2026, 8, 7), listed.getEstimatedStartDate(), "列表卡片与详情同源,不能只在列表补"); + assertEquals(LocalDate.of(2026, 8, 24), listed.getEstimatedEndDate()); + + when(loadingManageService.getById(WAYBILL_ID)).thenReturn(null); + when(waybillService.getById(WAYBILL_ID)).thenReturn(row); + + TripVO detailed = service.detail(tripQuery(String.valueOf(WAYBILL_ID))); + + assertEquals(LocalDate.of(2026, 8, 7), detailed.getEstimatedStartDate(), "管理端详情走这条路,不留空"); + assertEquals(LocalDate.of(2026, 8, 24), detailed.getEstimatedEndDate()); + } + @Test @DisplayName("配载单在两次查询之间被删掉时,不给出没有主键的运次") void loadingMissingIsDropped() {