贴标申请,仓储转运

This commit is contained in:
2026-10-14 11:36:35 +08:00
parent 83dc6dea3f
commit e14bdb4f49
37 changed files with 884 additions and 32 deletions
@@ -0,0 +1,85 @@
package com.baiyue.lastleg.discard.service;
import com.baiyue.lastleg.discard.entity.CargoDiscardApplication;
import com.baiyue.lastleg.discard.entity.CargoDiscardPhoto;
import com.baiyue.lastleg.discard.gateway.CargoDiscardPhotoFileGateway;
import com.baiyue.lastleg.discard.mapper.CargoDiscardPhotoMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.server.ResponseStatusException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
class CargoDiscardPhotoServiceTest {
private final CargoDiscardPhotoMapper photos = mock(CargoDiscardPhotoMapper.class);
private final CargoDiscardPhotoFileGateway files = mock(CargoDiscardPhotoFileGateway.class);
private final CargoDiscardPhotoService service = new CargoDiscardPhotoService();
private final CargoDiscardApplication application = new CargoDiscardApplication();
private final List<CargoDiscardPhoto> stored = new ArrayList<>();
@BeforeEach void setup() {
application.setId(1L); application.setCustomerId("7");
ReflectionTestUtils.setField(service, "photos", photos); ReflectionTestUtils.setField(service, "files", files);
when(photos.listApplication("7", 1L)).thenAnswer(invocation -> stored);
when(photos.insert(any(CargoDiscardPhoto.class))).thenAnswer(invocation -> { stored.add(invocation.getArgument(0)); return 1; });
when(files.upload(eq("7"), eq(1L), eq(9L), any())).thenReturn(new CargoDiscardPhotoFileGateway.UploadedFile(101L, "discard.png", "image/png", 8L));
}
private CargoDiscardPhoto photo(long fileId, String palletNo) {
var photo = new CargoDiscardPhoto(); photo.setFileId(fileId); photo.setPalletNo(palletNo);
photo.setCustomerId("7"); photo.setApplicationId(1L); stored.add(photo); return photo;
}
@Test void uploadsRestoreForPdaButOnlySubmittedPhotosAppearInBothDetails() {
var uploaded = service.upload(application, "PALLET-A", "operator", 9L, new MockMultipartFile("file", new byte[]{1}));
assertEquals(101L, uploaded.fileId()); assertEquals("PALLET-A", uploaded.palletNo());
assertEquals(1, service.list(application, "PALLET-A", false).size());
assertTrue(service.list(application, null, true).isEmpty());
assertThrows(ResponseStatusException.class, () -> service.download(application, null, 101L, true));
service.confirm(application, "PALLET-A", List.of(101L), false);
assertEquals(1, service.list(application, null, true).size());
assertNotNull(service.list(application, null, true).get(0).submittedAt());
service.download(application, null, 101L, true); verify(files).download("7", 1L, 101L);
service.confirm(application, "PALLET-A", List.of(101L), true);
verify(photos, times(1)).updateById(any(CargoDiscardPhoto.class));
}
@Test void noPhotosDuplicatesAndCrossPalletOrApplicationReferencesCannotSubmit() {
photo(101L, "PALLET-A"); photo(102L, "PALLET-B");
for (var ids : List.of(List.<Long>of(), List.of(101L, 101L), List.of(102L), List.of(999L)))
assertThrows(ResponseStatusException.class, () -> service.confirm(application, "PALLET-A", ids, false));
assertThrows(ResponseStatusException.class, () -> service.download(application, "PALLET-A", 102L, false));
verify(files, never()).validate(anyString(), anyLong(), anyLong());
verify(photos, never()).updateById(any(CargoDiscardPhoto.class));
}
@Test void ownershipValidationFailureDoesNotBindAnyPhoto() {
photo(101L, "PALLET-A"); photo(102L, "PALLET-A");
doThrow(new ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST)).when(files).validate("7", 1L, 102L);
assertThrows(ResponseStatusException.class, () -> service.confirm(application, "PALLET-A", List.of(101L, 102L), false));
verify(photos, never()).updateById(any(CargoDiscardPhoto.class));
assertTrue(stored.stream().allMatch(p -> p.getSubmittedAt() == null));
}
@Test void completedEvidenceCannotChangeAndReplayDoesNotWrite() {
photo(101L, "PALLET-A").setSubmittedAt(LocalDateTime.now()); photo(102L, "PALLET-A");
service.confirm(application, "PALLET-A", List.of(101L), true);
assertThrows(ResponseStatusException.class, () -> service.confirm(application, "PALLET-A", List.of(102L), true));
assertThrows(ResponseStatusException.class, () -> service.confirm(application, "PALLET-A", List.of(101L, 102L), true));
verifyNoInteractions(files); verify(photos, never()).updateById(any(CargoDiscardPhoto.class));
}
@Test void uploadLimitIsPerPalletAndStopsBeforeFileStorage() {
for (long id=1; id<=20; id++) photo(id, "PALLET-A");
assertThrows(ResponseStatusException.class, () -> service.upload(application, "PALLET-A", "operator", 9L, new MockMultipartFile("file", new byte[]{1})));
verify(files, never()).upload(anyString(), anyLong(), anyLong(), any());
assertEquals(101L, service.upload(application, "PALLET-B", "operator", 9L, new MockMultipartFile("file", new byte[]{1})).fileId());
}
}
@@ -67,6 +67,7 @@ class CargoDiscardServiceTest {
@BeforeEach
void setUp() {
service = new CargoDiscardService();
ReflectionTestUtils.setField(service, "photoService", org.mockito.Mockito.mock(CargoDiscardPhotoService.class));
ReflectionTestUtils.setField(service, "applications", applications);
ReflectionTestUtils.setField(service, "items", items);
ReflectionTestUtils.setField(service, "discardCartons", discardCartons);