This commit is contained in:
2026-08-17 14:50:00 +08:00
parent a34b5d5ba0
commit 4abcb2b80f
6 changed files with 31 additions and 10 deletions
@@ -2,6 +2,7 @@ package com.baiyue.firstleg.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.firstleg.entity.LoadingPickTaskEntity;
import com.baiyue.firstleg.entity.ContainerBookingEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@@ -44,6 +45,12 @@ public interface LoadingPickTaskMapper extends BaseMapper<LoadingPickTaskEntity>
+ "AND task.loading_plan_id=#{loadingPlanId} AND booking.warehouse_id=#{warehouseId} LIMIT 1")
LoadingPickTaskEntity selectLoadingByPlan(@Param("loadingPlanId") long loadingPlanId, @Param("warehouseId") long warehouseId);
@Select("SELECT booking.* FROM fl_loading_pick_task task "
+ "JOIN fl_loading_plan plan ON plan.id=task.loading_plan_id "
+ "JOIN fl_container_booking booking ON booking.id=plan.container_booking_id "
+ "WHERE task.id=#{taskId} AND booking.record_status='ACTIVE'")
ContainerBookingEntity selectActiveBookingByTask(@Param("taskId") long taskId);
@Select("""
<script>
SELECT task.id AS taskId, task.loading_plan_id AS loadingPlanId,
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baiyue.firstleg.entity.LoadingPickItemEntity;
import com.baiyue.firstleg.entity.LoadingPickHistoryEntity;
import com.baiyue.firstleg.entity.LoadingPickTaskEntity;
import com.baiyue.firstleg.entity.ContainerBookingEntity;
import com.baiyue.firstleg.mapper.LoadingPickHistoryMapper;
import com.baiyue.firstleg.entity.LoadingPlanItemEntity;
import com.baiyue.firstleg.mapper.LoadingPickItemMapper;
@@ -81,6 +82,10 @@ public class LoadingPickRepository {
return tasks.selectPendingForOperator(operatorId, keyword);
}
public ContainerBookingEntity activeBookingByTask(long taskId) {
return tasks.selectActiveBookingByTask(taskId);
}
public LoadingPickItemEntity item(long taskId, long itemId) {
return items.selectOne(new LambdaQueryWrapper<LoadingPickItemEntity>()
.eq(LoadingPickItemEntity::getPickTaskId, taskId)
@@ -607,8 +607,8 @@ public class LoadingPickService {
String workflowStatus = "COMPLETED".equals(task.getTaskStatus()) ? "COMPLETED"
: assigned == null ? "UNASSIGNED"
: repository.allTaskItemsResolved(task.getId()) ? "AWAITING_REVIEW" : "IN_PROGRESS";
var booking = smartLoadingRepository.booking(task.getContainerBookingId());
if (booking == null || !"ACTIVE".equals(booking.getRecordStatus())) {
var booking = repository.activeBookingByTask(task.getId());
if (booking == null || !Objects.equals(task.getContainerBookingId(), booking.getId())) {
throw new BizException(ResultCode.NOT_FOUND, "PDA拣货任务不存在或柜次已非有效存续记录");
}
var owners = repository.inboundOwners(task.getId());
@@ -50,4 +50,17 @@ class LoadingPickPdaTaskSqlContractTest {
.contains("label.inbound_detail_id = plan_item.inbound_detail_id")
.contains("label.box_code AS boxCode");
}
@Test
void taskDetailResolvesOnlyTheActiveBookingOwnedByItsCurrentPlan() throws Exception {
String sql = LoadingPickTaskMapper.class
.getDeclaredMethod("selectActiveBookingByTask", long.class)
.getAnnotation(Select.class).value()[0];
assertThat(sql)
.contains("plan.id=task.loading_plan_id")
.contains("booking.id=plan.container_booking_id")
.contains("task.id=#{taskId}")
.contains("booking.record_status='ACTIVE'");
}
}
@@ -79,7 +79,7 @@ class LoadingPickServiceTest {
booking.setContainerNo("CSLU1234567");
booking.setSourceType("SIMULATION");
booking.setRecordStatus("ACTIVE");
when(smartLoadingRepository.booking(99L)).thenReturn(booking);
when(repository.activeBookingByTask(20L)).thenReturn(booking);
}
@Test
@@ -228,6 +228,7 @@ class LoadingPickServiceTest {
when(repository.taskByCabinet("CAB-001", 101L)).thenReturn(task);
when(repository.taskByPlan(10L, 101L)).thenReturn(task);
when(smartLoadingRepository.booking(40L)).thenReturn(booking);
when(repository.activeBookingByTask(20L)).thenReturn(booking);
when(repository.items(20L, 101L)).thenReturn(List.of());
when(repository.cartonLabels(20L)).thenReturn(List.of());
@@ -272,13 +273,8 @@ class LoadingPickServiceTest {
@Test
void taskDetailRejectsMergedContainerSource() {
LoadingPickTaskEntity task = task();
ContainerBookingEntity merged = new ContainerBookingEntity();
merged.setId(99L);
merged.setSourceType("OCEAN_BOOKING");
merged.setRecordStatus("MERGED");
merged.setMergedIntoContainerBookingId(88L);
when(repository.task(20L)).thenReturn(task);
when(smartLoadingRepository.booking(99L)).thenReturn(merged);
when(repository.activeBookingByTask(20L)).thenReturn(null);
when(repository.items(20L, 101L)).thenReturn(List.of());
when(repository.cartonLabels(20L)).thenReturn(List.of());
@@ -225,4 +225,4 @@ pwsh scripts/local-db-full-acceptance.ps1 -DryRun
node scripts/admin-test-env-acceptance.mjs --modules suppliers
```
模块覆盖列表、统计、新增、详情、编辑、启停、重复名称、非法 scope、客户账号权限拒绝、`tenantId != 0` 和错误响应 `requestId/traceId`。本轮代码交付不执行该测试环境命令。
模块覆盖列表、统计、新增、详情、编辑、启停、重复名称、客户账号权限拒绝、`tenantId != 0` 和错误响应 `requestId/traceId`;同时断言订舱供应商不暴露国内或国外范围字段。本轮代码交付不执行该测试环境命令。