提交
This commit is contained in:
+56
-1
@@ -10,6 +10,7 @@ import com.baiyue.lastleg.inboundplan.pda.entity.InboundPalletMerge;
|
||||
import com.baiyue.lastleg.inboundplan.pda.entity.InboundPdaOperation;
|
||||
import com.baiyue.lastleg.inboundplan.pda.entity.InboundPdaTask;
|
||||
import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway;
|
||||
import com.baiyue.lastleg.inboundplan.pda.gateway.UnloadPhotoFileGateway;
|
||||
import com.baiyue.lastleg.inboundplan.pda.repository.PdaWorkflowRepository;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -20,6 +21,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -33,6 +35,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -44,6 +47,7 @@ class InboundPdaWorkflowServiceTest {
|
||||
@Mock WarehouseResourceGateway warehouse;
|
||||
@Mock InboundStockReceiptService stockReceipts;
|
||||
@Mock InboundUnloadCompletedOutboxService unloadCompletedOutbox;
|
||||
@Mock UnloadPhotoFileGateway unloadPhotoFiles;
|
||||
private InboundPdaWorkflowService service;
|
||||
|
||||
private InboundPlan plan;
|
||||
@@ -64,6 +68,7 @@ class InboundPdaWorkflowServiceTest {
|
||||
ReflectionTestUtils.setField(service, "warehouse", warehouse);
|
||||
ReflectionTestUtils.setField(service, "stockReceipts", stockReceipts);
|
||||
ReflectionTestUtils.setField(service, "unloadCompletedOutbox", unloadCompletedOutbox);
|
||||
ReflectionTestUtils.setField(service, "unloadPhotoFiles", unloadPhotoFiles);
|
||||
ReflectionTestUtils.setField(service, "sourceObjectMapper", new ObjectMapper().findAndRegisterModules());
|
||||
service.initializeObjectMapper();
|
||||
plan = plan();
|
||||
@@ -76,7 +81,7 @@ class InboundPdaWorkflowServiceTest {
|
||||
target = allocation(31L, targetLine.getId(), targetPallet.getId(), 3, 3, 0);
|
||||
source = allocation(32L, sourceLine.getId(), sourcePallet.getId(), 2, 2, 2);
|
||||
otherWarehouse = allocation(33L, sourceLine.getId(), otherWarehousePallet.getId(), 2, 2, 2);
|
||||
when(repository.lockPlan("100", "LIP1")).thenReturn(plan);
|
||||
lenient().when(repository.lockPlan("100", "LIP1")).thenReturn(plan);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -326,6 +331,8 @@ class InboundPdaWorkflowServiceTest {
|
||||
|
||||
assertEquals(List.of(101L, 103L), result.unloadPhotoFileIds());
|
||||
assertEquals(result.unloadPhotoUploadedAt().plusDays(2), result.estimatedEmptyReturnAt());
|
||||
verify(unloadPhotoFiles).validate("100", task.getId(), 101L);
|
||||
verify(unloadPhotoFiles).validate("100", task.getId(), 103L);
|
||||
verify(repository).update(task);
|
||||
ArgumentCaptor<InboundPdaOperation> operation = ArgumentCaptor.forClass(InboundPdaOperation.class);
|
||||
verify(repository).insert(operation.capture());
|
||||
@@ -344,6 +351,54 @@ class InboundPdaWorkflowServiceTest {
|
||||
verify(repository, never()).update(task);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadUnloadPhotosRejectsAFileOwnedByAnotherBusinessTask() {
|
||||
activeTask();
|
||||
org.mockito.Mockito.doThrow(new IllegalArgumentException("ownership mismatch"))
|
||||
.when(unloadPhotoFiles).validate("100", task.getId(), 101L);
|
||||
|
||||
assertThrows(ResponseStatusException.class, () -> service.uploadUnloadPhotos("100", "LIP1",
|
||||
new PdaRequests.UnloadPhotos(List.of(101L), "unload-photo-wrong-owner", "7", "worker")));
|
||||
|
||||
verify(repository, never()).update(task);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadUnloadPhotoFileBindsTheFileToTheActivePdaTask() {
|
||||
activeTask();
|
||||
var file = new MockMultipartFile("file", "unload.jpg", "image/jpeg", new byte[] {1, 2, 3});
|
||||
when(unloadPhotoFiles.upload("100", task.getId(), 7L, file))
|
||||
.thenReturn(new UnloadPhotoFileGateway.UploadedFile(101L, "unload.jpg", "image/jpeg", 3L));
|
||||
|
||||
var result = service.uploadUnloadPhotoFile("100", "LIP1", 7L, file);
|
||||
|
||||
assertEquals(101L, result.fileId());
|
||||
assertEquals("unload.jpg", result.fileName());
|
||||
assertEquals("image/jpeg", result.contentType());
|
||||
assertEquals(3L, result.sizeBytes());
|
||||
verify(unloadPhotoFiles).upload("100", task.getId(), 7L, file);
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadUnloadPhotoFileRejectsEmptyFileBeforeCallingFileService() {
|
||||
var file = new MockMultipartFile("file", "unload.jpg", "image/jpeg", new byte[0]);
|
||||
|
||||
assertThrows(ResponseStatusException.class,
|
||||
() -> service.uploadUnloadPhotoFile("100", "LIP1", 7L, file));
|
||||
|
||||
verify(unloadPhotoFiles, never()).upload(any(), anyLong(), anyLong(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void uploadUnloadPhotoFileRejectsNonImageBeforeCallingFileService() {
|
||||
var file = new MockMultipartFile("file", "unload.pdf", "application/pdf", new byte[] {1});
|
||||
|
||||
assertThrows(ResponseStatusException.class,
|
||||
() -> service.uploadUnloadPhotoFile("100", "LIP1", 7L, file));
|
||||
|
||||
verify(unloadPhotoFiles, never()).upload(any(), anyLong(), anyLong(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void completesWhenMergedAllocationsPreserveExactLineTotals() {
|
||||
activeTask();
|
||||
|
||||
+8
-17
@@ -2,13 +2,12 @@ package com.baiyue.lastleg.inboundplan.pda.service;
|
||||
|
||||
import com.baiyue.common.event.EventEnvelope;
|
||||
import com.baiyue.common.event.EventTypes;
|
||||
import com.baiyue.common.event.OverseasContainerUnloadedV1;
|
||||
import com.baiyue.common.event.RegionCode;
|
||||
import com.baiyue.lastleg.entity.LastlegEventOutbox;
|
||||
import com.baiyue.lastleg.entity.LastlegOrder;
|
||||
import com.baiyue.lastleg.inboundplan.entity.InboundPlan;
|
||||
import com.baiyue.lastleg.inboundplan.pda.entity.InboundPdaTask;
|
||||
import com.baiyue.lastleg.mapper.LastlegEventOutboxMapper;
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -29,7 +28,6 @@ import static org.mockito.Mockito.when;
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class InboundUnloadCompletedOutboxServiceTest {
|
||||
@Mock LastlegEventOutboxMapper outbox;
|
||||
@Mock LastlegOrderMapper orders;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
|
||||
private InboundUnloadCompletedOutboxService service;
|
||||
|
||||
@@ -37,17 +35,15 @@ class InboundUnloadCompletedOutboxServiceTest {
|
||||
void setUp() {
|
||||
service = new InboundUnloadCompletedOutboxService();
|
||||
ReflectionTestUtils.setField(service, "mapper", outbox);
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "objectMapper", objectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
void writesAValidOverseasToCnEnvelopeUsingTheSourceBookingId() throws Exception {
|
||||
InboundPlan plan = new InboundPlan(); plan.setSourceOrderId(11L); plan.setContainerNo("MSCU1");
|
||||
void writesAValidOverseasToCnEnvelopeUsingTheContainerNo() throws Exception {
|
||||
InboundPlan plan = new InboundPlan(); plan.setContainerNo("MSCU1");
|
||||
InboundPdaTask task = new InboundPdaTask(); task.setId(22L); task.setCustomerId("100");
|
||||
task.setUnloadPhotoUploadedAt(LocalDateTime.of(2026, 8, 20, 10, 0)); task.setVersion(3);
|
||||
LastlegOrder order = new LastlegOrder(); order.setSourceContainerBookingId("9001");
|
||||
when(orders.selectById(11L)).thenReturn(order);
|
||||
task.setUnloadPhotoUploadedAt(LocalDateTime.of(2026, 8, 20, 10, 0));
|
||||
task.setCompletedAt(LocalDateTime.of(2026, 8, 20, 10, 5)); task.setVersion(3);
|
||||
|
||||
service.publish(plan, task, List.of(101L));
|
||||
|
||||
@@ -57,15 +53,10 @@ class InboundUnloadCompletedOutboxServiceTest {
|
||||
assertEquals(EventTypes.OVERSEAS_CONTAINER_UNLOADED, envelope.eventType());
|
||||
assertEquals(RegionCode.OVERSEAS, envelope.sourceRegion());
|
||||
assertEquals(RegionCode.CN, envelope.targetRegion());
|
||||
assertEquals("9001", envelope.aggregateId());
|
||||
assertEquals("MSCU1", envelope.aggregateId());
|
||||
assertEquals("MSCU1", envelope.payload().path("containerNo").asText());
|
||||
OverseasContainerUnloadedV1 payload = objectMapper.treeToValue(envelope.payload(), OverseasContainerUnloadedV1.class);
|
||||
assertEquals("2026-08-20T10:05:00Z", payload.unloadingCompletedAt().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsPlansWhoseSourceOrderLostTheContainerBookingId() {
|
||||
InboundPlan plan = new InboundPlan(); plan.setSourceOrderId(11L);
|
||||
InboundPdaTask task = new InboundPdaTask(); task.setId(22L); task.setCustomerId("100");
|
||||
when(orders.selectById(11L)).thenReturn(new LastlegOrder());
|
||||
assertThrows(IllegalStateException.class, () -> service.publish(plan, task, List.of(101L)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user