diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java index b9734c9d..4e1e37b4 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketControllerService.java @@ -100,6 +100,9 @@ public class QmsIssueTicketControllerService { @Resource private IQmsPqcInspectionPointItemsService pqcInspectionPointItemsService; + @Resource + private QmsIssueTicketProcessControllerService issueTicketProcessControllerService; + /** * 批量删除质量问题工单 * 仅允许删除来源类型为PQC(sourceType=3)且状态为待流转(status=0)的工单, @@ -273,9 +276,9 @@ public class QmsIssueTicketControllerService { throw new NflgException(STATE.BusinessError, "只能发起PQC工单"); } - // 3. 校验工单状态为待流转 - if (!Objects.equals(ticket.getStatus(), (short) 0)) { - throw new NflgException(STATE.BusinessError, "工单状态不是待流转"); + // 3. 校验工单状态为待流转或处理中 + if (!Objects.equals(ticket.getStatus(), (short) 0) && !Objects.equals(ticket.getStatus(), (short) 1)) { + throw new NflgException(STATE.BusinessError, "工单状态不是待流转或处理中"); } // 4. 更新工单的事故类型和备注 @@ -295,12 +298,24 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicketToDo::getHasProcessed, true) .update(); + Set redispatchableTaskResultIds = getPqcRedispatchableTaskResultIds(ticket); + // 5. 按处理人分组合并不合格项ID Map> userTaskMap = new LinkedHashMap<>(); for (QmsPqcTicketDispatchQO.AssigneeItem item : request.getAssignees()) { + List taskResultIds = Arrays.stream(item.getTaskResultIds().split(",")) + .filter(StrUtil::isNotBlank) + .map(String::trim) + .filter(taskResultId -> redispatchableTaskResultIds.contains(Long.valueOf(taskResultId))) + .distinct() + .collect(Collectors.toList()); + if (taskResultIds.isEmpty()) { + continue; + } userTaskMap.computeIfAbsent(item.getUserId(), k -> new ArrayList<>()) - .add(item.getTaskResultIds()); + .addAll(taskResultIds); } + VUtil.trueThrowBusinessError(userTaskMap.isEmpty()).throwMessage("请选择未分派或已驳回的不合格项"); // 6. 批量查询处理人信息 List userIds = new ArrayList<>(userTaskMap.keySet()); @@ -346,6 +361,40 @@ public class QmsIssueTicketControllerService { .update(); } + private Set getPqcRedispatchableTaskResultIds(QmsIssueTicket ticket) { + List allUnqualified = pqcTaskRecordDetailsService.lambdaQuery() + .eq(QmsPqcTaskRecordDetails::getTaskId, ticket.getSourceId()) + .eq(QmsPqcTaskRecordDetails::getReviewEnable, false) + .list(); + Set allUnqualifiedIds = allUnqualified.stream() + .map(QmsPqcTaskRecordDetails::getId) + .collect(Collectors.toSet()); + if (allUnqualifiedIds.isEmpty()) { + return Collections.emptySet(); + } + + List processes = issueTicketProcessService.lambdaQuery() + .eq(QmsIssueTicketProcess::getIssueTicketId, ticket.getId()) + .list(); + Set effectivelyDispatched = new HashSet<>(); + for (QmsIssueTicketProcess p : processes) { + if (StrUtil.isBlank(p.getTaskResultIds())) { + continue; + } + if (Objects.equals(p.getApprovalStatus(), (short) 1)) { + continue; + } + Arrays.stream(p.getTaskResultIds().split(",")) + .filter(StrUtil::isNotBlank) + .map(String::trim) + .map(Long::valueOf) + .forEach(effectivelyDispatched::add); + } + + allUnqualifiedIds.removeAll(effectivelyDispatched); + return allUnqualifiedIds; + } + /** * 巡检工单分派(支持多人) * 1. 校验工单存在且来源类型为巡检(sourceType=2) @@ -363,15 +412,33 @@ public class QmsIssueTicketControllerService { QmsIssueTicket ticket = issueTicketService.getById(request.getId()); VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 校验工单来源类型为巡检 if (!Objects.equals(ticket.getSourceType(), (short) 2)) { + if (CollectionUtil.isNotEmpty(request.getHandlers())) { + QmsIssueTicketProcessAddQO addRequest = new QmsIssueTicketProcessAddQO(); + addRequest.setIssueTicketId(request.getId()); + addRequest.setHandlers(request.getHandlers().stream().map(item -> { + QmsIssueTicketProcessAddQO.HandlerItem handlerItem = new QmsIssueTicketProcessAddQO.HandlerItem(); + handlerItem.setTaskResultId(item.getTaskResultId()); + handlerItem.setHandlerUserId(item.getHandlerUserId()); + return handlerItem; + }).collect(Collectors.toList())); + issueTicketProcessControllerService.add(addRequest); + return; + } throw new NflgException(STATE.BusinessError, "只能分派巡检工单"); } + Short approvalStatus = request.getApprovalStatus(); + if (approvalStatus == null) { + VUtil.trueThrowBusinessError(!Objects.equals(ticket.getStatus(), (short) 0)) + .throwMessage("审批状态不能为空"); + approvalStatus = 0; + } + issueTicketToDoService.processed(ticket.getId()); // 3. 根据审批状态分支处理 - if (request.getApprovalStatus() == 1) { + if (approvalStatus == 1) { // 驳回:不创建处理记录,工单改为待流转,推送消息给创建人 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) @@ -404,7 +471,7 @@ public class QmsIssueTicketControllerService { // 更新工单审批状态和意见 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) - .set(QmsIssueTicket::getApprovalStatus, request.getApprovalStatus()) + .set(QmsIssueTicket::getApprovalStatus, approvalStatus) .set(request.getApprovalOpinion() != null, QmsIssueTicket::getApprovalOpinion, request.getApprovalOpinion()) .set(QmsIssueTicket::getUpdateUserId, currentUserId) @@ -2715,10 +2782,10 @@ public class QmsIssueTicketControllerService { // 8. 设置权限字段 if (isCreator) { // 创建人: - // - isDispatch=true(状态=0或1时) + // - isDispatch=true(存在未有效分派的不合格项时) // - isReview=true(状态=2时) // - isEdit=false(创建人无编辑权限) - vo.setIsDispatch(ticket.getStatus() != null && (ticket.getStatus() == 0 || ticket.getStatus() == 1)); + vo.setIsDispatch(hasPqcUndispatchedOrRejectedItems(ticket, processes)); vo.setIsReview(ticket.getStatus() != null && ticket.getStatus() == 2); vo.setIsEdit(false); vo.setIsShut(ticket.getStatus() != null && ticket.getStatus() == 2); @@ -2742,6 +2809,38 @@ public class QmsIssueTicketControllerService { return vo; } + private boolean hasPqcUndispatchedOrRejectedItems(QmsIssueTicket ticket, List processes) { + if (ticket.getStatus() == null || (ticket.getStatus() != 0 && ticket.getStatus() != 1)) { + return false; + } + List allUnqualified = pqcTaskRecordDetailsService.lambdaQuery() + .eq(QmsPqcTaskRecordDetails::getTaskId, ticket.getSourceId()) + .eq(QmsPqcTaskRecordDetails::getReviewEnable, false) + .list(); + Set allUnqualifiedIds = allUnqualified.stream() + .map(QmsPqcTaskRecordDetails::getId) + .collect(Collectors.toSet()); + if (allUnqualifiedIds.isEmpty()) { + return false; + } + + Set effectivelyDispatched = new HashSet<>(); + for (QmsIssueTicketProcess p : processes) { + if (StrUtil.isBlank(p.getTaskResultIds())) { + continue; + } + if (Objects.equals(p.getApprovalStatus(), (short) 1)) { + continue; + } + Arrays.stream(p.getTaskResultIds().split(",")) + .filter(StrUtil::isNotBlank) + .map(String::trim) + .map(Long::valueOf) + .forEach(effectivelyDispatched::add); + } + return !effectivelyDispatched.containsAll(allUnqualifiedIds); + } + /** * 解析文件列表 */ diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketProcessControllerService.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketProcessControllerService.java index a98ff508..39a162c5 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketProcessControllerService.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/service/QmsIssueTicketProcessControllerService.java @@ -95,7 +95,28 @@ public class QmsIssueTicketProcessControllerService { handlerUserIds.add(entry.getKey()); } - if (Objects.equals(ticket.getSourceType(), (short) 3)) { + if (Objects.equals(ticket.getSourceType(), (short) 1)) { + issueTicketToDoService.processed(ticket.getId()); + + for (Long handlerUserId : handlerUserIds) { + QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() + .setTicketId(ticket.getId()) + .setHandlerUserId(handlerUserId) + .setHasProcessed(false) + .setIsRead(false); + issueTicketToDoService.save(todoItem); + } + + if (!Objects.equals(ticket.getStatus(), (short) 1)) { + issueTicketService.lambdaUpdate() + .eq(QmsIssueTicket::getId, ticket.getId()) + .set(QmsIssueTicket::getStatus, (short) 1) + .set(QmsIssueTicket::getUpdateUserId, currentUserId) + .set(QmsIssueTicket::getUpdateUserName, currentUserName) + .set(QmsIssueTicket::getUpdateTime, now) + .update(); + } + } else if (Objects.equals(ticket.getSourceType(), (short) 3)) { issueTicketToDoService.lambdaUpdate() .eq(QmsIssueTicketToDo::getTicketId, ticket.getId()) .eq(QmsIssueTicketToDo::getHasProcessed, false) @@ -560,21 +581,20 @@ public class QmsIssueTicketProcessControllerService { // 3. 根据审批状态处理 if (approvalStatus == 1) { - boolean allHandlersRejected = isAllPqcHandlersRejected(ticket.getId()); - if (allHandlersRejected) { - issueTicketService.lambdaUpdate() - .eq(QmsIssueTicket::getId, ticket.getId()) - .set(QmsIssueTicket::getStatus, (short) 0) - .set(QmsIssueTicket::getUpdateUserId, currentUserId) - .set(QmsIssueTicket::getUpdateUserName, currentUserName) - .set(QmsIssueTicket::getUpdateTime, now) - .update(); + issueTicketService.lambdaUpdate() + .eq(QmsIssueTicket::getId, ticket.getId()) + .set(QmsIssueTicket::getStatus, (short) 1) + .set(QmsIssueTicket::getUpdateUserId, currentUserId) + .set(QmsIssueTicket::getUpdateUserName, currentUserName) + .set(QmsIssueTicket::getUpdateTime, now) + .update(); - QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() - .setTicketId(ticket.getId()) - .setHandlerUserId(ticket.getCreateUserId()); - issueTicketToDoService.save(todoItem); - } + QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() + .setTicketId(ticket.getId()) + .setHandlerUserId(ticket.getCreateUserId()) + .setHasProcessed(false) + .setIsRead(false); + issueTicketToDoService.save(todoItem); } else if (approvalStatus == 0) { // 通过:校验措施(临时措施或永久措施至少填一个) boolean hasMeasures = checkPqcMeasures(process.getId()); @@ -665,29 +685,4 @@ public class QmsIssueTicketProcessControllerService { .anyMatch(p -> p.getApprovalTime() != null || currentUserId.equals(p.getHandlerUserId()))); } - private boolean isAllPqcHandlersRejected(Long ticketId) { - List processes = issueTicketProcessService.lambdaQuery() - .eq(QmsIssueTicketProcess::getIssueTicketId, ticketId) - .list(); - - List dispatchedProcesses = processes.stream() - .filter(p -> StrUtil.isNotBlank(p.getTaskResultIds())) - .toList(); - List effectiveProcesses = dispatchedProcesses.isEmpty() - ? processes - : dispatchedProcesses; - - Map> processMap = effectiveProcesses.stream() - .filter(p -> p.getHandlerUserId() != null) - .collect(Collectors.groupingBy(QmsIssueTicketProcess::getHandlerUserId)); - if (processMap.isEmpty()) { - return false; - } - - return processMap - .values() - .stream() - .allMatch(list -> list.stream() - .anyMatch(p -> Objects.equals(p.getApprovalStatus(), (short) 1))); - } } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsIssueTicketDispatchMultipleQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsIssueTicketDispatchMultipleQO.java index 03b5e468..b4e9c209 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsIssueTicketDispatchMultipleQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsIssueTicketDispatchMultipleQO.java @@ -1,5 +1,7 @@ package com.nflg.wms.common.pojo.qo; +import com.fasterxml.jackson.annotation.JsonAlias; +import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -15,6 +17,7 @@ public class QmsIssueTicketDispatchMultipleQO { * 工单ID(qms_issue_ticket.id) */ @NotNull(message = "工单ID不能为空") + @JsonAlias({"ticketId", "issueTicketId"}) private Long id; /** @@ -22,14 +25,38 @@ public class QmsIssueTicketDispatchMultipleQO { */ private List handlerUserIds; + /** + * 按不合格项分派处理人 + */ + @Valid + private List handlers; + /** * 审批状态(0=通过,1=驳回) */ - @NotNull(message = "审批状态不能为空") private Short approvalStatus; /** * 审批意见 */ private String approvalOpinion; + + /** + * 处理人项 + */ + @Data + public static class HandlerItem { + + /** + * 任务结果ID + */ + @NotNull(message = "任务结果ID不能为空") + private Long taskResultId; + + /** + * 处理人用户ID + */ + @NotNull(message = "处理人用户ID不能为空") + private Long handlerUserId; + } } diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsPqcTicketDispatchQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsPqcTicketDispatchQO.java index 76327d9a..1a265464 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsPqcTicketDispatchQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/QmsPqcTicketDispatchQO.java @@ -1,5 +1,6 @@ package com.nflg.wms.common.pojo.qo; +import com.fasterxml.jackson.annotation.JsonAlias; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -17,6 +18,7 @@ public class QmsPqcTicketDispatchQO { * 工单ID(必传) */ @NotNull(message = "工单ID不能为空") + @JsonAlias({"id", "issueTicketId"}) private Long ticketId; /** @@ -34,6 +36,7 @@ public class QmsPqcTicketDispatchQO { */ @NotEmpty(message = "处理人列表不能为空") @Valid + @JsonAlias("handlers") private List assignees; /** @@ -45,12 +48,14 @@ public class QmsPqcTicketDispatchQO { * 不合格项ID(多个用逗号拼接) */ @NotEmpty(message = "不合格项ID不能为空") + @JsonAlias("taskResultId") private String taskResultIds; /** * 处理人ID */ @NotNull(message = "处理人ID不能为空") + @JsonAlias("handlerUserId") private Long userId; } }