🐛 修正分段改址的出发地同步与站数校验,详情字段移出列表
运单分支中间站改址后逐段同步 departure;无配载单的站数变化显式拒绝;已撤销异常不得再跟进或完成;配载单号、子运单号与可调整站点只在详情组装,列表路径不新增查询。
This commit is contained in:
+41
-29
@@ -135,7 +135,9 @@ public class ExceptionDisposalServiceImpl
|
||||
|
||||
@Override
|
||||
public ExceptionDisposalVO detail(Long id) {
|
||||
ExceptionDisposalVO vo = toVO(getExisting(id));
|
||||
ExceptionDisposal entity = getExisting(id);
|
||||
ExceptionDisposalVO vo = convertVO(entity);
|
||||
fillRouteNodes(vo, fillRouteAndCargo(vo, entity.getWaybillId()));
|
||||
vo.setFollowRecords(followRecords(id));
|
||||
return vo;
|
||||
}
|
||||
@@ -375,7 +377,7 @@ public class ExceptionDisposalServiceImpl
|
||||
throw new ServiceException("跟进说明不能超过500字");
|
||||
}
|
||||
ExceptionDisposal disposal = getExisting(request.getId());
|
||||
if (STATUS_COMPLETED.equals(disposal.getDisposalStatus())) {
|
||||
if (WaybillProcessSupport.SETTLED_DISPOSAL_STATUSES.contains(disposal.getDisposalStatus())) {
|
||||
throw new ServiceException("已完成的异常不允许继续跟进");
|
||||
}
|
||||
// 上传了附件但没写说明时,跟进说明留空,列表按附件回退展示
|
||||
@@ -401,7 +403,7 @@ public class ExceptionDisposalServiceImpl
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void complete(Long id) {
|
||||
ExceptionDisposal disposal = getExisting(id);
|
||||
if (STATUS_COMPLETED.equals(disposal.getDisposalStatus())) {
|
||||
if (WaybillProcessSupport.SETTLED_DISPOSAL_STATUSES.contains(disposal.getDisposalStatus())) {
|
||||
throw new ServiceException("异常已完成,请勿重复操作");
|
||||
}
|
||||
disposal.setDisposalStatus(STATUS_COMPLETED);
|
||||
@@ -423,7 +425,7 @@ public class ExceptionDisposalServiceImpl
|
||||
throw new ServiceException("存在无效的异常记录");
|
||||
}
|
||||
for (ExceptionDisposal disposal : disposals) {
|
||||
if (STATUS_COMPLETED.equals(disposal.getDisposalStatus())) {
|
||||
if (WaybillProcessSupport.SETTLED_DISPOSAL_STATUSES.contains(disposal.getDisposalStatus())) {
|
||||
throw new ServiceException("已完成的异常不允许重复完成");
|
||||
}
|
||||
disposal.setDisposalStatus(STATUS_COMPLETED);
|
||||
@@ -697,11 +699,14 @@ public class ExceptionDisposalServiceImpl
|
||||
.collect(Collectors.joining(TRANSIT_ADDRESS_JOINER));
|
||||
sourceTaskInfoJson = loading.getTaskInfoJson();
|
||||
} else {
|
||||
// 运单的 route_json 是路线段形状,司机端按段解析:只按段改地址,绝不整份换成站点行。
|
||||
// 没变就一个键都不动,避免把历史数据里缺省的字段顺手补齐成另一份结构。
|
||||
routeJson = sourceAddresses.equals(targetAddresses)
|
||||
? null
|
||||
: rewriteWaybillRouteSegments(waybill.getRouteJson(), targetAddresses);
|
||||
// 运单的 route_json 是路线段形状,司机端按段解析:只按段改地址,不整份换成站点行
|
||||
List<Map<String, Object>> segments = routeSegments(waybill.getRouteJson());
|
||||
boolean addressChanged = !sourceAddresses.equals(targetAddresses);
|
||||
// 段形状可识别时站数必须等于段数 + 1;认不出段形状时不改 route_json
|
||||
if (addressChanged && !segments.isEmpty() && segments.size() + 1 != targetAddresses.size()) {
|
||||
throw new ServiceException("无配载单的运单不支持增减途经站");
|
||||
}
|
||||
routeJson = addressChanged ? rewriteWaybillRouteSegments(segments, targetAddresses) : null;
|
||||
sourceTaskInfoJson = waybill.getTaskInfoJson();
|
||||
}
|
||||
String taskInfoJson = appendRouteChangeRecord(sourceTaskInfoJson, followContent);
|
||||
@@ -773,22 +778,20 @@ public class ExceptionDisposalServiceImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* 按路线段改写运单路线:第 i 段的到达地对应第 i+1 站,首段出发地对应首站。
|
||||
* 其它键(segmentNo、transportType、未知键)原样保留。
|
||||
* 按路线段改写运单路线:每段的出发地对应第 i 站、到达地对应第 i+1 站,其它键(segmentNo、
|
||||
* transportType、未知键)原样保留。
|
||||
* <p>
|
||||
* 站数变了或现有 route_json 不是可识别的段数组时返回 null,调用方跳过路线改写:
|
||||
* 段形状没有装卸归属,说不出哪一段被删掉或被挪动,硬写等于重写这趟车的行程;
|
||||
* 历史节点行(PC 改运单路线写下的 address + tags)同理不动,改写会让司机端读不出路线。
|
||||
* 现有 route_json 认不出段形状(空、坏 JSON、PC 节点行)时返回 null,调用方跳过路线改写;
|
||||
* 站数与段数不匹配由调用方拒绝。
|
||||
*/
|
||||
private String rewriteWaybillRouteSegments(String routeJson, List<String> targetAddresses) {
|
||||
List<Map<String, Object>> segments = routeSegments(routeJson);
|
||||
if (segments.isEmpty() || segments.size() + 1 != targetAddresses.size()) {
|
||||
private String rewriteWaybillRouteSegments(List<Map<String, Object>> segments, List<String> targetAddresses) {
|
||||
if (segments.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
List<Map<String, Object>> rewritten = new ArrayList<>(segments.size());
|
||||
for (int index = 0; index < segments.size(); index++) {
|
||||
Map<String, Object> segment = new LinkedHashMap<>(segments.get(index));
|
||||
rewriteSegmentPoint(segment, "departure", index == 0 ? targetAddresses.get(0) : null);
|
||||
rewriteSegmentPoint(segment, "departure", targetAddresses.get(index));
|
||||
rewriteSegmentPoint(segment, "arrival", targetAddresses.get(index + 1));
|
||||
rewritten.add(segment);
|
||||
}
|
||||
@@ -796,15 +799,11 @@ public class ExceptionDisposalServiceImpl
|
||||
}
|
||||
|
||||
private void rewriteSegmentPoint(Map<String, Object> segment, String point, String targetAddress) {
|
||||
if (targetAddress == null) {
|
||||
return;
|
||||
}
|
||||
String currentAddress = firstNonBlank(text(segment.get(point + "Address")),
|
||||
text(segment.get(point + "Name")), "");
|
||||
if (Objects.equals(currentAddress, targetAddress)) {
|
||||
return;
|
||||
}
|
||||
// 站名与地址是同一份文本:调整页只有一个地址输入框,改了地址站名也得跟着变
|
||||
segment.put(point + "Address", targetAddress);
|
||||
segment.put(point + "Name", targetAddress);
|
||||
}
|
||||
@@ -966,7 +965,14 @@ public class ExceptionDisposalServiceImpl
|
||||
return disposal;
|
||||
}
|
||||
|
||||
/** 列表与上报结果共用的转换:不含详情页的配载单号、子运单号与可调整站点 */
|
||||
private ExceptionDisposalVO toVO(ExceptionDisposal entity) {
|
||||
ExceptionDisposalVO vo = convertVO(entity);
|
||||
fillRouteAndCargo(vo, entity.getWaybillId());
|
||||
return vo;
|
||||
}
|
||||
|
||||
private ExceptionDisposalVO convertVO(ExceptionDisposal entity) {
|
||||
ExceptionDisposalVO vo = BeanUtil.copyProperties(entity, ExceptionDisposalVO.class);
|
||||
if (vo == null) {
|
||||
return null;
|
||||
@@ -975,18 +981,17 @@ public class ExceptionDisposalServiceImpl
|
||||
vo.setUpdateUserName(UserDisplayCache.getUserRealName(entity.getUpdateUser()));
|
||||
vo.setDisposalStatusName(statusName(entity.getDisposalStatus()));
|
||||
vo.setScenePhotoList(splitPhotos(entity.getScenePhotos()));
|
||||
fillRouteAndCargo(vo, entity.getWaybillId());
|
||||
return vo;
|
||||
}
|
||||
|
||||
/** 按关联运单补齐详情页路线 / 货物 / 配载单展示字段 */
|
||||
private void fillRouteAndCargo(ExceptionDisposalVO vo, Long waybillId) {
|
||||
/** 按关联运单补齐路线与货物展示字段,返回本次取到的运单;运单不存在时返回 null */
|
||||
private Waybill fillRouteAndCargo(ExceptionDisposalVO vo, Long waybillId) {
|
||||
if (vo == null || waybillId == null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
Waybill waybill = waybillService.getById(waybillId);
|
||||
if (waybill == null || Objects.equals(waybill.getIsDeleted(), 1)) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
Map<String, String> route = new HashMap<>(2);
|
||||
route.put("start", Func.toStr(waybill.getDepartureName(), ""));
|
||||
@@ -997,8 +1002,7 @@ public class ExceptionDisposalServiceImpl
|
||||
cargo.put("name", Func.toStr(waybill.getCargoName(), ""));
|
||||
cargo.put("weight", formatWeight(waybill.getQuantity(), waybill.getQuantityUnit()));
|
||||
vo.setCargo(cargo);
|
||||
|
||||
fillRouteNodes(vo, waybill);
|
||||
return waybill;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1008,6 +1012,14 @@ public class ExceptionDisposalServiceImpl
|
||||
* 运单自己的路线段——历史异常仍要能打开,不能因为配载单不在了就打不开详情。
|
||||
*/
|
||||
private void fillRouteNodes(ExceptionDisposalVO vo, Waybill waybill) {
|
||||
if (vo == null) {
|
||||
return;
|
||||
}
|
||||
if (waybill == null) {
|
||||
vo.setChildWaybillNos(List.of());
|
||||
vo.setRouteNodes(List.of());
|
||||
return;
|
||||
}
|
||||
LoadingManage loading = findLoading(waybill.getLoadingNo());
|
||||
if (loading == null) {
|
||||
vo.setChildWaybillNos(new ArrayList<>());
|
||||
|
||||
+18
-2
@@ -40,8 +40,8 @@ import static org.mockito.Mockito.when;
|
||||
/**
|
||||
* 异常详情下发的配载单、子运单与可编辑站点。
|
||||
* <p>
|
||||
* 有配载单时站点取配载单的站点行(这趟车的执行主体就是配载单);没有配载单才退回运单的路线段,
|
||||
* 站点地址必须沿用改路线时的比对口径(地址优先、站名兜底),否则原样提交会被判成改过地址。
|
||||
* 有配载单时站点取配载单的站点行;没有配载单才退回运单的路线段。
|
||||
* 站点地址与改路线时的比对口径一致(地址优先、站名兜底)。
|
||||
*/
|
||||
class ExceptionDisposalDetailPayloadTest {
|
||||
|
||||
@@ -224,6 +224,22 @@ class ExceptionDisposalDetailPayloadTest {
|
||||
"原样提交时站点地址要与运单段地址一致,缺地址才用站名兜底");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("关联运单已删除时详情照常打开,配载单号 / 子运单号 / 站点各给空值")
|
||||
void deletedWaybillGivesEmptyDetailFields() {
|
||||
stubDisposal();
|
||||
Waybill deleted = new Waybill();
|
||||
deleted.setId(WAYBILL_ID);
|
||||
deleted.setIsDeleted(1);
|
||||
when(waybillService.getById(WAYBILL_ID)).thenReturn(deleted);
|
||||
|
||||
ExceptionDisposalVO vo = assertDoesNotThrow(this::detailResponse);
|
||||
|
||||
assertNull(vo.getLoadingNo());
|
||||
assertEquals(List.of(), vo.getChildWaybillNos());
|
||||
assertEquals(List.of(), vo.getRouteNodes());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 夹具
|
||||
|
||||
private void stubDisposal() {
|
||||
|
||||
+45
-2
@@ -11,21 +11,29 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.springblade.system.cache.UserDisplayCache;
|
||||
import org.springblade.transport.mapper.ExceptionDisposalFollowRecordMapper;
|
||||
import org.springblade.transport.mapper.ExceptionDisposalMapper;
|
||||
import org.springblade.transport.mapper.LoadingManageMapper;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposal;
|
||||
import org.springblade.transport.pojo.entity.Waybill;
|
||||
import org.springblade.transport.pojo.vo.ExceptionDisposalVO;
|
||||
import org.springblade.transport.service.IDriverWaybillService;
|
||||
import org.springblade.transport.service.IWaybillService;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
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.assertNull;
|
||||
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.mockStatic;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -40,6 +48,8 @@ class ExceptionDisposalListQueryTest {
|
||||
private static final Long WAYBILL_ID = 5401L;
|
||||
|
||||
private ExceptionDisposalMapper disposalMapper;
|
||||
private IWaybillService waybillService;
|
||||
private LoadingManageMapper loadingManageMapper;
|
||||
private ExceptionDisposalServiceImpl service;
|
||||
|
||||
@BeforeAll
|
||||
@@ -48,16 +58,19 @@ class ExceptionDisposalListQueryTest {
|
||||
MapperBuilderAssistant assistant = new MapperBuilderAssistant(configuration, "");
|
||||
assistant.setCurrentNamespace("test");
|
||||
TableInfoHelper.initTableInfo(assistant, ExceptionDisposal.class);
|
||||
TableInfoHelper.initTableInfo(assistant, Waybill.class);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
disposalMapper = mock(ExceptionDisposalMapper.class);
|
||||
waybillService = mock(IWaybillService.class);
|
||||
loadingManageMapper = mock(LoadingManageMapper.class);
|
||||
service = new ExceptionDisposalServiceImpl(
|
||||
mock(ExceptionDisposalFollowRecordMapper.class),
|
||||
mock(IWaybillService.class),
|
||||
waybillService,
|
||||
mock(IDriverWaybillService.class),
|
||||
mock(LoadingManageMapper.class));
|
||||
loadingManageMapper);
|
||||
inject("baseMapper", disposalMapper);
|
||||
when(disposalMapper.selectPage(any(), any())).thenReturn(new Page<ExceptionDisposal>(1, 10));
|
||||
}
|
||||
@@ -88,6 +101,36 @@ class ExceptionDisposalListQueryTest {
|
||||
assertFalse(wrapper.getTargetSql().contains("waybill_id"), wrapper.getTargetSql());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("列表不组装详情字段:每行不查配载单、不查子运单")
|
||||
void listPageDoesNotLoadDetailFields() {
|
||||
ExceptionDisposal disposal = new ExceptionDisposal();
|
||||
disposal.setId(6501L);
|
||||
disposal.setWaybillId(WAYBILL_ID);
|
||||
disposal.setDisposalStatus("pending");
|
||||
disposal.setIsDeleted(0);
|
||||
Page<ExceptionDisposal> entityPage = new Page<>(1, 10);
|
||||
entityPage.setRecords(List.of(disposal));
|
||||
when(disposalMapper.selectPage(any(), any())).thenReturn(entityPage);
|
||||
Waybill waybill = new Waybill();
|
||||
waybill.setId(WAYBILL_ID);
|
||||
waybill.setLoadingNo("PZ20261023001");
|
||||
when(waybillService.getById(WAYBILL_ID)).thenReturn(waybill);
|
||||
|
||||
IPage<ExceptionDisposalVO> page;
|
||||
try (MockedStatic<UserDisplayCache> ignored = mockStatic(UserDisplayCache.class)) {
|
||||
page = service.selectPage(new Page<>(1, 10), new ExceptionDisposalVO());
|
||||
}
|
||||
|
||||
assertEquals(1, page.getRecords().size());
|
||||
ExceptionDisposalVO vo = page.getRecords().get(0);
|
||||
assertNull(vo.getLoadingNo(), "配载单号只在详情下发");
|
||||
assertNull(vo.getChildWaybillNos(), "子运单号只在详情下发");
|
||||
assertNull(vo.getRouteNodes(), "可调整站点只在详情下发");
|
||||
verify(loadingManageMapper, never()).selectOne(any());
|
||||
verify(waybillService, never()).listByIds(any());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 夹具
|
||||
|
||||
private LambdaQueryWrapper<ExceptionDisposal> capturedQuery(ExceptionDisposalVO query) {
|
||||
|
||||
+38
-3
@@ -15,6 +15,7 @@ import org.springblade.system.cache.UserDisplayCache;
|
||||
import org.springblade.transport.mapper.ExceptionDisposalFollowRecordMapper;
|
||||
import org.springblade.transport.mapper.ExceptionDisposalMapper;
|
||||
import org.springblade.transport.mapper.LoadingManageMapper;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalFollowRequest;
|
||||
import org.springblade.transport.pojo.dto.ExceptionDisposalRejectRequest;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposal;
|
||||
import org.springblade.transport.pojo.entity.ExceptionDisposalFollowRecord;
|
||||
@@ -38,10 +39,10 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* 拒绝与撤销:两个动作都了结异常,但只有拒绝留痕。
|
||||
* 拒绝与撤销:两个动作都了结异常,只有拒绝留痕。
|
||||
* <p>
|
||||
* 拒绝复用已完成这个终态(台账仍显示「已处理」),所以它与「完成」的区别只落在跟进记录的第一句;
|
||||
* 撤销是上报人收回,不是处置,因此不留跟进记录。
|
||||
* 拒绝复用已完成这个终态(台账仍显示「已处理」),并写一条「拒绝:…」的跟进记录;
|
||||
* 撤销置为已撤销,不写跟进记录。终态(已完成 / 已撤销)不允许再跟进、再完成。
|
||||
*/
|
||||
class ExceptionDisposalRejectRevokeTest {
|
||||
|
||||
@@ -253,6 +254,33 @@ class ExceptionDisposalRejectRevokeTest {
|
||||
assertEquals("该异常已处理", exception.getMessage());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 终态门禁
|
||||
|
||||
@Test
|
||||
@DisplayName("已撤销的异常不能再跟进:终态不允许回到处理中")
|
||||
void followRevokedDisposalRejected() {
|
||||
stubDisposal("revoked", REPORTER_ID);
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> runAsReporter(() -> service.follow(followRequest("已核实,等待补件"))));
|
||||
|
||||
assertEquals("已完成的异常不允许继续跟进", exception.getMessage());
|
||||
verify(disposalMapper, never()).updateById(any(ExceptionDisposal.class));
|
||||
verify(followRecordMapper, never()).insert(any(ExceptionDisposalFollowRecord.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("已撤销的异常不能再完成:撤销后不能改成已完成")
|
||||
void completeRevokedDisposalRejected() {
|
||||
stubDisposal("revoked", REPORTER_ID);
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> runAsReporter(() -> service.complete(DISPOSAL_ID)));
|
||||
|
||||
assertEquals("异常已完成,请勿重复操作", exception.getMessage());
|
||||
verify(disposalMapper, never()).updateById(any(ExceptionDisposal.class));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ 夹具
|
||||
|
||||
private void stubDisposal(String status, Long reporterId) {
|
||||
@@ -271,6 +299,13 @@ class ExceptionDisposalRejectRevokeTest {
|
||||
return request;
|
||||
}
|
||||
|
||||
private ExceptionDisposalFollowRequest followRequest(String content) {
|
||||
ExceptionDisposalFollowRequest request = new ExceptionDisposalFollowRequest();
|
||||
request.setId(DISPOSAL_ID);
|
||||
request.setFollowContent(content);
|
||||
return request;
|
||||
}
|
||||
|
||||
private ExceptionDisposalFollowRecord insertedRecord() {
|
||||
ArgumentCaptor<ExceptionDisposalFollowRecord> captor =
|
||||
ArgumentCaptor.forClass(ExceptionDisposalFollowRecord.class);
|
||||
|
||||
+31
-8
@@ -49,8 +49,8 @@ import static org.mockito.Mockito.when;
|
||||
/**
|
||||
* 同意并调整路线:先写跟进记录、再改载体路线、最后了结。
|
||||
* <p>
|
||||
* 载体跟配载单走——配载单是这趟车的执行主体,司机端打卡读它的站点行;没有配载单才改运单,
|
||||
* 而运单的 route_json 是司机端按段解析的形状,改成站点行就读不出路线了。
|
||||
* 载体跟配载单走:配载单是这趟车的执行主体,司机端打卡读它的站点行;没有配载单才改运单,
|
||||
* 运单的 route_json 是路线段形状。
|
||||
*/
|
||||
class ExceptionDisposalRouteAdjustTest {
|
||||
|
||||
@@ -360,22 +360,45 @@ class ExceptionDisposalRouteAdjustTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("运单站数变了时不动路线:段形状说不出哪一站被删,硬写等于重写行程")
|
||||
void adjustRouteSkipsWaybillRouteWhenStationCountChanges() {
|
||||
@DisplayName("改中间站地址时段首尾都同步:上一段到达地与下一段出发地写成同一个新址")
|
||||
void adjustRouteSyncsMiddleStationOnBothSegments() {
|
||||
stubPendingDisposal();
|
||||
Waybill waybill = waybill(null, "in_progress", segmentRouteJson());
|
||||
when(waybillService.getById(WAYBILL_ID)).thenReturn(waybill);
|
||||
|
||||
asScheduler(() -> service.adjustRoute(request(
|
||||
node("start", START, null),
|
||||
node("end", NEW_END, null))));
|
||||
node("transit", TRANSIT_SECOND, null),
|
||||
node("end", END, null))));
|
||||
|
||||
Waybill updated = updatedWaybill();
|
||||
assertEquals(segmentRouteJson(), updated.getRouteJson(), "站数对不上时保留原路线");
|
||||
assertEquals(NEW_END, updated.getArrivalAddress());
|
||||
List<Map<String, Object>> segments = JsonUtil.readListMap(updatedWaybill().getRouteJson());
|
||||
assertEquals(2, segments.size(), "站数不变,段数也不变");
|
||||
assertEquals(TRANSIT_SECOND, segments.get(0).get("arrivalAddress"));
|
||||
assertEquals(TRANSIT_SECOND, segments.get(0).get("arrivalName"), "站名跟着地址一起改");
|
||||
assertEquals(TRANSIT_SECOND, segments.get(1).get("departureAddress"),
|
||||
"下一段的出发地必须与上一段的到达地一致");
|
||||
assertEquals(TRANSIT_SECOND, segments.get(1).get("departureName"));
|
||||
assertEquals(START, segments.get(0).get("departureAddress"), "首站地址不可改");
|
||||
assertEquals(END, segments.get(1).get("arrivalAddress"), "没改的到达地原样保留");
|
||||
assertEquals("completed", updatedDisposal().getDisposalStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("运单站数变化时拒绝:无配载单的运单只支持改地址,不支持增减途经站")
|
||||
void adjustRouteRejectsWaybillStationCountChange() {
|
||||
stubPendingDisposal();
|
||||
Waybill waybill = waybill(null, "in_progress", segmentRouteJson());
|
||||
when(waybillService.getById(WAYBILL_ID)).thenReturn(waybill);
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class, () -> asScheduler(
|
||||
() -> service.adjustRoute(request(
|
||||
node("start", START, null),
|
||||
node("end", NEW_END, null)))));
|
||||
|
||||
assertEquals("无配载单的运单不支持增减途经站", exception.getMessage());
|
||||
verifyNoWrite();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("目的地未变而只见中间站变化时,按途经站数量说明")
|
||||
void adjustRouteReportsTransitCountChange() {
|
||||
|
||||
Reference in New Issue
Block a user