✅ 补运次读服务的边界单测与管理端运次列表/详情用例

运次聚合五条边界、排序键、空子单集合、字符串主键、跨项目接单需求 OR;
管理端运次列表与详情的用例(此前该实现零覆盖)。
This commit is contained in:
2026-10-17 20:14:42 +08:00
parent 5d980278f2
commit e8196e7ef7
2 changed files with 630 additions and 0 deletions
@@ -0,0 +1,272 @@
package org.springblade.transport.service.impl;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.transport.pojo.entity.ExceptionDisposal;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.AdminWaybillCardVO;
import org.springblade.transport.pojo.vo.AdminWaybillDetailVO;
import org.springblade.transport.pojo.vo.TripStationVO;
import org.springblade.transport.pojo.vo.TripVO;
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.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* 调度端列表与详情的运次口径:一卡一运次、整趟车的站点与货物。
* <p>
* 卡片上的状态、站点与货物汇总都出自共享运次读服务,本类只做字段裁剪;这里钉住的是
* 「运次字段有没有被摆到卡片与详情上」,以及取不到运次时按运单主键与配载单主键的回落路径。
*/
class ManageTripListDetailTest {
private static final String LOADING_NO = "PZ-20261017-001";
private static final Long LOADING_ID = 2111350784070275074L;
private static final Long CHILD_A = 2111350784070275123L;
private static final Long CHILD_B = 2102780956493299713L;
private ManageWaybillServiceImpl service;
private IWaybillService waybillService;
private IExceptionDisposalService exceptionDisposalService;
private ITripQueryService tripQueryService;
private ILoadingManageService loadingManageService;
private IDriverWaybillService driverWaybillService;
@BeforeAll
static void initTableInfo() {
MybatisConfiguration configuration = new MybatisConfiguration();
MapperBuilderAssistant assistant = new MapperBuilderAssistant(configuration, "");
assistant.setCurrentNamespace("test");
TableInfoHelper.initTableInfo(assistant, Waybill.class);
TableInfoHelper.initTableInfo(assistant, ExceptionDisposal.class);
TableInfoHelper.initTableInfo(assistant, LoadingManage.class);
}
@BeforeEach
void setUp() {
waybillService = mock(IWaybillService.class);
exceptionDisposalService = mock(IExceptionDisposalService.class);
tripQueryService = mock(ITripQueryService.class);
loadingManageService = mock(ILoadingManageService.class);
driverWaybillService = mock(IDriverWaybillService.class);
service = new ManageWaybillServiceImpl(
waybillService,
mock(IDriverService.class),
exceptionDisposalService,
mock(IRiskDisposalService.class),
driverWaybillService,
tripQueryService,
loadingManageService);
when(exceptionDisposalService.list(ArgumentMatchers.<Wrapper<ExceptionDisposal>>any()))
.thenReturn(new ArrayList<>());
when(waybillService.list(ArgumentMatchers.<Wrapper<Waybill>>any())).thenReturn(new ArrayList<>());
}
@Test
@DisplayName("列表一卡一运次:单号、组织类型、起经终、站点数、货物汇总都取运次字段")
void pageListShowsOneCardPerTrip() {
when(tripQueryService.page(any())).thenReturn(pageOf(1, trip()));
IPage<AdminWaybillCardVO> page = service.pageList(1, 10, null, null, null, null, null, null);
assertEquals(1, page.getTotal());
assertEquals(1, page.getRecords().size(), "四张子单只出一条卡");
AdminWaybillCardVO card = page.getRecords().get(0);
assertEquals(String.valueOf(LOADING_ID), card.getTripId());
assertEquals(LOADING_NO, card.getLoadingNo());
assertEquals(LOADING_NO, card.getTripNo());
assertEquals("load", card.getTransportType(), "有配载单即为公路配载");
assertEquals(2, card.getStatus());
assertEquals(4, card.getWaybillCount());
assertEquals(3, card.getStationCount());
assertEquals("南宁吴圩机场", card.getFromName());
assertEquals("新福兴硅科技有限公司", card.getViaName());
assertEquals("宾阳", card.getToName());
assertEquals("石英砂A 131.84吨、技嘉4070显卡 30吨", card.getCargoSummary());
assertEquals("161.84吨", card.getTotalWeight());
assertEquals("2026-09-23 23:23:42", card.getCreateTime(), "卡片时间取运次排序键");
assertEquals(Long.valueOf(CHILD_A), card.getId(), "旧 id 仍是运单主键,打卡订正等按它进入");
assertEquals("YD-20260825-0006", card.getWaybillNo());
assertFalse(card.getNeedReassign());
}
@Test
@DisplayName("详情按运次主键取:配载单号、组织类型、站点 ①②③ 与每站货物都带运单号")
void detailShowsWholeTripStations() {
when(tripQueryService.detail(any())).thenReturn(trip());
AdminWaybillDetailVO detail = service.detail(String.valueOf(LOADING_ID));
assertEquals(String.valueOf(LOADING_ID), detail.getTripId());
assertEquals(LOADING_NO, detail.getLoadingNo());
assertEquals(LOADING_NO, detail.getTripNo());
assertEquals("load", detail.getTransportOrgType());
assertEquals(2, detail.getStatus());
assertEquals(3, detail.getStationCount());
assertEquals(3, detail.getStations().size());
assertEquals(3, detail.getRoutePoints().size(), "点位列与站点同源");
assertEquals("161.84吨", detail.getTotalWeight());
TripStationVO first = detail.getStations().get(0);
assertEquals(1, first.getIndex());
assertEquals("装货", first.getOperationTypeLabel());
assertEquals("2102780956493299713", first.getCargos().get(0).getWaybillId(), "货物条目带所属子运单主键");
assertEquals("YD-20260923-0008", first.getCargos().get(0).getWaybillNo());
TripStationVO second = detail.getStations().get(1);
assertEquals("装卸", second.getOperationTypeLabel());
assertEquals(2, second.getCargos().size());
assertEquals("YD-20260923-0008", second.getCargos().get(0).getWaybillNo(), "同一站可卸一张、装另一张");
assertEquals("2131150784070275011", second.getCargos().get(1).getWaybillId());
}
@Test
@DisplayName("取不到运次时按运单主键与配载单主键回落:整单被拒的配载单仍能打开并重新派单")
void detailFallsBackWhenTripIsNotReachable() {
when(tripQueryService.detail(any())).thenThrow(new ServiceException("运次不存在或无权操作"));
when(waybillService.getById(CHILD_A)).thenReturn(null);
when(loadingManageService.getById(LOADING_ID)).thenReturn(loading());
AdminWaybillDetailVO detail = service.detail(String.valueOf(LOADING_ID));
assertEquals(String.valueOf(LOADING_ID), detail.getTripId());
assertEquals(LOADING_NO, detail.getLoadingNo());
assertEquals("load", detail.getTransportOrgType());
assertTrue(detail.getNeedReassign(), "整单被拒时按配载单回落,标记待重新派单");
assertEquals(3, detail.getStationCount(), "子单为空时站点退回配载单自己的发货/途经/到货");
assertEquals("南宁吴圩机场", detail.getFromName());
assertEquals("宾阳", detail.getToName());
}
@Test
@DisplayName("运次主键不是数字时直接拒绝,不去查库")
void detailRefusesUnparsableTripId() {
assertThrows(ServiceException.class, () -> service.detail("not-a-number"));
assertThrows(ServiceException.class, () -> service.detail(null));
}
// ------------------------------------------------------------ 夹具
private Page<TripVO> pageOf(long total, TripVO... trips) {
Page<TripVO> page = new Page<>(1, 10, total);
page.setRecords(List.of(trips));
return page;
}
/**
* 一趟 4 张子单的配载运次:站点与货物按本库真实样本同形(三站,第二站装卸)
*/
private TripVO trip() {
TripVO trip = new TripVO();
trip.setId(String.valueOf(LOADING_ID));
trip.setTripNo(LOADING_NO);
trip.setLoadingNo(LOADING_NO);
trip.setTransportOrgType("load");
trip.setStatus(2);
trip.setRequireAccept(false);
trip.setWaybillCount(4);
trip.setDriverName("黄宇富");
trip.setVehicleNo("桂A32523");
trip.setDepartureName("南宁吴圩机场");
trip.setTransitName("新福兴硅科技有限公司");
trip.setArrivalName("宾阳");
trip.setStationCount(3);
trip.setCargoSummary("石英砂A 131.84吨、技嘉4070显卡 30吨");
trip.setTotalQuantity(new BigDecimal("161.84"));
trip.setQuantityUnit("吨");
trip.setSortTime(at(1790177022000L));
trip.setEstimatedStartDate(LocalDate.of(2026, 8, 25));
trip.setEstimatedEndDate(LocalDate.of(2026, 9, 23));
trip.setWaybills(List.of(
tripWaybill(CHILD_A, "YD-20260825-0006"),
tripWaybill(2111350784070275124L, "YD-20260825-0007"),
tripWaybill(2111350784070275125L, "YD-20260825-0008"),
tripWaybill(CHILD_B, "YD-20260923-0008")));
trip.setStations(List.of(
station(1, "南宁吴圩机场", "load", "装货", cargo("2102780956493299713", "YD-20260923-0008", "技嘉4070显卡", "30")),
station(2, "武宣", "load_unload", "装卸",
cargo("2102780956493299713", "YD-20260923-0008", "技嘉4070显卡", "30"),
cargo("2131150784070275011", "YD-20260825-0006", "石英砂A", "42.10")),
station(3, "宾阳", "unload", "卸货", cargo("2131150784070275011", "YD-20260825-0006", "石英砂A", "42.10"))));
return trip;
}
private TripVO.TripWaybillVO tripWaybill(Long id, String waybillNo) {
TripVO.TripWaybillVO child = new TripVO.TripWaybillVO();
child.setId(String.valueOf(id));
child.setWaybillNo(waybillNo);
child.setBusinessStatus("running");
return child;
}
private TripStationVO station(int index, String name, String operationType, String label,
TripStationVO.TripCargoVO... cargos) {
TripStationVO station = new TripStationVO();
station.setIndex(index);
station.setName(name);
station.setAddress(name);
station.setOperationType(operationType);
station.setOperationTypeLabel(label);
station.setTags(new ArrayList<>());
station.setCargos(List.of(cargos));
return station;
}
private TripStationVO.TripCargoVO cargo(String waybillId, String waybillNo, String cargoName, String quantity) {
TripStationVO.TripCargoVO cargo = new TripStationVO.TripCargoVO();
cargo.setWaybillId(waybillId);
cargo.setWaybillNo(waybillNo);
cargo.setCargoName(cargoName);
cargo.setQuantity(new BigDecimal(quantity));
cargo.setQuantityUnit("吨");
return cargo;
}
private LoadingManage loading() {
LoadingManage loading = new LoadingManage();
loading.setId(LOADING_ID);
loading.setLoadingNo(LOADING_NO);
loading.setDriverName("黄宇富");
loading.setDriverPhone("17587421208");
loading.setVehicleNo("桂A32523");
loading.setDepartureAddress("南宁吴圩机场");
loading.setTransitAddress("武宣");
loading.setArrivalAddress("宾阳");
loading.setCargoName("石英砂A");
return loading;
}
private Date at(long millis) {
return new Date(millis);
}
}
@@ -0,0 +1,358 @@
package org.springblade.transport.service.impl;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.TripQueryVO;
import org.springblade.transport.pojo.vo.TripVO;
import org.springblade.transport.service.ILoadingManageService;
import org.springblade.transport.service.IWaybillService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* 运次读服务的聚合边界:四档状态、排序键、空子单集合与主键下发形态。
* <p>
* 断言都从服务出口读({@code page} / {@code detail}),不直接调判定函数:随卡片下发的
* {@code status} 与 {@code requireAccept} 是两个字段,只验静态判定看不出服务有没有把子单真身取回来——
* 库层分组行只投影主键、分组键与排序键,business_status 是 NULL。
*/
class TripReadServiceBoundaryTest {
private static final String PHONE = "17587421208";
private static final String LOADING_NO = "PZ-20261017-001";
/** 19 位雪花号,按数字下发会被双精度取整 */
private static final Long LOADING_ID = 2111350784070275074L;
private static final Long CHILD_A = 2111350784070275123L;
private static final Long CHILD_B = 2102780956493299713L;
private static final String ACCEPT_YES = "[{\"key\":\"accept\",\"name\":\"接单\",\"enabled\":true,\"confirmMode\":\"yes\"}]";
private static final String ACCEPT_NO = "[{\"key\":\"accept\",\"name\":\"接单\",\"enabled\":true,\"confirmMode\":\"no_confirm_accept\"}]";
private IWaybillService waybillService;
private ILoadingManageService loadingManageService;
private TripQueryServiceImpl service;
@BeforeAll
static void initTableInfo() {
MybatisConfiguration configuration = new MybatisConfiguration();
MapperBuilderAssistant assistant = new MapperBuilderAssistant(configuration, "");
assistant.setCurrentNamespace("test");
TableInfoHelper.initTableInfo(assistant, Waybill.class);
TableInfoHelper.initTableInfo(assistant, LoadingManage.class);
}
@BeforeEach
void setUp() {
waybillService = mock(IWaybillService.class);
loadingManageService = mock(ILoadingManageService.class);
service = new TripQueryServiceImpl(waybillService, loadingManageService);
lenient().when(waybillService.list(anyWaybillWrapper())).thenReturn(List.of());
lenient().when(loadingManageService.list(anyLoadingWrapper())).thenReturn(List.of());
}
@Test
@DisplayName("子单全部完成 → 运次已完成(2)")
void allChildrenCompleted() {
stubLoadedTrip(
child(CHILD_A, "completed", null, ACCEPT_NO, at(1787657033000L)),
child(CHILD_B, "completed", "accepted", ACCEPT_NO, at(1787671422000L)));
TripVO trip = onlyTrip();
assertEquals(2, trip.getStatus(), "终态且含已完成为已完成档");
assertEquals(2, trip.getWaybillCount());
assertEquals("accepted", trip.getAcceptStatus(), "任一子单已接单即整单已接单");
}
@Test
@DisplayName("子单全部取消 → 运次已取消(3),不是运输中")
void allChildrenCancelled() {
stubLoadedTrip(
child(CHILD_A, "cancelled", null, ACCEPT_NO, at(1787657033000L)),
child(CHILD_B, "cancelled", null, ACCEPT_NO, at(1787671422000L)));
TripVO trip = onlyTrip();
assertEquals(3, trip.getStatus(), "已取消子单必须进运次,否则全取消会被算成运输中");
}
@Test
@DisplayName("混合终态且含 completed → 运次已完成(2),不看取消的那张")
void mixedTerminalWithCompleted() {
stubLoadedTrip(
child(CHILD_A, "completed", null, ACCEPT_NO, at(1787657033000L)),
child(CHILD_B, "cancelled", null, ACCEPT_NO, at(1787671422000L)));
TripVO trip = onlyTrip();
assertEquals(2, trip.getStatus());
}
@Test
@DisplayName("需接单且未接单 → 待接单(0)")
void requireAcceptWithoutAcceptance() {
Waybill required = child(CHILD_A, "pending", "pending", ACCEPT_YES, at(1787657033000L));
required.setProjectId(1L);
required.setProjectName("MK项目测试-1");
stubLoadedTrip(required);
TripVO trip = onlyTrip();
assertEquals(Boolean.TRUE, trip.getRequireAccept());
assertEquals("pending", trip.getAcceptStatus());
assertEquals(0, trip.getStatus());
}
@Test
@DisplayName("不需接单 → 运输中(1)")
void withoutAcceptRequirement() {
Waybill notRequired = child(CHILD_A, "pending", null, ACCEPT_NO, at(1787657033000L));
notRequired.setProjectId(2L);
notRequired.setProjectName("武宣建筑原料运输项目");
stubLoadedTrip(notRequired);
TripVO trip = onlyTrip();
assertEquals(Boolean.FALSE, trip.getRequireAccept());
assertEquals(1, trip.getStatus());
}
@Test
@DisplayName("跨项目子单的接单需求按 OR 合并:一张要接单整趟车都要接单")
void crossProjectRequirementMergesWithOr() {
Waybill required = child(CHILD_A, "running", null, ACCEPT_YES, at(1787657033000L));
required.setProjectId(1L);
required.setProjectName("MK项目测试-1");
Waybill notRequired = child(CHILD_B, "running", null, ACCEPT_NO, at(1787671422000L));
notRequired.setProjectId(2L);
notRequired.setProjectName("武宣建筑原料运输项目");
stubLoadedTrip(required, notRequired);
TripVO trip = onlyTrip();
assertEquals(Boolean.TRUE, trip.getRequireAccept());
assertEquals(0, trip.getStatus());
assertEquals(Boolean.TRUE, trip.getWaybills().get(0).getRequireAccept());
assertEquals(Boolean.FALSE, trip.getWaybills().get(1).getRequireAccept());
}
@Test
@DisplayName("跨项目但都没接单节点 → 整趟车不需要接单")
void crossProjectWithoutAnyRequirement() {
Waybill first = child(CHILD_A, "running", null, null, at(1787657033000L));
first.setProjectId(1L);
Waybill second = child(CHILD_B, "running", null, ACCEPT_NO, at(1787671422000L));
second.setProjectId(2L);
stubLoadedTrip(first, second);
TripVO trip = onlyTrip();
assertEquals(Boolean.FALSE, trip.getRequireAccept());
assertEquals(1, trip.getStatus());
}
@Test
@DisplayName("排序键取子单 create_time 的最大值,不取第一张也不取最后一张")
void sortTimeIsMaxChildCreateTime() {
Date earliest = at(1787657033000L);
Date latest = at(1787671422000L);
Date middle = at(1787663000000L);
stubLoadedTrip(
child(CHILD_A, "running", null, ACCEPT_NO, middle),
child(2111350784070275999L, "running", null, ACCEPT_NO, latest),
child(CHILD_B, "running", null, ACCEPT_NO, earliest));
TripVO trip = onlyTrip();
assertEquals(latest, trip.getSortTime());
assertEquals(3, trip.getWaybillCount());
assertEquals(earliest, trip.getWaybills().get(0).getCreateTime(), "子单按创建时间升序摆");
}
@Test
@DisplayName("子单集合为空不抛异常:列表不给这张卡,详情直接拒绝而不是 NPE")
void emptyChildrenDoNotThrow() {
stubLoadedTrip();
IPage<TripVO> page = service.page(TripQueryVO.forDriver(PHONE));
assertTrue(page.getRecords().isEmpty(), "配载单在、可见子单为空时不给没有子单的运次");
when(loadingManageService.getById(LOADING_ID)).thenReturn(loading());
assertThrows(ServiceException.class, () -> service.detail(detailQuery()),
"子单全被拒单的配载运次对司机不可见");
}
@Test
@DisplayName("子单状态为空时不抛异常:读不出状态按没走完兜底,不崩也不误判成终态")
void nullBusinessStatusDoesNotThrow() {
Waybill blank = new Waybill();
blank.setId(CHILD_A);
blank.setWaybillNo("YD-20260920-0003");
blank.setLoadingNo(LOADING_NO);
blank.setBusinessStatus(null);
stubLoadedTrip(blank);
TripVO trip = onlyTrip();
assertEquals(1, trip.getStatus(), "读不出状态按没走完处理,不是终态也不抛异常");
assertEquals(1, trip.getWaybillCount());
}
@Test
@DisplayName("未配载运次按主键回查真身:分组行没有状态列,拿它当子单会让接单需求恒为 false")
void loneTripReadsStateFromFetchedWaybill() {
// 段一给的行只有主键、分组键与排序键,真身要靠段二回查
Waybill row = new Waybill();
row.setId(CHILD_A);
row.setCreateTime(at(1787657033000L));
stubPage(1, row);
Waybill bare = new Waybill();
bare.setId(CHILD_A);
bare.setWaybillNo("YD-20260920-0003");
bare.setBusinessStatus("pending");
bare.setDriverAcceptStatus("pending");
bare.setProcessJson(ACCEPT_YES);
bare.setDriverPhone(PHONE);
when(waybillService.list(anyWaybillWrapper())).thenReturn(List.of(bare));
TripVO trip = onlyTrip();
assertEquals("2111350784070275123", trip.getId());
assertNull(trip.getLoadingNo());
assertEquals(19, trip.getId().length(), "19 位雪花号的末位不被取整");
assertEquals(Boolean.TRUE, trip.getRequireAccept(), "接单需求取自回查到的真身");
assertEquals(0, trip.getStatus());
assertEquals(1, trip.getWaybillCount());
}
@Test
@DisplayName("运次主键按字符串下发:19 位雪花号的末位不被双精度取整")
void tripIdIsSentAsString() {
stubLoadedTrip(child(CHILD_A, "running", null, ACCEPT_NO, at(1787657033000L)));
TripVO trip = onlyTrip();
assertNotNull(trip.getId());
assertEquals("2111350784070275074", trip.getId());
assertEquals(19, trip.getId().length());
assertEquals("2111350784070275123", trip.getWaybills().get(0).getId());
assertEquals(19, trip.getWaybills().get(0).getId().length());
assertTrue(trip.getId() instanceof String);
}
@Test
@DisplayName("货物与合计重量按整趟车算:同名同单位合并,单位不一致时合计留空")
void cargoSummarySpansWholeTrip() {
Waybill first = child(CHILD_A, "running", null, ACCEPT_NO, at(1787657033000L));
first.setCargoName("石英砂A");
first.setQuantity(new BigDecimal("42.10"));
first.setQuantityUnit("吨");
Waybill second = child(CHILD_B, "running", null, ACCEPT_NO, at(1787671422000L));
second.setCargoName("石英砂A");
second.setQuantity(new BigDecimal("47.57"));
second.setQuantityUnit("吨");
stubLoadedTrip(first, second);
TripVO trip = onlyTrip();
assertEquals("石英砂A 89.67吨", trip.getCargoSummary());
assertEquals(0, new BigDecimal("89.67").compareTo(trip.getTotalQuantity()));
assertEquals("吨", trip.getQuantityUnit());
}
// ------------------------------------------------------------ 夹具
@SuppressWarnings("unchecked")
private static Wrapper<Waybill> anyWaybillWrapper() {
return ArgumentMatchers.<Wrapper<Waybill>>any();
}
@SuppressWarnings("unchecked")
private static Wrapper<LoadingManage> anyLoadingWrapper() {
return ArgumentMatchers.<Wrapper<LoadingManage>>any();
}
/** 配载运次:段一给一行分组行,段二给配载单与这一组的子单 */
private void stubLoadedTrip(Waybill... children) {
Waybill row = new Waybill();
row.setId(children.length == 0 ? CHILD_A : children[0].getId());
row.setLoadingNo(LOADING_NO);
stubPage(1, row);
when(loadingManageService.list(anyLoadingWrapper())).thenReturn(List.of(loading()));
when(waybillService.list(anyWaybillWrapper())).thenReturn(List.of(children));
}
private void stubPage(long total, Waybill... rows) {
when(waybillService.page(any(), any())).thenAnswer(invocation -> {
Page<Waybill> page = invocation.getArgument(0);
page.setRecords(List.of(rows));
page.setTotal(total);
return page;
});
}
private TripVO onlyTrip() {
IPage<TripVO> page = service.page(TripQueryVO.forDriver(PHONE));
assertEquals(1, page.getRecords().size(), "本页应只有一个运次");
return page.getRecords().get(0);
}
private TripQueryVO detailQuery() {
TripQueryVO query = TripQueryVO.forDriver(PHONE);
query.setTripId(String.valueOf(LOADING_ID));
return query;
}
private LoadingManage loading() {
LoadingManage loading = new LoadingManage();
loading.setId(LOADING_ID);
loading.setLoadingNo(LOADING_NO);
loading.setDriverPhone(PHONE);
loading.setDriverName("黄宇富");
loading.setVehicleNo("桂A32523");
loading.setProjectName("武宣建筑原料运输项目");
return loading;
}
private Waybill child(Long id, String businessStatus, String acceptStatus, String processJson, Date createTime) {
Waybill waybill = new Waybill();
waybill.setId(id);
waybill.setWaybillNo("YD-" + id);
waybill.setLoadingNo(LOADING_NO);
waybill.setBusinessStatus(businessStatus);
waybill.setDriverAcceptStatus(acceptStatus);
waybill.setDriverPhone(PHONE);
waybill.setProcessJson(processJson);
waybill.setCreateTime(createTime);
return waybill;
}
private Date at(long millis) {
return new Date(millis);
}
}