fix(lastleg): return persisted grouped dispatch replay facts
This commit is contained in:
+6
-1
@@ -556,7 +556,12 @@ public class DispatchService {
|
|||||||
drafts.updateById(draft);
|
drafts.updateById(draft);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response(dispatch, items.findByDispatchOrder(customerId, dispatch.getId()));
|
// Exact grouped replay must return the same persisted timestamp precision
|
||||||
|
// on the initial call as on later reads from DATETIME(3).
|
||||||
|
DispatchOrder responseOrder = preserveExactReplay
|
||||||
|
? Objects.requireNonNull(orders.lockById(customerId, dispatch.getId()), "Saved dispatch is missing")
|
||||||
|
: dispatch;
|
||||||
|
return response(responseOrder, items.findByDispatchOrder(customerId, dispatch.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
+28
-4
@@ -584,6 +584,14 @@ class DispatchServiceTest {
|
|||||||
verify(orders, never()).insert(any(DispatchOrder.class));
|
verify(orders, never()).insert(any(DispatchOrder.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void groupedInitialResponseUsesPersistedTimestampPrecisionForExactReplay() {
|
||||||
|
var fixture = twoGroupFixture(true);
|
||||||
|
var first = service.preArrangeDraft("7", fixture.request());
|
||||||
|
assertEquals(123_000_000, first.get(0).dispatch().createdAt().getNano());
|
||||||
|
assertEquals(first, service.preArrangeDraft("7", fixture.request()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void changedMembershipDuplicateSourceExpiredDraftAndCapacityFailBeforeCreatingAnyGroup() {
|
void changedMembershipDuplicateSourceExpiredDraftAndCapacityFailBeforeCreatingAnyGroup() {
|
||||||
var fixture = twoGroupFixture();
|
var fixture = twoGroupFixture();
|
||||||
@@ -613,7 +621,8 @@ class DispatchServiceTest {
|
|||||||
var jdbc = new org.springframework.jdbc.core.JdbcTemplate(ds);
|
var jdbc = new org.springframework.jdbc.core.JdbcTemplate(ds);
|
||||||
jdbc.execute("CREATE TABLE dispatch_probe(id BIGINT PRIMARY KEY)");
|
jdbc.execute("CREATE TABLE dispatch_probe(id BIGINT PRIMARY KEY)");
|
||||||
org.mockito.Mockito.doAnswer(call -> { var row=(DispatchOrder)call.getArgument(0);
|
org.mockito.Mockito.doAnswer(call -> { var row=(DispatchOrder)call.getArgument(0);
|
||||||
jdbc.update("INSERT INTO dispatch_probe VALUES(?)",row.getId());return 1; }).when(orders).insert(any(DispatchOrder.class));
|
jdbc.update("INSERT INTO dispatch_probe VALUES(?)",row.getId());
|
||||||
|
fixture.savedOrders().put(row.getId(), row);return 1; }).when(orders).insert(any(DispatchOrder.class));
|
||||||
var transaction = new org.springframework.transaction.support.TransactionTemplate(
|
var transaction = new org.springframework.transaction.support.TransactionTemplate(
|
||||||
new org.springframework.jdbc.datasource.DataSourceTransactionManager(ds));
|
new org.springframework.jdbc.datasource.DataSourceTransactionManager(ds));
|
||||||
assertThrows(ResponseStatusException.class, () -> transaction.execute(status -> service.preArrangeDraft("7",fixture.request())));
|
assertThrows(ResponseStatusException.class, () -> transaction.execute(status -> service.preArrangeDraft("7",fixture.request())));
|
||||||
@@ -622,6 +631,10 @@ class DispatchServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private GroupFixture twoGroupFixture() {
|
private GroupFixture twoGroupFixture() {
|
||||||
|
return twoGroupFixture(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GroupFixture twoGroupFixture(boolean databaseTimestampPrecision) {
|
||||||
var draft = new DispatchDraft(); draft.setId(1L);draft.setDraftToken("draft-multi");draft.setOperatorId("7");
|
var draft = new DispatchDraft(); draft.setId(1L);draft.setDraftToken("draft-multi");draft.setOperatorId("7");
|
||||||
draft.setStatus("ACTIVE");draft.setExpiresAt(LocalDateTime.now().plusMinutes(30));
|
draft.setStatus("ACTIVE");draft.setExpiresAt(LocalDateTime.now().plusMinutes(30));
|
||||||
lenient().when(drafts.lockActive("draft-multi","7")).thenReturn(draft);
|
lenient().when(drafts.lockActive("draft-multi","7")).thenReturn(draft);
|
||||||
@@ -629,7 +642,17 @@ class DispatchServiceTest {
|
|||||||
var allCandidates = new java.util.ArrayList<DispatchPalletCandidate>();
|
var allCandidates = new java.util.ArrayList<DispatchPalletCandidate>();
|
||||||
var savedOrders = new java.util.HashMap<Long,DispatchOrder>();
|
var savedOrders = new java.util.HashMap<Long,DispatchOrder>();
|
||||||
var savedItems = new java.util.HashMap<Long,java.util.ArrayList<DispatchItem>>();
|
var savedItems = new java.util.HashMap<Long,java.util.ArrayList<DispatchItem>>();
|
||||||
lenient().doAnswer(call -> {var row=(DispatchOrder)call.getArgument(0);savedOrders.put(row.getId(),row);return 1;})
|
lenient().doAnswer(call -> {
|
||||||
|
var row=(DispatchOrder)call.getArgument(0);
|
||||||
|
if (databaseTimestampPrecision) {
|
||||||
|
row.setCreatedAt(row.getCreatedAt().withNano(123_456_000));
|
||||||
|
var persisted = new DispatchOrder();
|
||||||
|
org.springframework.beans.BeanUtils.copyProperties(row, persisted);
|
||||||
|
persisted.setCreatedAt(row.getCreatedAt().withNano(123_000_000));
|
||||||
|
savedOrders.put(row.getId(), persisted);
|
||||||
|
} else savedOrders.put(row.getId(),row);
|
||||||
|
return 1;
|
||||||
|
})
|
||||||
.when(orders).insert(any(DispatchOrder.class));
|
.when(orders).insert(any(DispatchOrder.class));
|
||||||
lenient().when(orders.lockById(eq("100"),any())).thenAnswer(call -> savedOrders.get(call.getArgument(1)));
|
lenient().when(orders.lockById(eq("100"),any())).thenAnswer(call -> savedOrders.get(call.getArgument(1)));
|
||||||
lenient().doAnswer(call -> {var row=(DispatchItem)call.getArgument(0);savedItems.computeIfAbsent(row.getDispatchOrderId(),k->new java.util.ArrayList<>()).add(row);return 1;})
|
lenient().doAnswer(call -> {var row=(DispatchItem)call.getArgument(0);savedItems.computeIfAbsent(row.getDispatchOrderId(),k->new java.util.ArrayList<>()).add(row);return 1;})
|
||||||
@@ -651,11 +674,12 @@ class DispatchServiceTest {
|
|||||||
}
|
}
|
||||||
lenient().when(draftContainers.findByToken("draft-multi")).thenReturn(containerList);
|
lenient().when(draftContainers.findByToken("draft-multi")).thenReturn(containerList);
|
||||||
return new GroupFixture(draft,containerList,allCandidates,new DispatchRequests.PreArrangeDraft("draft-multi",List.of(
|
return new GroupFixture(draft,containerList,allCandidates,new DispatchRequests.PreArrangeDraft("draft-multi",List.of(
|
||||||
new DispatchRequests.DraftGroup(21L,List.of(10L,11L),List.of()),new DispatchRequests.DraftGroup(22L,List.of(12L,13L),List.of()))));
|
new DispatchRequests.DraftGroup(21L,List.of(10L,11L),List.of()),new DispatchRequests.DraftGroup(22L,List.of(12L,13L),List.of()))),savedOrders);
|
||||||
}
|
}
|
||||||
|
|
||||||
private record GroupFixture(DispatchDraft draft,List<DispatchDraftContainer> containers,
|
private record GroupFixture(DispatchDraft draft,List<DispatchDraftContainer> containers,
|
||||||
List<DispatchPalletCandidate> candidates,DispatchRequests.PreArrangeDraft request) { }
|
List<DispatchPalletCandidate> candidates,DispatchRequests.PreArrangeDraft request,
|
||||||
|
java.util.Map<Long, DispatchOrder> savedOrders) { }
|
||||||
|
|
||||||
private DispatchPalletCandidate candidate(long planPalletId, Long warehousePalletId, String destination) {
|
private DispatchPalletCandidate candidate(long planPalletId, Long warehousePalletId, String destination) {
|
||||||
return candidate(planPalletId, warehousePalletId, destination, 12);
|
return candidate(planPalletId, warehousePalletId, destination, 12);
|
||||||
|
|||||||
Reference in New Issue
Block a user