This commit is contained in:
2026-08-15 10:05:03 +08:00
parent bafabf7217
commit 233f8f312d
5 changed files with 45 additions and 3 deletions
@@ -125,7 +125,8 @@ public final class LoadingPickDtos {
Long operatorId, String operatorName, LocalDateTime createdAt) {
}
public record Task(Long id, Long loadingPlanId, Long containerBookingId, String cabinetNo,
public record Task(Long id, Long loadingPlanId, Long containerBookingId, Long inboundId,
Integer inboundVersion, Integer loadingVersion, String cabinetNo,
String currentContainerNo, String taskStatus,
String workflowStatus, Integer version, Assignment assignment,
Review review, List<PickItem> items) {
@@ -578,7 +578,16 @@ public class LoadingPickService {
: assigned == null ? "UNASSIGNED"
: repository.allTaskItemsResolved(task.getId()) ? "AWAITING_REVIEW" : "IN_PROGRESS";
var booking = smartLoadingRepository.booking(task.getContainerBookingId());
return new Task(task.getId(), task.getLoadingPlanId(), task.getContainerBookingId(), task.getCabinetNo(),
var owners = repository.inboundOwners(task.getId());
Long detailInboundId = source.isEmpty() ? null : source.get(0).getInboundId();
var owner = detailInboundId == null ? null : owners.stream()
.filter(value -> detailInboundId.equals(value.inboundId())).findFirst().orElse(null);
var inbound = owner == null || owner.tenantId() == null || owner.inboundId() == null
? null : repository.inbound(owner.tenantId(), owner.inboundId());
var plan = smartLoadingRepository.plan(task.getLoadingPlanId());
return new Task(task.getId(), task.getLoadingPlanId(), task.getContainerBookingId(),
owner == null ? null : owner.inboundId(), inbound == null ? null : inbound.version(),
plan == null ? null : plan.getVersion(), task.getCabinetNo(),
booking == null ? null : booking.getContainerNo(), task.getTaskStatus(),
workflowStatus, task.getVersion(), assignment, review, items);
}
@@ -124,11 +124,14 @@ components:
schemas:
Task:
type: object
required: [id, loadingPlanId, containerBookingId, cabinetNo, taskStatus, workflowStatus, version, items]
required: [id, loadingPlanId, containerBookingId, inboundId, inboundVersion, loadingVersion, cabinetNo, taskStatus, workflowStatus, version, items]
properties:
id: {type: integer, format: int64}
loadingPlanId: {type: integer, format: int64}
containerBookingId: {type: integer, format: int64}
inboundId: {type: integer, format: int64, description: Stable inbound identity selected from the task item; evidence identity is taskId+inboundId+loadingPlanId+containerBookingId}
inboundVersion: {type: integer, minimum: 0, description: Current fl_inbound_order.version for inboundId; never inferred from PDA task version}
loadingVersion: {type: integer, minimum: 0, description: Current fl_loading_plan.version for loadingPlanId; used as the loading/evidence concurrency snapshot}
cabinetNo: {type: string}
currentContainerNo: {type: string, nullable: true, description: Mutable transport display field; changing it never resynchronizes the task or item versions and it is never task identity}
taskStatus: {type: string, enum: [LOADING, COMPLETED]}
@@ -33,6 +33,9 @@ class PdaConvergenceOpenApiContractTest {
.contains("advances every associated inbound from WAIT_SPLIT to LOADING with optimistic locking")
.contains("workflowStatus may later become AWAITING_REVIEW")
.contains("without using containerNo as an association key")
.contains("evidence identity is taskId+inboundId+loadingPlanId+containerBookingId")
.contains("Current fl_inbound_order.version for inboundId")
.contains("Current fl_loading_plan.version for loadingPlanId")
.contains("CompleteLoadingRequest");
String taskLookup = yaml.substring(
@@ -229,6 +229,32 @@ class LoadingPickServiceTest {
verify(inboundHistories, never()).insert(any(InboundStatusHistoryEntity.class));
}
@Test
void taskDetailReturnsServerInboundAndLoadingVersions() {
LoadingPickTaskEntity task = task();
when(repository.task(20L)).thenReturn(task);
when(repository.items(20L, 101L)).thenReturn(List.of(item()));
when(repository.cartonLabels(20L)).thenReturn(List.of());
when(repository.assignment(20L)).thenReturn(null);
when(repository.review(20L)).thenReturn(null);
when(repository.allTaskItemsResolved(20L)).thenReturn(false);
when(repository.inboundOwners(20L)).thenReturn(List.of(
new LoadingPickItemMapper.InboundOwner(101L, 50L)));
when(repository.inbound(101L, 50L)).thenReturn(
new LoadingInboundMapper.Snapshot(50L, 101L, "LOADING", 7));
var plan = new com.baiyue.firstleg.entity.LoadingPlanEntity();
plan.setId(10L); plan.setVersion(11);
when(smartLoadingRepository.plan(10L)).thenReturn(plan);
var result = service.task(20L, 101L);
assertThat(result.inboundId()).isEqualTo(50L);
assertThat(result.inboundVersion()).isEqualTo(7);
assertThat(result.loadingVersion()).isEqualTo(11);
assertThat(result.loadingPlanId()).isEqualTo(10L);
assertThat(result.containerBookingId()).isEqualTo(99L);
}
@Test
void claimStartsLoadingAndSameOperatorReentryDoesNotDuplicateStartHistory() {
LoadingPickTaskEntity task = task();