feat(lastleg): redispatch returned cargo and reconcile source signatures
This commit is contained in:
+1
-1
@@ -54,7 +54,7 @@ class SmartDispatchControllerTest {
|
||||
void preArrangeResolvesSingleCustomerAndAuthenticatedOperator() {
|
||||
DispatchRequests.PreArrange request = new DispatchRequests.PreArrange(
|
||||
List.of(10L, 11L), "APT-1", "SUCCESS", "PENDING");
|
||||
when(service.resolveCustomerScopeForPallets(List.of(10L, 11L))).thenReturn("100");
|
||||
when(service.resolveCustomerScopeForSources(List.of(10L, 11L), List.of())).thenReturn("100");
|
||||
|
||||
controller.preArrange(platform(), request);
|
||||
|
||||
|
||||
+48
@@ -32,6 +32,7 @@ class DispatchPickOrderAttributionServiceTest {
|
||||
@Mock private DispatchPdaPickOrderMapper attributions;
|
||||
@Mock private LastlegOrderMapper orders;
|
||||
@Mock private LastlegOrderStatusHistoryMapper history;
|
||||
@Mock private com.baiyue.lastleg.inventory.mapper.ReturnStockReceiptMapper returnReceipts;
|
||||
|
||||
@Test
|
||||
void completionStatusIsCalculatedBeforeMysqlMutatesShippedPackages() throws NoSuchMethodException {
|
||||
@@ -108,11 +109,58 @@ class DispatchPickOrderAttributionServiceTest {
|
||||
verify(orders,never()).increasePicked(anyString(),anyLong(),anyLong());
|
||||
}
|
||||
|
||||
@Test void returnedTwoPackagesHaveTheirOwnReceiptAttributionAndRejectExcess() {
|
||||
var receipt = new com.baiyue.lastleg.inventory.entity.ReturnStockReceipt();
|
||||
receipt.setId(201L); receipt.setOrderId(101L); receipt.setReceivedPackages(2L);
|
||||
when(returnReceipts.available("t1", 91L)).thenReturn(List.of(receipt));
|
||||
when(returnReceipts.lock("t1", 201L)).thenReturn(receipt);
|
||||
when(orders.increasePicked("t1", 101L, 2L)).thenReturn(1);
|
||||
var service = service();
|
||||
assertEquals(List.of(new DispatchPickOrderAttributionService.OrderPackages(101L, 2L)),
|
||||
service.attribute("t1", pick(81L, 91L, 2L, 0L), null, 201L));
|
||||
var capture = ArgumentCaptor.forClass(DispatchPdaPickOrder.class);
|
||||
verify(attributions).insert(capture.capture());
|
||||
assertEquals(201L, capture.getValue().getReturnReceiptId()); assertEquals(null, capture.getValue().getReceiptId());
|
||||
when(returnReceipts.picked("t1", 201L)).thenReturn(2L);
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
() -> service.attribute("t1", pick(82L, 91L, 1L, 0L), null, 201L));
|
||||
}
|
||||
|
||||
@Test void selectedReturnCannotUseFallbackOrLeavePartialAttributionWhenOnlyTwoOfThreeAreAvailable() {
|
||||
var receipt = new com.baiyue.lastleg.inventory.entity.ReturnStockReceipt();
|
||||
receipt.setId(201L); receipt.setOrderId(101L); receipt.setReceivedPackages(2L);
|
||||
when(returnReceipts.available("t1", 91L)).thenReturn(List.of(receipt));
|
||||
when(returnReceipts.lock("t1", 201L)).thenReturn(receipt);
|
||||
assertThrows(org.springframework.web.server.ResponseStatusException.class,
|
||||
() -> service().attribute("t1", pick(81L, 91L, 3L, 0L), 101L, 201L));
|
||||
verify(attributions, never()).insert(any(DispatchPdaPickOrder.class));
|
||||
verify(orders, never()).increasePicked(anyString(), anyLong(), anyLong());
|
||||
verify(attributions, never()).availableReceipts(anyString(), anyLong());
|
||||
}
|
||||
|
||||
@Test void departureLocksSourceOrdersInNumericOrderInsteadOfPickOrder() {
|
||||
var high = new DispatchPdaPickOrder(); high.setOrderId(10L); high.setPackages(1L);
|
||||
var low = new DispatchPdaPickOrder(); low.setOrderId(2L); low.setPackages(1L);
|
||||
when(attributions.listPick("t1", 81L)).thenReturn(List.of(high, low));
|
||||
for (long id : List.of(2L, 10L)) {
|
||||
var order = new LastlegOrder(); order.setId(id); order.setPackageCount(1);
|
||||
order.setPickedPackageCount(1); order.setShippedPackageCount(0);
|
||||
when(orders.lockById("t1", id)).thenReturn(order);
|
||||
when(orders.transferPickedToShipped("t1", id, 1L, "OUT1")).thenReturn(1);
|
||||
when(orders.markDispatchOutbound("t1", id)).thenReturn(1);
|
||||
}
|
||||
service().depart("t1", "OUT1", "DP1", List.of(pick(81L, 91L, 2L, 0L)), LocalDateTime.now());
|
||||
var sequence = inOrder(orders);
|
||||
sequence.verify(orders).lockById("t1", 2L);
|
||||
sequence.verify(orders).lockById("t1", 10L);
|
||||
}
|
||||
|
||||
private DispatchPickOrderAttributionService service() {
|
||||
DispatchPickOrderAttributionService service = new DispatchPickOrderAttributionService();
|
||||
ReflectionTestUtils.setField(service, "attributions", attributions);
|
||||
ReflectionTestUtils.setField(service, "orders", orders);
|
||||
ReflectionTestUtils.setField(service, "history", history);
|
||||
ReflectionTestUtils.setField(service, "returnReceipts", returnReceipts);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.baiyue.lastleg.dispatch.pda.service;
|
||||
|
||||
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class ReturnedDispatchAllowancePersistenceTest {
|
||||
@Test void realSqlAllowsOnlyTwoReturnedPackagesToDepartAgainWithoutRewritingOriginalTotals() throws Exception {
|
||||
var db = database(); var named = new NamedParameterJdbcTemplate(db.getDataSource());
|
||||
String pick = sql("increasePicked", String.class, Long.class, long.class);
|
||||
String depart = sql("transferPickedToShipped", String.class, Long.class, long.class, String.class);
|
||||
var args = Map.<String,Object>of("customerId", "A", "id", 1L, "packages", 2L, "outboundNo", "OUT-NEW");
|
||||
assertThat(named.update(pick, args)).isZero();
|
||||
db.update("INSERT INTO ll_return_stock_receipt VALUES(10,'A',1,100,2)");
|
||||
assertThat(named.update(pick, args)).isEqualTo(1);
|
||||
assertThat(named.update(pick, args)).isZero();
|
||||
assertThat(named.update(depart, args)).isEqualTo(1);
|
||||
assertThat(named.update(depart, args)).isZero();
|
||||
assertThat(db.queryForObject("SELECT package_count FROM ll_order WHERE id=1", Integer.class)).isEqualTo(2);
|
||||
assertThat(db.queryForObject("SELECT shipped_package_count FROM ll_order WHERE id=1", Integer.class)).isEqualTo(4);
|
||||
assertThat(db.queryForObject("SELECT picked_package_count FROM ll_order WHERE id=1", Integer.class)).isZero();
|
||||
assertThatThrownBy(() -> db.update("INSERT INTO ll_return_stock_receipt VALUES(11,'A',1,100,2)"))
|
||||
.isInstanceOf(org.springframework.dao.DuplicateKeyException.class);
|
||||
assertThat(named.update(pick, Map.of("customerId", "OTHER", "id", 1L, "packages", 1L))).isZero();
|
||||
}
|
||||
|
||||
@Test void concurrentRedispatchPicksCannotSpendTheSameReturnTwice() throws Exception {
|
||||
var db = database(); db.update("INSERT INTO ll_return_stock_receipt VALUES(10,'A',1,100,2)");
|
||||
var tx = new TransactionTemplate(new DataSourceTransactionManager(db.getDataSource()));
|
||||
var named = new NamedParameterJdbcTemplate(db.getDataSource());
|
||||
String pick = sql("increasePicked", String.class, Long.class, long.class);
|
||||
var start = new CountDownLatch(1); var pool = Executors.newFixedThreadPool(2);
|
||||
Callable<Integer> attempt = () -> {
|
||||
start.await();
|
||||
return tx.execute(status -> {
|
||||
db.queryForObject("SELECT id FROM ll_order WHERE customer_id='A' AND id=1 FOR UPDATE", Long.class);
|
||||
db.queryForObject("SELECT id FROM ll_return_stock_receipt WHERE customer_id='A' AND id=10 FOR UPDATE", Long.class);
|
||||
return named.update(pick, Map.of("customerId", "A", "id", 1L, "packages", 2L));
|
||||
});
|
||||
};
|
||||
try {
|
||||
var a = pool.submit(attempt); var b = pool.submit(attempt); start.countDown();
|
||||
assertThat(a.get(5, TimeUnit.SECONDS) + b.get(5, TimeUnit.SECONDS)).isEqualTo(1);
|
||||
assertThat(db.queryForObject("SELECT picked_package_count FROM ll_order WHERE id=1", Integer.class)).isEqualTo(2);
|
||||
} finally { pool.shutdownNow(); }
|
||||
}
|
||||
private JdbcTemplate database() {
|
||||
var db = new JdbcTemplate(new DriverManagerDataSource("jdbc:h2:mem:"+UUID.randomUUID()+";MODE=MySQL;DB_CLOSE_DELAY=-1;LOCK_TIMEOUT=5000", "sa", ""));
|
||||
db.execute("CREATE TABLE ll_order(id BIGINT PRIMARY KEY, customer_id VARCHAR(20), package_count INT,shipped_package_count INT,picked_package_count INT,detained INT,current_status VARCHAR(40),outbound_order_no VARCHAR(50),updated_at TIMESTAMP)");
|
||||
db.execute("CREATE TABLE ll_return_stock_receipt(id BIGINT PRIMARY KEY,customer_id VARCHAR(20),order_id BIGINT,inventory_ledger_id BIGINT,received_packages BIGINT,UNIQUE(customer_id,inventory_ledger_id))");
|
||||
db.update("INSERT INTO ll_order(id,customer_id,package_count,shipped_package_count,picked_package_count,detained,current_status) VALUES(1,'A',2,2,0,0,'COMPLETED')");
|
||||
return db;
|
||||
}
|
||||
private String sql(String name, Class<?>... args) throws Exception {
|
||||
return String.join(" ", LastlegOrderMapper.class.getMethod(name,args).getAnnotation(Update.class).value())
|
||||
.replace("#{customerId}", ":customerId").replace("#{id}", ":id").replace("#{packages}", ":packages").replace("#{outboundNo}", ":outboundNo");
|
||||
}
|
||||
}
|
||||
+54
@@ -37,6 +37,7 @@ import java.util.List;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
@@ -55,6 +56,7 @@ class DispatchServiceTest {
|
||||
@Mock DispatchBolMapper bolLines;
|
||||
@Mock DispatchPalletLockMapper locks;
|
||||
@Mock DispatchCandidateMapper candidates;
|
||||
@Mock com.baiyue.lastleg.dispatch.mapper.ReturnDispatchCandidateMapper returnCandidates;
|
||||
@Mock DispatchDraftMapper drafts;
|
||||
@Mock DispatchDraftContainerMapper draftContainers;
|
||||
@Mock DispatchPdaTaskMapper pdaTasks;
|
||||
@@ -72,6 +74,7 @@ class DispatchServiceTest {
|
||||
ReflectionTestUtils.setField(service, "bolLines", bolLines);
|
||||
ReflectionTestUtils.setField(service, "locks", locks);
|
||||
ReflectionTestUtils.setField(service, "candidates", candidates);
|
||||
ReflectionTestUtils.setField(service, "returnCandidates", returnCandidates);
|
||||
ReflectionTestUtils.setField(service, "drafts", drafts);
|
||||
ReflectionTestUtils.setField(service, "draftContainers", draftContainers);
|
||||
ReflectionTestUtils.setField(service, "pdaTasks", pdaTasks);
|
||||
@@ -497,6 +500,57 @@ class DispatchServiceTest {
|
||||
assertEquals("PLAN:11", plannedOnly.sourcePalletKey());
|
||||
}
|
||||
|
||||
@Test void returnedReceiptPreArrangementUsesItsOwnReferenceAndTheRealTargetPalletLock() throws Exception {
|
||||
var candidate = candidate(10L, 900L, "ONT8", 2);
|
||||
candidate.planId(null); candidate.planPalletId(null); candidate.returnReceiptId(701L); candidate.returnReceiptNo("RSR-701");
|
||||
when(returnCandidates.lockSelected("100", List.of(701L))).thenReturn(List.of(candidate));
|
||||
service.preArrange("100", "7", new DispatchRequests.PreArrange(List.of(), null, null, null, null, null, List.of(701L)));
|
||||
var item = ArgumentCaptor.forClass(DispatchItem.class); verify(items).insert(item.capture());
|
||||
assertEquals(null, item.getValue().getPlanPalletId()); assertEquals(701L, item.getValue().getReturnReceiptId());
|
||||
assertEquals(2, item.getValue().getPackageCount());
|
||||
var lock = ArgumentCaptor.forClass(DispatchPalletLock.class); verify(locks).insert(lock.capture());
|
||||
assertEquals("RECEIVED:900", lock.getValue().getActiveKey()); assertEquals(701L, lock.getValue().getReturnReceiptId());
|
||||
verify(candidates, never()).lockSelected(any(), any());
|
||||
var json = new com.fasterxml.jackson.databind.ObjectMapper().valueToTree(candidate);
|
||||
assertEquals("RETURN_RECEIPT", json.path("sourceType").asText());
|
||||
assertEquals("RSR-701", json.path("returnReceiptNo").asText()); assertTrue(json.path("planPalletId").isNull());
|
||||
}
|
||||
|
||||
@Test void plannedAndReturnedSourcesCreateOneDispatchWithBothReferencesAndTheirExactQuantities() {
|
||||
var planned = candidate(10L, 900L, "ONT8", 3);
|
||||
var returned = candidate(11L, 901L, "ONT8", 2);
|
||||
returned.planId(null); returned.planPalletId(null); returned.returnReceiptId(701L); returned.returnReceiptNo("RSR-701");
|
||||
when(candidates.lockSelected("100", List.of(10L))).thenReturn(List.of(planned));
|
||||
when(returnCandidates.lockSelected("100", List.of(701L))).thenReturn(List.of(returned));
|
||||
service.preArrange("100", "7", new DispatchRequests.PreArrange(List.of(10L), null, null, null, null, null, List.of(701L)));
|
||||
var dispatch = ArgumentCaptor.forClass(DispatchOrder.class); verify(orders).insert(dispatch.capture());
|
||||
assertEquals(5, dispatch.getValue().getPackageCount()); assertEquals(2, dispatch.getValue().getPalletCount());
|
||||
var inserted = ArgumentCaptor.forClass(DispatchItem.class);
|
||||
verify(items, org.mockito.Mockito.times(2)).insert(inserted.capture());
|
||||
var normalItem = inserted.getAllValues().stream().filter(row -> row.getReturnReceiptId() == null).findFirst().orElseThrow();
|
||||
var returnItem = inserted.getAllValues().stream().filter(row -> row.getReturnReceiptId() != null).findFirst().orElseThrow();
|
||||
assertEquals(10L, normalItem.getPlanPalletId()); assertEquals(3, normalItem.getPackageCount());
|
||||
assertEquals(null, returnItem.getPlanPalletId()); assertEquals(701L, returnItem.getReturnReceiptId()); assertEquals(2, returnItem.getPackageCount());
|
||||
assertEquals(normalItem.getDispatchOrderId(), returnItem.getDispatchOrderId());
|
||||
var lock = ArgumentCaptor.forClass(DispatchPalletLock.class);
|
||||
verify(locks, org.mockito.Mockito.times(2)).insert(lock.capture());
|
||||
assertEquals(java.util.Set.of("RECEIVED:900", "RECEIVED:901"), lock.getAllValues().stream()
|
||||
.map(DispatchPalletLock::getActiveKey).collect(java.util.stream.Collectors.toSet()));
|
||||
}
|
||||
|
||||
@Test void mixedSourcesOnTheSamePhysicalPalletAreRejectedBeforeAnyDispatchOrLockWrite() {
|
||||
var planned = candidate(10L, 900L, "ONT8", 3);
|
||||
var returned = candidate(11L, 900L, "ONT8", 2);
|
||||
returned.planId(null); returned.planPalletId(null); returned.returnReceiptId(701L); returned.returnReceiptNo("RSR-701");
|
||||
when(candidates.lockSelected("100", List.of(10L))).thenReturn(List.of(planned));
|
||||
when(returnCandidates.lockSelected("100", List.of(701L))).thenReturn(List.of(returned));
|
||||
var failure = assertThrows(ResponseStatusException.class, () -> service.preArrange("100", "7",
|
||||
new DispatchRequests.PreArrange(List.of(10L), null, null, null, null, null, List.of(701L))));
|
||||
assertEquals(409, failure.getStatusCode().value()); assertTrue(failure.getReason().contains("同一实物托盘"));
|
||||
verify(orders, never()).insert(any(DispatchOrder.class)); verify(items, never()).insert(any(DispatchItem.class));
|
||||
verify(locks, never()).insert(any(DispatchPalletLock.class)); verify(pdaTasks, never()).insert(any(DispatchPdaTask.class));
|
||||
}
|
||||
|
||||
private DispatchPalletCandidate candidate(long planPalletId, Long warehousePalletId, String destination) {
|
||||
return candidate(planPalletId, warehousePalletId, destination, 12);
|
||||
}
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.baiyue.lastleg.dispatch.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import com.baiyue.lastleg.dispatch.mapper.ReturnDispatchCandidateMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
class ReturnDispatchCandidatePersistenceTest {
|
||||
@Test void actualReturnOnANewPalletCanBeSelectedWithoutAnInboundPlanPallet() throws Exception {
|
||||
var data = new DriverManagerDataSource("jdbc:h2:mem:"+UUID.randomUUID()+";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
||||
var db = new JdbcTemplate(data);
|
||||
db.execute("CREATE TABLE ll_return_stock_receipt(id BIGINT,receipt_no VARCHAR(50),customer_id VARCHAR(20),order_id BIGINT,inventory_position_id BIGINT,inventory_balance_id BIGINT,exception_order_id BIGINT,received_packages BIGINT,received_at TIMESTAMP)");
|
||||
db.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR(20),customer_name VARCHAR(50),order_type VARCHAR(50),order_no VARCHAR(50),detained INT)");
|
||||
db.execute("CREATE TABLE ll_inventory_position(id BIGINT,customer_id VARCHAR(20),pallet_id BIGINT,pallet_no VARCHAR(50),overseas_warehouse_id VARCHAR(50),available_packages BIGINT)");
|
||||
db.execute("CREATE TABLE ll_inventory_balance(id BIGINT,customer_id VARCHAR(20),inbound_code VARCHAR(50),overseas_warehouse_name VARCHAR(50),overseas_warehouse_code VARCHAR(50))");
|
||||
db.execute("CREATE TABLE ll_exception_order(id BIGINT,customer_id VARCHAR(20),delivery_order_id BIGINT)");
|
||||
db.execute("CREATE TABLE ll_delivery_order(id BIGINT,customer_id VARCHAR(20),destination_type VARCHAR(20),destination_warehouse_code VARCHAR(50),destination_warehouse_name VARCHAR(50),delivery_address VARCHAR(100),postal_code VARCHAR(50),contact_name VARCHAR(50),contact_phone VARCHAR(50))");
|
||||
db.execute("CREATE TABLE ll_dispatch_pda_pick_order(customer_id VARCHAR(20),return_receipt_id BIGINT,packages BIGINT)");
|
||||
db.execute("CREATE TABLE ll_dispatch_pallet_lock(customer_id VARCHAR(20),source_pallet_key VARCHAR(50),status VARCHAR(20),expires_at TIMESTAMP,draft_token VARCHAR(50))");
|
||||
db.update("INSERT INTO ll_order VALUES(1,'A','客户A','FIRST_LEG','LM-1',0)");
|
||||
db.update("INSERT INTO ll_inventory_position VALUES(2,'A',900,'RETURN-PALLET','92',2)");
|
||||
db.update("INSERT INTO ll_inventory_balance VALUES(3,'A','IN-1','海外仓','WH')");
|
||||
db.update("INSERT INTO ll_exception_order VALUES(4,'A',5)");
|
||||
db.update("INSERT INTO ll_delivery_order VALUES(5,'A','FBA','ONT8','ONT8',NULL,NULL,NULL,NULL)");
|
||||
db.update("INSERT INTO ll_return_stock_receipt VALUES(6,'RSR-6','A',1,2,3,4,2,CURRENT_TIMESTAMP)");
|
||||
var config = new MybatisConfiguration(); config.addMapper(ReturnDispatchCandidateMapper.class);
|
||||
var factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(data); factory.setConfiguration(config);
|
||||
var mapper = new SqlSessionTemplate(factory.getObject()).getMapper(ReturnDispatchCandidateMapper.class);
|
||||
var rows = mapper.available("A", "RSR-6", "ONT8", null);
|
||||
assertThat(rows).hasSize(1); var row = rows.get(0);
|
||||
assertThat(row.packageCount()).isEqualTo(2); assertThat(row.planPalletId()).isNull();
|
||||
assertThat(row.sourceType()).isEqualTo("RETURN_RECEIPT"); assertThat(row.returnReceiptNo()).isEqualTo("RSR-6");
|
||||
assertThat(row.warehousePalletId()).isEqualTo(900); assertThat(row.grossWeightKg()).isNull();
|
||||
assertThat(mapper.lockSelected("A", List.of(6L))).hasSize(1);
|
||||
assertThat(mapper.lockSelected("B", List.of(6L))).isEmpty();
|
||||
db.update("INSERT INTO ll_dispatch_pallet_lock VALUES('A','RECEIVED:900','ACTIVE',NULL,'another-draft')");
|
||||
assertThat(mapper.available("A", null, null, "this-draft")).isEmpty();
|
||||
db.update("DELETE FROM ll_dispatch_pallet_lock");
|
||||
db.update("INSERT INTO ll_dispatch_pda_pick_order VALUES('A',6,1)");
|
||||
// Even if the position also has unrelated available stock, this receipt contributes only its unspent one box.
|
||||
db.update("UPDATE ll_inventory_position SET available_packages=8 WHERE id=2");
|
||||
var partial = mapper.available("A", null, null, null);
|
||||
assertThat(partial).hasSize(1); assertThat(partial.get(0).packageCount()).isEqualTo(1);
|
||||
assertThat(mapper.lockSelected("A", List.of(6L)).get(0).packageCount()).isEqualTo(1);
|
||||
db.update("INSERT INTO ll_dispatch_pda_pick_order VALUES('A',6,1)");
|
||||
assertThat(mapper.available("A", null, null, null)).isEmpty();
|
||||
assertThat(mapper.lockSelected("A", List.of(6L))).isEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user