449 lines
23 KiB
Java
449 lines
23 KiB
Java
package com.baiyue.warehouse.service;
|
|
|
|
import com.baiyue.common.core.exception.BizException;
|
|
import com.baiyue.warehouse.dto.PalletRequests;
|
|
import com.baiyue.warehouse.dto.WarehousePalletBatchRequests;
|
|
import com.baiyue.warehouse.dto.WarehouseResourceLockRequests;
|
|
import com.baiyue.warehouse.dto.WarehouseResourceLockResponse;
|
|
import com.baiyue.warehouse.entity.WarehousePalletBatchEntity;
|
|
import com.baiyue.warehouse.entity.WarehousePalletBatchItemEntity;
|
|
import com.baiyue.warehouse.entity.WarehousePalletBindingEntity;
|
|
import com.baiyue.warehouse.entity.WarehouseLocationEntity;
|
|
import com.baiyue.warehouse.entity.WarehousePalletEntity;
|
|
import com.baiyue.warehouse.entity.WarehouseResourceLockEntity;
|
|
import com.baiyue.warehouse.mapper.WarehousePalletBatchItemMapper;
|
|
import com.baiyue.warehouse.mapper.WarehousePalletBatchMapper;
|
|
import com.baiyue.warehouse.repository.WarehouseResourceLockRepository;
|
|
import com.baiyue.warehouse.repository.WarehouseResourceRepository;
|
|
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.mockito.ArgumentCaptor;
|
|
import org.mockito.InOrder;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
import java.util.List;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.anyLong;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
@ExtendWith(MockitoExtension.class)
|
|
class WarehousePalletBatchServiceTest {
|
|
private static final long WAREHOUSE = 201L;
|
|
private static final long CUSTOMER_A = 101L;
|
|
private static final long CUSTOMER_B = 102L;
|
|
|
|
@Mock WarehousePalletBatchMapper batches;
|
|
@Mock WarehousePalletBatchItemMapper items;
|
|
@Mock WarehouseResourceService resources;
|
|
@Mock WarehouseResourceLockService locks;
|
|
@Mock WarehouseResourceLockRepository lockRecords;
|
|
@Mock WarehouseResourceRepository repository;
|
|
private WarehousePalletBatchService service;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
service = new WarehousePalletBatchService();
|
|
ReflectionTestUtils.setField(service, "batches", batches);
|
|
ReflectionTestUtils.setField(service, "items", items);
|
|
ReflectionTestUtils.setField(service, "resources", resources);
|
|
ReflectionTestUtils.setField(service, "locks", locks);
|
|
ReflectionTestUtils.setField(service, "lockRecords", lockRecords);
|
|
ReflectionTestUtils.setField(service, "repository", repository);
|
|
ReflectionTestUtils.setField(service, "objectMapper", new ObjectMapper());
|
|
}
|
|
|
|
@Test
|
|
void reservesPublicPalletsButIsolatesEachCrossCustomerLock() {
|
|
when(batches.insertIgnore(any())).thenReturn(1);
|
|
stubNewResources();
|
|
|
|
var response = service.ensureReserved(request());
|
|
|
|
assertThat(response.status()).isEqualTo("RESERVED");
|
|
assertThat(response.items()).extracting(item -> item.customerId()).containsExactly(CUSTOMER_A, CUSTOMER_B);
|
|
ArgumentCaptor<Long> scope = ArgumentCaptor.forClass(Long.class);
|
|
verify(resources, times(2)).createPallet(scope.capture(), anyLong(), any(PalletRequests.SaveRequest.class));
|
|
assertThat(scope.getAllValues()).containsOnly(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE);
|
|
verify(batches, never()).lockByKey(WAREHOUSE, "container-1");
|
|
ArgumentCaptor<WarehouseResourceLockRequests.ReserveRequest> reservations =
|
|
ArgumentCaptor.forClass(WarehouseResourceLockRequests.ReserveRequest.class);
|
|
verify(locks, times(2)).reserve(reservations.capture());
|
|
assertThat(reservations.getAllValues()).extracting(value -> value.customerId())
|
|
.containsExactly(CUSTOMER_A, CUSTOMER_B);
|
|
assertThat(reservations.getAllValues()).extracting(value -> value.businessId())
|
|
.containsExactly("container:plan-a:1", "container:plan-b:2");
|
|
}
|
|
|
|
@Test
|
|
void missingSourcePalletCodeUsesWarehouseGeneratedPhysicalCode() {
|
|
when(batches.insertIgnore(any())).thenReturn(1);
|
|
when(resources.createPallet(anyLong(), anyLong(), any())).thenReturn(301L);
|
|
when(resources.pallet(0L, WAREHOUSE, 301L)).thenReturn(pallet(301L, 401L, "PAL-301"));
|
|
when(locks.reserve(any())).thenAnswer(call -> {
|
|
WarehouseResourceLockRequests.ReserveRequest value = call.getArgument(0);
|
|
return lockResponse(value.customerId(), 501L);
|
|
});
|
|
var request = new WarehousePalletBatchRequests.EnsureReserved(WAREHOUSE, "container-generated", List.of(
|
|
new WarehousePalletBatchRequests.Item(CUSTOMER_A, "container:generated:1", "PLAN-G", 1,
|
|
"STANDARD", null, null)));
|
|
|
|
var response = service.ensureReserved(request);
|
|
|
|
ArgumentCaptor<PalletRequests.SaveRequest> saves = ArgumentCaptor.forClass(PalletRequests.SaveRequest.class);
|
|
verify(resources).createPallet(org.mockito.ArgumentMatchers.eq(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE),
|
|
org.mockito.ArgumentMatchers.eq(WAREHOUSE), saves.capture());
|
|
assertThat(saves.getValue().palletCode()).isNull();
|
|
assertThat(response.items()).extracting(value -> value.palletCode()).containsExactly("PAL-301");
|
|
}
|
|
|
|
@Test
|
|
void concurrentSameRequestReplaysWinningBatchWithoutCreatingResources() {
|
|
AtomicReference<WarehousePalletBatchEntity> inserted = new AtomicReference<>();
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenAnswer(call -> inserted.get());
|
|
when(batches.insertIgnore(any())).thenAnswer(call -> {
|
|
WarehousePalletBatchEntity losingInsert = call.getArgument(0);
|
|
WarehousePalletBatchEntity winner = batch(losingInsert.getId(), "RESERVED", 1);
|
|
winner.setRequestHash(losingInsert.getRequestHash());
|
|
inserted.set(winner);
|
|
return 0;
|
|
});
|
|
when(items.lockByBatch(anyLong())).thenReturn(List.of(item(1L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED")));
|
|
|
|
var response = service.ensureReserved(request());
|
|
|
|
assertThat(response.replayed()).isTrue();
|
|
assertThat(response.batchId()).isEqualTo(inserted.get().getId());
|
|
InOrder order = org.mockito.Mockito.inOrder(batches);
|
|
order.verify(batches).insertIgnore(any());
|
|
order.verify(batches).lockByKey(WAREHOUSE, "container-1");
|
|
verify(resources, never()).createPallet(anyLong(), anyLong(), any());
|
|
verify(locks, never()).reserve(any());
|
|
}
|
|
|
|
@Test
|
|
void sameBatchKeyWithDifferentPayloadIsRejectedAsA0409() {
|
|
WarehousePalletBatchEntity existing = batch(11L, "RESERVED", 1);
|
|
existing.setRequestHash("different");
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(existing);
|
|
|
|
assertThatThrownBy(() -> service.ensureReserved(request()))
|
|
.isInstanceOf(BizException.class)
|
|
.hasMessageContaining("different pallet request");
|
|
verify(resources, never()).createPallet(anyLong(), anyLong(), any());
|
|
}
|
|
|
|
@Test
|
|
void existingBusinessBindingIsRejectedBeforeAnyPalletIsCreated() {
|
|
when(batches.insertIgnore(any())).thenReturn(1);
|
|
when(repository.lockPalletBinding(CUSTOMER_A, WAREHOUSE, "INBOUND_PLAN_AUTO", "container:plan-a:1"))
|
|
.thenReturn(new WarehousePalletBindingEntity());
|
|
|
|
assertThatThrownBy(() -> service.ensureReserved(request()))
|
|
.isInstanceOf(BizException.class)
|
|
.hasMessageContaining("already bound");
|
|
verify(resources, never()).createPallet(anyLong(), anyLong(), any());
|
|
}
|
|
|
|
@Test
|
|
void confirmValidatesAndBindsEveryItemInItsOwnCustomerScope() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
List<WarehousePalletBatchItemEntity> batchItems = List.of(
|
|
item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED"),
|
|
item(22L, CUSTOMER_B, 302L, 402L, 502L, 2, "RESERVED"));
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(batchItems);
|
|
when(lockRecords.find(CUSTOMER_A, 501L)).thenReturn(lock(CUSTOMER_A, batchItems.get(0)));
|
|
when(lockRecords.find(CUSTOMER_B, 502L)).thenReturn(lock(CUSTOMER_B, batchItems.get(1)));
|
|
|
|
var response = service.confirm(new WarehousePalletBatchRequests.Confirm(WAREHOUSE, "container-1", "confirm-1"));
|
|
|
|
assertThat(response.status()).isEqualTo("CONFIRMED");
|
|
assertThat(response.items()).extracting(value -> value.status()).containsOnly("CONFIRMED");
|
|
verify(repository).lockPalletBinding(CUSTOMER_A, WAREHOUSE, "INBOUND_PLAN_AUTO", "business-1");
|
|
verify(repository).lockPalletBinding(CUSTOMER_B, WAREHOUSE, "INBOUND_PLAN_AUTO", "business-2");
|
|
ArgumentCaptor<WarehousePalletBindingEntity> bindings = ArgumentCaptor.forClass(WarehousePalletBindingEntity.class);
|
|
verify(repository, times(2)).insertPalletBinding(bindings.capture());
|
|
assertThat(bindings.getAllValues()).extracting(WarehousePalletBindingEntity::getCustomerId)
|
|
.containsExactly(CUSTOMER_A, CUSTOMER_B);
|
|
verify(lockRecords, never()).close(any(), org.mockito.ArgumentMatchers.eq("CONFIRMED"));
|
|
}
|
|
|
|
@Test
|
|
void repeatedConfirmIsIdempotentAndDoesNotBindAgain() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
when(lockRecords.find(CUSTOMER_A, 501L)).thenReturn(lock(CUSTOMER_A, item));
|
|
var command = new WarehousePalletBatchRequests.Confirm(WAREHOUSE, "container-1", "confirm-1");
|
|
|
|
service.confirm(command);
|
|
var response = service.confirm(command);
|
|
|
|
assertThat(response.replayed()).isTrue();
|
|
verify(lockRecords, times(1)).find(CUSTOMER_A, 501L);
|
|
verify(repository, times(1)).insertPalletBinding(any());
|
|
}
|
|
|
|
@Test
|
|
void terminalConfirmRejectsDifferentCommandPayload() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
when(lockRecords.find(CUSTOMER_A, 501L)).thenReturn(lock(CUSTOMER_A, item));
|
|
service.confirm(new WarehousePalletBatchRequests.Confirm(WAREHOUSE, "container-1", "confirm-1"));
|
|
|
|
assertThatThrownBy(() -> service.confirm(
|
|
new WarehousePalletBatchRequests.Confirm(WAREHOUSE, "container-1", "confirm-2")))
|
|
.isInstanceOf(BizException.class)
|
|
.hasMessageContaining("different payload");
|
|
}
|
|
|
|
@Test
|
|
void confirmedBatchKeepsLockActiveForSubsequentPhysicalRelease() {
|
|
assertPhysicalLifecycleAfterConfirm("RELEASED");
|
|
}
|
|
|
|
@Test
|
|
void confirmedBatchKeepsLockActiveForSubsequentPhysicalScrap() {
|
|
assertPhysicalLifecycleAfterConfirm("SCRAPPED");
|
|
}
|
|
|
|
@Test
|
|
void compensationReleasesOnlyThisBatchUsingEachCustomerScope() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
List<WarehousePalletBatchItemEntity> batchItems = List.of(
|
|
item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED"),
|
|
item(22L, CUSTOMER_B, 302L, 402L, 502L, 2, "RESERVED"));
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(batchItems);
|
|
|
|
var response = service.compensate(
|
|
new WarehousePalletBatchRequests.Compensate(WAREHOUSE, "container-1", "compensate-1", "lastleg failed"));
|
|
|
|
assertThat(response.status()).isEqualTo("COMPENSATED");
|
|
verify(locks).release(CUSTOMER_A, 501L);
|
|
verify(locks).release(CUSTOMER_B, 502L);
|
|
assertThat(batchItems).extracting(WarehousePalletBatchItemEntity::getStatus).containsOnly("RELEASED");
|
|
}
|
|
|
|
@Test
|
|
void compensationRejectsConfirmedOrAlreadyBoundResources() {
|
|
WarehousePalletBatchEntity confirmed = batch(11L, "CONFIRMED", 1);
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(confirmed);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of());
|
|
var command = new WarehousePalletBatchRequests.Compensate(
|
|
WAREHOUSE, "container-1", "compensate-1", "lastleg failed");
|
|
|
|
assertThatThrownBy(() -> service.compensate(command)).isInstanceOf(BizException.class);
|
|
verify(locks, never()).release(anyLong(), anyLong());
|
|
}
|
|
|
|
@Test
|
|
void compensationRejectsBindingToThisBatchPallet() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
WarehousePalletBindingEntity binding = new WarehousePalletBindingEntity();
|
|
binding.setPalletId(301L);
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
when(repository.lockPalletBinding(CUSTOMER_A, WAREHOUSE, "INBOUND_PLAN_AUTO", "business-1"))
|
|
.thenReturn(binding);
|
|
|
|
assertThatThrownBy(() -> service.compensate(new WarehousePalletBatchRequests.Compensate(
|
|
WAREHOUSE, "container-1", "compensate-1", "lastleg failed")))
|
|
.isInstanceOf(BizException.class)
|
|
.hasMessageContaining("cannot be compensated");
|
|
verify(locks, never()).release(anyLong(), anyLong());
|
|
}
|
|
|
|
@Test
|
|
void compensationAllowsUnrelatedOldBindingToDifferentPallet() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
WarehousePalletBindingEntity oldBinding = new WarehousePalletBindingEntity();
|
|
oldBinding.setPalletId(999L);
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
when(repository.lockPalletBinding(CUSTOMER_A, WAREHOUSE, "INBOUND_PLAN_AUTO", "business-1"))
|
|
.thenReturn(oldBinding);
|
|
|
|
service.compensate(new WarehousePalletBatchRequests.Compensate(
|
|
WAREHOUSE, "container-1", "compensate-1", "lastleg failed"));
|
|
|
|
verify(locks).release(CUSTOMER_A, 501L);
|
|
}
|
|
|
|
@Test
|
|
void terminalCompensationOnlyReplaysIdenticalCommandAndReason() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
var command = new WarehousePalletBatchRequests.Compensate(
|
|
WAREHOUSE, "container-1", "compensate-1", "lastleg failed");
|
|
|
|
service.compensate(command);
|
|
assertThat(service.compensate(command).replayed()).isTrue();
|
|
assertThatThrownBy(() -> service.compensate(new WarehousePalletBatchRequests.Compensate(
|
|
WAREHOUSE, "container-1", "compensate-1", "different reason")))
|
|
.isInstanceOf(BizException.class)
|
|
.hasMessageContaining("different payload");
|
|
verify(locks, times(1)).release(CUSTOMER_A, 501L);
|
|
}
|
|
|
|
@Test
|
|
void sameRequestAfterCompensationReusesPalletAndCreatesNextAttemptLocks() {
|
|
WarehousePalletBatchEntity batch = batch(11L, "COMPENSATED", 1);
|
|
List<WarehousePalletBatchItemEntity> batchItems = List.of(
|
|
item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RELEASED"),
|
|
item(22L, CUSTOMER_B, 302L, 402L, 502L, 2, "RELEASED"));
|
|
AtomicInteger calls = new AtomicInteger();
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenAnswer(call -> {
|
|
if (batch.getRequestHash() == null) {
|
|
return null;
|
|
}
|
|
return batch;
|
|
});
|
|
when(batches.insertIgnore(any())).thenAnswer(call -> {
|
|
WarehousePalletBatchEntity candidate = call.getArgument(0);
|
|
batch.setRequestHash(candidate.getRequestHash());
|
|
return 0;
|
|
});
|
|
when(items.lockByBatch(11L)).thenReturn(batchItems);
|
|
when(resources.pallet(0L, WAREHOUSE, 301L)).thenReturn(pallet(301L, 401L, "PAL-301"));
|
|
when(resources.pallet(0L, WAREHOUSE, 302L)).thenReturn(pallet(302L, 402L, "PAL-302"));
|
|
when(locks.reserve(any())).thenAnswer(call -> lockResponse(
|
|
((WarehouseResourceLockRequests.ReserveRequest) call.getArgument(0)).customerId(),
|
|
601L + calls.getAndIncrement()));
|
|
|
|
var response = service.ensureReserved(request());
|
|
|
|
assertThat(response.attemptNo()).isEqualTo(2);
|
|
assertThat(response.items()).extracting(value -> value.palletId()).containsExactly(301L, 302L);
|
|
verify(resources, never()).createPallet(anyLong(), anyLong(), any());
|
|
ArgumentCaptor<WarehouseResourceLockRequests.ReserveRequest> reservations =
|
|
ArgumentCaptor.forClass(WarehouseResourceLockRequests.ReserveRequest.class);
|
|
verify(locks, times(2)).reserve(reservations.capture());
|
|
assertThat(reservations.getAllValues()).extracting(value -> value.reservationKey())
|
|
.allMatch(key -> key.contains(":2:"));
|
|
}
|
|
|
|
private void stubNewResources() {
|
|
AtomicInteger created = new AtomicInteger();
|
|
when(resources.createPallet(anyLong(), anyLong(), any())).thenAnswer(call -> 301L + created.getAndIncrement());
|
|
when(resources.pallet(0L, WAREHOUSE, 301L)).thenReturn(pallet(301L, 401L, "PAL-301"));
|
|
when(resources.pallet(0L, WAREHOUSE, 302L)).thenReturn(pallet(302L, 402L, "PAL-302"));
|
|
when(locks.reserve(any())).thenAnswer(call -> {
|
|
WarehouseResourceLockRequests.ReserveRequest value = call.getArgument(0);
|
|
return lockResponse(value.customerId(), 500L + value.palletId() - 300L);
|
|
});
|
|
}
|
|
|
|
private void assertPhysicalLifecycleAfterConfirm(String terminalStatus) {
|
|
WarehousePalletBatchEntity batch = batch(11L, "RESERVED", 1);
|
|
WarehousePalletBatchItemEntity item = item(21L, CUSTOMER_A, 301L, 401L, 501L, 1, "RESERVED");
|
|
WarehouseResourceLockEntity active = lock(CUSTOMER_A, item);
|
|
when(batches.lockByKey(WAREHOUSE, "container-1")).thenReturn(batch);
|
|
when(items.lockByBatch(11L)).thenReturn(List.of(item));
|
|
when(lockRecords.find(CUSTOMER_A, 501L)).thenReturn(active);
|
|
|
|
service.confirm(new WarehousePalletBatchRequests.Confirm(WAREHOUSE, "container-1", "confirm-1"));
|
|
|
|
assertThat(batch.getStatus()).isEqualTo("CONFIRMED");
|
|
assertThat(item.getStatus()).isEqualTo("CONFIRMED");
|
|
assertThat(active.getStatus()).isEqualTo("ACTIVE");
|
|
verify(lockRecords, never()).close(active, "CONFIRMED");
|
|
|
|
WarehouseLocationEntity virtual = new WarehouseLocationEntity();
|
|
virtual.setLocationType("VIRTUAL");
|
|
virtual.setStatus("ACTIVE");
|
|
when(lockRecords.findLocation(CUSTOMER_A, WAREHOUSE, 401L)).thenReturn(virtual);
|
|
when(lockRecords.close(active, terminalStatus)).thenReturn(1);
|
|
WarehouseResourceLockService physicalLifecycle = new WarehouseResourceLockService();
|
|
ReflectionTestUtils.setField(physicalLifecycle, "repository", lockRecords);
|
|
if ("RELEASED".equals(terminalStatus)) {
|
|
when(lockRecords.releasePalletAtVirtualLocation(active)).thenReturn(1);
|
|
assertThat(physicalLifecycle.release(CUSTOMER_A, 501L).status()).isEqualTo("RELEASED");
|
|
} else {
|
|
when(lockRecords.scrapPalletAtVirtualLocation(active)).thenReturn(1);
|
|
assertThat(physicalLifecycle.scrap(CUSTOMER_A, 501L).status()).isEqualTo("SCRAPPED");
|
|
}
|
|
}
|
|
|
|
private static WarehousePalletBatchRequests.EnsureReserved request() {
|
|
return new WarehousePalletBatchRequests.EnsureReserved(WAREHOUSE, "container-1", List.of(
|
|
new WarehousePalletBatchRequests.Item(CUSTOMER_B, "container:plan-b:2", "PLAN-B", 2, "STANDARD", "ONT8", "CONT-ONT8-001"),
|
|
new WarehousePalletBatchRequests.Item(CUSTOMER_A, "container:plan-a:1", "PLAN-A", 1, "STANDARD", "LAX9", "CONT-LAX9-001")));
|
|
}
|
|
|
|
private static WarehousePalletBatchEntity batch(long id, String status, int attempt) {
|
|
WarehousePalletBatchEntity entity = new WarehousePalletBatchEntity();
|
|
entity.setId(id);
|
|
entity.setWarehouseId(WAREHOUSE);
|
|
entity.setBatchKey("container-1");
|
|
entity.setStatus(status);
|
|
entity.setAttemptNo(attempt);
|
|
return entity;
|
|
}
|
|
|
|
private static WarehousePalletBatchItemEntity item(long id, long customerId, long palletId,
|
|
long locationId, long lockId, int sequence, String status) {
|
|
WarehousePalletBatchItemEntity entity = new WarehousePalletBatchItemEntity();
|
|
entity.setId(id);
|
|
entity.setBatchId(11L);
|
|
entity.setCustomerId(customerId);
|
|
entity.setWarehouseId(WAREHOUSE);
|
|
entity.setBusinessKey("business-" + sequence);
|
|
entity.setInboundPlanNo("PLAN-" + sequence);
|
|
entity.setSequenceNo(sequence);
|
|
entity.setPalletId(palletId);
|
|
entity.setPalletCode("PAL-" + palletId);
|
|
entity.setLocationId(locationId);
|
|
entity.setResourceLockId(lockId);
|
|
entity.setStatus(status);
|
|
return entity;
|
|
}
|
|
|
|
private static WarehousePalletEntity pallet(long id, long locationId, String code) {
|
|
WarehousePalletEntity entity = new WarehousePalletEntity();
|
|
entity.setId(id);
|
|
entity.setWarehouseId(WAREHOUSE);
|
|
entity.setLocationId(locationId);
|
|
entity.setPalletCode(code);
|
|
entity.setStatus("OCCUPIED");
|
|
return entity;
|
|
}
|
|
|
|
private static WarehouseResourceLockEntity lock(long customerId, WarehousePalletBatchItemEntity item) {
|
|
WarehouseResourceLockEntity entity = new WarehouseResourceLockEntity();
|
|
entity.setId(item.getResourceLockId());
|
|
entity.setCustomerId(customerId);
|
|
entity.setWarehouseId(WAREHOUSE);
|
|
entity.setPalletId(item.getPalletId());
|
|
entity.setLocationId(item.getLocationId());
|
|
entity.setBusinessType("INBOUND_PLAN_AUTO");
|
|
entity.setBusinessId(item.getBusinessKey());
|
|
entity.setStatus("ACTIVE");
|
|
return entity;
|
|
}
|
|
|
|
private static WarehouseResourceLockResponse lockResponse(long customerId, long lockId) {
|
|
return new WarehouseResourceLockResponse(lockId, customerId, WAREHOUSE, 0L, 0L,
|
|
"INBOUND_PLAN_AUTO", "business", "reservation", "ACTIVE", null, null);
|
|
}
|
|
}
|