This commit is contained in:
2026-09-04 11:35:19 +08:00
parent c3729249c4
commit f23f3ea26d
21 changed files with 476 additions and 97 deletions
@@ -8,6 +8,7 @@ import com.baiyue.firstleg.dto.LoadingPickDtos.SkipRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.BatchRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.BatchItemRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.ClaimRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.AssignRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.CompleteLoadingRequest;
import com.baiyue.firstleg.dto.LoadingPickDtos.Task;
import com.baiyue.firstleg.client.WarehousePalletLocationClient;
@@ -513,6 +514,99 @@ class LoadingPickServiceTest {
verify(repository, times(1)).createAssignment(20L, 9L, "operator", 9L, "operator", "CLAIMED");
}
@Test
void claimRechecksSameOperationAfterWaitingForTaskLock() {
LoadingPickTaskEntity task = task();
LoadingPickOperationEntity completed = taskOperation("claim-race", "CLAIM");
when(repository.operation("claim-race")).thenReturn(null, completed);
when(repository.taskForUpdate(20L)).thenReturn(task);
when(repository.task(20L)).thenReturn(task);
when(repository.items(20L)).thenReturn(List.of());
Task replay = service.claim(20L, new ClaimRequest(0, "claim-race"), 9L, "operator");
assertThat(replay.id()).isEqualTo(20L);
verify(repository, never()).createAssignment(anyLong(), anyLong(), anyString(), anyLong(),
anyString(), anyString());
verify(smartLoadingRepository, never()).startPicking(anyLong(), anyLong(), anyString());
}
@Test
void assignRechecksSameOperationAfterWaitingForTaskLock() {
LoadingPickTaskEntity task = task();
LoadingPickOperationEntity completed = taskOperation("assign-race", "ASSIGN");
when(repository.operation("assign-race")).thenReturn(null, completed);
when(repository.taskForUpdate(20L)).thenReturn(task);
when(repository.task(20L)).thenReturn(task);
when(repository.items(20L)).thenReturn(List.of());
Task replay = service.assign(20L, new AssignRequest(11L, "picker", 0, "assign-race"),
9L, "operator");
assertThat(replay.id()).isEqualTo(20L);
verify(repository, never()).createAssignment(anyLong(), anyLong(), anyString(), anyLong(),
anyString(), anyString());
verify(repository, never()).reassign(anyLong(), anyLong(), anyString(), anyLong(),
anyString(), anyString(), anyInt());
}
@Test
void pickRechecksSameHistoryAfterWaitingForTaskLock() {
LoadingPickTaskEntity task = task();
LoadingPickHistoryEntity completed = itemHistory("pick-race", "PICK",
"20|30|101|2|MANUAL|[]");
when(repository.history("pick-race")).thenReturn(null, completed);
when(repository.taskForUpdate(20L)).thenReturn(task);
when(repository.assignment(20L)).thenReturn(assignment());
when(repository.items(20L, 101L)).thenReturn(List.of(item()));
Task replay = service.pick(20L, 30L,
new PickRequest(101L, 2, List.of(), 0, "pick-race"), 9L, "operator");
assertThat(replay.id()).isEqualTo(20L);
verify(repository, never()).pick(anyLong(), anyInt(), anyString(), anyString(), anyInt(), anyLong());
verify(repository, never()).insert(any(LoadingPickHistoryEntity.class));
verify(repository, never()).touchTask(anyLong(), anyInt());
}
@Test
void partialRechecksSameHistoryAfterWaitingForTaskLock() {
LoadingPickTaskEntity task = task();
LoadingPickHistoryEntity completed = itemHistory("partial-race", "PARTIAL",
"PARTIAL|20|30|101|1|MANUAL|[]");
when(repository.history("partial-race")).thenReturn(null, completed);
when(repository.taskForUpdate(20L)).thenReturn(task);
when(repository.assignment(20L)).thenReturn(assignment());
when(repository.items(20L, 101L)).thenReturn(List.of(item()));
Task replay = service.partial(20L, 30L,
new PartialPickRequest(101L, 1, List.of(), 0, "partial-race"), 9L, "operator");
assertThat(replay.id()).isEqualTo(20L);
verify(repository, never()).partial(anyLong(), anyInt(), anyString(), anyString(), anyInt(), anyLong());
verify(repository, never()).insert(any(LoadingPickHistoryEntity.class));
verify(repository, never()).touchTask(anyLong(), anyInt());
}
@Test
void skipRechecksSameHistoryAfterWaitingForTaskLock() {
LoadingPickTaskEntity task = task();
LoadingPickHistoryEntity completed = itemHistory("skip-race", "SKIP",
"SKIP|20|30|101|damaged");
when(repository.history("skip-race")).thenReturn(null, completed);
when(repository.taskForUpdate(20L)).thenReturn(task);
when(repository.assignment(20L)).thenReturn(assignment());
when(repository.items(20L, 101L)).thenReturn(List.of(item()));
Task replay = service.skip(20L, 30L,
new SkipRequest(101L, 0, "skip-race", "damaged"), 9L, "operator");
assertThat(replay.id()).isEqualTo(20L);
verify(repository, never()).skip(anyLong(), anyInt(), anyLong());
verify(repository, never()).insert(any(LoadingPickHistoryEntity.class));
verify(repository, never()).touchTask(anyLong(), anyInt());
}
@Test
void keepsPartialPickLockedUntilManualCompletion() {
LoadingPickTaskEntity task = task();
@@ -1289,6 +1383,41 @@ class LoadingPickServiceTest {
return assignment;
}
private static LoadingPickOperationEntity taskOperation(String operationId, String action) {
LoadingPickOperationEntity operation = new LoadingPickOperationEntity();
operation.setPickTaskId(20L);
operation.setOperationId(operationId);
operation.setRequestHash(hashForTest(action + "|20|0"));
if ("ASSIGN".equals(action)) {
operation.setRequestHash(hashForTest("ASSIGN|20|11|picker|0"));
}
operation.setActionType(action);
operation.setOperatorId(9L);
operation.setOperatorName("operator");
return operation;
}
private static LoadingPickHistoryEntity itemHistory(String operationId, String action, String canonical) {
LoadingPickHistoryEntity history = new LoadingPickHistoryEntity();
history.setPickTaskId(20L);
history.setPickItemId(30L);
history.setOperationId(operationId);
history.setRequestHash(hashForTest(canonical));
history.setActionType(action);
history.setOperatorId(9L);
history.setOperatorName("operator");
return history;
}
private static String hashForTest(String value) {
try {
return java.util.HexFormat.of().formatHex(java.security.MessageDigest.getInstance("SHA-256")
.digest(value.getBytes(java.nio.charset.StandardCharsets.UTF_8)));
} catch (java.security.NoSuchAlgorithmException exception) {
throw new IllegalStateException(exception);
}
}
private static GroupSnapshot coloadGroup(String status, Long lockedPlanId, Member... members) {
GroupSnapshot group = mock(GroupSnapshot.class);
when(group.groupId()).thenReturn(700L);