fix(firstleg): allow audited carrier node time corrections
This commit is contained in:
+3
@@ -24,6 +24,9 @@ class CarrierScheduleQueryOpenApiContractTest {
|
||||
.contains("enum: [READY, MANUAL_REQUIRED, STOPPED]")
|
||||
.contains("latestActualNode:")
|
||||
.contains("latestActualAt:")
|
||||
.contains("current latestActualNode may append an audited correction fact")
|
||||
.contains("replace latestActualAt")
|
||||
.contains("cannot be earlier")
|
||||
.contains("internal execution fields are intentionally absent")
|
||||
.doesNotContain("enum: [READY, MANUAL_REQUIRED, ARRIVED")
|
||||
.doesNotContain("/{queryId}/attempts:")
|
||||
|
||||
+46
@@ -292,6 +292,52 @@ class CarrierScheduleQueryServiceTest {
|
||||
verify(repository).completeOperation(eq(1L), eq(7L), eq("manual-empty-1"), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void manualActualMayCorrectCurrentNodeTimeThroughNewImmutableFact() {
|
||||
CarrierScheduleQueryEntity before = task(0, 3);
|
||||
before.setStatus("READY"); before.setLatestStandardNode("PICKED_UP");
|
||||
before.setLatestNodeObservedAt(NOW.minusDays(1));
|
||||
CarrierScheduleQueryEntity after = task(0, 4);
|
||||
after.setStatus("READY"); after.setLatestStandardNode("PICKED_UP");
|
||||
after.setLatestNodeObservedAt(NOW.minusDays(2));
|
||||
when(repository.lock(1L)).thenReturn(before); when(repository.find(1L)).thenReturn(after);
|
||||
when(repository.insertIfAbsent(any(CarrierScheduleNodeFactEntity.class))).thenReturn(true);
|
||||
when(repository.updateState(any(), any(Integer.class), anyLong(), anyString())).thenReturn(1);
|
||||
|
||||
var result = service.addManualNode(1L, 7L, "admin", "manual-picked-up-correction",
|
||||
new ManualNodeRequest(3, "PICKED_UP", NOW, null, NOW.minusDays(2), null,
|
||||
"Los Angeles", "修正提柜时间"));
|
||||
|
||||
assertThat(result.query().query().latestActualNode()).isEqualTo("PICKED_UP");
|
||||
assertThat(result.query().query().latestActualAt()).isEqualTo(NOW.minusDays(2));
|
||||
ArgumentCaptor<CarrierScheduleNodeFactEntity> fact =
|
||||
ArgumentCaptor.forClass(CarrierScheduleNodeFactEntity.class);
|
||||
verify(repository).insertIfAbsent(fact.capture());
|
||||
assertThat(fact.getValue().getActualAt()).isEqualTo(NOW.minusDays(2));
|
||||
verify(repository).updateState(before, 3, 7L, "admin");
|
||||
verify(repository).completeOperation(eq(1L), eq(7L), eq("manual-picked-up-correction"), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void manualActualRejectsEarlierStandardNodeWithoutAppendingFact() {
|
||||
CarrierScheduleQueryEntity task = task(0, 3);
|
||||
task.setStatus("READY"); task.setLatestStandardNode("PICKED_UP");
|
||||
task.setLatestNodeObservedAt(NOW.minusDays(1));
|
||||
when(repository.lock(1L)).thenReturn(task);
|
||||
|
||||
assertThatThrownBy(() -> service.addManualNode(1L, 7L, "admin", "manual-pickup-ready-late",
|
||||
new ManualNodeRequest(3, "PICKUP_READY", NOW, null, NOW.plusDays(2), null,
|
||||
"Los Angeles", "倒序补录可提柜")))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("不得早于当前最新实际节点");
|
||||
|
||||
verify(repository, never()).insertIfAbsent(any(CarrierScheduleNodeFactEntity.class));
|
||||
verify(repository, never()).updateState(any(), any(Integer.class), anyLong(), anyString());
|
||||
verify(repository, never()).insert(any(com.baiyue.firstleg.portschedule.entity.CarrierScheduleQueryHistoryEntity.class));
|
||||
verify(repository, never()).completeOperation(anyLong(), anyLong(), anyString(), anyString());
|
||||
verify(nodeOutbox, never()).publish(any(), any(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void manualEstimatedFactAdvancesVersionWithoutAdvancingActualProgress() {
|
||||
CarrierScheduleQueryEntity before = task(0, 3);
|
||||
|
||||
Reference in New Issue
Block a user