From a1bcb519c9a01605c0b466c6463f4498a9912b6d Mon Sep 17 00:00:00 2001 From: liuyihe <2513762445@qq.com> Date: Mon, 10 Aug 2026 12:50:22 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A3=85=E6=9F=9C=E5=8F=AA=E8=83=BD=E9=99=90?= =?UTF-8?q?=E5=88=B6=E4=B8=80=E4=B8=AA=E4=BA=BA=E6=8B=A3=E8=B4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/sql/头程数据库统一增量-MySQL8.sql | 43 +------ .../PlatformLoadingPdaController.java | 22 ---- .../baiyue/firstleg/dto/LoadingPickDtos.java | 2 +- .../LoadingPickItemAssignmentEntity.java | 25 ---- .../LoadingPickItemAssignmentMapper.java | 27 ----- .../repository/LoadingPickRepository.java | 18 --- .../firstleg/service/LoadingPickService.java | 109 +++--------------- .../db/phase3-pda-convergence-schema.sql | 18 +-- .../openapi/phase3-pda-convergence-v1.yaml | 18 --- .../PdaConvergenceOpenApiContractTest.java | 2 - .../PdaConvergenceSqlContractTest.java | 2 - .../service/LoadingPickServiceTest.java | 51 -------- 12 files changed, 18 insertions(+), 319 deletions(-) delete mode 100644 firstleg/src/main/java/com/baiyue/firstleg/entity/LoadingPickItemAssignmentEntity.java delete mode 100644 firstleg/src/main/java/com/baiyue/firstleg/mapper/LoadingPickItemAssignmentMapper.java diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index f09c53b52..069ab01c8 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -8585,7 +8585,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation ( UNIQUE KEY uk_loading_pick_operation_id (operation_id), KEY idx_loading_pick_operation_task (pick_task_id, created_at), CONSTRAINT fk_loading_pick_operation_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), - CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW')) + CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'REVIEW')) ) ENGINE=InnoDB COMMENT='柜次PDA任务级幂等审计'; DROP TRIGGER IF EXISTS trg_loading_pick_review_before_update; @@ -8722,47 +8722,6 @@ USE baiyue_firstleg; ALTER TABLE fl_loading_pick_item ADD COLUMN IF NOT EXISTS release_mode VARCHAR(10) NULL COMMENT 'AUTO按比例释放,MANUAL按人工选择释放' AFTER item_status, ADD COLUMN IF NOT EXISTS release_location_ids JSON NULL COMMENT '人工选择释放库位ID;空数组表示明确释放0个' AFTER release_mode; --- PDA 多人协作:领取粒度由整柜任务下沉为单条拣货明细。 -CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment ( - pick_item_id BIGINT UNSIGNED NOT NULL, - assignee_id BIGINT UNSIGNED NOT NULL, - assignee_name VARCHAR(64) NOT NULL, - assigned_by BIGINT UNSIGNED NOT NULL, - assigned_by_name VARCHAR(64) NULL, - assignment_type VARCHAR(16) NOT NULL COMMENT 'CLAIMED/ASSIGNED', - version INT UNSIGNED NOT NULL DEFAULT 0, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (pick_item_id), - KEY idx_loading_pick_item_assignee (assignee_id, updated_at), - CONSTRAINT fk_loading_pick_item_assignment_item FOREIGN KEY (pick_item_id) REFERENCES fl_loading_pick_item (id), - CONSTRAINT chk_loading_pick_item_assignment_type CHECK (assignment_type IN ('CLAIMED', 'ASSIGNED')) -) ENGINE=InnoDB COMMENT='PDA拣货明细领取与作业员分配'; - -ALTER TABLE fl_loading_pick_operation - DROP CHECK IF EXISTS chk_loading_pick_operation_action, - ADD CONSTRAINT chk_loading_pick_operation_action - CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW')); - -DROP PROCEDURE IF EXISTS assert_phase3_pda_item_assignment_schema; -DELIMITER $$ -CREATE PROCEDURE assert_phase3_pda_item_assignment_schema() -BEGIN - IF (SELECT COUNT(*) FROM information_schema.tables - WHERE table_schema='baiyue_firstleg' AND table_name='fl_loading_pick_item_assignment') <> 1 - OR (SELECT COUNT(*) FROM information_schema.statistics - WHERE table_schema='baiyue_firstleg' AND table_name='fl_loading_pick_item_assignment' - AND index_name='idx_loading_pick_item_assignee') <> 2 - OR (SELECT COUNT(*) FROM information_schema.referential_constraints - WHERE constraint_schema='baiyue_firstleg' - AND constraint_name='fk_loading_pick_item_assignment_item') <> 1 THEN - SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='PDA明细级多人分配表创建失败'; - END IF; -END$$ -DELIMITER ; -CALL assert_phase3_pda_item_assignment_schema(); -DROP PROCEDURE IF EXISTS assert_phase3_pda_item_assignment_schema; - ALTER TABLE fl_inbound_pallet_allocation ADD COLUMN IF NOT EXISTS reservation_id BIGINT UNSIGNED NULL COMMENT '仓库预占资源唯一ID,A0共享场景用于区分托盘' AFTER location_code; diff --git a/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformLoadingPdaController.java b/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformLoadingPdaController.java index 4e5c352d5..26bc461fa 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformLoadingPdaController.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformLoadingPdaController.java @@ -62,28 +62,6 @@ public class PlatformLoadingPdaController { return ApiResponse.success(service.assign(taskId, request, user.userId(), user.username())); } - /** 同一柜按 PDA 明细领取,多个作业员可分别处理不同入库单明细。 */ - @PostMapping("/tasks/{taskId}/items/{itemId}/claim") - @PreAuthorize("hasAuthority('platform:firstleg:pda:work')") - public ApiResponse claimItem(@AuthenticationPrincipal AuthenticatedUser user, - @PathVariable @Positive long taskId, - @PathVariable @Positive long itemId, - @Valid @RequestBody ClaimRequest request) { - FirstlegScopeGuard.platform(user); - return ApiResponse.success(service.claimItem(taskId, itemId, request, user.userId(), user.username())); - } - - /** 管理员可将单条 PDA 明细分配给指定仓库作业员。 */ - @PostMapping("/tasks/{taskId}/items/{itemId}/assign") - @PreAuthorize("hasAuthority('platform:firstleg:pda:assign')") - public ApiResponse assignItem(@AuthenticationPrincipal AuthenticatedUser user, - @PathVariable @Positive long taskId, - @PathVariable @Positive long itemId, - @Valid @RequestBody AssignRequest request) { - FirstlegScopeGuard.platform(user); - return ApiResponse.success(service.assignItem(taskId, itemId, request, user.userId(), user.username())); - } - @PostMapping("/tasks/{taskId}/items/{itemId}/pick") @PreAuthorize("hasAuthority('platform:firstleg:pda:work')") public ApiResponse pick(@AuthenticationPrincipal AuthenticatedUser user, diff --git a/firstleg/src/main/java/com/baiyue/firstleg/dto/LoadingPickDtos.java b/firstleg/src/main/java/com/baiyue/firstleg/dto/LoadingPickDtos.java index a73e54c31..6f5f1619c 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/dto/LoadingPickDtos.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/dto/LoadingPickDtos.java @@ -76,7 +76,7 @@ public final class LoadingPickDtos { public record PickItem(Long id, Long loadingPlanItemId, Long inboundId, Long inboundDetailId, Integer plannedPackageCount, Integer pickedPackageCount, - String itemStatus, Integer version, Assignment assignment) { + String itemStatus, Integer version) { } public record Assignment(Long assigneeId, String assigneeName, Long assignedBy, diff --git a/firstleg/src/main/java/com/baiyue/firstleg/entity/LoadingPickItemAssignmentEntity.java b/firstleg/src/main/java/com/baiyue/firstleg/entity/LoadingPickItemAssignmentEntity.java deleted file mode 100644 index cbaf49495..000000000 --- a/firstleg/src/main/java/com/baiyue/firstleg/entity/LoadingPickItemAssignmentEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baiyue.firstleg.entity; - -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Getter; -import lombok.Setter; - -import java.time.LocalDateTime; - -/** PDA 拣货明细的作业员领取或分配记录。 */ -@Getter -@Setter -@TableName("fl_loading_pick_item_assignment") -public class LoadingPickItemAssignmentEntity { - @TableId - private Long pickItemId; - private Long assigneeId; - private String assigneeName; - private Long assignedBy; - private String assignedByName; - private String assignmentType; - private Integer version; - private LocalDateTime createdAt; - private LocalDateTime updatedAt; -} diff --git a/firstleg/src/main/java/com/baiyue/firstleg/mapper/LoadingPickItemAssignmentMapper.java b/firstleg/src/main/java/com/baiyue/firstleg/mapper/LoadingPickItemAssignmentMapper.java deleted file mode 100644 index bf2df6098..000000000 --- a/firstleg/src/main/java/com/baiyue/firstleg/mapper/LoadingPickItemAssignmentMapper.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baiyue.firstleg.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baiyue.firstleg.entity.LoadingPickItemAssignmentEntity; -import org.apache.ibatis.annotations.Insert; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Update; - -/** 明细级作业员分配,允许同一柜的不同明细并行领取。 */ -@Mapper -public interface LoadingPickItemAssignmentMapper extends BaseMapper { - @Insert("INSERT INTO fl_loading_pick_item_assignment " - + "(pick_item_id,assignee_id,assignee_name,assigned_by,assigned_by_name,assignment_type,version) " - + "VALUES (#{itemId},#{assigneeId},#{assigneeName},#{operatorId},#{operatorName},#{type},0)") - int create(@Param("itemId") long itemId, @Param("assigneeId") long assigneeId, - @Param("assigneeName") String assigneeName, @Param("operatorId") long operatorId, - @Param("operatorName") String operatorName, @Param("type") String type); - - @Update("UPDATE fl_loading_pick_item_assignment SET assignee_id=#{assigneeId},assignee_name=#{assigneeName}," - + "assigned_by=#{operatorId},assigned_by_name=#{operatorName},assignment_type=#{type},version=version+1 " - + "WHERE pick_item_id=#{itemId} AND version=#{expectedVersion}") - int reassign(@Param("itemId") long itemId, @Param("assigneeId") long assigneeId, - @Param("assigneeName") String assigneeName, @Param("operatorId") long operatorId, - @Param("operatorName") String operatorName, @Param("type") String type, - @Param("expectedVersion") int expectedVersion); -} diff --git a/firstleg/src/main/java/com/baiyue/firstleg/repository/LoadingPickRepository.java b/firstleg/src/main/java/com/baiyue/firstleg/repository/LoadingPickRepository.java index de69fa0f8..34b314a46 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/repository/LoadingPickRepository.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/repository/LoadingPickRepository.java @@ -9,11 +9,9 @@ import com.baiyue.firstleg.entity.LoadingPlanItemEntity; import com.baiyue.firstleg.mapper.LoadingPickItemMapper; import com.baiyue.firstleg.mapper.LoadingPickTaskMapper; import com.baiyue.firstleg.mapper.LoadingPickAssignmentMapper; -import com.baiyue.firstleg.mapper.LoadingPickItemAssignmentMapper; import com.baiyue.firstleg.mapper.LoadingPickOperationMapper; import com.baiyue.firstleg.mapper.LoadingPickReviewMapper; import com.baiyue.firstleg.entity.LoadingPickAssignmentEntity; -import com.baiyue.firstleg.entity.LoadingPickItemAssignmentEntity; import com.baiyue.firstleg.entity.LoadingPickOperationEntity; import com.baiyue.firstleg.entity.LoadingPickReviewEntity; import com.baiyue.firstleg.loading.mapper.InboundLoadingPickTaskMapper; @@ -35,8 +33,6 @@ public class LoadingPickRepository { @Resource private LoadingPickAssignmentMapper assignments; @Resource - private LoadingPickItemAssignmentMapper itemAssignments; - @Resource private LoadingPickReviewMapper reviews; @Resource private LoadingPickOperationMapper operations; @@ -169,20 +165,6 @@ public class LoadingPickRepository { type, expectedVersion); } - public LoadingPickItemAssignmentEntity itemAssignment(long itemId) { - return itemAssignments.selectById(itemId); - } - - public int createItemAssignment(long itemId, long assigneeId, String assigneeName, - long operatorId, String operatorName, String type) { - return itemAssignments.create(itemId, assigneeId, assigneeName, operatorId, operatorName, type); - } - - public int reassignItem(long itemId, long assigneeId, String assigneeName, long operatorId, - String operatorName, String type, int expectedVersion) { - return itemAssignments.reassign(itemId, assigneeId, assigneeName, operatorId, operatorName, - type, expectedVersion); - } public LoadingPickReviewEntity review(long taskId) { return reviews.selectById(taskId); diff --git a/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java b/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java index cf84c3c07..e579abbdb 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java @@ -14,7 +14,6 @@ import com.baiyue.firstleg.dto.LoadingPickDtos.AssignRequest; import com.baiyue.firstleg.dto.LoadingPickDtos.ReviewRequest; import com.baiyue.firstleg.dto.LoadingPickDtos.Operation; import com.baiyue.firstleg.entity.LoadingPickAssignmentEntity; -import com.baiyue.firstleg.entity.LoadingPickItemAssignmentEntity; import com.baiyue.firstleg.entity.LoadingPickHistoryEntity; import com.baiyue.firstleg.entity.LoadingPickItemEntity; import com.baiyue.firstleg.entity.LoadingPickOperationEntity; @@ -119,38 +118,6 @@ public class LoadingPickService { return view(task, null); } - /** - * 领取单条 PDA 明细。柜次任务只是汇总容器,作业所有权必须以明细为粒度, - * 才能让多个仓库人员在同一柜中并行处理不同入库单。 - */ - @Transactional - public Task claimItem(long taskId, long itemId, ClaimRequest request, long operatorId, String operatorName) { - String operationId = operation(request.operationId()); - String requestHash = hash("ITEM_CLAIM|" + taskId + '|' + itemId + '|' - + request.expectedAssignmentVersion()); - Task replay = replayTaskOperation(taskId, operationId, requestHash, operatorId); - if (replay != null) return replay; - LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); - LoadingPickItemEntity item = repository.item(taskId, itemId); - requireAssignableItem(item); - LoadingPickItemAssignmentEntity existing = repository.itemAssignment(itemId); - if (existing == null) { - try { - if (request.expectedAssignmentVersion() != 0 || repository.createItemAssignment(itemId, operatorId, - operatorName, operatorId, operatorName, "CLAIMED") != 1) { - throw conflict("PDA拣货明细已被其他作业员领取"); - } - } catch (DuplicateKeyException exception) { - throw conflict("PDA拣货明细已被其他作业员领取"); - } - } else if (!Long.valueOf(operatorId).equals(existing.getAssigneeId()) - || !request.expectedAssignmentVersion().equals(existing.getVersion())) { - throw conflict("PDA拣货明细已分配给其他作业员或分配版本已变化"); - } - insertOperation(taskId, operationId, requestHash, "ITEM_CLAIM", operatorId, operatorName); - return view(task, null); - } - @Transactional public Task assign(long taskId, AssignRequest request, long operatorId, String operatorName) { String operationId = operation(request.operationId()); @@ -172,29 +139,6 @@ public class LoadingPickService { return view(task, null); } - @Transactional - public Task assignItem(long taskId, long itemId, AssignRequest request, long operatorId, String operatorName) { - String operationId = operation(request.operationId()); - String assigneeName = request.assigneeName().trim(); - String requestHash = hash("ITEM_ASSIGN|" + taskId + '|' + itemId + '|' - + request.assigneeId() + '|' + assigneeName + '|' + request.expectedAssignmentVersion()); - Task replay = replayTaskOperation(taskId, operationId, requestHash, operatorId); - if (replay != null) return replay; - LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); - LoadingPickItemEntity item = repository.item(taskId, itemId); - requireAssignableItem(item); - LoadingPickItemAssignmentEntity existing = repository.itemAssignment(itemId); - int changed = existing == null - ? request.expectedAssignmentVersion() == 0 - ? repository.createItemAssignment(itemId, request.assigneeId(), assigneeName, operatorId, - operatorName, "ASSIGNED") : 0 - : repository.reassignItem(itemId, request.assigneeId(), assigneeName, operatorId, operatorName, - "ASSIGNED", request.expectedAssignmentVersion()); - if (changed != 1) throw conflict("PDA拣货明细分配版本已变化"); - insertOperation(taskId, operationId, requestHash, "ITEM_ASSIGN", operatorId, operatorName); - return view(task, null); - } - @Transactional public Task pick(long taskId, long itemId, PickRequest request, long operatorId, String operatorName) { ReleaseSelection release = releaseSelection(request.releaseMode(), request.locationIds()); @@ -210,12 +154,11 @@ public class LoadingPickService { } return view(requiredTask(taskId), request.warehouseId()); } - LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); + LoadingPickTaskEntity task = requiredAssignedLoadingTaskForUpdate(taskId, operatorId); LoadingPickItemEntity item = repository.item(taskId, itemId, request.warehouseId()); if (item == null) { throw new BizException(ResultCode.NOT_FOUND, "PDA拣货明细不存在"); } - requireItemAssignee(taskId, itemId, operatorId); if (repository.pick(itemId, request.pickedPackageCount(), release.mode(), release.json(), request.version(), request.warehouseId()) != 1) { throw conflict("拣货数量超过计划箱数或明细版本已变化"); @@ -247,9 +190,8 @@ public class LoadingPickService { assertReplay(replay, taskId, itemId, requestHash); return view(requiredTask(taskId), request.warehouseId()); } - LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); + LoadingPickTaskEntity task = requiredAssignedLoadingTaskForUpdate(taskId, operatorId); requireWarehouseItem(taskId, itemId, request.warehouseId()); - requireItemAssignee(taskId, itemId, operatorId); if (repository.partial(itemId, request.finalPickedPackageCount(), release.mode(), release.json(), request.version(), request.warehouseId()) != 1) { throw conflict("部分拣货箱数必须大于已拣箱数且小于计划箱数,或明细版本已变化"); @@ -272,9 +214,8 @@ public class LoadingPickService { assertReplay(replay, taskId, itemId, requestHash); return view(requiredTask(taskId), request.warehouseId()); } - LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); + LoadingPickTaskEntity task = requiredAssignedLoadingTaskForUpdate(taskId, operatorId); LoadingPickItemEntity item = requireWarehouseItem(taskId, itemId, request.warehouseId()); - requireItemAssignee(taskId, itemId, operatorId); if (repository.hasPickedOrPartialItem(taskId, item.getInboundId())) { throw conflict("同一入库单已存在已拣或部分拣货明细,不能跳拣并恢复智能装柜候选"); } @@ -402,27 +343,14 @@ public class LoadingPickService { return task; } - private void requireItemAssignee(long taskId, long itemId, long operatorId) { - LoadingPickItemAssignmentEntity assignment = repository.itemAssignment(itemId); - if (assignment != null) { - if (!Long.valueOf(operatorId).equals(assignment.getAssigneeId())) { - throw conflict("PDA拣货明细已分配给其他作业员"); - } - return; - } - // 兼容已上线的整柜领取调用;新作业必须走明细领取接口。 - LoadingPickAssignmentEntity legacy = repository.assignment(taskId); - if (legacy == null || !Long.valueOf(operatorId).equals(legacy.getAssigneeId())) { - throw conflict("请先领取PDA拣货明细"); - } - } - - private static void requireAssignableItem(LoadingPickItemEntity item) { - if (item == null) throw new BizException(ResultCode.NOT_FOUND, "PDA拣货明细不存在"); - if ("PICKED".equals(item.getItemStatus()) || "PARTIAL".equals(item.getItemStatus()) - || "SKIPPED".equals(item.getItemStatus())) { - throw conflict("已完成或已跳拣的PDA明细不能再领取或改派"); + private LoadingPickTaskEntity requiredAssignedLoadingTaskForUpdate(long taskId, long operatorId) { + LoadingPickTaskEntity task = requiredLoadingTaskForUpdate(taskId); + LoadingPickAssignmentEntity assignment = repository.assignment(taskId); + if (assignment == null) throw conflict("请先领取PDA拣货任务"); + if (!Long.valueOf(operatorId).equals(assignment.getAssigneeId())) { + throw conflict("PDA拣货任务已分配给其他作业员"); } + return task; } private LoadingPickItemEntity requireWarehouseItem(long taskId, long itemId, long warehouseId) { @@ -436,15 +364,10 @@ public class LoadingPickService { private Task view(LoadingPickTaskEntity task, Long warehouseId) { List source = warehouseId == null ? repository.items(task.getId()) : repository.items(task.getId(), warehouseId); - List items = source.stream().map(item -> { - LoadingPickItemAssignmentEntity assignedItem = repository.itemAssignment(item.getId()); - Assignment itemAssignment = assignedItem == null ? null : new Assignment(assignedItem.getAssigneeId(), - assignedItem.getAssigneeName(), assignedItem.getAssignedBy(), assignedItem.getAssignedByName(), - assignedItem.getAssignmentType(), assignedItem.getVersion()); - return new PickItem(item.getId(), item.getLoadingPlanItemId(), item.getInboundId(), + List items = source.stream() + .map(item -> new PickItem(item.getId(), item.getLoadingPlanItemId(), item.getInboundId(), item.getInboundDetailId(), item.getPlannedPackageCount(), item.getPickedPackageCount(), - item.getItemStatus(), item.getVersion(), itemAssignment); - }).toList(); + item.getItemStatus(), item.getVersion())).toList(); LoadingPickAssignmentEntity assigned = repository.assignment(task.getId()); LoadingPickReviewEntity reviewed = repository.review(task.getId()); Assignment assignment = assigned == null ? null : new Assignment(assigned.getAssigneeId(), @@ -452,11 +375,9 @@ public class LoadingPickService { assigned.getAssignmentType(), assigned.getVersion()); Review review = reviewed == null ? null : new Review(reviewed.getReviewStatus(), reviewed.getReviewedBy(), reviewed.getReviewedByName(), reviewed.getRemark(), reviewed.getVersion()); - boolean hasPickedItem = source.stream().anyMatch(item -> item.getPickedPackageCount() != null - && item.getPickedPackageCount() > 0); String workflowStatus = "COMPLETED".equals(task.getTaskStatus()) ? "COMPLETED" - : repository.allTaskItemsResolved(task.getId()) ? "AWAITING_REVIEW" - : hasPickedItem ? "IN_PROGRESS" : "PENDING"; + : assigned == null ? "UNASSIGNED" + : repository.allTaskItemsResolved(task.getId()) ? "AWAITING_REVIEW" : "IN_PROGRESS"; return new Task(task.getId(), task.getLoadingPlanId(), task.getContainerNo(), task.getTaskStatus(), workflowStatus, task.getVersion(), assignment, review, items); } diff --git a/firstleg/src/main/resources/db/phase3-pda-convergence-schema.sql b/firstleg/src/main/resources/db/phase3-pda-convergence-schema.sql index 8ce8f9e99..a207bbb7e 100644 --- a/firstleg/src/main/resources/db/phase3-pda-convergence-schema.sql +++ b/firstleg/src/main/resources/db/phase3-pda-convergence-schema.sql @@ -45,25 +45,9 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation ( UNIQUE KEY uk_loading_pick_operation_id (operation_id), KEY idx_loading_pick_operation_task (pick_task_id, created_at), CONSTRAINT fk_loading_pick_operation_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id), - CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW')) + CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'REVIEW')) ) ENGINE=InnoDB COMMENT='柜次PDA任务级幂等审计'; -CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment ( - pick_item_id BIGINT UNSIGNED NOT NULL, - assignee_id BIGINT UNSIGNED NOT NULL, - assignee_name VARCHAR(64) NOT NULL, - assigned_by BIGINT UNSIGNED NOT NULL, - assigned_by_name VARCHAR(64) NULL, - assignment_type VARCHAR(16) NOT NULL COMMENT 'CLAIMED/ASSIGNED', - version INT UNSIGNED NOT NULL DEFAULT 0, - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), - PRIMARY KEY (pick_item_id), - KEY idx_loading_pick_item_assignee (assignee_id, updated_at), - CONSTRAINT fk_loading_pick_item_assignment_item FOREIGN KEY (pick_item_id) REFERENCES fl_loading_pick_item (id), - CONSTRAINT chk_loading_pick_item_assignment_type CHECK (assignment_type IN ('CLAIMED', 'ASSIGNED')) -) ENGINE=InnoDB COMMENT='PDA拣货明细领取与作业员分配'; - DROP TRIGGER IF EXISTS trg_loading_pick_review_before_update; DELIMITER $$ CREATE TRIGGER trg_loading_pick_review_before_update diff --git a/firstleg/src/main/resources/openapi/phase3-pda-convergence-v1.yaml b/firstleg/src/main/resources/openapi/phase3-pda-convergence-v1.yaml index e681be2b6..28d1d2c48 100644 --- a/firstleg/src/main/resources/openapi/phase3-pda-convergence-v1.yaml +++ b/firstleg/src/main/resources/openapi/phase3-pda-convergence-v1.yaml @@ -29,24 +29,6 @@ paths: content: {application/json: {schema: {$ref: '#/components/schemas/AssignRequest'}}} responses: '200': {description: Assigned task or A0409 on assignment version conflict} - /api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/claim: - post: - summary: 领取单条PDA拣货明细;同柜不同明细可由不同仓库人员并行作业 - parameters: [{$ref: '#/components/parameters/TaskId'}, {$ref: '#/components/parameters/ItemId'}] - requestBody: - required: true - content: {application/json: {schema: {$ref: '#/components/schemas/ClaimRequest'}}} - responses: - '200': {description: 返回含明细作业员信息的PDA任务} - /api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/assign: - post: - summary: 将单条PDA拣货明细分配或改派给指定仓库人员 - parameters: [{$ref: '#/components/parameters/TaskId'}, {$ref: '#/components/parameters/ItemId'}] - requestBody: - required: true - content: {application/json: {schema: {$ref: '#/components/schemas/AssignRequest'}}} - responses: - '200': {description: 返回含明细作业员信息的PDA任务} /api/platform/v1/first-leg/pda-loading/tasks/{taskId}/items/{itemId}/pick: post: summary: Increment a picked item owned by the authenticated assignee diff --git a/firstleg/src/test/java/com/baiyue/firstleg/controller/PdaConvergenceOpenApiContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/controller/PdaConvergenceOpenApiContractTest.java index ed9b9b3a3..890a564c5 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/controller/PdaConvergenceOpenApiContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/controller/PdaConvergenceOpenApiContractTest.java @@ -16,8 +16,6 @@ class PdaConvergenceOpenApiContractTest { .contains("/api/platform/v1/first-leg/pda-loading/tasks:") .contains("/tasks/{taskId}/claim:") .contains("/tasks/{taskId}/assign:") - .contains("/tasks/{taskId}/items/{itemId}/claim:") - .contains("/tasks/{taskId}/items/{itemId}/assign:") .contains("/tasks/{taskId}/items/{itemId}/pick:") .contains("/tasks/{taskId}/items/{itemId}/partial:") .contains("/tasks/{taskId}/items/{itemId}/skip:") diff --git a/firstleg/src/test/java/com/baiyue/firstleg/loading/repository/PdaConvergenceSqlContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/loading/repository/PdaConvergenceSqlContractTest.java index 76b84d773..8bdf3a4ba 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/loading/repository/PdaConvergenceSqlContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/loading/repository/PdaConvergenceSqlContractTest.java @@ -18,10 +18,8 @@ class PdaConvergenceSqlContractTest { .getContentAsString(StandardCharsets.UTF_8); assertThat(sql) .contains("CREATE TABLE IF NOT EXISTS fl_loading_pick_assignment") - .contains("CREATE TABLE IF NOT EXISTS fl_loading_pick_item_assignment") .contains("CREATE TABLE IF NOT EXISTS fl_loading_pick_review") .contains("CREATE TABLE IF NOT EXISTS fl_loading_pick_operation") - .contains("'ITEM_CLAIM', 'ITEM_ASSIGN'") .contains("UNIQUE KEY uk_loading_pick_operation_id") .contains("trg_loading_pick_review_before_update") .contains("trg_loading_pick_operation_before_delete") diff --git a/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java index 49ff7cf7a..3e92b9f46 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/service/LoadingPickServiceTest.java @@ -3,13 +3,11 @@ package com.baiyue.firstleg.service; import com.baiyue.common.core.exception.BizException; import com.baiyue.firstleg.dto.LoadingPickDtos.PartialPickRequest; import com.baiyue.firstleg.dto.LoadingPickDtos.PickRequest; -import com.baiyue.firstleg.dto.LoadingPickDtos.ClaimRequest; import com.baiyue.firstleg.dto.LoadingPickDtos.ReviewRequest; import com.baiyue.firstleg.dto.LoadingPickDtos.SkipRequest; import com.baiyue.firstleg.entity.LoadingPickAssignmentEntity; import com.baiyue.firstleg.entity.LoadingPickHistoryEntity; import com.baiyue.firstleg.entity.LoadingPickItemEntity; -import com.baiyue.firstleg.entity.LoadingPickItemAssignmentEntity; import com.baiyue.firstleg.entity.LoadingPickOperationEntity; import com.baiyue.firstleg.entity.LoadingPickTaskEntity; import com.baiyue.firstleg.repository.LoadingPickRepository; @@ -112,47 +110,6 @@ class LoadingPickServiceTest { verify(settlementService, never()).settle(20L, 9L, "operator"); } - @Test - void permitsItemAssigneeWithoutCabinetAssignee() { - LoadingPickTaskEntity task = task(); - LoadingPickItemEntity item = item(); - when(repository.history("item-owner-pick")).thenReturn(null); - when(repository.task(20L)).thenReturn(task); - when(repository.taskForUpdate(20L)).thenReturn(task); - when(repository.item(20L, 30L, 101L)).thenReturn(item); - when(repository.itemAssignment(30L)).thenReturn(itemAssignment(9L, "operator")); - when(repository.pick(30L, 2, "MANUAL", "[]", 0, 101L)).thenReturn(1); - when(repository.touchTask(20L, 0)).thenReturn(1); - when(repository.items(20L, 101L)).thenReturn(List.of(item)); - - service.pick(20L, 30L, new PickRequest(101L, 2, List.of(), 0, "item-owner-pick"), - 9L, "operator"); - - } - - @Test - void permitsTwoWorkersToClaimDifferentItemsInOneCabinet() { - LoadingPickTaskEntity task = task(); - LoadingPickItemEntity first = item(); - LoadingPickItemEntity second = item(); - second.setId(31L); - when(repository.taskForUpdate(20L)).thenReturn(task); - when(repository.task(20L)).thenReturn(task); - when(repository.item(20L, 30L)).thenReturn(first); - when(repository.item(20L, 31L)).thenReturn(second); - when(repository.itemAssignment(30L)).thenReturn(null); - when(repository.itemAssignment(31L)).thenReturn(null); - when(repository.createItemAssignment(30L, 9L, "worker-a", 9L, "worker-a", "CLAIMED")).thenReturn(1); - when(repository.createItemAssignment(31L, 10L, "worker-b", 10L, "worker-b", "CLAIMED")).thenReturn(1); - when(repository.items(20L)).thenReturn(List.of(first, second)); - - service.claimItem(20L, 30L, new ClaimRequest(0, "claim-a"), 9L, "worker-a"); - service.claimItem(20L, 31L, new ClaimRequest(0, "claim-b"), 10L, "worker-b"); - - verify(repository).createItemAssignment(30L, 9L, "worker-a", 9L, "worker-a", "CLAIMED"); - verify(repository).createItemAssignment(31L, 10L, "worker-b", 10L, "worker-b", "CLAIMED"); - } - @Test void reviewSettlesResolvedItemsAndCompletesPlan() { LoadingPickTaskEntity task = task(); @@ -231,12 +188,4 @@ class LoadingPickServiceTest { return assignment; } - private static LoadingPickItemAssignmentEntity itemAssignment(long assigneeId, String assigneeName) { - LoadingPickItemAssignmentEntity assignment = new LoadingPickItemAssignmentEntity(); - assignment.setPickItemId(30L); - assignment.setAssigneeId(assigneeId); - assignment.setAssigneeName(assigneeName); - assignment.setVersion(0); - return assignment; - } }