贴标申请,仓储转运
This commit is contained in:
+12
@@ -12,6 +12,7 @@ import java.util.Set;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class MerchantCargoDiscardControllerTest {
|
||||
private final CargoDiscardService service = mock(CargoDiscardService.class);
|
||||
@@ -36,6 +37,17 @@ class MerchantCargoDiscardControllerTest {
|
||||
() -> controller.page(user(0L, "PLATFORM"), query));
|
||||
}
|
||||
|
||||
@Test void photoDownloadUsesTokenCustomerAndReturnsPrivateImageBytes() {
|
||||
byte[] bytes = {1, 2, 3};
|
||||
when(service.downloadPhoto("100", "DS001", 101L)).thenReturn(
|
||||
new com.baiyue.lastleg.discard.gateway.CargoDiscardPhotoFileGateway.DownloadedFile(bytes, "discard.png", "image/png"));
|
||||
var response = controller.downloadPhoto(user(100L, "MERCHANT"), "DS001", 101L);
|
||||
org.junit.jupiter.api.Assertions.assertArrayEquals(bytes, response.getBody());
|
||||
org.junit.jupiter.api.Assertions.assertEquals("no-store", response.getHeaders().getCacheControl());
|
||||
verify(service).downloadPhoto("100", "DS001", 101L);
|
||||
assertThrows(ResponseStatusException.class, () -> controller.downloadPhoto(user(0L, "PLATFORM"), "DS001", 101L));
|
||||
}
|
||||
|
||||
private static AuthenticatedUser user(long tenantId, String appCode) {
|
||||
return new AuthenticatedUser(1L, tenantId, tenantId, 9L, "merchant", appCode, "WEB", Set.of());
|
||||
}
|
||||
|
||||
+36
-4
@@ -37,10 +37,12 @@ class PdaCargoDiscardServiceTest {
|
||||
private CargoDiscardApplication application;
|
||||
private CargoDiscardItem item;
|
||||
private final PdaWarehouseIdentity identity = new PdaWarehouseIdentity("OP", "operator", 99L);
|
||||
private PdaCargoDiscardDtos.Confirm request(int actual) { return new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, actual))); }
|
||||
private final com.baiyue.lastleg.discard.service.CargoDiscardPhotoService photoService = mock(com.baiyue.lastleg.discard.service.CargoDiscardPhotoService.class);
|
||||
private PdaCargoDiscardDtos.Confirm request(int actual) { return new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, actual)), List.of(101L)); }
|
||||
|
||||
@BeforeEach void setup() {
|
||||
service = new PdaCargoDiscardService();
|
||||
ReflectionTestUtils.setField(service, "photoService", photoService);
|
||||
ReflectionTestUtils.setField(service, "applications", applications);
|
||||
ReflectionTestUtils.setField(service, "items", items);
|
||||
ReflectionTestUtils.setField(service, "cartons", cartons);
|
||||
@@ -93,8 +95,8 @@ class PdaCargoDiscardServiceTest {
|
||||
void finishedQuantityCannotChange(String status) { finished(status); assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", request(0))); noWrites(); }
|
||||
@Test void missingOrForeignLineAndWrongPalletCannotRecover() {
|
||||
finished("PDA_COMPLETED");
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of())));
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(999L, 1)))));
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(), List.of(101L))));
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(999L, 1)), List.of(101L))));
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "OTHER-PALLET", request(1))); noWrites();
|
||||
}
|
||||
@Test void foreignWarehouseHasNoApplication() {
|
||||
@@ -116,7 +118,37 @@ class PdaCargoDiscardServiceTest {
|
||||
when(items.listApplication("CUSTOMER", 1L)).thenReturn(List.of(item, pending)); when(profiles.selectById(23L)).thenReturn(other);
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", request(1))); noWrites();
|
||||
}
|
||||
@Test void duplicateLineCannotRecover() { finished("COMPLETED"); assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, 1), new PdaCargoDiscardDtos.ActualLine(11L, 1))))); noWrites(); }
|
||||
@Test void duplicateLineCannotRecover() { finished("COMPLETED"); assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, 1), new PdaCargoDiscardDtos.ActualLine(11L, 1)), List.of(101L)))); noWrites(); }
|
||||
@Test void loadedForeignCustomerItemCannotRecover() { finished("COMPLETED"); item.setCustomerId("OTHER"); assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", request(1))); noWrites(); }
|
||||
@Test void loadedDifferentApplicationItemCannotRecover() { finished("COMPLETED"); item.setApplicationId(2L); assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", request(1))); noWrites(); }
|
||||
|
||||
@ParameterizedTest @ValueSource(ints = {3, 1, 0})
|
||||
void threeLocalOrdersUploadConfirmAndReplayWithFullPartialAndZeroActualDisposal(int actual) {
|
||||
var realPhotos = new com.baiyue.lastleg.discard.service.CargoDiscardPhotoService();
|
||||
var photoMapper = mock(com.baiyue.lastleg.discard.mapper.CargoDiscardPhotoMapper.class);
|
||||
var photoFiles = mock(com.baiyue.lastleg.discard.gateway.CargoDiscardPhotoFileGateway.class);
|
||||
var stored = new java.util.ArrayList<com.baiyue.lastleg.discard.entity.CargoDiscardPhoto>();
|
||||
ReflectionTestUtils.setField(realPhotos, "photos", photoMapper); ReflectionTestUtils.setField(realPhotos, "files", photoFiles);
|
||||
ReflectionTestUtils.setField(service, "photoService", realPhotos);
|
||||
when(photoMapper.listApplication("CUSTOMER", 1L)).thenAnswer(invocation -> stored);
|
||||
when(photoMapper.insert(any(com.baiyue.lastleg.discard.entity.CargoDiscardPhoto.class))).thenAnswer(invocation -> { stored.add(invocation.getArgument(0)); return 1; });
|
||||
when(photoFiles.upload(eq("CUSTOMER"), eq(1L), eq(9L), any())).thenReturn(new com.baiyue.lastleg.discard.gateway.CargoDiscardPhotoFileGateway.UploadedFile(101L, "discard.png", "image/png", 8L));
|
||||
when(applications.readNoByWarehouse("CD-1", "99")).thenReturn(application);
|
||||
item.setDiscardPackages(3);
|
||||
assertThrows(ResponseStatusException.class, () -> service.confirm(identity, "CD-1", "PALLET-1", new PdaCargoDiscardDtos.Confirm(List.of(new PdaCargoDiscardDtos.ActualLine(11L, actual)), List.of())));
|
||||
verifyNoInteractions(adjustments);
|
||||
service.uploadPhoto(identity, "CD-1", "PALLET-1", 9L, new org.springframework.mock.web.MockMultipartFile("file", new byte[]{1}));
|
||||
assertEquals(1, service.photos(identity, "CD-1", "PALLET-1").size());
|
||||
assertTrue(realPhotos.list(application, null, true).isEmpty());
|
||||
service.confirm(identity, "CD-1", "PALLET-1", request(actual));
|
||||
assertEquals(CargoDiscardService.PDA_COMPLETED, application.getStatus());
|
||||
assertEquals(actual, application.getTotalPackages());
|
||||
assertEquals(new BigDecimal("5.00").multiply(BigDecimal.valueOf(actual)), application.getTotalFee());
|
||||
assertEquals(1, realPhotos.list(application, null, true).size());
|
||||
assertNotNull(realPhotos.list(application, null, true).get(0).submittedAt());
|
||||
service.confirm(identity, "CD-1", "PALLET-1", request(actual));
|
||||
verify(adjustments, times(1)).discardPalletItem(eq("CUSTOMER"), same(application), same(item), anyList(), eq(actual), eq("OP"), any());
|
||||
verify(photoMapper, times(1)).updateById(any(com.baiyue.lastleg.discard.entity.CargoDiscardPhoto.class));
|
||||
assertThrows(ResponseStatusException.class, () -> service.uploadPhoto(identity, "CD-1", "PALLET-1", 9L, new org.springframework.mock.web.MockMultipartFile("file", new byte[]{1})));
|
||||
}
|
||||
}
|
||||
|
||||
+85
@@ -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());
|
||||
}
|
||||
}
|
||||
+1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user