✨ 管理端运单列表与详情按运次下发,首页待办按运次去重
管理端列表/待处理/详情/统计切到共享运次服务,运次主键按字符串下发; 首页「重新派单待处理」的 feed 与角标改为按运次键在库层分组去重, 一张配载单的多张子单被拒只出一条待办。重新派单写入与组织过滤未动。
This commit is contained in:
+26
@@ -92,4 +92,30 @@ public class AdminWaybillCardVO implements Serializable {
|
||||
@Schema(description = "采购方是否已付款(预留)")
|
||||
private Boolean buyerPaid;
|
||||
|
||||
/* ===== 运次(一趟车)字段:列表按运次下发,卡片的展示单号与路线取这些 ===== */
|
||||
|
||||
@Schema(description = "运次主键:配载单主键或运单主键,按字符串下发(19 位雪花号按数字下发会被前端取整)")
|
||||
private String tripId;
|
||||
|
||||
@Schema(description = "配载单号,未配载为空")
|
||||
private String loadingNo;
|
||||
|
||||
@Schema(description = "展示单号:有配载取配载单号,否则取运单号")
|
||||
private String tripNo;
|
||||
|
||||
@Schema(description = "途经站点:整趟车中间各站按顺序以「 → 」连接,无中间站为空")
|
||||
private String viaName;
|
||||
|
||||
@Schema(description = "站点数(整趟车,含起终点)")
|
||||
private Integer stationCount;
|
||||
|
||||
@Schema(description = "货物汇总(整趟车,同名货物合并且单位一致时取数量合计)")
|
||||
private String cargoSummary;
|
||||
|
||||
@Schema(description = "合计重量(整趟车同单位时才有值,单位不一致为空)")
|
||||
private String totalWeight;
|
||||
|
||||
@Schema(description = "子运单数(可见口径;配载运次即整趟车的子单数)")
|
||||
private Integer waybillCount;
|
||||
|
||||
}
|
||||
|
||||
+23
@@ -135,6 +135,29 @@ public class AdminWaybillDetailVO implements Serializable {
|
||||
@Schema(description = "途打卡记录")
|
||||
private List<DriverEnrouteRecordVO> enrouteRecords;
|
||||
|
||||
/* ===== 运次(一趟车)字段:详情按运次下发,与司机端接单页同一口径 ===== */
|
||||
|
||||
@Schema(description = "运次主键:配载单主键或运单主键,按字符串下发(19 位雪花号按数字下发会被前端取整)")
|
||||
private String tripId;
|
||||
|
||||
@Schema(description = "配载单号,未配载为空")
|
||||
private String loadingNo;
|
||||
|
||||
@Schema(description = "展示单号:有配载取配载单号,否则取运单号")
|
||||
private String tripNo;
|
||||
|
||||
@Schema(description = "途经站点:整趟车中间各站按顺序以「 → 」连接,无中间站为空")
|
||||
private String viaName;
|
||||
|
||||
@Schema(description = "站点数(整趟车,含起终点)")
|
||||
private Integer stationCount;
|
||||
|
||||
@Schema(description = "货物汇总(整趟车,同名货物合并且单位一致时取数量合计)")
|
||||
private String cargoSummary;
|
||||
|
||||
@Schema(description = "站点任务安排(整趟车按实际途经顺序,第 1 站即 ①;配载运次含每站装卸与货物条目)")
|
||||
private List<TripStationVO> stations;
|
||||
|
||||
@Data
|
||||
@Schema(description = "装卸点")
|
||||
public static class AdminRoutePointVO implements Serializable {
|
||||
|
||||
+2
-2
@@ -99,9 +99,9 @@ public class ManageWaybillController extends BladeController {
|
||||
|
||||
@GetMapping("/detail")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@Operation(summary = "运单详情", description = "调度端查看运单详情(含 punchNodes / enrouteRecords),不校验司机归属与组织;字段对齐小程序 pages/waybill/detail")
|
||||
@Operation(summary = "运次详情", description = "调度端查看整趟车详情(含 stations / punchNodes / enrouteRecords),不校验司机归属与组织;id 传运次主键字符串,已拒单的运单主键回落成单票视图")
|
||||
public R<AdminWaybillDetailVO> detail(
|
||||
@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
|
||||
@Parameter(description = "运次主键(配载单主键或运单主键,字符串)", required = true) @RequestParam String id) {
|
||||
return R.data(manageWaybillService.detail(id));
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -63,9 +63,12 @@ public interface IManageWaybillService {
|
||||
String exception, String transportType, String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 调度端运单详情(不校验司机归属)
|
||||
* 调度端运次详情(不校验司机归属)
|
||||
* <p>
|
||||
* 传运次主键:配载单主键或未配载运单主键,都按字符串。已拒单的子运单按运次取不到(运次口径
|
||||
* 不含已拒子单),此时按运单主键回落成单票视图,供重新派单等从运单进入的场景使用。
|
||||
*/
|
||||
AdminWaybillDetailVO detail(Long id);
|
||||
AdminWaybillDetailVO detail(String tripId);
|
||||
|
||||
/**
|
||||
* 待处理运单(待接单 / 运输中;可筛需重新派单)
|
||||
|
||||
+764
-139
File diff suppressed because it is too large
Load Diff
+45
-3
@@ -2,7 +2,7 @@ package org.springblade.transport.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
@@ -17,7 +17,9 @@ import org.springblade.transport.pojo.vo.AdminTodoItemVO;
|
||||
import org.springblade.transport.service.IDriverService;
|
||||
import org.springblade.transport.service.IDriverWaybillService;
|
||||
import org.springblade.transport.service.IExceptionDisposalService;
|
||||
import org.springblade.transport.service.ILoadingManageService;
|
||||
import org.springblade.transport.service.IRiskDisposalService;
|
||||
import org.springblade.transport.service.ITripQueryService;
|
||||
import org.springblade.transport.service.IWaybillService;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
@@ -49,6 +51,7 @@ class ManageAdminHomeFeedTest {
|
||||
|
||||
private static final Long EXCEPTION_ID = 8801L;
|
||||
private static final String REJECTED_WAYBILL_NO = "YD-20261010-0001";
|
||||
private static final String REJECTED_LOADING_NO = "PZ-20261017-001";
|
||||
|
||||
private ManageWaybillServiceImpl service;
|
||||
private IWaybillService waybillService;
|
||||
@@ -72,7 +75,9 @@ class ManageAdminHomeFeedTest {
|
||||
mock(IDriverService.class),
|
||||
exceptionService,
|
||||
mock(IRiskDisposalService.class),
|
||||
mock(IDriverWaybillService.class));
|
||||
mock(IDriverWaybillService.class),
|
||||
mock(ITripQueryService.class),
|
||||
mock(ILoadingManageService.class));
|
||||
when(exceptionService.list(ArgumentMatchers.<Wrapper<ExceptionDisposal>>any()))
|
||||
.thenReturn(new ArrayList<>());
|
||||
when(waybillService.list(ArgumentMatchers.<Wrapper<Waybill>>any()))
|
||||
@@ -141,6 +146,43 @@ class ManageAdminHomeFeedTest {
|
||||
"拒单发生在昨日 22:00,异常上报于 26 小时前(更早),故重派条目在前");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("整单拒绝的多张子单按运次收成一条:同一配载单只出一条重新派单待办")
|
||||
void rejectedLoadingChildrenCollapseToOneTodo() {
|
||||
// 库层按运次分组后,一张配载单无论几张子单被拒都只回一行(分组键见下面的 SQL 断言)
|
||||
Waybill grouped = rejectedWaybill(7210L, "黄大富", "车辆不符");
|
||||
grouped.setLoadingNo(REJECTED_LOADING_NO);
|
||||
when(waybillService.list(ArgumentMatchers.<Wrapper<Waybill>>any())).thenReturn(List.of(grouped));
|
||||
|
||||
List<AdminTodoItemVO> feed = service.buildAdminFeed();
|
||||
|
||||
assertEquals(1, feed.size(), "整单拒绝只应出一条待办");
|
||||
assertEquals(REJECTED_LOADING_NO, feed.get(0).getWaybillNo(), "配载运次的待办展示配载单号");
|
||||
assertEquals(Long.valueOf(7210L), feed.get(0).getId(), "跳转参数仍是运单主键:重新派单按运单写入");
|
||||
|
||||
ArgumentCaptor<Wrapper<Waybill>> captor = ArgumentCaptor.forClass(Wrapper.class);
|
||||
verify(waybillService).list(captor.capture());
|
||||
QueryWrapper<Waybill> wrapper = (QueryWrapper<Waybill>) captor.getValue();
|
||||
String sql = wrapper.getTargetSql();
|
||||
assertTrue(sql.contains("GROUP BY"), "去重要落在库层分组上,否则多张被拒子单会各出一条:" + sql);
|
||||
assertTrue(sql.contains("CONCAT('W', id)"),
|
||||
"分组键与运次读服务同源:有配载按配载单号、未配载每张运单自成一组:" + sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("两张未配载运单被拒仍是两条待办:未配载运单各自就是一趟运次")
|
||||
void twoLoneRejectedWaybillsStayTwoTodos() {
|
||||
when(waybillService.list(ArgumentMatchers.<Wrapper<Waybill>>any())).thenReturn(List.of(
|
||||
rejectedWaybill(7221L, "黄大富", null),
|
||||
rejectedWaybill(7222L, "黄宇富", null)));
|
||||
|
||||
List<AdminTodoItemVO> feed = service.buildAdminFeed();
|
||||
|
||||
assertEquals(2, feed.size(), "未配载运单不合并");
|
||||
assertEquals(List.of(7221L, 7222L),
|
||||
feed.stream().map(AdminTodoItemVO::getId).sorted().collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("判据只认「已拒单 + 未取消未完成」,已取消已完成即便被拒过也不参与")
|
||||
void reassignQueryExcludesTerminalStatus() {
|
||||
@@ -148,7 +190,7 @@ class ManageAdminHomeFeedTest {
|
||||
|
||||
ArgumentCaptor<Wrapper<Waybill>> captor = ArgumentCaptor.forClass(Wrapper.class);
|
||||
verify(waybillService).list(captor.capture());
|
||||
LambdaQueryWrapper<Waybill> wrapper = (LambdaQueryWrapper<Waybill>) captor.getValue();
|
||||
QueryWrapper<Waybill> wrapper = (QueryWrapper<Waybill>) captor.getValue();
|
||||
String sql = wrapper.getTargetSql();
|
||||
|
||||
assertTrue(sql.contains("driver_accept_status"), "重派判据要落在接单状态上:" + sql);
|
||||
|
||||
Reference in New Issue
Block a user