优化
This commit is contained in:
+3
-2
@@ -18,9 +18,10 @@ class PalletAllocationDtosValidationTest {
|
||||
LocalDateTime expiresAt = LocalDateTime.now().plusMinutes(30);
|
||||
|
||||
assertThat(validator.validate(new PalletAllocationDtos.ReserveRequest(0L, 20L, "FIRSTLEG", 88L,
|
||||
"RK-001", "measure-88", 9L, BigDecimal.ONE, BigDecimal.ONE, "STANDARD", expiresAt, true))).isEmpty();
|
||||
"RK-001", "measure-88", 9L, BigDecimal.ONE,
|
||||
List.of(new PalletAllocationDtos.PalletReference(7001L, 30L)), expiresAt, true))).isEmpty();
|
||||
assertThat(validator.validate(new PalletAllocationDtos.ConfirmRequest(0L, 20L, "FIRSTLEG", 88L,
|
||||
9L, BigDecimal.ONE, BigDecimal.ONE, 20))).isEmpty();
|
||||
9L, BigDecimal.ONE, 20))).isEmpty();
|
||||
assertThat(validator.validate(new PalletAllocationDtos.ReleaseRequest(0L, "FIRSTLEG", 88L, 9L,
|
||||
"入库补偿"))).isEmpty();
|
||||
assertThat(validator.validate(new PalletAllocationDtos.SelectiveReleaseRequest(0L, "FIRSTLEG", 88L,
|
||||
|
||||
+10
-2
@@ -10,7 +10,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class InitialWarehouseResourceSeedSqlContractTest {
|
||||
@Test
|
||||
void initializesReusablePalletMasterDataAndAvailableLocationsForBothDomesticWarehouses() throws Exception {
|
||||
void initializesReusablePalletsAndYiwuLocationGrid() throws Exception {
|
||||
assertModuleSeed(Files.readString(Path.of("src", "main", "resources", "db", "phase2-pallet-seed.sql"),
|
||||
StandardCharsets.UTF_8));
|
||||
assertUnifiedSeed(Files.readString(Path.of("..", "deploy", "sql", "头程数据库统一增量-MySQL8.sql"),
|
||||
@@ -30,7 +30,15 @@ class InitialWarehouseResourceSeedSqlContractTest {
|
||||
assertThat(sql)
|
||||
.contains("0," + yiwuId + ",'TP-001'")
|
||||
.contains("0," + dongguanId + ",'TP-002'")
|
||||
.contains("(" + idPrefix + "201,0," + yiwuId + ",'A','A区','A1'")
|
||||
.contains("WHEN zones.zone_index = 0 AND slots.slot_number = 1 THEN 201")
|
||||
.contains("ELSE 203 + zones.zone_index * 15 + slots.slot_number")
|
||||
.contains("SELECT zone_index + 1 FROM zones WHERE zone_index < 5")
|
||||
.contains("SELECT slot_number + 1 FROM slots WHERE slot_number < 15")
|
||||
.contains("CONCAT(CHAR(65 + zones.zone_index), slots.slot_number)")
|
||||
.contains("CROSS JOIN slots")
|
||||
.contains("location_code REGEXP '^[A-F]([1-9]|1[0-5])$'")
|
||||
.contains("<> 90 THEN")
|
||||
.contains("义乌仓 A-F 每区 15 个普通库位初始化不完整")
|
||||
.contains("(" + idPrefix + "202,0," + yiwuId + ",'A','A区','A0'")
|
||||
.contains("(" + idPrefix + "203,0," + dongguanId + ",'A','A区','A1'")
|
||||
.contains("(" + idPrefix + "204,0," + dongguanId + ",'A','A区','A0'")
|
||||
|
||||
+27
-38
@@ -47,50 +47,48 @@ class PalletLocationAllocationServiceTest {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class TestConfig {
|
||||
@Bean PalletVolumeSplitter splitter() { return new PalletVolumeSplitter(); }
|
||||
@Bean ObjectMapper objectMapper() { return new ObjectMapper(); }
|
||||
}
|
||||
|
||||
@Test
|
||||
void reusesOnePalletMasterForMultipleAllocations() {
|
||||
void oneConfirmedWeightImageCreatesOneAllocationWithoutCapacityMatching() {
|
||||
when(locations.findActiveResources(10001, "FIRSTLEG", 88)).thenReturn(List.of());
|
||||
when(pallets.findReusable(10001, 20, "木托盘", new BigDecimal("2")))
|
||||
.thenReturn(List.of(pallet(30, "TP-001")));
|
||||
when(pallets.findOwned(10001, 20, 30)).thenReturn(pallet(30, "TP-001"));
|
||||
when(locations.reserveAvailable(any())).thenReturn(List.of(
|
||||
new LocationDtos.ReservationResult(101, "LR101", 30, "TP-001", 40, "A-01", false,
|
||||
LocalDateTime.now().plusMinutes(30)),
|
||||
new LocationDtos.ReservationResult(102, "LR102", 30, "TP-001", 41, "A-02", false,
|
||||
LocalDateTime.now().plusMinutes(30))));
|
||||
|
||||
var request = new PalletAllocationDtos.ReserveRequest(10001, 20, "FIRSTLEG", 88, "RK-001", "measure-001",
|
||||
9001, new BigDecimal("4"), new BigDecimal("2"), "木托盘", LocalDateTime.now().plusMinutes(30), true);
|
||||
assertThat(service.reserve(request).allocations()).hasSize(2)
|
||||
.extracting(PalletAllocationDtos.AllocationResult::palletId)
|
||||
.containsOnly(30L);
|
||||
9001, new BigDecimal("4"), List.of(new PalletAllocationDtos.PalletReference(7001, 30)),
|
||||
LocalDateTime.now().plusMinutes(30), true);
|
||||
assertThat(service.reserve(request).allocations()).singleElement().satisfies(item -> {
|
||||
assertThat(item.palletId()).isEqualTo(30L);
|
||||
assertThat(item.allocatedVolumeCbm()).isEqualByComparingTo("4");
|
||||
assertThat(item.palletCapacityCbm()).isEqualByComparingTo("1.2");
|
||||
});
|
||||
|
||||
org.mockito.ArgumentCaptor<LocationDtos.ReserveCommand> command =
|
||||
org.mockito.ArgumentCaptor.forClass(LocationDtos.ReserveCommand.class);
|
||||
verify(locations).reserveAvailable(command.capture());
|
||||
assertThat(command.getValue().targets()).hasSize(2)
|
||||
.extracting(LocationDtos.ReservationTarget::palletId)
|
||||
.containsOnly(30L);
|
||||
assertThat(command.getValue().targets()).singleElement()
|
||||
.extracting(LocationDtos.ReservationTarget::palletId).isEqualTo(30L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleCase02() {
|
||||
when(locations.findActiveResources(10001, "FIRSTLEG", 99)).thenReturn(List.of());
|
||||
when(pallets.findReusable(10001, 20, "STANDARD", new BigDecimal("2")))
|
||||
.thenReturn(List.of(pallet(30, "TP-001")));
|
||||
when(pallets.findOwned(10001, 20, 30)).thenReturn(pallet(30, "TP-001"));
|
||||
when(locations.reserveAvailable(any())).thenReturn(List.of(
|
||||
new LocationDtos.ReservationResult(101, "LR101", 30, "TP-001", 40, "A0", true,
|
||||
LocalDateTime.now().plusMinutes(30))));
|
||||
|
||||
var request = new PalletAllocationDtos.ReserveRequest(10001, 20, "FIRSTLEG", 99, "RK-001", "measure-99",
|
||||
9001, new BigDecimal("2"), new BigDecimal("2"), null, LocalDateTime.now().plusMinutes(30), true);
|
||||
9001, new BigDecimal("2"), List.of(new PalletAllocationDtos.PalletReference(7001, 30)),
|
||||
LocalDateTime.now().plusMinutes(30), true);
|
||||
var result = service.reserve(request);
|
||||
|
||||
assertThat(result.allocations().get(0).locationCode()).isEqualTo("A0");
|
||||
verify(pallets).findReusable(10001, 20, "STANDARD", new BigDecimal("2"));
|
||||
verify(pallets).findOwned(10001, 20, 30);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,7 +127,7 @@ class PalletLocationAllocationServiceTest {
|
||||
|
||||
assertThat(result.palletCount()).isEqualTo(1);
|
||||
assertThat(result.allocations().get(0).state()).isEqualTo("RESERVED");
|
||||
verify(pallets, never()).findReusable(any(Long.class), any(Long.class), any(), any());
|
||||
verify(pallets, never()).findOwned(anyLong(), anyLong(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -139,9 +137,10 @@ class PalletLocationAllocationServiceTest {
|
||||
when(locations.findActiveResources(10001L, "FIRSTLEG", 88L)).thenReturn(List.of(resource));
|
||||
when(locations.confirmOccupied(any())).thenReturn(List.of(new LocationDtos.OccupancyResult(
|
||||
301L, "OC-301", 101L, 30L, 40L, "A-01", false)));
|
||||
when(pallets.findOwnedIncludingDeleted(10001L, 20L, 30L)).thenReturn(pallet(30L, "TP-001"));
|
||||
|
||||
service.confirm(new PalletAllocationDtos.ConfirmRequest(10001L, 20L, "FIRSTLEG", 88L,
|
||||
9001L, new BigDecimal("1.0"), new BigDecimal("2.0"), 20));
|
||||
9001L, new BigDecimal("1.0"), 20));
|
||||
|
||||
org.mockito.ArgumentCaptor<LocationDtos.ConfirmCommand> command =
|
||||
org.mockito.ArgumentCaptor.forClass(LocationDtos.ConfirmCommand.class);
|
||||
@@ -152,10 +151,10 @@ class PalletLocationAllocationServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void confirmDistributesRemainderWithoutZeroPackageAllocations() {
|
||||
void confirmedImageCountDefinesPalletCountEvenWhenItExceedsPackageCount() {
|
||||
List<LocationDtos.ActiveResource> resources = new ArrayList<>();
|
||||
List<LocationDtos.OccupancyResult> occupancyResults = new ArrayList<>();
|
||||
for (int index = 1; index <= 10; index++) {
|
||||
for (int index = 1; index <= 3; index++) {
|
||||
long reservationId = 100L + index;
|
||||
long palletId = 200L + index;
|
||||
long locationId = 300L + index;
|
||||
@@ -163,33 +162,21 @@ class PalletLocationAllocationServiceTest {
|
||||
"TP-" + index, locationId, "A-" + index, false, "RESERVED"));
|
||||
occupancyResults.add(new LocationDtos.OccupancyResult(400L + index, "OC-" + index,
|
||||
reservationId, palletId, locationId, "A-" + index, false));
|
||||
PalletEntity pallet = pallet(palletId, "TP-" + index);
|
||||
when(pallets.findOwnedIncludingDeleted(10001L, 20L, palletId)).thenReturn(pallet);
|
||||
}
|
||||
when(locations.findActiveResources(10001L, "FIRSTLEG", 89L)).thenReturn(resources);
|
||||
when(locations.confirmOccupied(any())).thenReturn(occupancyResults);
|
||||
|
||||
service.confirm(new PalletAllocationDtos.ConfirmRequest(10001L, 20L, "FIRSTLEG", 89L,
|
||||
9001L, new BigDecimal("12.0"), new BigDecimal("1.2"), 12));
|
||||
9001L, new BigDecimal("12.0"), 2));
|
||||
|
||||
org.mockito.ArgumentCaptor<LocationDtos.ConfirmCommand> command =
|
||||
org.mockito.ArgumentCaptor.forClass(LocationDtos.ConfirmCommand.class);
|
||||
verify(locations).confirmOccupied(command.capture());
|
||||
assertThat(command.getValue().targets())
|
||||
.extracting(LocationDtos.OccupancyTarget::allocatedPackageCount)
|
||||
.containsExactly(2, 2, 1, 1, 1, 1, 1, 1, 1, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void confirmRejectsMorePalletsThanPackages() {
|
||||
List<LocationDtos.ActiveResource> resources = List.of(
|
||||
new LocationDtos.ActiveResource(101L, null, 20L, 30L, "TP-001", 40L, "A-01", false, "RESERVED"),
|
||||
new LocationDtos.ActiveResource(102L, null, 20L, 31L, "TP-002", 41L, "A-02", false, "RESERVED"));
|
||||
when(locations.findActiveResources(10001L, "FIRSTLEG", 90L)).thenReturn(resources);
|
||||
|
||||
assertThatThrownBy(() -> service.confirm(new PalletAllocationDtos.ConfirmRequest(10001L, 20L,
|
||||
"FIRSTLEG", 90L, 9001L, new BigDecimal("2.0"), new BigDecimal("1.0"), 1)))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("托盘数量超过入库单总箱数");
|
||||
verify(locations, never()).confirmOccupied(any());
|
||||
.containsExactly(1, 1, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -490,13 +477,15 @@ class PalletLocationAllocationServiceTest {
|
||||
|
||||
private static PalletAllocationDtos.ReserveRequest reserve(long businessId) {
|
||||
return new PalletAllocationDtos.ReserveRequest(10001, 20, "FIRSTLEG", businessId, "RK-001", "measure-001",
|
||||
9001, new BigDecimal("2"), new BigDecimal("2"), "木托盘", LocalDateTime.now().plusMinutes(30), true);
|
||||
9001, new BigDecimal("2"), List.of(new PalletAllocationDtos.PalletReference(7001, 30)),
|
||||
LocalDateTime.now().plusMinutes(30), true);
|
||||
}
|
||||
|
||||
private static PalletEntity pallet(long id, String code) {
|
||||
PalletEntity entity = new PalletEntity();
|
||||
entity.setId(id);
|
||||
entity.setPalletCode(code);
|
||||
entity.setCapacityCbm(new BigDecimal("1.2"));
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.baiyue.warehouse.service;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
class PalletVolumeSplitterTest {
|
||||
private final PalletVolumeSplitter splitter = new PalletVolumeSplitter();
|
||||
|
||||
@Test
|
||||
void shouldHandleCase01() {
|
||||
var result = splitter.split(new BigDecimal("20"), new BigDecimal("2"));
|
||||
assertThat(result.palletCount()).isEqualTo(10);
|
||||
assertThat(result.allocations()).allMatch(item -> item.allocatedVolumeCbm().compareTo(new BigDecimal("2")) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleCase02() {
|
||||
var result = splitter.split(new BigDecimal("20.1"), new BigDecimal("2"));
|
||||
assertThat(result.palletCount()).isEqualTo(11);
|
||||
assertThat(result.allocations().get(10).allocatedVolumeCbm()).isEqualByComparingTo("0.1");
|
||||
assertThat(result.allocations()).extracting(PalletVolumeSplitter.Allocation::allocationNo)
|
||||
.containsExactly(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleCase03() {
|
||||
assertThatThrownBy(() -> splitter.split(null, BigDecimal.ONE)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> splitter.split(BigDecimal.ZERO, BigDecimal.ONE)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> splitter.split(BigDecimal.ONE, BigDecimal.ZERO)).isInstanceOf(BizException.class);
|
||||
assertThatThrownBy(() -> splitter.split(new BigDecimal("10001"), BigDecimal.ONE)).isInstanceOf(BizException.class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user