feat: complete overseas pda warehouse operations

This commit is contained in:
2026-08-25 11:20:36 +08:00
parent 45a3b9adfd
commit 042d0b738a
69 changed files with 4679 additions and 4 deletions
@@ -29,7 +29,7 @@ class SchemaChineseCommentContractTest {
Path.of("..", "scripts", "db", "incremental.sql"), StandardCharsets.UTF_8);
List<TableDefinition> tables = parseAndAssert(baseline, "仓储基线 SQL");
assertEquals(7, tables.size(), "仓储表数量变化时必须同步表索引和备注迁移");
assertEquals(8, tables.size(), "仓储表数量变化时必须同步表索引和备注迁移");
parseAndAssert(incremental, "统一增量 SQL");
int marker = incremental.indexOf("2026-08-18 / 025 Chinese table and column comments");
@@ -0,0 +1,91 @@
package com.baiyue.warehouse.service;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.warehouse.dto.PalletTransitionRequests;
import com.baiyue.warehouse.entity.WarehousePalletEntity;
import com.baiyue.warehouse.entity.WarehousePalletOperationEntity;
import com.baiyue.warehouse.mapper.WarehousePalletTransitionMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class WarehousePalletTransitionServiceTest {
@Mock private WarehousePalletTransitionMapper mapper;
private WarehousePalletTransitionService service;
@BeforeEach void setUp() {
service = new WarehousePalletTransitionService();
ReflectionTestUtils.setField(service, "mapper", mapper);
}
@Test void appliesVersionedPublicPalletTransitionAndPersistsCompensationReceipt() {
WarehousePalletEntity pallet = pallet("P-1", "IDLE", 4);
when(mapper.lockPublicPallet(88L, 10L)).thenReturn(pallet);
when(mapper.countActiveLocation(88L, 20L)).thenReturn(1L);
when(mapper.transition(88L, 10L, "OCCUPIED", 20L, 4)).thenReturn(1);
var response = service.apply(10L, new PalletTransitionRequests.Apply(
88L, 4, "OCCUPIED", 20L, "operation-1", "assemble"));
assertEquals("APPLIED", response.operationStatus());
assertEquals(5, response.afterVersion());
ArgumentCaptor<WarehousePalletOperationEntity> captor = ArgumentCaptor.forClass(WarehousePalletOperationEntity.class);
verify(mapper).insert(captor.capture());
assertEquals("IDLE", captor.getValue().getBeforeStatus());
assertEquals("OCCUPIED", captor.getValue().getAfterStatus());
assertEquals(4, captor.getValue().getBeforeVersion());
}
@Test void exactReplayDoesNotMutatePhysicalPalletAgain() {
WarehousePalletOperationEntity existing = operation();
when(mapper.findOperation("operation-1")).thenReturn(existing);
var response = service.apply(10L, new PalletTransitionRequests.Apply(
88L, 4, "OCCUPIED", 20L, "operation-1", "any changed reason"));
assertTrue(response.replayed());
verify(mapper, never()).transition(anyLong(), anyLong(), anyString(), anyLong(), anyInt());
}
@Test void compensationRequiresExactAppliedVersionAndRestoresBeforeState() {
WarehousePalletOperationEntity existing = operation();
when(mapper.lockOperation("operation-1")).thenReturn(existing);
when(mapper.transition(88L, 10L, "IDLE", 11L, 5)).thenReturn(1);
var response = service.compensate(10L, "operation-1", new PalletTransitionRequests.Compensate(88L));
assertEquals("COMPENSATED", response.operationStatus());
verify(mapper).updateById(existing);
}
@Test void staleVersionIsRejectedWithoutPhysicalMutation() {
when(mapper.lockPublicPallet(88L, 10L)).thenReturn(pallet("P-1", "IDLE", 5));
assertThrows(BizException.class, () -> service.apply(10L, new PalletTransitionRequests.Apply(
88L, 4, "OCCUPIED", 20L, "operation-1", null)));
verify(mapper, never()).transition(anyLong(), anyLong(), anyString(), anyLong(), anyInt());
}
private static WarehousePalletEntity pallet(String code, String status, int version) {
WarehousePalletEntity value = new WarehousePalletEntity(); value.setId(10L); value.setCustomerId(0L);
value.setWarehouseId(88L); value.setLocationId(11L); value.setPalletCode(code);
value.setStatus(status); value.setVersion(version); return value;
}
private static WarehousePalletOperationEntity operation() {
WarehousePalletOperationEntity value = new WarehousePalletOperationEntity(); value.setId(1L);
value.setOperationKey("operation-1");
value.setRequestHash("f17b4386e6fdecbaab1d066ae4fefa47dba0687ff27361b8f92ef097d4e8072e");
value.setWarehouseId(88L); value.setPalletId(10L); value.setPalletCode("P-1");
value.setBeforeStatus("IDLE"); value.setAfterStatus("OCCUPIED"); value.setBeforeLocationId(11L);
value.setAfterLocationId(20L); value.setBeforeVersion(4); value.setAfterVersion(5);
value.setOperationStatus("APPLIED"); return value;
}
}