This commit is contained in:
2026-09-16 15:21:08 +08:00
parent 912feca56f
commit 8f0622058d
20 changed files with 447 additions and 41 deletions
@@ -15,6 +15,38 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class LoadingPalletLabelServiceTest {
@Test
void printsAllAndWarehouseSubsetThroughSharedFbaRendererWithoutRegeneratingCodes() {
var service = org.mockito.Mockito.spy(new LoadingPalletLabelService());
var print = mock(com.baiyue.firstleg.client.PrintPdfClient.class);
ReflectionTestUtils.setField(service, "printClient", print);
ReflectionTestUtils.setField(service, "internalToken", "test-token");
var label1 = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabel(1L, 1L, 1L, 1L,
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 1, "MSCU6639870-141-001");
var label2 = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabel(2L, 1L, 1L, 1L,
"IN-1", "MSCU6639870", "SCK8", "141", "FBA destination", 2, "MSCU6639870-141-002");
var manifest = new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelManifest(10L, "LP-1", "MSCU6639870", 2,
List.of(new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelGroup("SCK8", "141", "FBA destination", 2, List.of(label1, label2))));
org.mockito.Mockito.doReturn(manifest).when(service).prepare(10L, 20L);
when(print.generateFbaPalletLabels(any(), any(), any())).thenReturn(org.springframework.http.ResponseEntity.ok()
.contentType(org.springframework.http.MediaType.APPLICATION_PDF).body("%PDF-test".getBytes()));
service.print(10L, 20L, null, "request-1");
service.print(10L, 20L, new com.baiyue.firstleg.dto.LoadingListDtos.PalletLabelPrintRequest("SCK8", 1), "request-2");
var captor = org.mockito.ArgumentCaptor.forClass(com.baiyue.firstleg.client.PrintPdfClient.FbaPalletRequest.class);
org.mockito.Mockito.verify(print, org.mockito.Mockito.times(2)).generateFbaPalletLabels(any(), any(), captor.capture());
var requests = captor.getAllValues();
assertThat(requests.get(0).templateCode()).isEqualTo("FBA_PALLET_A4_LANDSCAPE_V1");
assertThat(requests.get(0).pageSpec().widthMm()).isEqualByComparingTo("297");
assertThat(requests.get(0).pageSpec().heightMm()).isEqualByComparingTo("210");
assertThat(requests.get(0).labels()).extracting(com.baiyue.firstleg.client.PrintPdfClient.FbaPalletLabel::palletCode)
.containsExactly("MSCU6639870-141-001", "MSCU6639870-141-002");
assertThat(requests.get(1).labels()).singleElement().satisfies(label -> {
assertThat(label.fbaWarehouseCode()).isEqualTo("SCK8");
assertThat(label.palletCode()).isEqualTo("MSCU6639870-141-001");
});
org.mockito.Mockito.verify(print, org.mockito.Mockito.never()).generateInboundMarks(any(), any(), any());
}
@Test
void generatesStableIndexesPerContainerAndFbaAndSkipsDropship() {
LoadingPalletLabelMapper mapper = mock(LoadingPalletLabelMapper.class);
@@ -495,7 +495,7 @@ class SmartLoadingServiceTest {
}
@Test
void manuallyAssignsCrossChannelWaitMeasureInboundUsingDeclaredFacts() {
void manuallyAssignsCrossChannelMeasurePendingInboundUsingDeclaredFacts() {
long customerId = 9L;
long inboundId = 10L;
long orderId = 30L;
@@ -506,7 +506,7 @@ class SmartLoadingServiceTest {
projection.setInboundCode("I10");
projection.setWarehouseId(100L);
projection.setChannelCode("SLOW");
projection.setProcessStatus("WAIT_MEASURE");
projection.setProcessStatus("MEASURE_PENDING");
var snapshot = new com.baiyue.firstleg.dto.OrderApprovedInboundCommand(
customerId, orderId, "O30", "I10", customerId, "客户", 100L, "义乌仓",
null, null, null, "FIRST_LEG", "SLOW", "慢船", null, null, null,
@@ -1046,6 +1046,56 @@ class SmartLoadingServiceTest {
verify(fbaPricingService).recalculateUnlockedContainerCustomerFees(eq(99L), eq(19L), anyString());
}
@Test
void removingSharedPalletChecksEveryInboundOnceAfterAllLinesAreRemoved() {
LoadingPlanItemEntity first = item(8L, 9L, 20L, 4);
LoadingPlanItemEntity sameInbound = item(9L, 9L, 21L, 2);
LoadingPlanItemEntity secondInbound = item(10L, 9L, 22L, 3);
secondInbound.setInboundId(11L);
LoadingPlanItemEntity otherCustomer = item(11L, 19L, 23L, 1);
List<LoadingPlanItemEntity> members = List.of(first, sameInbound, secondInbound, otherCustomer);
members.forEach(value -> value.setPalletId(801L));
when(repository.plan(1L)).thenReturn(plan("EDITING", 2), plan("EDITING", 3));
when(repository.booking(99L)).thenReturn(booking());
when(repository.activeItemsByPallet(801L)).thenReturn(members);
when(repository.touch(1L, 2, 7L, "u")).thenReturn(1);
when(repository.remove(eq(1L), anyLong(), eq(0), eq(7L), eq("u"))).thenReturn(1);
Plan result = service.removePallet(1L, 801L,
new com.baiyue.firstleg.dto.SmartLoadingDtos.RemovePalletRequest(2, "remove-shared-pallet"),
7L, "u");
assertThat(result.items()).isEmpty();
var ordered = inOrder(repository, loadingModelBridge);
for (LoadingPlanItemEntity member : members) {
ordered.verify(repository).remove(1L, member.getId(), 0, 7L, "u");
}
ordered.verify(loadingModelBridge).removeIfUnallocated(1L, 9L, 10L);
ordered.verify(loadingModelBridge).removeIfUnallocated(1L, 9L, 11L);
ordered.verify(loadingModelBridge).removeIfUnallocated(1L, 19L, 10L);
verify(loadingModelBridge, times(3)).removeIfUnallocated(anyLong(), anyLong(), anyLong());
verify(repository).touch(1L, 2, 7L, "u");
}
@Test
void sharedPalletWithAnyPickedMemberCannotRemoveLinesOrLinks() {
LoadingPlanItemEntity first = item(8L, 9L, 20L, 4);
LoadingPlanItemEntity second = item(9L, 9L, 21L, 3);
second.setInboundId(11L);
when(repository.plan(1L)).thenReturn(plan("LOADING", 2));
when(repository.activeItemsByPallet(801L)).thenReturn(List.of(first, second));
when(loadingPickService.mutationSnapshot(1L)).thenReturn(
new LoadingPickService.MutationSnapshot(77L, "LOADING", 5, Map.of(9L, 3)));
assertThatThrownBy(() -> service.removePallet(1L, 801L,
new com.baiyue.firstleg.dto.SmartLoadingDtos.RemovePalletRequest(2, "keep-picked-pallet"),
7L, "u")).isInstanceOf(BizException.class).hasMessageContaining("已发生实物拣货");
verify(repository, never()).remove(anyLong(), anyLong(), anyInt(), anyLong(), anyString());
verify(loadingPickService, never()).remove(anyLong());
verify(loadingModelBridge, never()).removeIfUnallocated(anyLong(), anyLong(), anyLong());
}
@Test
void removesAllUnpickedItemsWithOnePlanVersionChange() {
LoadingPlanEntity initial = plan("EDITING", 2);
@@ -10,6 +10,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@@ -69,9 +71,11 @@ class SplitPreloadServiceTest {
assertThat(captor.getValue().getRemark()).isEqualTo("智能装柜分配自动建立");
}
@Test
void pendingReviewPreAllocationCreatesAProvisionalPreloadLifecycle() {
when(repository.findInbound(10, 20)).thenReturn(new InboundSnapshot(20L, 10L, "PREPARING", 0));
@ParameterizedTest
@ValueSource(strings = {"PREPARING", "WAIT_MEASURE", "MEASURING", "MEASURE_PENDING", "MEASURE_REJECTED",
"WAIT_PRICING", "FEE_CONFIRMING", "INBOUNDING", "WAIT_SPLIT"})
void preAllocationCreatesAProvisionalPreloadLifecycleForEveryCandidateState(String processStatus) {
when(repository.findInbound(10, 20)).thenReturn(new InboundSnapshot(20L, 10L, processStatus, 0));
when(repository.findPlan(10, 20)).thenReturn(null);
service.ensurePendingForPreAllocation(10, 20, 7, "admin");
@@ -80,7 +84,17 @@ class SplitPreloadServiceTest {
org.mockito.ArgumentCaptor.forClass(PreloadPlanEntity.class);
verify(repository).createPlan(captor.capture());
assertThat(captor.getValue().getStatus()).isEqualTo("PENDING");
assertThat(captor.getValue().getRemark()).contains("审核前");
assertThat(captor.getValue().getRemark()).isEqualTo("智能装柜提前分配自动建立");
}
@Test
void preAllocationRejectsPalletizingState() {
when(repository.findInbound(10, 20)).thenReturn(new InboundSnapshot(20L, 10L, "WAIT_PALLETIZE", 0));
assertThatThrownBy(() -> service.ensurePendingForPreAllocation(10, 20, 7, "admin"))
.isInstanceOf(com.baiyue.common.core.exception.BizException.class)
.hasMessage("订单当前状态不能加入装柜清单");
verify(repository, never()).createPlan(any());
}
@Test