提交
This commit is contained in:
@@ -82,6 +82,8 @@ test('fleet stays a business slice and its policies have no infrastructure depen
|
||||
'TransportTaskProjection->trip.FleetTripEntity', 'TransportTaskProjection->trip.TransportTripChanged',
|
||||
'TransportTaskService->business.FleetPoolOrderQueries', 'TransportTaskService->driver.DriverService',
|
||||
'TransportTaskService->reporting.TripOperationsEvidenceGateway',
|
||||
// 取货照片沿既有运输边界读取车次身份/时间,并复用司机资格与证照授权;不开放 Mapper。
|
||||
'TransportReviewPhotos->driver.DriverService', 'TransportReviewPhotos->trip.FleetTripEntity',
|
||||
].some(reference => `${edge.source}->${edge.target}` === `com.baiyue.lastleg.dispatch.transport.${reference.replace('->', '->com.baiyue.lastleg.fleet.')}`)),
|
||||
'dispatch must use fleet ports and guards, not its persistence mappers');
|
||||
const incomingEdges = report.classDependencies.filter(edge => edge.source.startsWith('com.baiyue.lastleg.transfer.') && edge.target.startsWith('com.baiyue.lastleg.fleet.'));
|
||||
|
||||
@@ -5253,6 +5253,11 @@ components:
|
||||
type: object
|
||||
x-java-record: DispatchContracts.DriverEvidence
|
||||
properties:
|
||||
masterLicenseFileId:
|
||||
type: string
|
||||
pattern: ^[1-9][0-9]*$
|
||||
nullable: true
|
||||
description: 取货排车显式冻结的司机主档驾驶证ID,包含在响应fileIds中;其余取货证照为本车上传。普通派送沿既有MASTER证照语义。
|
||||
photoFileIds:
|
||||
type: array
|
||||
maxItems: 20
|
||||
|
||||
+19
@@ -86,6 +86,25 @@ public class DispatchAggregatePersistenceTest {
|
||||
verify(e.files,never()).download(anyLong(),anyLong());verifyNoInteractions(e.dispatchFiles);
|
||||
}
|
||||
|
||||
/** 取货已保存的补传证照保持本车归属,只有明确主档引用可以读取司机证照。 */
|
||||
@Test void pickupSavedLicenseUploadsDoNotBecomeMasterLicenseReferences() throws Exception {
|
||||
var e=new DriverEvidenceFixture();var number=e.dispatch(ResourceMode.MASTER,71L,List.of(81L,91L));
|
||||
var row=e.f.repository.find(number);
|
||||
var resources=e.f.json.readValue(row.getResourcesJson(),DispatchContracts.Resources.class);
|
||||
var d=resources.driver();var proof=d.evidence();
|
||||
var next=new DispatchContracts.Resources(resources.vehicle(),new DispatchContracts.DriverSnapshot(d.mode(),d.driverId(),d.name(),d.phone(),
|
||||
new DispatchContracts.DriverEvidence(proof.licenseNo(),proof.licenseExpiresOn(),proof.fileIds(),proof.expectedTaskEndAt(),proof.photoFileIds(),81L)));
|
||||
e.f.db.update("UPDATE ll_dispatch_order SET task_type='PICKUP', resources_json=? WHERE dispatch_no=?",e.f.json.writeValueAsString(next),number);
|
||||
var kind=com.baiyue.lastleg.dispatch.gateway.DispatchEvidenceGateway.Kind.DRIVER;
|
||||
var uploaded=new com.baiyue.lastleg.dispatch.gateway.DispatchEvidenceGateway.File(91L,"pickup.png","image/png",3L);
|
||||
when(e.dispatchFiles.metadata(row.getId(),kind,91L)).thenReturn(uploaded);
|
||||
assertThat(e.f.service.evidenceMetadata(e.f.actor,number,kind,91L)).isEqualTo(uploaded);
|
||||
verifyNoInteractions(e.driverRows,e.history,e.files);
|
||||
e.allowFile(81L);
|
||||
assertThat(e.f.service.evidenceMetadata(e.f.actor,number,kind,81L).fileId()).isEqualTo(81L);
|
||||
verify(e.files).metadata(71L,81L);
|
||||
}
|
||||
|
||||
/** MASTER改外配的编辑尚未保存时,新上传文件只走本车归属,不误借旧司机白名单。 */
|
||||
@Test void unsavedExternalUploadOnMasterDispatchRetainsOriginalDispatchFileReads() throws Exception {
|
||||
var e=new DriverEvidenceFixture();var number=e.dispatch(ResourceMode.MASTER,71L,List.of(81L));
|
||||
|
||||
+21
@@ -15,6 +15,27 @@ import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class TransportTaskProjectionTest {
|
||||
/** 照片写入使审核失效,后续出发、到仓、结案均保留同一资源的照片。 */
|
||||
@Test void photosInvalidateReviewAndSurviveExecutionProjection() throws Exception {
|
||||
var roots=mock(DispatchAggregateRepository.class);var links=mock(TransportTaskRepository.class);
|
||||
var json=new ObjectMapper().findAndRegisterModules();
|
||||
var projection=new TransportTaskProjection(roots,links,mock(UsTruckOrderRepository.class),mock(DispatchNumberGenerator.class),json);
|
||||
org.springframework.test.util.ReflectionTestUtils.setField(projection,"pickupFacts",mock(com.baiyue.lastleg.fleet.pickup.FleetPickupRepository.class));
|
||||
var row=new DispatchAggregate();row.setId(2L);row.setDispatchNo("PC1");row.setTaskType("PICKUP");row.setStatus("ACTIVE");row.setRecordVersion(10L);row.setReviewRound(1L);row.setReviewState("APPROVED");row.setStage("LOADING");
|
||||
var oldReview=new com.baiyue.lastleg.dispatch.port.DispatchContracts.Review(com.baiyue.lastleg.dispatch.port.DispatchTypes.ReviewStatus.APPROVED,null,"OP",java.time.Instant.now(),1,"basis",null,null);
|
||||
row.setDispatchReviewJson(json.writeValueAsString(oldReview));row.setLoadingReviewJson(json.writeValueAsString(oldReview));
|
||||
row.setResourcesJson("{\"vehicle\":{\"mode\":\"MASTER\",\"vehicleId\":7,\"evidenceFileIds\":[]},\"driver\":{\"mode\":\"MASTER\",\"driverId\":8}}");
|
||||
when(roots.lock("PC1")).thenReturn(row);when(roots.saveState(eq(row),anyLong())).thenReturn(1);when(links.byTrip(1L)).thenReturn(row);
|
||||
var photos=new com.baiyue.lastleg.dispatch.port.DispatchContracts.DriverEvidence("LICENSE",java.time.LocalDate.of(2099,1,1),java.util.List.of(33L),java.time.Instant.parse("2098-01-01T00:00:00Z"),java.util.List.of(22L),33L);
|
||||
projection.savePhotos("PC1","OP",java.util.List.of(21L),photos);
|
||||
assertThat(row.getReviewState()).isEqualTo("DRAFT");assertThat(row.getRecordVersion()).isEqualTo(11L);assertThat(row.getStage()).isEqualTo("BEFORE_LOADING");
|
||||
var trip=new FleetTripEntity();trip.setId(1L);trip.setTripNo("TR1");trip.setTripPurpose("PICKUP");trip.setVehicleId(7L);trip.setDriverId(8L);trip.setStatus("IN_TRANSIT");
|
||||
projection.changed(new TransportTripChanged(trip,"PICKUP_PICKED","装货","OP"));
|
||||
trip.setStatus("COMPLETED");projection.changed(new TransportTripChanged(trip,"PICKUP_ARRIVED","到仓","OP"));
|
||||
var saved=json.readValue(row.getResourcesJson(),com.baiyue.lastleg.dispatch.port.DispatchContracts.Resources.class);
|
||||
assertThat(saved.vehicle().evidenceFileIds()).containsExactly(21L);assertThat(saved.driver().evidence()).isEqualTo(photos);
|
||||
assertThat(row.getStage()).isEqualTo("DELIVERED");
|
||||
}
|
||||
/** 已出发也不能跳过照片阶段,全部取货照片确认后才进入派送中。 */
|
||||
@Test void oldDepartureDoesNotSkipPickupPhotosStage() {
|
||||
var roots=mock(DispatchAggregateRepository.class);var links=mock(TransportTaskRepository.class);var pickups=mock(com.baiyue.lastleg.fleet.pickup.FleetPickupRepository.class);
|
||||
|
||||
+8
@@ -22,6 +22,14 @@ class TransportTaskServiceTest {
|
||||
DispatchAggregateRepository roots;TransportTaskRepository links;FleetTripRepository tripRepo;FleetTripService trips;
|
||||
UsTruckOrderRepository trucks;TripOperationsEvidenceGateway files;TransportTaskService service;FleetTripEntity trip;UsTruckOrder order;
|
||||
final Map<String,String> commands=new HashMap<>();
|
||||
/** 审核已改变的旧页面不能通过仍相同的车次版本覆盖资源和照片。 */
|
||||
@Test void staleDispatchVersionCannotAssignEvenWhenTripVersionMatches() {
|
||||
var root=roots.find("PC1");root.setTaskType("PICKUP");root.setRecordVersion(9L);when(roots.lock("PC1")).thenReturn(root);
|
||||
trip.setTripPurpose("PICKUP");trip.setStatus("PLANNED");
|
||||
var photos=mock(TransportReviewPhotos.class);org.springframework.test.util.ReflectionTestUtils.setField(service,"reviewPhotos",photos);
|
||||
assertThatThrownBy(()->service.assign("PC1","OP",new TransportTaskModels.Assign(3L,7L,8L,"保存",8L,null,null))).hasMessageContaining("刷新");
|
||||
verify(trips,never()).assign(anyString(),anyString(),any());verifyNoInteractions(photos);
|
||||
}
|
||||
@BeforeEach void setup(){
|
||||
roots=mock(DispatchAggregateRepository.class);links=mock(TransportTaskRepository.class);tripRepo=mock(FleetTripRepository.class);trips=mock(FleetTripService.class);
|
||||
trucks=mock(UsTruckOrderRepository.class);files=mock(TripOperationsEvidenceGateway.class);
|
||||
|
||||
Reference in New Issue
Block a user