fix(acceptance): complete overseas fulfillment closure
This commit is contained in:
+2
-1
@@ -300,7 +300,8 @@ public class PdaPalletOperationService {
|
||||
if (unbind && changes.stream().noneMatch(change -> "IDLE".equals(change.targetStatus()))) {
|
||||
throw conflict("解绑必须清空来源托盘");
|
||||
}
|
||||
changes.sort(Comparator.comparingLong(change -> change.pallet().palletId()));
|
||||
changes.sort(Comparator.comparingInt((PalletChange change) -> "IDLE".equals(change.targetStatus()) ? 0 : 1)
|
||||
.thenComparingLong(change -> change.pallet().palletId()));
|
||||
return new Plan(pallets, moves, changes);
|
||||
}
|
||||
|
||||
|
||||
@@ -589,12 +589,12 @@ CREATE TABLE IF NOT EXISTS ll_container_plan_conversion_command (
|
||||
snapshot_hash CHAR(64) NOT NULL COMMENT '确认的柜级快照SHA-256',
|
||||
warehouse_id BIGINT NOT NULL COMMENT '海外接柜仓ID',
|
||||
batch_key VARCHAR(160) NOT NULL COMMENT '海外仓托盘批次幂等键',
|
||||
status VARCHAR(32) NOT NULL COMMENT 'PREPARED/APPLYING/LOCAL_COMMITTED/COMPLETED',
|
||||
status VARCHAR(32) NOT NULL COMMENT '转换状态:PREPARED、APPLYING、LOCAL_COMMITTED或COMPLETED',
|
||||
preparation_json JSON NOT NULL COMMENT '稳定计划号与托盘业务键快照',
|
||||
result_json JSON NULL COMMENT '本地计划提交结果',
|
||||
last_error VARCHAR(1000) NULL COMMENT '最近一次跨服务错误',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||||
PRIMARY KEY(id),
|
||||
UNIQUE KEY uk_ll_container_conversion_command(source_container_booking_id),
|
||||
UNIQUE KEY uk_ll_container_conversion_batch(warehouse_id,batch_key),
|
||||
|
||||
+14
-8
@@ -18,6 +18,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
@@ -74,19 +75,21 @@ class PdaPalletOperationServiceTest {
|
||||
}
|
||||
|
||||
@Test void localConcurrencyFailureCompensatesEveryAppliedPhysicalTransitionInReverseSafeForm() {
|
||||
var source = pallet(10L, "SOURCE", 88L, 1);
|
||||
var target = pallet(20L, "TARGET", 88L, 2);
|
||||
var source = new PalletPhysicalGateway.PalletReference(20L, "SOURCE", 88L, 1020L,
|
||||
"OCCUPIED", null, 1);
|
||||
var target = new PalletPhysicalGateway.PalletReference(10L, "TARGET", 88L, 1010L,
|
||||
"IDLE", null, 2);
|
||||
when(physical.resolve("SOURCE")).thenReturn(source);
|
||||
when(physical.resolve("TARGET")).thenReturn(target);
|
||||
when(physical.resolveLocation(88L, target.locationId())).thenReturn(
|
||||
new PalletPhysicalGateway.LocationReference(target.locationId(), "LOC-" + target.locationId(),
|
||||
"STORAGE", "ACTIVE"));
|
||||
PalletInventoryRow planned = row(100L, 10L, 1L, 5L);
|
||||
PalletInventoryRow stale = row(100L, 10L, 2L, 5L);
|
||||
when(mapper.content("88", 10L)).thenReturn(List.of(planned));
|
||||
when(mapper.content("88", 20L)).thenReturn(List.of());
|
||||
when(mapper.palletPackages("88", 10L)).thenReturn(5L);
|
||||
when(mapper.palletPackages("88", 20L)).thenReturn(0L);
|
||||
PalletInventoryRow planned = row(100L, 20L, 1L, 5L);
|
||||
PalletInventoryRow stale = row(100L, 20L, 2L, 5L);
|
||||
when(mapper.content("88", 20L)).thenReturn(List.of(planned));
|
||||
when(mapper.content("88", 10L)).thenReturn(List.of());
|
||||
when(mapper.palletPackages("88", 20L)).thenReturn(5L);
|
||||
when(mapper.palletPackages("88", 10L)).thenReturn(0L);
|
||||
when(mapper.lockPosition("88", 100L)).thenReturn(stale);
|
||||
|
||||
AtomicReference<PdaPalletOperation> operation = new AtomicReference<>();
|
||||
@@ -103,6 +106,9 @@ class PdaPalletOperationServiceTest {
|
||||
|
||||
assertThrows(ResponseStatusException.class, () -> service.assemble(identity(), request));
|
||||
|
||||
InOrder transitions = inOrder(physical);
|
||||
transitions.verify(physical).apply(eq(88L), eq(source), eq("IDLE"), anyLong(), anyString(), any());
|
||||
transitions.verify(physical).apply(eq(88L), eq(target), eq("OCCUPIED"), anyLong(), anyString(), any());
|
||||
verify(physical, times(2)).compensate(eq(88L), any(PalletPhysicalGateway.Transition.class));
|
||||
assertEquals("FAILED_COMPENSATED", operation.get().getStatus());
|
||||
verify(positions, never()).updateById(any(com.baiyue.lastleg.inventory.entity.InventoryPosition.class));
|
||||
|
||||
Reference in New Issue
Block a user