暂存提交

This commit is contained in:
2026-08-19 16:24:02 +08:00
parent f5c4bf130a
commit 6acb6178da
354 changed files with 25000 additions and 198 deletions
@@ -0,0 +1,35 @@
package com.baiyue.lastleg.dropship;
import org.junit.jupiter.api.Test;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class DropshipSchemaContractTest {
@Test
void baselineAndIncrementalSqlKeepContainerAndMultiPalletIndexes() throws Exception {
String baseline = Files.readString(
Path.of("src", "main", "resources", "db", "lastleg.sql"), StandardCharsets.UTF_8).toLowerCase();
String migration = Files.readString(
Path.of("..", "scripts", "db", "incremental.sql"), StandardCharsets.UTF_8).toLowerCase();
assertThat(baseline).contains(
"key idx_ll_order_container(customer_id,container_no)",
"unique key uk_ll_dropship_profile_order_pallet(customer_id,order_id,source_pallet_no)",
"unique key uk_ll_dropship_sku_inventory(profile_id,sku_code)",
"key idx_ll_dropship_profile_order(customer_id,order_id)",
"warehouse_pallet_id bigint null comment '仓库实物托盘id'",
"pallet_no varchar(128) null comment '托盘号'",
"status varchar(32) not null default 'pending_inbound'");
assertThat(migration).contains(
"add key idx_ll_order_container (customer_id,container_no)",
"add unique key uk_ll_dropship_profile_order_pallet(customer_id,order_id,source_pallet_no)",
"add unique key uk_ll_dropship_sku_profile(profile_id,sku_code)",
"add key idx_ll_dropship_profile_order(customer_id,order_id)",
"modify column warehouse_pallet_id bigint null",
"modify column pallet_no varchar(128) null");
}
}
@@ -0,0 +1,148 @@
package com.baiyue.lastleg.dropship.service;
import com.baiyue.lastleg.dropship.dto.DropshipRequests;
import com.baiyue.lastleg.dropship.entity.DropshipOrderProfile;
import com.baiyue.lastleg.dropship.entity.DropshipSkuInventory;
import com.baiyue.lastleg.dropship.entity.DropshipCarton;
import com.baiyue.lastleg.dropship.entity.DropshipCartonLedger;
import com.baiyue.lastleg.dropship.mapper.DropshipCartonLedgerMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipCartonMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipOrderProfileMapper;
import com.baiyue.lastleg.dropship.mapper.DropshipSkuInventoryMapper;
import com.baiyue.lastleg.entity.LastlegOrder;
import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway;
import com.baiyue.lastleg.inboundplan.pda.entity.InboundStockReceipt;
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class DropshipOrderServiceTest {
@Mock private LastlegOrderMapper orders;
@Mock private DropshipOrderProfileMapper profiles;
@Mock private DropshipSkuInventoryMapper skuInventory;
@Mock private DropshipCartonMapper cartons;
@Mock private DropshipCartonLedgerMapper ledger;
@Mock private WarehouseResourceGateway warehouse;
@InjectMocks private DropshipOrderService service;
@Test
void receivesMultiplePalletsForOneInboundOrder() {
LastlegOrder order = new LastlegOrder();
order.setId(10L);
order.setCustomerId("C-1");
order.setOrderType("ONE_CLICK_DROPSHIP");
order.setOrderNo("LL-10");
order.setPackageCount(3);
order.setProductQuantity(30);
when(orders.selectById(10L)).thenReturn(order);
when(profiles.listOrder("C-1", 10L)).thenReturn(List.of());
DropshipRequests.Receive request = new DropshipRequests.Receive("C-1", 10L, 20L, "EVENT-1",
List.of(
new DropshipRequests.Pallet("SOURCE-P-1", List.of(
new DropshipRequests.SkuPackages("SKU-A", "Product A", 2, 20,
List.of("MARK-1", "MARK-2")))),
new DropshipRequests.Pallet("SOURCE-P-2", List.of(
new DropshipRequests.SkuPackages("SKU-A", "Product A", 1, 10,
List.of("MARK-3"))))));
assertThat(service.receive(request)).isEqualTo(3);
verifyNoInteractions(warehouse);
verify(profiles, times(2)).insert(any(DropshipOrderProfile.class));
verify(skuInventory, times(2)).insert(any(DropshipSkuInventory.class));
verify(cartons, times(3)).insert(any(DropshipCarton.class));
verify(ledger, times(3)).insert(any(DropshipCartonLedger.class));
ArgumentCaptor<DropshipOrderProfile> profilesCaptor = ArgumentCaptor.forClass(DropshipOrderProfile.class);
verify(profiles, times(2)).insert(profilesCaptor.capture());
assertThat(profilesCaptor.getAllValues()).extracting(DropshipOrderProfile::getSourcePalletNo)
.containsExactly("SOURCE-P-1", "SOURCE-P-2");
assertThat(profilesCaptor.getAllValues()).extracting(DropshipOrderProfile::getCustomerId)
.containsOnly("C-1");
assertThat(profilesCaptor.getAllValues()).extracting(DropshipOrderProfile::getStatus)
.containsOnly("PENDING_INBOUND");
assertThat(profilesCaptor.getAllValues()).extracting(DropshipOrderProfile::getWarehousePalletId)
.containsOnlyNulls();
ArgumentCaptor<DropshipCarton> cartonCaptor = ArgumentCaptor.forClass(DropshipCarton.class);
verify(cartons, times(3)).insert(cartonCaptor.capture());
assertThat(cartonCaptor.getAllValues()).extracting(DropshipCarton::getStatus)
.containsOnly("PENDING_INBOUND");
ArgumentCaptor<DropshipCartonLedger> ledgerCaptor = ArgumentCaptor.forClass(DropshipCartonLedger.class);
verify(ledger, times(3)).insert(ledgerCaptor.capture());
assertThat(ledgerCaptor.getAllValues()).extracting(DropshipCartonLedger::getOperationType)
.containsOnly("SNAPSHOT_CREATED");
assertThat(ledgerCaptor.getAllValues()).extracting(DropshipCartonLedger::getDeltaPackages)
.containsOnly(0L);
}
@Test
void activatesMultiplePalletsOnlyAfterPdaStockIn() {
DropshipOrderProfile first = profile(1L, "SOURCE-P-1");
DropshipOrderProfile second = profile(2L, "SOURCE-P-2");
when(profiles.listOrder("C-1", 10L)).thenReturn(List.of(first, second));
DropshipCarton firstCarton = carton(11L, 1L, "MARK-1");
DropshipCarton secondCarton = carton(12L, 2L, "MARK-2");
when(cartons.listProfile("C-1", 1L)).thenReturn(List.of(firstCarton));
when(cartons.listProfile("C-1", 2L)).thenReturn(List.of(secondCarton));
service.activateAfterStockIn("C-1", 10L, 50L, List.of(
receipt(101L, "WH-P-1", 201L, 1), receipt(102L, "WH-P-2", 202L, 1)));
assertThat(first.getStatus()).isEqualTo("ACTIVE");
assertThat(first.getWarehousePalletId()).isEqualTo(101L);
assertThat(firstCarton.getStatus()).isEqualTo("AVAILABLE");
assertThat(firstCarton.getWarehousePalletId()).isEqualTo(101L);
verify(profiles, times(2)).updateById(any(DropshipOrderProfile.class));
verify(cartons, times(2)).updateById(any(DropshipCarton.class));
ArgumentCaptor<DropshipCartonLedger> facts = ArgumentCaptor.forClass(DropshipCartonLedger.class);
verify(ledger, times(2)).insert(facts.capture());
assertThat(facts.getAllValues()).extracting(DropshipCartonLedger::getOperationType).containsOnly("STOCK_IN");
assertThat(facts.getAllValues()).extracting(DropshipCartonLedger::getDeltaPackages).containsOnly(1L);
}
@Test
void repeatedPdaActivationIsANoOp() {
DropshipOrderProfile active = profile(1L, "SOURCE-P-1");
active.setStatus("ACTIVE");
when(profiles.listOrder("C-1", 10L)).thenReturn(List.of(active));
service.activateAfterStockIn("C-1", 10L, 50L,
List.of(receipt(101L, "WH-P-1", 201L, 1)));
verify(profiles, never()).updateById(any(DropshipOrderProfile.class));
verify(cartons, never()).updateById(any(DropshipCarton.class));
verify(ledger, never()).insert(any(DropshipCartonLedger.class));
}
private static DropshipOrderProfile profile(long id, String sourcePalletNo) {
DropshipOrderProfile profile = new DropshipOrderProfile();
profile.setId(id); profile.setCustomerId("C-1"); profile.setOrderId(10L);
profile.setSourcePalletNo(sourcePalletNo); profile.setStatus("PENDING_INBOUND"); profile.setVersion(0L);
return profile;
}
private static DropshipCarton carton(long id, long profileId, String mark) {
DropshipCarton carton = new DropshipCarton();
carton.setId(id); carton.setCustomerId("C-1"); carton.setOrderId(10L); carton.setProfileId(profileId);
carton.setCartonMark(mark); carton.setSkuCode("SKU-A"); carton.setStatus("PENDING_INBOUND"); carton.setVersion(0L);
return carton;
}
private static InboundStockReceipt receipt(long palletId, String palletNo, long positionId, long packages) {
InboundStockReceipt receipt = new InboundStockReceipt();
receipt.setOrderId(10L); receipt.setWarehousePalletId(palletId); receipt.setPalletNo(palletNo);
receipt.setInventoryPositionId(positionId); receipt.setReceivedPackages(packages);
return receipt;
}
}