提交
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
||||
package com.baiyue.lastleg.inventory.mapper;
|
||||
|
||||
import org.apache.ibatis.mapping.Environment;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
|
||||
import java.util.UUID;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class InventoryCartonOwnershipTest {
|
||||
@Test void realSqlRequiresMatchingCustomerWarehouseAndInboundForEachCarton() {
|
||||
var ds = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
||||
var db = new JdbcTemplate(ds);
|
||||
db.execute("CREATE TABLE ll_inbound_plan_carton(order_id BIGINT,customer_id VARCHAR,carton_mark VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR,inbound_code VARCHAR,overseas_warehouse_id VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_inbound_order(id BIGINT,customer_id VARCHAR,inbound_code VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_order(id BIGINT,customer_id VARCHAR,inbound_order_id BIGINT,operating_warehouse_id VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_carton(transfer_order_id BIGINT,customer_id VARCHAR,carton_mark VARCHAR,customer_carton_mark VARCHAR,status VARCHAR)");
|
||||
db.update("INSERT INTO ll_inbound_order VALUES(1,'C1','IN1'),(2,'C1','IN2')");
|
||||
db.update("INSERT INTO ll_order VALUES(10,'C1','IN1','WH1'),(20,'C1','IN2','WH1')");
|
||||
db.update("INSERT INTO ll_inbound_plan_carton VALUES(10,'C1','BOX1'),(20,'C1','OTHER-ORDER')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_order VALUES(30,'C1',1,'WH1'),(40,'C2',1,'WH1')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_carton VALUES(30,'C1','TRANSFER-BOX','CUSTOMER-BOX','COUNTED'),(30,'C1','UNCHECKED','CUSTOMER-UNCHECKED','NOT_RECEIVED'),(40,'C2','OTHER-CUSTOMER',NULL,'COUNTED')");
|
||||
var config = new Configuration(new Environment("test", new JdbcTransactionFactory(), ds));
|
||||
config.addMapper(InventoryBalanceMapper.class);
|
||||
try (var session = new SqlSessionFactoryBuilder().build(config).openSession()) {
|
||||
var mapper = session.getMapper(InventoryBalanceMapper.class);
|
||||
for (String mark : new String[]{"BOX1", "TRANSFER-BOX", "CUSTOMER-BOX"}) {
|
||||
assertTrue(mapper.cartonBelongsToInbound("C1", "WH1", 1L, mark));
|
||||
assertFalse(mapper.cartonBelongsToInbound("C1", "WH2", 1L, mark));
|
||||
assertFalse(mapper.cartonBelongsToInbound("C2", "WH1", 1L, mark));
|
||||
assertFalse(mapper.cartonBelongsToInbound("C1", "WH1", 2L, mark));
|
||||
}
|
||||
for (String mark : new String[]{"MISSING", "OTHER-ORDER", "OTHER-CUSTOMER", "UNCHECKED"})
|
||||
assertFalse(mapper.cartonBelongsToInbound("C1", "WH1", 1L, mark));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -75,6 +75,7 @@ class PdaPalletOperationServiceTest {
|
||||
|
||||
@BeforeEach void setUp() {
|
||||
service = new PdaPalletOperationService();
|
||||
ReflectionTestUtils.setField(service, "cartonMeasurements", org.mockito.Mockito.mock(com.baiyue.lastleg.relabel.service.RelabelCartonMeasurementService.class));
|
||||
ReflectionTestUtils.setField(service, "mapper", mapper);
|
||||
ReflectionTestUtils.setField(service, "inventoryCommands", inventoryCommands);
|
||||
ReflectionTestUtils.setField(service, "positions", positions);
|
||||
|
||||
+15
-1
@@ -212,9 +212,13 @@ class RelabelApplicationServiceTest {
|
||||
|
||||
private RelabelApplicationService service;
|
||||
|
||||
private com.baiyue.lastleg.service.CompactBusinessNumberService compactNumbers;
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
compactNumbers = org.mockito.Mockito.mock(com.baiyue.lastleg.service.CompactBusinessNumberService.class);
|
||||
service = new RelabelApplicationService();
|
||||
ReflectionTestUtils.setField(service, "compactNumbers", compactNumbers);
|
||||
org.mockito.Mockito.lenient().when(compactNumbers.next(org.mockito.ArgumentMatchers.anyString(), org.mockito.ArgumentMatchers.anyString())).thenAnswer(call -> call.getArgument(0) + "-CS-261016102030");
|
||||
ReflectionTestUtils.setField(service, "bindingGuard", bindingGuard);
|
||||
ReflectionTestUtils.setField(service, "returnPackingTraces", org.mockito.Mockito.mock(com.baiyue.lastleg.returnreceipt.mapper.ReturnPackingTraceMapper.class));
|
||||
ReflectionTestUtils.setField(service, "skuConversions", org.mockito.Mockito.mock(com.baiyue.lastleg.relabel.service.ReturnSkuConversionService.class));
|
||||
@@ -251,11 +255,21 @@ class RelabelApplicationServiceTest {
|
||||
balance.setOverseasWarehouseId("WH-1"); balance.setInboundOrderId(301L); balance.setInboundOrderNo("IN-1");
|
||||
balance.setInboundCode("CODE-1"); balance.setSkuCode("SKU-A"); balance.setProductNameZh("Chinese name");
|
||||
lenient().when(inventoryBalances.selectById(any(Long.class))).thenReturn(balance);
|
||||
lenient().when(inventoryBalances.cartonBelongsToInbound(anyString(), anyString(), anyLong(), anyString())).thenReturn(true);
|
||||
ReflectionTestUtils.setField(service, "feeSources", feeSources);
|
||||
lenient().when(feeSources.publishApproved(any(), any(), any())).thenReturn(new OverseasFeeSource());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void rejectsCartonOutsideSelectedInboundBeforeCreatingOrHoldingInventory() {
|
||||
when(inventoryBalances.cartonBelongsToInbound(eq("10001"), eq("WH-1"), eq(301L), anyString())).thenReturn(false);
|
||||
var error = assertThrows(ResponseStatusException.class, () -> service.create("10001", "operator-1", request("bad-carton", 1, 1)));
|
||||
assertEquals("当前箱子不存在或不属于当前订单", error.getReason());
|
||||
verify(applications, never()).insert(any(RelabelApplication.class));
|
||||
verify(inventoryCommands, never()).hold(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createBuildsPendingRelabelTailOrderItemsAndBothHistories() {
|
||||
RelabelRequests.Create request = request("key-1", 10, 6);
|
||||
@@ -286,7 +300,7 @@ class RelabelApplicationServiceTest {
|
||||
assertEquals("PENDING_REVIEW", tailOrder.getValue().getCurrentStatus());
|
||||
assertEquals("RELABEL:PENDING_REVIEW", tailOrder.getValue().getSubOrderStatus());
|
||||
assertEquals("CUSTOMER", tailOrder.getValue().getSourceRegion());
|
||||
assertTrue(tailOrder.getValue().getOrderNo().matches("RL-WH-\\d{8}-\\d{6}"));
|
||||
assertTrue(tailOrder.getValue().getOrderNo().matches("TB-CS-[0-9]{12}"));
|
||||
assertNull(tailOrder.getValue().getInboundCode());
|
||||
assertEquals(application.getValue().getRelabelNo() + ":WH-1", tailOrder.getValue().getSourceInboundId());
|
||||
assertEquals(tailOrder.getValue().getRelabelOrderNo(), application.getValue().getRelabelNo());
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package com.baiyue.lastleg.relabel.service;
|
||||
|
||||
import com.baiyue.lastleg.relabel.entity.*;
|
||||
import com.baiyue.lastleg.relabel.mapper.*;
|
||||
import com.baiyue.lastleg.relabel.pda.entity.PdaRelabelHistory;
|
||||
import com.baiyue.lastleg.relabel.pda.mapper.PdaRelabelHistoryMapper;
|
||||
import com.baiyue.lastleg.palletops.dto.PalletOperationRequests.MeasuredCartonBinding;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
|
||||
class RelabelCartonMeasurementServiceTest {
|
||||
final RelabelCartonMeasurementService boxes = new RelabelCartonMeasurementService();
|
||||
final RelabelPalletMeasurementService pallets = new RelabelPalletMeasurementService();
|
||||
final RelabelPalletMeasurementMapper mapper = mock(RelabelPalletMeasurementMapper.class);
|
||||
final PdaRelabelHistoryMapper histories = mock(PdaRelabelHistoryMapper.class);
|
||||
final RelabelItemMapper items = mock(RelabelItemMapper.class);
|
||||
final ObjectMapper json = new ObjectMapper();
|
||||
final RelabelApplication app = new RelabelApplication();
|
||||
final List<PdaRelabelHistory> records = new ArrayList<>();
|
||||
@BeforeEach void setup() {
|
||||
app.setId(1L); app.setCustomerId("7"); app.setRelabelNo("RL-1"); app.setOverseasWarehouseId("92");
|
||||
for (Object service : List.of(boxes,pallets)) {
|
||||
ReflectionTestUtils.setField(service,"mapper",mapper);
|
||||
ReflectionTestUtils.setField(service,"histories",histories);
|
||||
ReflectionTestUtils.setField(service,"json",json);
|
||||
}
|
||||
ReflectionTestUtils.setField(pallets,"items",items);
|
||||
ReflectionTestUtils.setField(pallets,"cartonMeasurements",boxes);
|
||||
when(mapper.transfer("7","RL-1")).thenReturn(10L);
|
||||
when(histories.selectList(any())).thenAnswer(i -> List.copyOf(records));
|
||||
when(mapper.originals("7",10L)).thenReturn(List.of());
|
||||
when(items.selectList(any())).thenReturn(List.of());
|
||||
when(mapper.cartons("7",10L)).thenReturn(List.of(box("BIG",100,60,50,50,"2.5"),box("SMALL1",100,50,40,40,"3.6"),box("SMALL2",100,50,40,40,"3.6")));
|
||||
}
|
||||
RelabelPalletMeasurementMapper.Carton box(String mark,long pallet,int l,int w,int h,String kg) {
|
||||
return new RelabelPalletMeasurementMapper.Carton((long)mark.hashCode(),mark,null,pallet,"P"+pallet,
|
||||
BigDecimal.valueOf(l),BigDecimal.valueOf(w),BigDecimal.valueOf(h),new BigDecimal(kg));
|
||||
}
|
||||
RelabelItem item(String mark) { var i=new RelabelItem(); i.setCartonMark(mark); i.setNotifiedPackageCount(1); return i; }
|
||||
void save(List<RelabelCartonMeasurementService.Move> moves) throws Exception {
|
||||
var h=new PdaRelabelHistory(); h.setAction("PALLET_BIND"); h.setDetailJson(json.writeValueAsString(Map.of("measuredCartons",moves))); records.add(h);
|
||||
}
|
||||
void stock(long source,long target,long third) {
|
||||
when(mapper.stock("7","92")).thenReturn(List.of(new RelabelPalletMeasurementMapper.Stock(1L,100L,"P100",source,1),
|
||||
new RelabelPalletMeasurementMapper.Stock(2L,200L,"P200",target,1),new RelabelPalletMeasurementMapper.Stock(3L,300L,"P300",third,1)));
|
||||
}
|
||||
void totals(long pallet,String cbm,String kg) {
|
||||
var p=pallets.snapshots(app).stream().filter(row -> row.palletId()==pallet).findFirst().orElseThrow();
|
||||
assertTrue(p.cartonAggregated()); assertNull(p.lengthCm());
|
||||
assertEquals(0,new BigDecimal(cbm).compareTo(p.volumeCbm())); assertEquals(0,new BigDecimal(kg).compareTo(p.grossWeightKg()));
|
||||
}
|
||||
@Test void movingMixedBoxSubtractsExactMetricsAndRebindingMovesSameBoxOnce() throws Exception {
|
||||
stock(3,0,0); totals(100,"0.31","9.7");
|
||||
save(boxes.prepare(app,List.of(item("CUSTOMER")),100L,200L,"P200",List.of(new MeasuredCartonBinding("CUSTOMER","SMALL1"))));
|
||||
stock(2,1,0); totals(100,"0.23","6.1"); totals(200,"0.08","3.6");
|
||||
assertDoesNotThrow(() -> pallets.requireMeasured(app));
|
||||
var rebind=boxes.prepare(app,List.of(item("CUSTOMER")),200L,300L,"P300",null);
|
||||
assertEquals("SMALL1",rebind.get(0).sourceCartonMark()); save(rebind); save(rebind);
|
||||
stock(2,0,1); totals(100,"0.23","6.1"); totals(300,"0.08","3.6");
|
||||
assertEquals(3,boxes.current(app).size()); assertDoesNotThrow(() -> pallets.requireMeasured(app));
|
||||
}
|
||||
@Test void equalSpecificationsNeedNoExtraBoxSelection() throws Exception {
|
||||
when(mapper.cartons("7",10L)).thenReturn(List.of(box("A",100,60,50,50,"2.5"),box("B",100,60,50,50,"2.50")));
|
||||
save(boxes.prepare(app,List.of(item("CUSTOMER")),100L,200L,"P200",null));
|
||||
stock(1,1,0); totals(100,"0.15","2.5"); totals(200,"0.15","2.5");
|
||||
}
|
||||
@Test void ambiguousForeignDuplicateAndAlreadyUsedBoxesAreRejected() throws Exception {
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("X")),100L,200L,"P200",null));
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("X")),100L,200L,"P200",List.of(new MeasuredCartonBinding("X","FOREIGN"))));
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("X"),item("Y")),100L,200L,"P200",List.of(new MeasuredCartonBinding("X","BIG"),new MeasuredCartonBinding("Y","BIG"))));
|
||||
save(boxes.prepare(app,List.of(item("X")),100L,200L,"P200",List.of(new MeasuredCartonBinding("X","BIG"))));
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("Y")),200L,300L,"P300",List.of(new MeasuredCartonBinding("Y","BIG"))));
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("X")),200L,300L,"P300",List.of(new MeasuredCartonBinding("X","SMALL1"))));
|
||||
}
|
||||
@Test void missingBoxMeasurementsOrUntrackedContentsCannotPassCompletion() {
|
||||
when(mapper.cartons("7",10L)).thenReturn(List.of(box("A",100,0,50,50,"2.5")));
|
||||
assertThrows(ResponseStatusException.class,()->boxes.prepare(app,List.of(item("A")),100L,200L,"P200",null));
|
||||
stock(1,0,0); assertThrows(ResponseStatusException.class,()->pallets.requireMeasured(app));
|
||||
when(mapper.cartons("7",10L)).thenReturn(List.of(box("A",100,60,50,50,"2.5")));
|
||||
stock(2,0,0); assertThrows(ResponseStatusException.class,()->pallets.requireMeasured(app));
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baiyue.lastleg.relabel.service;
|
||||
|
||||
import com.baiyue.lastleg.relabel.mapper.RelabelPalletMeasurementMapper;
|
||||
import org.apache.ibatis.mapping.Environment;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import java.util.UUID;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class RelabelPalletMeasurementMapperTest {
|
||||
@Test void realSqlGroupsMeasuredCartonsAndKeepsCustomerTransferAndPalletBoundaries() {
|
||||
var ds = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
||||
var db = new JdbcTemplate(ds);
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_pallet(id BIGINT,customer_id VARCHAR,transfer_order_id BIGINT,warehouse_pallet_id BIGINT,status VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_carton(customer_id VARCHAR,transfer_order_id BIGINT,transfer_pallet_id BIGINT,status VARCHAR,length_cm DECIMAL(12,2),width_cm DECIMAL(12,2),height_cm DECIMAL(12,2),gross_weight_kg DECIMAL(12,3))");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_pallet VALUES(1,'7',10,100,'COMPLETED'),(2,'8',10,200,'COMPLETED'),(3,'7',20,300,'COMPLETED'),(4,'7',10,400,'BOUND')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_carton VALUES('7',10,1,'COUNTED',60,50,50,2.5),('7',10,1,'COUNTED',60,50,50,2.5),('7',10,1,'COUNTED',50,40,40,3.6),('7',10,1,'NOT_RECEIVED',60,50,50,2.5),('8',10,2,'COUNTED',60,50,50,2.5),('7',20,3,'COUNTED',60,50,50,2.5),('7',10,4,'COUNTED',60,50,50,2.5),('7',10,2,'COUNTED',60,50,50,2.5)");
|
||||
db.execute("ALTER TABLE ll_warehouse_transfer_carton ADD id BIGINT GENERATED BY DEFAULT AS IDENTITY");
|
||||
db.execute("ALTER TABLE ll_warehouse_transfer_carton ADD carton_mark VARCHAR DEFAULT 'BOX'");
|
||||
db.execute("ALTER TABLE ll_warehouse_transfer_carton ADD customer_carton_mark VARCHAR DEFAULT 'CUSTOMER'");
|
||||
db.execute("ALTER TABLE ll_warehouse_transfer_pallet ADD pallet_no VARCHAR DEFAULT 'P100'");
|
||||
var configuration = new Configuration(new Environment("test", new JdbcTransactionFactory(), ds));
|
||||
configuration.addMapper(RelabelPalletMeasurementMapper.class);
|
||||
try (var session = new SqlSessionFactoryBuilder().build(configuration).openSession()) {
|
||||
var rows = session.getMapper(RelabelPalletMeasurementMapper.class).cartonSpecs("7", 10L);
|
||||
assertThat(rows).hasSize(2).allSatisfy(row -> assertThat(row.palletId()).isEqualTo(100L));
|
||||
assertThat(rows.get(0).lengthCm()).isEqualByComparingTo("50");
|
||||
assertThat(rows.get(0).cartons()).isEqualTo(1);
|
||||
assertThat(rows.get(1).lengthCm()).isEqualByComparingTo("60");
|
||||
assertThat(rows.get(1).grossWeightKg()).isEqualByComparingTo("2.5");
|
||||
assertThat(rows.get(1).cartons()).isEqualTo(2);
|
||||
var boxes = session.getMapper(RelabelPalletMeasurementMapper.class).cartons("7", 10L);
|
||||
assertThat(boxes).hasSize(3).allSatisfy(box -> {
|
||||
assertThat(box.palletId()).isEqualTo(100L);
|
||||
assertThat(box.palletCode()).isEqualTo("P100");
|
||||
assertThat(box.cartonMark()).isEqualTo("BOX");
|
||||
assertThat(box.customerCartonMark()).isEqualTo("CUSTOMER");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -29,6 +29,7 @@ class RelabelPalletMeasurementServiceTest {
|
||||
ReflectionTestUtils.setField(service,"mapper",mapper); ReflectionTestUtils.setField(service,"applications",apps);
|
||||
ReflectionTestUtils.setField(service,"items",items); ReflectionTestUtils.setField(service,"histories",histories);
|
||||
ReflectionTestUtils.setField(service,"tasks",tasks); ReflectionTestUtils.setField(service,"json",json);
|
||||
ReflectionTestUtils.setField(service,"cartonMeasurements",mock(RelabelCartonMeasurementService.class));
|
||||
app.setId(1L);app.setCustomerId("7");app.setRelabelNo("RL-1");app.setOverseasWarehouseId("92");
|
||||
app.setStatus("READY_FOR_OUTBOUND");app.setFulfillmentStatus("WAIT_PRE_DISPATCH");
|
||||
when(apps.findAnyByRelabelNo("RL-1")).thenReturn(app);when(apps.lockAnyByRelabelNo("RL-1")).thenReturn(app);
|
||||
@@ -49,6 +50,45 @@ class RelabelPalletMeasurementServiceTest {
|
||||
var p = service.snapshots(app).get(0);assertTrue(p.inherited()); assertEquals(new BigDecimal("80"),p.grossWeightKg());
|
||||
assertEquals(BigDecimal.ONE,p.volumeCbm());assertDoesNotThrow(() -> service.requireMeasured(app));
|
||||
}
|
||||
@Test void cartonMeasuredSourceShowsRealBoxSpecsWithoutInventingPalletDimensions() {
|
||||
cartonMeasuredSource();
|
||||
var p = service.snapshots(app).get(0);
|
||||
assertTrue(p.inherited()); assertNull(p.lengthCm()); assertNull(p.widthCm()); assertNull(p.heightCm());
|
||||
assertEquals(1, p.sourceCartonSpecs().size());
|
||||
assertEquals(new BigDecimal("60"), p.sourceCartonSpecs().get(0).lengthCm());
|
||||
assertEquals(2, p.sourceCartonSpecs().get(0).cartons());
|
||||
assertEquals(new BigDecimal("5.0"), p.grossWeightKg());
|
||||
assertEquals(new BigDecimal("0.3"), p.volumeCbm());
|
||||
assertDoesNotThrow(() -> service.requireMeasured(app));
|
||||
}
|
||||
@Test void incompleteOrMismatchedSourceCartonsCannotBypassMeasurement() {
|
||||
cartonMeasuredSource();
|
||||
for (var spec : List.of(
|
||||
new RelabelPalletMeasurementMapper.CartonSpec(100L,new BigDecimal("60"),new BigDecimal("50"),new BigDecimal("50"),new BigDecimal("2.5"),1),
|
||||
new RelabelPalletMeasurementMapper.CartonSpec(100L,new BigDecimal("61"),new BigDecimal("50"),new BigDecimal("50"),new BigDecimal("2.5"),2),
|
||||
new RelabelPalletMeasurementMapper.CartonSpec(100L,new BigDecimal("60"),new BigDecimal("50"),new BigDecimal("50"),new BigDecimal("3"),2),
|
||||
new RelabelPalletMeasurementMapper.CartonSpec(100L,BigDecimal.ZERO,new BigDecimal("50"),new BigDecimal("50"),new BigDecimal("2.5"),2))) {
|
||||
when(mapper.cartonSpecs("7",10L)).thenReturn(List.of(spec));
|
||||
assertThrows(ResponseStatusException.class, () -> service.requireMeasured(app));
|
||||
}
|
||||
when(mapper.cartonSpecs("7",10L)).thenReturn(List.of());
|
||||
assertThrows(ResponseStatusException.class, () -> service.requireMeasured(app));
|
||||
}
|
||||
@Test void changedCartonMeasuredPalletMustBeRemeasuredInsteadOfReusingOldBoxSpecs() {
|
||||
cartonMeasuredSource();
|
||||
when(mapper.movements("7",100L)).thenReturn(1);
|
||||
var p = service.snapshots(app).get(0);
|
||||
assertFalse(p.inherited()); assertTrue(p.sourceCartonSpecs().isEmpty());
|
||||
assertNull(p.volumeCbm());
|
||||
assertThrows(ResponseStatusException.class, () -> service.requireMeasured(app));
|
||||
}
|
||||
private void cartonMeasuredSource() {
|
||||
when(mapper.originals("7",10L)).thenReturn(List.of(new RelabelPalletMeasurementMapper.Original(100L,"OLD",2,
|
||||
BigDecimal.ZERO,BigDecimal.ZERO,BigDecimal.ZERO,new BigDecimal("5.0"),new BigDecimal("0.3"))));
|
||||
when(mapper.stock("7","92")).thenReturn(List.of(stock(1,100,"OLD",2,1)));
|
||||
when(mapper.cartonSpecs("7",10L)).thenReturn(List.of(new RelabelPalletMeasurementMapper.CartonSpec(100L,
|
||||
new BigDecimal("60"),new BigDecimal("50"),new BigDecimal("50"),new BigDecimal("2.5"),2)));
|
||||
}
|
||||
@Test void partialSplitRequiresBothNewPalletAndOriginalRemainderMeasurements() throws Exception {
|
||||
split(); var values = service.snapshots(app);assertEquals(2,values.size());
|
||||
assertTrue(values.stream().allMatch(p -> p.volumeCbm()==null && p.grossWeightKg()==null));
|
||||
|
||||
+3
-3
@@ -184,7 +184,7 @@ class ReturnInventoryServiceTest {
|
||||
var receipt = new ReturnReceipt(); receipt.setId(21L); receipt.setUnitType("PARCEL"); receipt.setUnitCode("PK-1");
|
||||
var source = service.createReceiptCarton(completedOrder(), receipt, null,
|
||||
List.of(new ReturnInventoryService.ReceiptLine("A", "商品A", 3)));
|
||||
assertThat(source.getCartonMark()).startsWith("RP");
|
||||
assertThat(source.getCartonMark()).startsWith("RP-").hasSizeLessThanOrEqualTo(16);
|
||||
assertThat(source.getSourceUnitType()).isEqualTo("PARCEL");
|
||||
verifyNoInteractions(numbers);
|
||||
assertThat(source.getLabelStatus()).isEqualTo("CONFIRMED");
|
||||
@@ -305,7 +305,7 @@ class ReturnInventoryServiceTest {
|
||||
|
||||
assertThat(created).hasSize(2);
|
||||
assertThat(created).extracting(ReturnInventoryCarton::getCartonMark)
|
||||
.allMatch(mark -> mark.matches("RC[A-F0-9]{16}#2-[12]"))
|
||||
.allMatch(mark -> mark.matches("RC[0-9A-Z]{1,13}#2-[12]"))
|
||||
.doesNotHaveDuplicates();
|
||||
assertThat(created.get(0).getCartonMark()).endsWith("#2-1");
|
||||
assertThat(created.get(1).getCartonMark()).endsWith("#2-2");
|
||||
@@ -538,7 +538,7 @@ class ReturnInventoryServiceTest {
|
||||
String a = ReflectionTestUtils.invokeMethod(service, "shortReturnMark", "RT-ORDER", 123L, "SAMEPREFIX-A", 2L, 1L);
|
||||
String b = ReflectionTestUtils.invokeMethod(service, "shortReturnMark", "RT-ORDER", 123L, "SAMEPREFIX-B", 2L, 1L);
|
||||
String second = ReflectionTestUtils.invokeMethod(service, "shortReturnMark", "RT-ORDER", 123L, "SAMEPREFIX-A", 2L, 2L);
|
||||
assertThat(a).isNotEqualTo(b).matches("RC[A-F0-9]{16}#2-1");
|
||||
assertThat(a).isNotEqualTo(b).matches("RC[0-9A-Z]{1,13}#2-1");
|
||||
assertThat(second).isEqualTo(a.substring(0, a.lastIndexOf('-') + 1) + "2");
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -121,9 +121,13 @@ class ReturnReceiptServiceTest {
|
||||
ReturnReceiptService service;
|
||||
PdaWarehouseIdentity identity;
|
||||
|
||||
private com.baiyue.lastleg.service.CompactBusinessNumberService compactNumbers;
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
compactNumbers = org.mockito.Mockito.mock(com.baiyue.lastleg.service.CompactBusinessNumberService.class);
|
||||
service = new ReturnReceiptService();
|
||||
ReflectionTestUtils.setField(service, "compactNumbers", compactNumbers);
|
||||
org.mockito.Mockito.lenient().when(compactNumbers.next(org.mockito.ArgumentMatchers.anyString(), org.mockito.ArgumentMatchers.anyString())).thenAnswer(call -> call.getArgument(0) + "-CS-261016102030");
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "orderItems", orderItems);
|
||||
ReflectionTestUtils.setField(service, "receipts", receipts);
|
||||
@@ -243,7 +247,7 @@ class ReturnReceiptServiceTest {
|
||||
when(orderItems.lockOrder(1L)).thenReturn(List.of(item(11L, "SKU-A", 50, 50), item(12L, "SKU-B", 40, 40)));
|
||||
when(fbaWarehouseValidator.required("200", "XLX6", null)).thenReturn(
|
||||
new FbaWarehouseValidator.VerifiedFbaWarehouse(200L, "XLX6", "FBA XLX6", "US", "CA"));
|
||||
when(numbers.next(eq("RELABEL"), eq("10"), anyLong())).thenReturn("RL-MULTI");
|
||||
when(compactNumbers.next(eq("TT"), eq("customer-1"))).thenReturn("RL-MULTI");
|
||||
when(lastlegOrders.selectById(99L)).thenReturn(tail);
|
||||
when(cartons.findAvailable("customer-1", "10")).thenReturn(List.of(first, second));
|
||||
when(inventory.matchesReturnSource(any(), eq("RT-MULTI"))).thenCallRealMethod();
|
||||
@@ -294,7 +298,7 @@ class ReturnReceiptServiceTest {
|
||||
when(orderItems.lockOrder(1L)).thenReturn(List.of(item(11L, "SKU-A", 100, 100)));
|
||||
when(fbaWarehouseValidator.required("200", "XLX6", null)).thenReturn(
|
||||
new FbaWarehouseValidator.VerifiedFbaWarehouse(200L, "XLX6", "FBA XLX6", "US", "CA"));
|
||||
when(numbers.next(eq("RELABEL"), eq("10"), anyLong())).thenReturn("RL-SECOND");
|
||||
when(compactNumbers.next(eq("TT"), eq("customer-1"))).thenReturn("RL-SECOND");
|
||||
when(lastlegOrders.selectById(99L)).thenReturn(tail);
|
||||
when(cartons.findAvailable("customer-1", "10")).thenReturn(List.of(carton));
|
||||
when(inventory.matchesReturnSource(any(), eq("RT-MULTI"))).thenCallRealMethod();
|
||||
@@ -349,7 +353,7 @@ class ReturnReceiptServiceTest {
|
||||
void createForecastPersistsCompleteTailOrderSourceAndReturnsItsBusinessNumber() {
|
||||
AtomicReference<ReturnOrder> saved = new AtomicReference<>();
|
||||
when(orders.findKey("customer-1", "create-key")).thenReturn(null);
|
||||
when(numbers.next(eq("RETURN"), eq("10"), anyLong())).thenReturn("RT-1");
|
||||
when(compactNumbers.next(eq("TT"), eq("customer-1"))).thenReturn("RT-1");
|
||||
when(orders.insert(any(ReturnOrder.class))).thenAnswer(invocation -> { saved.set(invocation.getArgument(0)); return 1; });
|
||||
when(orders.findNo("customer-1", "RT-1")).thenAnswer(invocation -> saved.get());
|
||||
when(orderItems.listOrder(anyLong())).thenReturn(List.of());
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package com.baiyue.lastleg.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import java.time.Instant;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class CompactBusinessNumberServiceTest {
|
||||
@Test void usesCustomerInitialsAndShanghaiSecondsWithoutSequenceSuffix() {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
var customers = mock(ReturnOrderReferenceResolver.class);
|
||||
when(customers.customerName("42")).thenReturn("柏悦物流");
|
||||
when(jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class))
|
||||
.thenAnswer(call -> Instant.now().getEpochSecond());
|
||||
String number = new CompactBusinessNumberService(jdbc, customers).next("TB", "42");
|
||||
assertTrue(number.matches("TB-BYWL-[0-9]{12}"), number);
|
||||
assertEquals("AB", CompactBusinessNumberService.initials("Alpha Beta"));
|
||||
}
|
||||
|
||||
@Test void usesDatabaseLogicalSecondAcrossInstancesAndClockRollback() {
|
||||
JdbcTemplate jdbc = mock(JdbcTemplate.class);
|
||||
var first = new CompactBusinessNumberService(jdbc, null);
|
||||
var second = new CompactBusinessNumberService(jdbc, null);
|
||||
Instant now = Instant.parse("2026-10-16T02:30:00Z");
|
||||
when(jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class))
|
||||
.thenReturn(now.getEpochSecond(), now.getEpochSecond() + 1, now.getEpochSecond() + 2);
|
||||
assertEquals("ZY-ABC-261016103000", first.allocate("ZY", "ABC", now));
|
||||
assertEquals("ZY-ABC-261016103001", second.allocate("ZY", "ABC", now));
|
||||
assertEquals("ZY-ABC-261016103002", first.allocate("ZY", "ABC", now.minusSeconds(60)));
|
||||
}
|
||||
|
||||
@Test void physicalLabelKeepsEveryIdBitAndIsCompact() {
|
||||
long id = 2087379674555461633L;
|
||||
String mark = LastlegOrderNoGenerator.compactCartonMark(id);
|
||||
assertTrue(mark.length() <= 16);
|
||||
assertEquals(id, Long.parseLong(mark.substring(3), 36));
|
||||
assertNotEquals(mark, LastlegOrderNoGenerator.compactCartonMark(id + 1_000_000));
|
||||
assertEquals(mark, new LastlegOrderNoGenerator().next("RETURN_CARTON", "92", id));
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.baiyue.lastleg.transfer.service;
|
||||
|
||||
import com.baiyue.lastleg.transfer.dto.WarehouseTransferRequests;
|
||||
import com.baiyue.lastleg.transfer.mapper.InboundSnapshotMapper;
|
||||
import org.apache.ibatis.mapping.Environment;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import java.util.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TransferInventorySourceTest {
|
||||
WarehouseTransferRequests.Create request(String inbound, String destination, String method, LocalDateTime arrival) {
|
||||
return new WarehouseTransferRequests.Create(inbound,List.of(),"WH",destination,"ADDRESS",1,BigDecimal.ZERO,
|
||||
method,arrival,null,null,null,null,false,"KEY",List.of(new WarehouseTransferRequests.Item("SKU","Product",1,null)));
|
||||
}
|
||||
@Test void inventoryDoesNotRequireRepeatedArrivalButExternalCargoStillDoes() {
|
||||
assertTrue(request("IN","ONT8",null,null).isInboundModeValid());
|
||||
assertFalse(request("IN",null,null,null).isInboundModeValid());
|
||||
assertFalse(request(null,null,null,null).isInboundModeValid());
|
||||
assertTrue(request(null,null,"CUSTOMER_DELIVERY",LocalDateTime.now()).isInboundModeValid());
|
||||
}
|
||||
@Test void originalBoxesIncludeBothSourcesButNeverAnotherCustomerWarehouseOrInbound() {
|
||||
var ds = new DriverManagerDataSource("jdbc:h2:mem:"+UUID.randomUUID()+";MODE=MySQL;DB_CLOSE_DELAY=-1","sa","");
|
||||
var db=new JdbcTemplate(ds);
|
||||
db.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR,inbound_code VARCHAR,overseas_warehouse_id VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_inbound_plan_carton(customer_id VARCHAR,order_id BIGINT,carton_mark VARCHAR,sku_code VARCHAR,destination_warehouse_code VARCHAR,destination_warehouse_name VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_order(id BIGINT,customer_id VARCHAR,lastleg_order_id BIGINT,operating_warehouse_id VARCHAR,destination_warehouse_code VARCHAR,destination_warehouse_name VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_item(id BIGINT,customer_id VARCHAR,transfer_order_id BIGINT,sku_code VARCHAR,product_name_zh VARCHAR)");
|
||||
db.execute("CREATE TABLE ll_warehouse_transfer_carton(customer_id VARCHAR,transfer_order_id BIGINT,transfer_item_id BIGINT,carton_mark VARCHAR,counted_quantity BIGINT,sku_items_json VARCHAR,status VARCHAR)");
|
||||
db.update("INSERT INTO ll_order VALUES(1,'A','IN','WH'),(2,'B','IN','WH'),(3,'A','IN','OTHER'),(4,'A','OTHER','WH')");
|
||||
db.update("INSERT INTO ll_inbound_plan_carton VALUES('A',1,'FIRST','S','ONT8','Amazon'),('B',2,'FOREIGN','S','ONT8','Amazon'),('A',3,'WRONG-WH','S','ONT8','Amazon'),('A',4,'WRONG-IN','S','ONT8','Amazon'),('B',1,'FORGED','S','ONT8','Amazon')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_order VALUES(10,'A',1,'WH','ONT8','Amazon')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_item VALUES(11,'A',10,'SKU','Product')");
|
||||
db.update("INSERT INTO ll_warehouse_transfer_carton VALUES('A',10,11,'MEASURED',20,NULL,'COUNTED'),('A',10,11,'EXPECTED',NULL,NULL,'EXPECTED'),('B',10,11,'FOREIGN2',20,NULL,'COUNTED')");
|
||||
var config=new Configuration(new Environment("test",new JdbcTransactionFactory(),ds)); config.addMapper(InboundSnapshotMapper.class);
|
||||
try(var session=new SqlSessionFactoryBuilder().build(config).openSession()) {
|
||||
var result=session.getMapper(InboundSnapshotMapper.class).sourceCartons("A","WH","IN");
|
||||
assertEquals(List.of("FIRST","MEASURED"),result.stream().map(InboundSnapshotMapper.SourceCarton::cartonMark).toList());
|
||||
assertEquals("ONT8",result.get(0).destinationWarehouseCode());
|
||||
assertNull(result.get(0).quantity()); assertEquals(20L,result.get(1).quantity());
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-42
@@ -203,9 +203,13 @@ class WarehouseTransferServiceTest {
|
||||
@Mock WarehouseTransferReceiptCoordinator receiptCoordinator;
|
||||
@Mock com.baiyue.lastleg.fleet.customer.FleetCustomerDirectory customerDirectory;
|
||||
|
||||
private com.baiyue.lastleg.service.CompactBusinessNumberService compactNumbers;
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
compactNumbers = org.mockito.Mockito.mock(com.baiyue.lastleg.service.CompactBusinessNumberService.class);
|
||||
service = new WarehouseTransferService();
|
||||
ReflectionTestUtils.setField(service, "compactNumbers", compactNumbers);
|
||||
org.mockito.Mockito.lenient().when(compactNumbers.next(org.mockito.ArgumentMatchers.anyString(), org.mockito.ArgumentMatchers.anyString())).thenAnswer(call -> call.getArgument(0) + "-CS-261016102030");
|
||||
ReflectionTestUtils.setField(service, "customerDirectory", customerDirectory);
|
||||
lenient().when(customerDirectory.find("TENANT-A")).thenReturn(
|
||||
new com.baiyue.lastleg.fleet.customer.FleetCustomerDirectory.Customer("TENANT-A", "C-A", "Customer A", null, null));
|
||||
@@ -416,7 +420,7 @@ class WarehouseTransferServiceTest {
|
||||
assertEquals("Customer A", tailOrder.getValue().getCustomerName());
|
||||
assertEquals(WarehouseTransferService.DRAFT, tailOrder.getValue().getCurrentStatus());
|
||||
assertEquals("WAREHOUSE_TRANSFER:DRAFT;RELABEL:PENDING_BINDING", tailOrder.getValue().getSubOrderStatus());
|
||||
assertTrue(tailOrder.getValue().getOrderNo().matches("WT-[0-9A-Z]{25}"));
|
||||
assertTrue(tailOrder.getValue().getOrderNo().matches("ZY-CS-[0-9]{12}"));
|
||||
assertNull(tailOrder.getValue().getTransferWarehouseId());
|
||||
verify(sourceOrders).insert(any(WarehouseTransferSourceOrder.class));
|
||||
verify(relabelApplications, never()).insert(any(RelabelApplication.class));
|
||||
@@ -461,10 +465,45 @@ class WarehouseTransferServiceTest {
|
||||
verifyNoInteractions(transfers);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transferRelabelRejectsUnknownAndForeignOrderCartonsBeforePersistence() {
|
||||
var request = new WarehouseTransferRequests.Create(
|
||||
"IN-1", List.of(11L), "WH-1", null, "FBA", null, "ONT8", null,
|
||||
null, null, null, null, null, null, null, 1,
|
||||
BigDecimal.ZERO, null, null, null, null, null, null, null, true,
|
||||
LocalDateTime.of(2026, 10, 16, 10, 0), "Contact", "123", null, "TRUCK",
|
||||
"carton-ownership", List.of(new WarehouseTransferRequests.Item("SKU-1", "Product", 1, null)),
|
||||
List.of(new WarehouseTransferRequests.RelabelItem("CARTON_LABEL", List.of("FOREIGN-BOX"), "SKU-1", null, 1, "FBA-1", "ONT8", null)));
|
||||
for (var cartons : List.of(List.<InboundSnapshotMapper.SourceCarton>of(),
|
||||
List.of(new InboundSnapshotMapper.SourceCarton("CURRENT-BOX", "SKU-1", null, null, null, null, null)))) {
|
||||
when(inboundSnapshots.sourceCartons("TENANT-A", "WH-1", "IN-1")).thenReturn(cartons);
|
||||
var error = assertThrows(ResponseStatusException.class, () -> service.create("TENANT-A", "USER-1", request));
|
||||
assertEquals("当前箱子不存在或不属于当前订单", error.getReason());
|
||||
}
|
||||
when(inboundSnapshots.sourceCartons("TENANT-A", "WH-1", "IN-1"))
|
||||
.thenReturn(List.of(new InboundSnapshotMapper.SourceCarton("FOREIGN-BOX", "SKU-1", null, null, null, null, null)));
|
||||
org.junit.jupiter.api.Assertions.assertDoesNotThrow(() ->
|
||||
ReflectionTestUtils.invokeMethod(service, "validateRelabelRequest", "TENANT-A", request));
|
||||
verifyNoInteractions(transfers);
|
||||
}
|
||||
|
||||
@Test
|
||||
void submittingOldDraftRechecksRelabelCartonOwnership() {
|
||||
var transfer = transfer(WarehouseTransferService.DRAFT);
|
||||
transfer.setNeedRelabel(true);
|
||||
when(transfers.lockNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
var binding = new com.baiyue.lastleg.transfer.entity.WarehouseTransferRelabelBinding();
|
||||
binding.setCustomerCartonMark("FOREIGN-BOX");
|
||||
when(relabelBindings.listOrder("TENANT-A", transfer.getId())).thenReturn(List.of(binding));
|
||||
var error = assertThrows(ResponseStatusException.class, () -> service.submit("TENANT-A", "WTR-1", "USER-1"));
|
||||
assertEquals("当前箱子不存在或不属于当前订单", error.getReason());
|
||||
verify(transfers, never()).updateById(any(WarehouseTransferOrder.class));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@NullSource
|
||||
@ValueSource(strings = {"NONE"})
|
||||
void transferWithoutDestinationCanBeCreatedAndSubmitted(String destinationType) {
|
||||
void inventoryTransferRequiresKnownDestination(String destinationType) {
|
||||
WarehouseTransferRequests.Create request = new WarehouseTransferRequests.Create(
|
||||
"IN-1", List.of(11L), "WH-1", null, destinationType, null, null, null,
|
||||
null, null, null, null, "123 Pickup Road", null, null, 5,
|
||||
@@ -473,53 +512,23 @@ class WarehouseTransferServiceTest {
|
||||
null, null, null, null, null, "key-no-fba",
|
||||
List.of(new WarehouseTransferRequests.Item("SKU-1", "Product", 5, "MARK-1")), null);
|
||||
|
||||
when(inboundSnapshots.findId("TENANT-A", "IN-1")).thenReturn(101L);
|
||||
when(orders.selectList(any())).thenReturn(List.of(historicalOrder()));
|
||||
WarehouseTransferOrder draft = transfer(WarehouseTransferService.DRAFT);
|
||||
draft.setFbaWarehouseCode(null);
|
||||
when(transfers.findNo(eq("TENANT-A"), anyString())).thenReturn(draft);
|
||||
when(transfers.lockNo("TENANT-A", "WTR-1")).thenReturn(draft);
|
||||
when(orders.selectById(draft.getLastlegOrderId())).thenReturn(tailOrder());
|
||||
when(transferItems.selectList(any())).thenReturn(List.of());
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
|
||||
service.create("TENANT-A", "USER-1", request);
|
||||
var result = service.submit("TENANT-A", "WTR-1", "USER-1");
|
||||
|
||||
ArgumentCaptor<WarehouseTransferOrder> created = ArgumentCaptor.forClass(WarehouseTransferOrder.class);
|
||||
verify(transfers).insert(created.capture());
|
||||
assertNull(created.getValue().getDestinationType());
|
||||
assertNull(created.getValue().getFbaWarehouseCode());
|
||||
assertEquals(WarehouseTransferService.PENDING_REVIEW, result.status());
|
||||
verify(relabelApplications, never()).insert(any(RelabelApplication.class));
|
||||
var error = assertThrows(ResponseStatusException.class, () -> service.create("TENANT-A","USER-1",request));
|
||||
assertEquals(400,error.getStatusCode().value());
|
||||
verifyNoInteractions(transfers,orders);
|
||||
}
|
||||
|
||||
@Test
|
||||
void merchantCanClearDestinationWhenEditingDraft() {
|
||||
WarehouseTransferOrder transfer = transfer(WarehouseTransferService.DRAFT);
|
||||
transfer.setDestinationType("FBA");
|
||||
transfer.setDestinationWarehouseCode("ONT8");
|
||||
LastlegOrder order = tailOrder();
|
||||
when(transfers.lockNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
when(transfers.findNo("TENANT-A", "WTR-1")).thenReturn(transfer);
|
||||
when(orders.selectById(transfer.getLastlegOrderId())).thenReturn(order);
|
||||
when(transferItems.selectList(any())).thenReturn(List.of());
|
||||
when(sourceOrders.selectList(any())).thenReturn(List.of());
|
||||
void inventoryDraftCannotClearDestination() {
|
||||
var transfer = transfer(WarehouseTransferService.DRAFT);
|
||||
when(transfers.lockNo("TENANT-A","WTR-1")).thenReturn(transfer);
|
||||
WarehouseTransferRequests.Create request = new WarehouseTransferRequests.Create(
|
||||
"IN-1", List.of(11L), "WH-1", null, "NONE", null, null, null,
|
||||
null, null, null, null, "123 Pickup Road", null, null, 5,
|
||||
new BigDecimal("0.2500"), "WAREHOUSE_PICKUP", LocalDateTime.of(2026, 9, 12, 10, 0),
|
||||
null, null, null, null, null, false, null, null, null, null, null, "edit-no-fba",
|
||||
List.of(new WarehouseTransferRequests.Item("SKU-1", "Product", 5, "MARK-1")), null);
|
||||
|
||||
var result = service.updateDraft("TENANT-A", "WTR-1", "USER-1", request);
|
||||
|
||||
assertEquals(WarehouseTransferService.DRAFT, result.status());
|
||||
assertNull(transfer.getDestinationType());
|
||||
assertNull(transfer.getDestinationWarehouseCode());
|
||||
assertNull(transfer.getFbaWarehouseCode());
|
||||
assertNull(order.getFbaWarehouseCode());
|
||||
verify(transfers).updateById(transfer);
|
||||
assertThrows(ResponseStatusException.class, () -> service.updateDraft("TENANT-A","WTR-1","USER-1",request));
|
||||
verify(transfers, never()).updateById(any(WarehouseTransferOrder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -544,7 +553,8 @@ class WarehouseTransferServiceTest {
|
||||
assertEquals("ONT8", transfer.getValue().getFbaWarehouseCode());
|
||||
assertNull(transfer.getValue().getFbaShipmentNo());
|
||||
assertEquals("ONT8", tailOrder.getValue().getFbaWarehouseCode());
|
||||
assertEquals("WAREHOUSE_PICKUP", transfer.getValue().getDeliveryMethod());
|
||||
assertEquals("INVENTORY_TRANSFER", transfer.getValue().getDeliveryMethod());
|
||||
assertNull(transfer.getValue().getEstimatedArrivalAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -620,7 +630,7 @@ class WarehouseTransferServiceTest {
|
||||
assertEquals(List.of(1, 2, 3, 4, 5), cartons.getAllValues().stream()
|
||||
.map(WarehouseTransferCarton::getCartonIndex).toList());
|
||||
assertTrue(cartons.getAllValues().stream().allMatch(value -> value.getCartonMark()
|
||||
.matches("WT-[0-9A-Z]{25}#5-[1-5]")));
|
||||
.matches("BX-[0-9A-Z]+")));
|
||||
when(transfers.findKey("TENANT-A", request.idempotencyKey())).thenReturn(transfer.getValue());
|
||||
clearInvocations(customerDirectory, orders, inboundOrders);
|
||||
service.create("TENANT-A", "USER-1", request);
|
||||
|
||||
Reference in New Issue
Block a user