diff --git a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsIssueTicketController.java b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsIssueTicketController.java index d6971a69..ae38390c 100644 --- a/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsIssueTicketController.java +++ b/nflg-qms-admin/src/main/java/com/nflg/qms/admin/controller/QmsIssueTicketController.java @@ -162,7 +162,7 @@ public class QmsIssueTicketController extends BaseController { /** * 查询PQC工单详情(本人相关) - * 创建人可查看全部问题明细和措施,处理人仅查看分配给自己的问题明细和措施 + * 创建人可查看全部问题明细和措施,处理人/直属领导仅查看本人相关问题明细和措施 */ @GetMapping("detail/my-pqc-ticket") public ApiResult myPqcTicketDetail(@NotNull(message = "ID不能为空") Long id) { 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 c97dc06f..65e8a027 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 @@ -1,4 +1,4 @@ -package com.nflg.qms.admin.service; +package com.nflg.qms.admin.service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; @@ -28,8 +28,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; /** - * 璐ㄩ噺闂宸ュ崟 ControllerService - * 璐ㄩ噺闂宸ュ崟 涓氬姟閫昏緫 + * 质量问题工单 ControllerService + * 质量问题工单 业务逻辑 */ @Service @Component @@ -102,48 +102,48 @@ public class QmsIssueTicketControllerService { private IQmsPqcInspectionPointItemsService pqcInspectionPointItemsService; /** - * 鍙戣捣宸℃宸ュ崟 - * 1. 鏍¢獙宸ュ崟瀛樺湪涓旀潵婧愮被鍨嬩负宸℃锛坰ourceType=2锛? - * 2. 鏍¢獙璐熻矗浜哄瓨鍦? - * 3. 鏇存柊宸ュ崟鐘舵€佷负澶勭悊涓紙status=1锛? - * 4. 璁剧疆瀹℃壒浜篒D鍜屽鍚? + * 发起巡检工单 + * 1. 校验工单存在且来源类型为巡检(sourceType=2) + * 2. 校验负责人存在 + * 3. 更新工单状态为处理中(status=1) + * 4. 设置审批人ID和姓名 */ @Transactional(rollbackFor = Exception.class) public void dispatch(@Valid QmsIssueTicketDispatchQO request) { - // 1. 鏍¢獙宸ュ崟瀛樺湪 + // 1. 校验工单存在 QmsIssueTicket ticket = issueTicketService.getById(request.getId()); - VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 鏍¢獙宸ュ崟鏉ユ簮绫诲瀷涓哄贰妫€ + // 2. 校验工单来源类型为巡检 if (!Objects.equals(ticket.getSourceType(), (short) 2)) { - throw new NflgException(STATE.BusinessError, "鍙兘鍙戣捣宸℃宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只能发起巡检工单"); } - // 3. 鏍¢獙璐熻矗浜哄瓨鍦? + // 3. 校验负责人存在 User handlerUser = userService.getById(request.getHandlerUserId()); - VUtil.trueThrowBusinessError(Objects.isNull(handlerUser)).throwMessage("璐熻矗浜轰笉瀛樺湪"); + VUtil.trueThrowBusinessError(Objects.isNull(handlerUser)).throwMessage("负责人不存在"); - // 4. 鏍¢獙宸ュ崟蹇呭~瀛楁瀹屾暣鎬? + // 4. 校验工单必填字段完整性 VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getTicketTitle())) - .throwMessage("宸ュ崟鏍囬涓嶈兘涓虹┖"); + .throwMessage("工单标题不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getProjectNo())) - .throwMessage("宸ョ▼缂栧彿涓嶈兘涓虹┖"); + .throwMessage("工程编号不能为空"); VUtil.trueThrowBusinessError(ticket.getIncidentType() == null) - .throwMessage("浜嬫晠绫诲瀷涓嶈兘涓虹┖"); + .throwMessage("事故类型不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getExceptionCode())) - .throwMessage("寮傚父浠g爜涓嶈兘涓虹┖"); + .throwMessage("异常代码不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getImpactQuantity())) - .throwMessage("褰卞搷鏁伴噺涓嶈兘涓虹┖"); + .throwMessage("影响数量不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getIncidentLocation())) - .throwMessage("浜嬩欢鍦扮偣涓嶈兘涓虹┖"); + .throwMessage("事件地点不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getIncidentDescription())) - .throwMessage("浜嬩欢鎻忚堪涓嶈兘涓虹┖"); + .throwMessage("事件描述不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getIncidentReason())) - .throwMessage("浜嬩欢鍘熷洜涓嶈兘涓虹┖"); + .throwMessage("事件原因不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(ticket.getIncidentConsequence())) - .throwMessage("浜嬩欢鍚庢灉涓嶈兘涓虹┖"); + .throwMessage("事件后果不能为空"); - // 5. 鏍¢獙宸ュ崟鍥剧墖瀛楁瀹屾暣鎬э紙濡傛灉鏈夊浘鐗囩殑璇濓級 + // 5. 校验工单图片字段完整性(如果有图片的话) if (StrUtil.isNotBlank(ticket.getImageIds())) { List imageIds = Arrays.stream(ticket.getImageIds().split(",")) .filter(StrUtil::isNotBlank) @@ -158,17 +158,17 @@ public class QmsIssueTicketControllerService { for (FileUploadRecord record : fileRecords) { VUtil.trueThrowBusinessError(StrUtil.isBlank(record.getFileName())) - .throwMessage("鍥剧墖鏂囦欢鍚嶄笉鑳戒负绌?); + .throwMessage("图片文件名不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(record.getUrl())) - .throwMessage("鍥剧墖URL涓嶈兘涓虹┖"); + .throwMessage("图片URL不能为空"); } } } - // 6. 鏇存柊宸ュ崟鐘舵€佸拰瀹℃壒浜轰俊鎭? + // 6. 更新工单状态和审批人信息 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, request.getId()) - .set(QmsIssueTicket::getStatus, (short) 1) // 鐘舵€侊細1=澶勭悊涓? + .set(QmsIssueTicket::getStatus, (short) 1) // 状态:1=处理中 .set(QmsIssueTicket::getApprovalUserId, request.getHandlerUserId()) .set(QmsIssueTicket::getApprovalUserName, handlerUser.getUserName()) .set(QmsIssueTicket::getApprovalTime, LocalDateTime.now()) @@ -177,7 +177,7 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, LocalDateTime.now()) .update(); - // 7. 鎺ㄩ€佸緟鍔炴秷鎭粰璐熻矗浜? + // 7. 推送待办消息给负责人 QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(request.getId()) .setHandlerUserId(request.getHandlerUserId()); @@ -185,12 +185,12 @@ public class QmsIssueTicketControllerService { } /** - * 鍙戣捣PQC宸ュ崟 - * 1. 鏍¢獙宸ュ崟瀛樺湪涓旀潵婧愮被鍨嬩负PQC锛坰ourceType=3锛? - * 2. 鎸夊鐞嗕汉鍒嗙粍鍚堝苟涓嶅悎鏍奸」ID - * 3. 涓烘瘡涓鐞嗕汉鍒涘缓澶勭悊璁板綍 - * 4. 鎺ㄩ€佸緟鍔炴秷鎭粰姣忎釜澶勭悊浜? - * 5. 鏇存柊宸ュ崟鐘舵€佷负澶勭悊涓? + * 发起PQC工单 + * 1. 校验工单存在且来源类型为PQC(sourceType=3) + * 2. 按处理人分组合并不合格项ID + * 3. 为每个处理人创建处理记录 + * 4. 推送待办消息给每个处理人 + * 5. 更新工单状态为处理中 */ @Transactional(rollbackFor = Exception.class) public void dispatchPqcTicket(QmsPqcTicketDispatchQO request) { @@ -198,21 +198,21 @@ public class QmsIssueTicketControllerService { String currentUserName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 1. 鏍¢獙宸ュ崟瀛樺湪 + // 1. 校验工单存在 QmsIssueTicket ticket = issueTicketService.getById(request.getTicketId()); - VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 鏍¢獙宸ュ崟鏉ユ簮绫诲瀷涓篜QC + // 2. 校验工单来源类型为PQC if (!Objects.equals(ticket.getSourceType(), (short) 3)) { - throw new NflgException(STATE.BusinessError, "鍙兘鍙戣捣PQC宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只能发起PQC工单"); } - // 3. 鏍¢獙宸ュ崟鐘舵€佷负寰呮祦杞? + // 3. 校验工单状态为待流转 if (!Objects.equals(ticket.getStatus(), (short) 0)) { - throw new NflgException(STATE.BusinessError, "宸ュ崟鐘舵€佷笉鏄緟娴佽浆"); + throw new NflgException(STATE.BusinessError, "工单状态不是待流转"); } - // 4. 鏇存柊宸ュ崟鐨勪簨鏁呯被鍨嬪拰澶囨敞 + // 4. 更新工单的事故类型和备注 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, request.getTicketId()) .set(request.getIncidentType() != null, QmsIssueTicket::getIncidentType, request.getIncidentType()) @@ -222,31 +222,31 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, now) .update(); - // 5. 鎸夊鐞嗕汉鍒嗙粍鍚堝苟涓嶅悎鏍奸」ID + // 5. 按处理人分组合并不合格项ID Map> userTaskMap = new LinkedHashMap<>(); for (QmsPqcTicketDispatchQO.AssigneeItem item : request.getAssignees()) { userTaskMap.computeIfAbsent(item.getUserId(), k -> new ArrayList<>()) .add(item.getTaskResultIds()); } - // 6. 鎵归噺鏌ヨ澶勭悊浜轰俊鎭? + // 6. 批量查询处理人信息 List userIds = new ArrayList<>(userTaskMap.keySet()); List users = userService.listByIds(userIds); Map userMap = users.stream() .collect(Collectors.toMap(User::getId, u -> u)); - // 7. 涓烘瘡涓鐞嗕汉鍒涘缓澶勭悊璁板綍骞舵帹閫佸緟鍔? + // 7. 为每个处理人创建处理记录并推送待办 for (Map.Entry> entry : userTaskMap.entrySet()) { Long userId = entry.getKey(); List taskResultIds = entry.getValue(); User user = userMap.get(userId); - VUtil.trueThrowBusinessError(user == null).throwMessage("澶勭悊浜轰笉瀛樺湪"); + VUtil.trueThrowBusinessError(user == null).throwMessage("处理人不存在"); - // 鎷兼帴涓嶅悎鏍奸」ID锛堢敤閫楀彿锛? + // 拼接不合格项ID(用逗号) String taskResultIdsStr = String.join(",", taskResultIds); - // 鍒涘缓澶勭悊璁板綍 + // 创建处理记录 QmsIssueTicketProcess process = new QmsIssueTicketProcess() .setIssueTicketId(ticket.getId()) .setHandlerUserId(userId) @@ -254,14 +254,14 @@ public class QmsIssueTicketControllerService { .setTaskResultIds(taskResultIdsStr); issueTicketProcessService.save(process); - // 鎺ㄩ€佸緟鍔炴秷鎭? + // 推送待办消息 QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(ticket.getId()) .setHandlerUserId(userId); issueTicketToDoService.save(todoItem); } - // 8. 鏇存柊宸ュ崟鐘舵€佷负1锛堝鐞嗕腑锛? + // 8. 更新工单状态为1(处理中) issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) .set(QmsIssueTicket::getStatus, (short) 1) @@ -272,11 +272,11 @@ public class QmsIssueTicketControllerService { } /** - * 宸℃宸ュ崟鍒嗘淳锛堟敮鎸佸浜猴級 - * 1. 鏍¢獙宸ュ崟瀛樺湪涓旀潵婧愮被鍨嬩负宸℃锛坰ourceType=2锛? - * 2. 鏍¢獙鎵€鏈夊鐞嗕汉瀛樺湪 - * 3. 涓烘瘡涓鐞嗕汉鍒涘缓涓€鏉″鐞嗚褰曪紙qms_issue_ticket_process锛? - * 4. 鎺ㄩ€佸緟鍔炴秷鎭粰姣忎釜澶勭悊浜? + * 巡检工单分派(支持多人) + * 1. 校验工单存在且来源类型为巡检(sourceType=2) + * 2. 校验所有处理人存在 + * 3. 为每个处理人创建一条处理记录(qms_issue_ticket_process) + * 4. 推送待办消息给每个处理人 */ @Transactional(rollbackFor = Exception.class) public void dispatchMultiple(@Valid QmsIssueTicketDispatchMultipleQO request) { @@ -284,18 +284,18 @@ public class QmsIssueTicketControllerService { String currentUserName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 1. 鏍¢獙宸ュ崟瀛樺湪 + // 1. 校验工单存在 QmsIssueTicket ticket = issueTicketService.getById(request.getId()); - VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 鏍¢獙宸ュ崟鏉ユ簮绫诲瀷涓哄贰妫€ + // 2. 校验工单来源类型为巡检 if (!Objects.equals(ticket.getSourceType(), (short) 2)) { - throw new NflgException(STATE.BusinessError, "鍙兘鍒嗘淳宸℃宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只能分派巡检工单"); } - // 3. 鏍规嵁瀹℃壒鐘舵€佸垎鏀鐞? + // 3. 根据审批状态分支处理 if (request.getApprovalStatus() == 1) { - // 椹冲洖锛氫笉鍒涘缓澶勭悊璁板綍锛屽伐鍗曟敼涓哄凡瀹屾垚锛屾帹閫佹秷鎭粰鍒涘缓浜? + // 驳回:不创建处理记录,工单改为已完成,推送消息给创建人 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) .set(QmsIssueTicket::getStatus, (short) 2) @@ -306,19 +306,19 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, now) .update(); - // 鎺ㄩ€佸緟鍔炴秷鎭粰鍒涘缓浜? + // 推送待办消息给创建人 QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(ticket.getId()) .setHandlerUserId(ticket.getCreateUserId()); issueTicketToDoService.save(todoItem); } else { - // 閫氳繃锛氭寜鐜版湁娴佺▼澶勭悊 - // 鏍¢獙涓嶈兘鍒嗛厤缁欒嚜宸? + // 通过:按现有流程处理 + // 校验不能分配给自己 if (request.getHandlerUserIds().contains(currentUserId)) { - throw new NflgException(STATE.BusinessError, "涓嶈兘灏嗗伐鍗曞垎閰嶇粰鑷繁"); + throw new NflgException(STATE.BusinessError, "不能将工单分配给自己"); } - // 鏇存柊宸ュ崟瀹℃壒鐘舵€佸拰鎰忚 + // 更新工单审批状态和意见 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) .set(QmsIssueTicket::getApprovalStatus, request.getApprovalStatus()) @@ -329,44 +329,44 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, now) .update(); - // 鎵归噺鏌ヨ骞舵牎楠屾墍鏈夊鐞嗕汉 + // 批量查询并校验所有处理人 List handlerUsers = userService.listByIds(request.getHandlerUserIds()); if (handlerUsers.size() != request.getHandlerUserIds().size()) { - throw new NflgException(STATE.BusinessError, "閮ㄥ垎澶勭悊浜轰笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "部分处理人不存在"); } - // 鏋勫缓澶勭悊浜篒D鍒扮敤鎴风殑鏄犲皠 + // 构建处理人ID到用户的映射 Map handlerUserMap = handlerUsers.stream() .collect(Collectors.toMap(User::getId, user -> user)); - // 涓烘瘡涓鐞嗕汉鍒涘缓澶勭悊璁板綍骞舵帹閫佸緟鍔? + // 为每个处理人创建处理记录并推送待办 List processes = new ArrayList<>(); List todoItems = new ArrayList<>(); for (Long handlerUserId : request.getHandlerUserIds()) { User handlerUser = handlerUserMap.get(handlerUserId); - // 鍒涘缓澶勭悊璁板綍 + // 创建处理记录 QmsIssueTicketProcess process = new QmsIssueTicketProcess() .setIssueTicketId(ticket.getId()) .setHandlerUserId(handlerUserId) .setHandlerUserName(handlerUser.getUserName()); processes.add(process); - // 鍒涘缓寰呭姙娑堟伅 + // 创建待办消息 QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(ticket.getId()) .setHandlerUserId(handlerUserId); todoItems.add(todoItem); } - // 鎵归噺淇濆瓨澶勭悊璁板綍 + // 批量保存处理记录 issueTicketProcessService.saveBatch(processes); - // 鎵归噺鎺ㄩ€佸緟鍔炴秷鎭? + // 批量推送待办消息 issueTicketToDoService.saveBatch(todoItems); - // 濡傛灉宸ュ崟鐘舵€佹槸寰呮祦杞?0)锛屾洿鏂颁负澶勭悊涓?1) + // 如果工单状态是待流转(0),更新为处理中(1) if (ticket.getStatus() != null && ticket.getStatus() == 0) { issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) @@ -388,10 +388,10 @@ public class QmsIssueTicketControllerService { private IDepartmentService departmentService; /** - * PDI鏂板缓宸ュ崟骞惰繑鍥炰笉鍚堟牸妫€娴嬮」 - * 1. 鍒涘缓宸ュ崟锛堝彧鍒涘缓宸ュ崟涓昏〃锛屼笉鍒涘缓澶勭悊鏄庣粏锛? - * 2. 鏌ヨ浠诲姟鐨勪笉鍚堟牸妫€娴嬮」 - * 3. 杩斿洖宸ュ崟ID鍜屼笉鍚堟牸妫€娴嬮」鍒楄〃 + * PDI新建工单并返回不合格检测项 + * 1. 创建工单(只创建工单主表,不创建处理明细) + * 2. 查询任务的不合格检测项 + * 3. 返回工单ID和不合格检测项列表 */ @Transactional(rollbackFor = Exception.class) public QmsPdiCreateTicketResultVO createAndQueryPdiTicket(@Valid QmsPdiCreateAndQueryTicketQO request) { @@ -399,51 +399,51 @@ public class QmsIssueTicketControllerService { String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 1. 鏌ヨ浠诲姟璁板綍 + // 1. 查询任务记录 QmsPdiTaskRecord taskRecord = pdiTaskRecordService.getById(request.getTaskRecordId()); if (Objects.isNull(taskRecord)) { - throw new NflgException(STATE.BusinessError, "PDI妫€娴嬩换鍔¤褰曚笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PDI检测任务记录不存在"); } - // 2. 鏍¢獙浠诲姟鐘舵€佸繀椤讳负3锛堝緟娴佽浆锛夋垨4锛堥€炬湡锛? + // 2. 校验任务状态必须为3(待流转)或4(逾期) if (!Objects.equals(taskRecord.getInspectionEnable(), 3) && !Objects.equals(taskRecord.getInspectionEnable(), 4)) { - throw new NflgException(STATE.BusinessError, "鍙湁寰呮祦杞垨閫炬湡鐘舵€佺殑浠诲姟鎵嶈兘鍒涘缓宸ュ崟锛屽綋鍓嶇姸鎬侊細" + taskRecord.getInspectionEnable()); + throw new NflgException(STATE.BusinessError, "只有待流转或逾期状态的任务才能创建工单,当前状态:" + taskRecord.getInspectionEnable()); } - // 3. 鏍¢獙鏄惁宸插瓨鍦ㄥ伐鍗? + // 3. 校验是否已存在工单 QmsIssueTicket existingTicket = issueTicketService.lambdaQuery() .eq(QmsIssueTicket::getSourceType, (short) 1) .eq(QmsIssueTicket::getSourceId, request.getTaskRecordId()) .one(); if (existingTicket != null) { - throw new NflgException(STATE.BusinessError, "璇ヤ换鍔″凡瀛樺湪宸ュ崟锛堝伐鍗曠紪鍙凤細" + existingTicket.getTicketNo() + "锛夛紝璇蜂娇鐢ㄨ拷鍔犲鐞嗚褰曟帴鍙?); + throw new NflgException(STATE.BusinessError, "该任务已存在工单(工单编号:" + existingTicket.getTicketNo() + "),请使用追加处理记录接口"); } - // 3. 鏌ヨ妫€娴嬭鍒? + // 3. 查询检测规则 QmsPdiDetectionRules rules = pdiDetectionRulesService.getById(taskRecord.getDetectionRulesId()); if (Objects.isNull(rules)) { - throw new NflgException(STATE.BusinessError, "PDI妫€娴嬭鍒欎笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PDI检测规则不存在"); } - // 4. 鐢熸垚宸ュ崟鏍囬 + // 4. 生成工单标题 String ticketTitle; if (Objects.equals(rules.getInspectionType(), 0)) { - // 鏂版満妫€娴嬶細鏈哄瀷缂栧彿-鏈哄彴鍙?璁㈠崟缂栧彿-鍑哄巶妫€楠?妫€娴嬬増鏈彿 + // 新机检测:机型编号-机台号-订单编号-出厂检验-检测版本号 String machineNo = rules.getModelNo() != null ? rules.getModelNo() : ""; String deviceNo = taskRecord.getDeviceNo() != null ? taskRecord.getDeviceNo() : ""; String orderNo = taskRecord.getOrderNo() != null ? taskRecord.getOrderNo() : ""; String version = rules.getInspectionVersion() != null ? rules.getInspectionVersion() : ""; - ticketTitle = machineNo + "-" + deviceNo + "-" + orderNo + "-鍑哄巶妫€楠?" + version; + ticketTitle = machineNo + "-" + deviceNo + "-" + orderNo + "-出厂检验-" + version; } else { - // 搴撳瓨妫€娴嬶細鏈哄瀷缂栧彿-璁㈠崟缂栧彿-搴撳瓨妫€楠?妫€娴嬬増鏈彿 + // 库存检测:机型编号-订单编号-库存检验-检测版本号 String machineNo = rules.getModelNo() != null ? rules.getModelNo() : ""; String orderNo = taskRecord.getOrderNo() != null ? taskRecord.getOrderNo() : ""; String version = rules.getInspectionVersion() != null ? rules.getInspectionVersion() : ""; - ticketTitle = machineNo + "-" + orderNo + "-搴撳瓨妫€楠?" + version; + ticketTitle = machineNo + "-" + orderNo + "-库存检验-" + version; } - // 5. 鏌ヨ鎵€鏈変笉鍚堟牸椤癸紝姹囨€荤敓鎴恑ncidentDescription + // 5. 查询所有不合格项,汇总生成incidentDescription String incidentDescription = ""; List allUnqualifiedResults = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, request.getTaskRecordId()) @@ -455,7 +455,7 @@ public class QmsIssueTicketControllerService { int index = 1; for (QmsPdiInspectionResults result : allUnqualifiedResults) { if (index > 1) { - descBuilder.append("锛?); + descBuilder.append(";"); } descBuilder.append(index).append(". "); descBuilder.append(result.getRemark() != null ? result.getRemark() : ""); @@ -464,16 +464,16 @@ public class QmsIssueTicketControllerService { incidentDescription = descBuilder.toString(); } - // 6. 缁熻涓嶅悎鏍兼娴嬮」鏁伴噺 + // 6. 统计不合格检测项数量 long unqualifiedCount = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, request.getTaskRecordId()) .eq(QmsPdiInspectionResults::getInspectionItemResults, false) .count(); - // 7. 鐢熸垚宸ュ崟缂栧彿 + // 7. 生成工单编号 String ticketNo = basdeSerialNumberControllerService.generateSerialNumber(38); - // 8. 鍒涘缓宸ュ崟涓昏〃 + // 8. 创建工单主表 QmsIssueTicket entity = new QmsIssueTicket() .setSourceType((short) 1) .setSourceId(request.getTaskRecordId()) @@ -495,16 +495,16 @@ public class QmsIssueTicketControllerService { issueTicketService.save(entity); - // 鍒涘缓宸ュ崟鎴愬姛鍚庯紝灏嗕换鍔$姸鎬佷粠3锛堝緟娴佽浆锛夋敼涓?锛堝凡瀹屾垚锛? + // 创建工单成功后,将任务状态从3(待流转)改为2(已完成) pdiTaskRecordService.lambdaUpdate() .eq(QmsPdiTaskRecord::getId, taskRecord.getId()) .set(QmsPdiTaskRecord::getInspectionEnable, 2) .update(); - // 9. 鏌ヨ璇ヤ换鍔$殑涓嶅悎鏍兼娴嬮」 + // 9. 查询该任务的不合格检测项 List unqualifiedItems = initiatePdiTicket(request.getTaskRecordId()); - // 10. 鏋勫缓杩斿洖缁撴灉 + // 10. 构建返回结果 QmsPdiCreateTicketResultVO result = new QmsPdiCreateTicketResultVO(); result.setTicketId(entity.getId()); result.setTicketNo(ticketNo); @@ -521,10 +521,10 @@ public class QmsIssueTicketControllerService { QmsPqcTaskRecord taskRecord = pqcTaskRecordService.getById(request.getTaskRecordId()); if (Objects.isNull(taskRecord)) { - throw new NflgException(STATE.BusinessError, "PQC妫€娴嬩换鍔¤褰曚笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PQC检测任务记录不存在"); } if (!Objects.equals(taskRecord.getStatus(), (short) 3)) { - throw new NflgException(STATE.BusinessError, "鍙湁宸插鏍哥殑PQC浠诲姟鎵嶈兘鍒涘缓宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只有已复核的PQC任务才能创建工单"); } QmsIssueTicket existingTicket = issueTicketService.lambdaQuery() @@ -533,21 +533,21 @@ public class QmsIssueTicketControllerService { .one(); if (existingTicket != null) { throw new NflgException(STATE.BusinessError, - "璇ヤ换鍔″凡瀛樺湪宸ュ崟锛堝伐鍗曠紪鍙凤細" + existingTicket.getTicketNo() + "锛夛紝璇蜂娇鐢ㄨ拷鍔犲鐞嗚褰曟帴鍙?); + "该任务已存在工单(工单编号:" + existingTicket.getTicketNo() + "),请使用追加处理记录接口"); } List allDetails = pqcTaskRecordDetailsService.lambdaQuery() .eq(QmsPqcTaskRecordDetails::getTaskId, request.getTaskRecordId()) .list(); if (CollectionUtil.isEmpty(allDetails)) { - throw new NflgException(STATE.BusinessError, "PQC浠诲姟涓嶅瓨鍦ㄦ娴嬮」"); + throw new NflgException(STATE.BusinessError, "PQC任务不存在检测项"); } List unqualifiedDetails = allDetails.stream() .filter(detail -> Boolean.FALSE.equals(detail.getReviewEnable())) .collect(Collectors.toList()); if (CollectionUtil.isEmpty(unqualifiedDetails)) { - throw new NflgException(STATE.BusinessError, "璇ヤ换鍔′笉瀛樺湪涓嶅悎鏍兼娴嬮」"); + throw new NflgException(STATE.BusinessError, "该任务不存在不合格检测项"); } QmsPqcInspectionPoint point = pqcInspectionPointService.getById(taskRecord.getInspectionPointId()); @@ -633,10 +633,10 @@ public class QmsIssueTicketControllerService { } /** - * PDI鍙戣捣宸ュ崟锛氭煡璇换鍔$殑涓嶅悎鏍兼娴嬮」 + * PDI发起工单:查询任务的不合格检测项 */ public List initiatePdiTicket(Long taskRecordId) { - // 鏌ヨ涓嶅悎鏍兼娴嬮」 + // 查询不合格检测项 List failedItems = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, taskRecordId) .eq(QmsPdiInspectionResults::getInspectionItemResults, false) @@ -646,7 +646,7 @@ public class QmsIssueTicketControllerService { return null; } - // 鏀堕泦鎵€鏈夋楠岄」ID锛堜粎鏌ヨtype=0/1/3鐨勶紝杩欎簺鏈塩omponentsDes绛夊瓧娈碉級 + // 收集所有检验项ID(仅查询type=0/1/3的,这些有componentsDes等字段) List statusItemIds = failedItems.stream() .filter(item -> item.getInspectionItemType() != null && item.getInspectionItemType() != 2) .map(QmsPdiInspectionResults::getInspectionItemId) @@ -654,7 +654,7 @@ public class QmsIssueTicketControllerService { .distinct() .collect(Collectors.toList()); - // 鏌ヨ妫€娴嬭鍒欑姸鎬侀」淇℃伅 + // 查询检测规则状态项信息 Map statusItemMap = new HashMap<>(); if (!statusItemIds.isEmpty()) { List statusItems = pdiStatusItemService.lambdaQuery() @@ -664,7 +664,7 @@ public class QmsIssueTicketControllerService { .collect(Collectors.toMap(QmsPdiDetectionRulesStatusItem::getId, item -> item, (a, b) -> a)); } - // 鏀堕泦鎵€鏈夊浘鐗嘔D锛堟娴嬬粨鏋滃浘鐗囷級 + // 收集所有图片ID(检测结果图片) Set imageIds = failedItems.stream() .map(QmsPdiInspectionResults::getInspectionItemImage) .filter(StrUtil::isNotBlank) @@ -673,7 +673,7 @@ public class QmsIssueTicketControllerService { .map(Long::valueOf) .collect(Collectors.toSet()); - // 鏀堕泦鎵€鏈夌ず渚嬪浘ID锛堢姸鎬侀」涓殑绀轰緥鍥撅級 + // 收集所有示例图ID(状态项中的示例图) Set exampleImageIds = statusItemMap.values().stream() .map(QmsPdiDetectionRulesStatusItem::getInspectionImage) .filter(StrUtil::isNotBlank) @@ -682,10 +682,10 @@ public class QmsIssueTicketControllerService { .map(Long::valueOf) .collect(Collectors.toSet()); - // 鍚堝苟鎵€鏈夊浘鐗嘔D + // 合并所有图片ID imageIds.addAll(exampleImageIds); - // 鏌ヨ鍥剧墖鏂囦欢淇℃伅 + // 查询图片文件信息 Map imageMap = new HashMap<>(); if (!imageIds.isEmpty()) { List records = fileUploadRecordService.lambdaQuery() @@ -695,7 +695,7 @@ public class QmsIssueTicketControllerService { .collect(Collectors.toMap(FileUploadRecord::getId, r -> r, (a, b) -> a)); } - // 鏋勫缓杩斿洖鍊? + // 构建返回值 final Map finalImageMap = imageMap; final Map finalStatusItemMap = statusItemMap; @@ -712,12 +712,12 @@ public class QmsIssueTicketControllerService { vo.setInspectionTime(item.getInspectionTime()); vo.setInspectionBy(item.getInspectionBy()); - // 浠庢娴嬭鍒欑姸鎬侀」涓幏鍙栭儴浠舵弿杩般€佹鏌ユ牳瀹炲唴瀹广€佹娴嬬ず渚嬪浘 - // 浠卼ype=0/1/3鏈夎繖浜涘瓧娈碉紝type=2锛堣杞﹀墠锛夋病鏈? + // 从检测规则状态项中获取部件描述、检查核实内容、检测示例图 + // 仅type=0/1/3有这些字段,type=2(装车前)没有 if (item.getInspectionItemType() != null && item.getInspectionItemType() != 2) { QmsPdiDetectionRulesStatusItem statusItem = finalStatusItemMap.get(item.getInspectionItemId()); if (statusItem != null) { - // 閫氳繃componentsId鏌ヨ閮ㄤ欢鍚嶇О + // 通过componentsId查询部件名称 if (statusItem.getComponentsId() != null) { QmsPdiComponentAnagement component = pdiComponentAnagementService.getById(statusItem.getComponentsId()); if (component != null) { @@ -726,7 +726,7 @@ public class QmsIssueTicketControllerService { } vo.setInspectionContent(statusItem.getInspectionContent()); - // 瑙f瀽妫€娴嬬ず渚嬪浘 + // 解析检测示例图 if (StrUtil.isNotBlank(statusItem.getInspectionImage())) { List exampleImageList = Arrays.stream(statusItem.getInspectionImage().split(",")) .filter(StrUtil::isNotBlank) @@ -746,7 +746,7 @@ public class QmsIssueTicketControllerService { }) .filter(Objects::nonNull) .collect(Collectors.toList()); - // 鍙栫涓€寮犲浘鐗囩殑URL浣滀负绀轰緥鍥? + // 取第一张图片的URL作为示例图 if (!exampleImageList.isEmpty()) { vo.setInspectionExampleImage(exampleImageList.get(0).getUrl()); } @@ -754,7 +754,7 @@ public class QmsIssueTicketControllerService { } } - // 瑙f瀽妫€楠岀幇鍦哄浘鐗囦负 FileDetailVO 鍒楄〃 + // 解析检验现场图片为 FileDetailVO 列表 if (StrUtil.isNotBlank(item.getInspectionItemImage())) { List imageList = Arrays.stream(item.getInspectionItemImage().split(",")) .filter(StrUtil::isNotBlank) @@ -784,22 +784,22 @@ public class QmsIssueTicketControllerService { } /** - * 瀹℃牳璐ㄩ噺闂宸ュ崟 - * 鏇存柊瀹℃壒鐘舵€併€佸鎵规剰瑙併€佸鎵逛汉淇℃伅銆佷簨鏁呯被鍨嬶紝骞舵洿鏂板伐鍗曠姸鎬? + * 审核质量问题工单 + * 更新审批状态、审批意见、审批人信息、事故类型,并更新工单状态 */ @Transactional(rollbackFor = Exception.class) public void incomingInspectionAudit(@Valid QmsIncomingInspectionIssueTicketAuditQO request) { - // 鏍¢獙宸ュ崟瀛樺湪 + // 校验工单存在 QmsIssueTicket entity = issueTicketService.getById(request.getId()); VUtil.trueThrowBusinessError(Objects.isNull(entity)) - .throwMessage("璐ㄩ噺闂宸ュ崟涓嶅瓨鍦?); - VUtil.trueThrowBusinessError(Objects.nonNull(entity.getApprovalStatus())).throwMessage("璇峰嬁閲嶅瀹℃壒"); + .throwMessage("质量问题工单不存在"); + VUtil.trueThrowBusinessError(Objects.nonNull(entity.getApprovalStatus())).throwMessage("请勿重复审批"); - // 鏍¢獙瀹℃壒鐘舵€佸悎娉曟€? + // 校验审批状态合法性 Set validApprovalStatus = Stream.of((short) 0, (short) 1, (short) 2, (short) 3, (short) 4, (short) 5, (short) 6) .collect(Collectors.toSet()); VUtil.trueThrowBusinessError(!validApprovalStatus.contains(request.getApprovalStatus())) - .throwMessage("瀹℃壒鐘舵€佷笉鍚堟硶"); + .throwMessage("审批状态不合法"); Long userId = UserUtil.getUserId(); String userName = UserUtil.getUserName(); @@ -823,7 +823,7 @@ public class QmsIssueTicketControllerService { issueTicketToDoService.processed(entity.getId()); - // 鎺ㄩ€佹秷鎭粰宸ュ崟鍒涘缓浜? + // 推送消息给工单创建人 if (entity.getCreateUserId() != null) { QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(entity.getId()) @@ -837,8 +837,8 @@ public class QmsIssueTicketControllerService { } /** - * 鏂板璐ㄩ噺闂宸ュ崟 - * 宸ュ崟缂栧彿鑷姩鐢熸垚锛屾潵婧愮被鍨嬪浐瀹氫负2锛堝贰妫€锛夛紝鐘舵€侀粯璁や负0锛堝緟娴佽浆锛? + * 新增质量问题工单 + * 工单编号自动生成,来源类型固定为2(巡检),状态默认为0(待流转) */ @Transactional(rollbackFor = Exception.class) public void add(@Valid QmsIssueTicketAddQO request) { @@ -846,21 +846,21 @@ public class QmsIssueTicketControllerService { String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 鏍¢獙 ticketTitle + projectNo 涓嶈兘閲嶅 + // 校验 ticketTitle + projectNo 不能重复 boolean exists = issueTicketService.lambdaQuery() .eq(QmsIssueTicket::getTicketTitle, request.getTicketTitle()) .eq(QmsIssueTicket::getProjectNo, request.getProjectNo()) .exists(); if (exists) { - throw new NflgException(STATE.BusinessError, "宸插瓨鍦ㄧ浉鍚屾爣棰樺拰宸ョ▼缂栧彿鐨勫伐鍗曪紝璇峰嬁閲嶅鍒涘缓"); + throw new NflgException(STATE.BusinessError, "已存在相同标题和工程编号的工单,请勿重复创建"); } - // 鑷姩鐢熸垚宸ュ崟缂栧彿 + // 自动生成工单编号 String ticketNo = basdeSerialNumberControllerService.generateSerialNumber(37); QmsIssueTicket entity = new QmsIssueTicket() .setSourceType((short) 2) - .setStatus((short) 0) // 寰呮祦杞姸鎬? + .setStatus((short) 0) // 待流转状态 .setTicketNo(ticketNo) .setTicketTitle(request.getTicketTitle()) .setProjectNo(request.getProjectNo()) @@ -887,10 +887,10 @@ public class QmsIssueTicketControllerService { } /** - * 鏂板宸℃宸ュ崟骞跺彂甯? - * 1. 鍒涘缓宸ュ崟锛堟潵婧愮被鍨嬪浐瀹氫负2-宸℃锛? - * 2. 鐩存帴璁剧疆涓哄鐞嗕腑鐘舵€侊紙status=1锛? - * 3. 璁剧疆璐熻矗浜轰负瀹℃壒浜? + * 新增巡检工单并发布 + * 1. 创建工单(来源类型固定为2-巡检) + * 2. 直接设置为处理中状态(status=1) + * 3. 设置负责人为审批人 */ @Transactional(rollbackFor = Exception.class) public void addAndDispatch(@Valid QmsIssueTicketAddAndDispatchQO request) { @@ -898,40 +898,40 @@ public class QmsIssueTicketControllerService { String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 鏍¢獙 ticketTitle + projectNo 涓嶈兘閲嶅 + // 校验 ticketTitle + projectNo 不能重复 boolean exists = issueTicketService.lambdaQuery() .eq(QmsIssueTicket::getTicketTitle, request.getTicketTitle()) .eq(QmsIssueTicket::getProjectNo, request.getProjectNo()) .exists(); if (exists) { - throw new NflgException(STATE.BusinessError, "宸插瓨鍦ㄧ浉鍚屾爣棰樺拰宸ョ▼缂栧彿鐨勫伐鍗曪紝璇峰嬁閲嶅鍒涘缓"); + throw new NflgException(STATE.BusinessError, "已存在相同标题和工程编号的工单,请勿重复创建"); } - // 1. 鏍¢獙璐熻矗浜哄瓨鍦? + // 1. 校验负责人存在 User handlerUser = userService.getById(request.getHandlerUserId()); - VUtil.trueThrowBusinessError(Objects.isNull(handlerUser)).throwMessage("璐熻矗浜轰笉瀛樺湪"); + VUtil.trueThrowBusinessError(Objects.isNull(handlerUser)).throwMessage("负责人不存在"); - // 2. 鏍¢獙璇锋眰蹇呭~瀛楁瀹屾暣鎬? + // 2. 校验请求必填字段完整性 VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getTicketTitle())) - .throwMessage("宸ュ崟鏍囬涓嶈兘涓虹┖"); + .throwMessage("工单标题不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getProjectNo())) - .throwMessage("宸ョ▼缂栧彿涓嶈兘涓虹┖"); + .throwMessage("工程编号不能为空"); VUtil.trueThrowBusinessError(request.getIncidentType() == null) - .throwMessage("浜嬫晠绫诲瀷涓嶈兘涓虹┖"); + .throwMessage("事故类型不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getExceptionCode())) - .throwMessage("寮傚父浠g爜涓嶈兘涓虹┖"); + .throwMessage("异常代码不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getImpactQuantity())) - .throwMessage("褰卞搷鏁伴噺涓嶈兘涓虹┖"); + .throwMessage("影响数量不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getIncidentLocation())) - .throwMessage("浜嬩欢鍦扮偣涓嶈兘涓虹┖"); + .throwMessage("事件地点不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getIncidentDescription())) - .throwMessage("浜嬩欢鎻忚堪涓嶈兘涓虹┖"); + .throwMessage("事件描述不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getIncidentReason())) - .throwMessage("浜嬩欢鍘熷洜涓嶈兘涓虹┖"); + .throwMessage("事件原因不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getIncidentConsequence())) - .throwMessage("浜嬩欢鍚庢灉涓嶈兘涓虹┖"); + .throwMessage("事件后果不能为空"); - // 3. 鏍¢獙鍥剧墖瀛楁瀹屾暣鎬э紙濡傛灉鏈夊浘鐗囩殑璇濓級 + // 3. 校验图片字段完整性(如果有图片的话) if (CollectionUtil.isNotEmpty(request.getImages())) { List imageIds = request.getImages().stream() .map(FileUploadVO::getId) @@ -945,17 +945,17 @@ public class QmsIssueTicketControllerService { for (FileUploadRecord record : fileRecords) { VUtil.trueThrowBusinessError(StrUtil.isBlank(record.getFileName())) - .throwMessage("鍥剧墖鏂囦欢鍚嶄笉鑳戒负绌?); + .throwMessage("图片文件名不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(record.getUrl())) - .throwMessage("鍥剧墖URL涓嶈兘涓虹┖"); + .throwMessage("图片URL不能为空"); } } } - // 4. 鑷姩鐢熸垚宸ュ崟缂栧彿 + // 4. 自动生成工单编号 String ticketNo = basdeSerialNumberControllerService.generateSerialNumber(37); - // 5. 鍒涘缓宸ュ崟瀹炰綋锛堢洿鎺ヨ缃负澶勭悊涓姸鎬侊級 + // 5. 创建工单实体(直接设置为处理中状态) QmsIssueTicket entity = new QmsIssueTicket() .setSourceType((short) 2) .setTicketNo(ticketNo) @@ -973,7 +973,7 @@ public class QmsIssueTicketControllerService { : StrUtil.join(",", request.getImages().stream().map(FileUploadVO::getId).toList()) ) .setRemark(request.getRemark()) - .setStatus((short) 1) // 鐩存帴璁剧疆涓哄鐞嗕腑 + .setStatus((short) 1) // 直接设置为处理中 .setApprovalUserId(request.getHandlerUserId()) .setApprovalUserName(handlerUser.getUserName()) .setApprovalTime(now) @@ -986,7 +986,7 @@ public class QmsIssueTicketControllerService { issueTicketService.save(entity); - // 6. 鎺ㄩ€佸緟鍔炴秷鎭粰璐熻矗浜? + // 6. 推送待办消息给负责人 QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(entity.getId()) .setHandlerUserId(request.getHandlerUserId()); @@ -994,8 +994,8 @@ public class QmsIssueTicketControllerService { } /** - * 淇敼宸℃宸ュ崟锛堝彂璧峰墠锛? - * 浠呭厑璁稿垱寤轰汉淇敼锛屼笖宸ュ崟鐘舵€佸繀椤讳负寰呮祦杞?0) + * 修改巡检工单(发起前) + * 仅允许创建人修改,且工单状态必须为待流转(0) */ @Transactional(rollbackFor = Exception.class) public void updateInspectionTicket(QmsIssueTicketUpdateQO request) { @@ -1003,27 +1003,27 @@ public class QmsIssueTicketControllerService { String currentUserName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 1. 鏌ヨ宸ュ崟 + // 1. 查询工单 QmsIssueTicket ticket = issueTicketService.getById(request.getId()); - VUtil.trueThrowBusinessError(ticket == null).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(ticket == null).throwMessage("工单不存在"); - // 2. 鏉冮檺鏍¢獙锛氬彧鏈夊垱寤轰汉鎵嶈兘淇敼 + // 2. 权限校验:只有创建人才能修改 VUtil.trueThrowBusinessError(!ticket.getCreateUserId().equals(currentUserId)) - .throwMessage("鍙湁鍒涘缓浜烘墠鑳戒慨鏀瑰伐鍗?); + .throwMessage("只有创建人才能修改工单"); - // 3. 鐘舵€佹牎楠岋細鍙湁寰呮祦杞姸鎬佹墠鑳戒慨鏀? + // 3. 状态校验:只有待流转状态才能修改 VUtil.trueThrowBusinessError(ticket.getStatus() != 0) - .throwMessage("鍙湁寰呮祦杞姸鎬佺殑宸ュ崟鎵嶈兘淇敼"); + .throwMessage("只有待流转状态的工单才能修改"); - // 4. 鏉ユ簮绫诲瀷鏍¢獙锛氬彧鑳戒慨鏀瑰贰妫€宸ュ崟 + // 4. 来源类型校验:只能修改巡检工单 VUtil.trueThrowBusinessError(ticket.getSourceType() != 2) - .throwMessage("鍙兘淇敼宸℃宸ュ崟"); + .throwMessage("只能修改巡检工单"); - // 5. 鏍¢獙鏄惁宸茶缃礋璐d汉锛堝凡鍙戣捣锛? + // 5. 校验是否已设置负责人(已发起) VUtil.trueThrowBusinessError(ticket.getApprovalUserId() != null) - .throwMessage("宸ュ崟宸插彂璧凤紝涓嶅厑璁镐慨鏀?); + .throwMessage("工单已发起,不允许修改"); - // 6. 鏇存柊宸ュ崟淇℃伅 + // 6. 更新工单信息 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, request.getId()) .set(QmsIssueTicket::getTicketTitle, request.getTicketTitle()) @@ -1049,25 +1049,25 @@ public class QmsIssueTicketControllerService { } /** - * 骞虫澘绔煡璇㈠贰妫€宸ュ崟鍒楄〃 - * 浠呮煡璇㈠綋鍓嶇櫥褰曚汉鍒涘缓鐨勫贰妫€宸ュ崟锛坰ourceType=2锛? + * 平板端查询巡检工单列表 + * 仅查询当前登录人创建的巡检工单(sourceType=2) */ public QmsIssueTicketTabletPageData searchTabletInspectionTickets(@Valid QmsIssueTicketTabletSearchQO request) { Long currentUserId = UserUtil.getUserId(); - // 鏋勫缓鏌ヨ鏉′欢 + // 构建查询条件 LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - // 鍥哄畾鏉′欢锛氫粎鏌ヨ宸℃宸ュ崟锛坰ourceType=2锛? + // 固定条件:仅查询巡检工单(sourceType=2) wrapper.eq(QmsIssueTicket::getSourceType, (short) 2); - // 鍥哄畾鏉′欢锛氫粎鏌ヨ褰撳墠鐧诲綍浜哄垱寤虹殑宸ュ崟 + // 固定条件:仅查询当前登录人创建的工单 wrapper.eq(QmsIssueTicket::getCreateUserId, currentUserId); - // 鍙€夋潯浠讹細宸ュ崟鐘舵€? + // 可选条件:工单状态 wrapper.eq(request.getStatus() != null, QmsIssueTicket::getStatus, request.getStatus()); - // 鍙€夋潯浠讹細鍏抽敭瀛楁ā绯婂尮閰嶏紙宸ュ崟鏍囬銆佸伐鍗曠紪鍙枫€佹彁浜や汉濮撳悕锛? + // 可选条件:关键字模糊匹配(工单标题、工单编号、提交人姓名) if (StrUtil.isNotBlank(request.getKey())) { wrapper.and(w -> w .like(QmsIssueTicket::getTicketTitle, request.getKey()) @@ -1076,14 +1076,14 @@ public class QmsIssueTicketControllerService { ); } - // 鎺掑簭锛氭寜鍒涘缓鏃堕棿鍊掑簭 + // 排序:按创建时间倒序 wrapper.orderByDesc(QmsIssueTicket::getCreateTime); - // 鍒嗛〉鏌ヨ + // 分页查询 Page page = new Page<>(request.getPage(), request.getPageSize()); Page resultPage = issueTicketService.page(page, wrapper); - // 杞崲涓篤O + // 转换为VO List voList = resultPage.getRecords().stream() .map(ticket -> { QmsIssueTicketVO vo = new QmsIssueTicketVO(); @@ -1103,14 +1103,14 @@ public class QmsIssueTicketControllerService { }) .collect(Collectors.toList()); - // 鏋勫缓鍒嗛〉缁撴灉 + // 构建分页结果 QmsIssueTicketTabletPageData pageData = new QmsIssueTicketTabletPageData(); pageData.setItems(voList); pageData.setTotal((int) resultPage.getTotal()); pageData.setPage((int) resultPage.getCurrent()); pageData.setPageSize((int) resultPage.getSize()); - // 缁熻宸ュ崟鍚勭姸鎬佹暟閲忥紙鍙粺璁?sourceType=2 涓斿綋鍓嶇敤鎴峰垱寤虹殑宸ュ崟锛? + // 统计工单各状态数量(只统计 sourceType=2 且当前用户创建的工单) Long pendingCount = issueTicketService.lambdaQuery() .eq(QmsIssueTicket::getSourceType, (short) 2) .eq(QmsIssueTicket::getCreateUserId, currentUserId) @@ -1135,10 +1135,10 @@ public class QmsIssueTicketControllerService { .eq(QmsIssueTicket::getStatus, (short) 3) .count(); - // 宸ュ崟鎬绘暟 = 寰呭鐞?+ 澶勭悊涓?+ 宸插畬鎴?+ 宸插叧闂? + // 工单总数 = 待处理 + 处理中 + 已完成 + 已关闭 long totalCount = pendingCount + processingCount + completedCount + closedCount; - // 璁剧疆缁熻瀛楁 + // 设置统计字段 pageData.setTotalCount(totalCount); pageData.setPendingCount(pendingCount); pageData.setProcessingCount(processingCount); @@ -1149,9 +1149,9 @@ public class QmsIssueTicketControllerService { } /** - * 鏂板PDI妫€娴嬪伐鍗? - * 宸ュ崟缂栧彿鑷姩鐢熸垚锛堝簭鍙?8锛夛紝鏉ユ簮绫诲瀷鍥哄畾涓?锛圥DI妫€娴嬩换鍔★級锛岀姸鎬侀粯璁や负0锛堝緟娴佽浆锛? - * 寮傛鏂板宸ュ崟澶勭悊璁板綍 + * 新增PDI检测工单 + * 工单编号自动生成(序号38),来源类型固定为1(PDI检测任务),状态默认为0(待流转) + * 异步新增工单处理记录 */ @Transactional(rollbackFor = Exception.class) public void addPdiTicket(@Valid QmsIssueTicketPdiAddQO request) { @@ -1159,54 +1159,54 @@ public class QmsIssueTicketControllerService { String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 鏍¢獙涓嶈兘鍒嗛厤缁欒嚜宸? + // 校验不能分配给自己 boolean containsSelf = request.getHandlers().stream() .anyMatch(h -> userId.equals(h.getHandlerUserId())); if (containsSelf) { - throw new NflgException(STATE.BusinessError, "涓嶈兘灏嗗伐鍗曞垎閰嶇粰鑷繁"); + throw new NflgException(STATE.BusinessError, "不能将工单分配给自己"); } - // 鏌ヨ浠诲姟璁板綍 + // 查询任务记录 QmsPdiTaskRecord taskRecord = pdiTaskRecordService.getById(request.getTaskRecordId()); if (Objects.isNull(taskRecord)) { - throw new NflgException(STATE.BusinessError, "PDI妫€娴嬩换鍔¤褰曚笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PDI检测任务记录不存在"); } - // 鏍¢獙浠诲姟鐘舵€佸繀椤讳负3锛堝緟娴佽浆锛夋垨4锛堥€炬湡锛? + // 校验任务状态必须为3(待流转)或4(逾期) if (!Objects.equals(taskRecord.getInspectionEnable(), 3) && !Objects.equals(taskRecord.getInspectionEnable(), 4)) { - throw new NflgException(STATE.BusinessError, "鍙湁寰呮祦杞垨閫炬湡鐘舵€佺殑浠诲姟鎵嶈兘鍒涘缓宸ュ崟锛屽綋鍓嶇姸鎬侊細" + taskRecord.getInspectionEnable()); + throw new NflgException(STATE.BusinessError, "只有待流转或逾期状态的任务才能创建工单,当前状态:" + taskRecord.getInspectionEnable()); } - // 鏍¢獙鏄惁宸插瓨鍦ㄥ伐鍗曪紙鍚屼竴taskRecordId鍙兘鍒涘缓涓€娆″伐鍗曪級 + // 校验是否已存在工单(同一taskRecordId只能创建一次工单) QmsIssueTicket existingTicket = issueTicketService.lambdaQuery() .eq(QmsIssueTicket::getSourceType, (short) 1) .eq(QmsIssueTicket::getSourceId, request.getTaskRecordId()) .one(); if (existingTicket != null) { - // 宸ュ崟宸插瓨鍦紝涓嶅厑璁搁噸澶嶅垱寤猴紝鎶涘嚭寮傚父鎻愮ず浣跨敤杩藉姞澶勭悊璁板綍鎺ュ彛 - throw new NflgException(STATE.BusinessError, "璇ヤ换鍔″凡瀛樺湪宸ュ崟锛堝伐鍗曠紪鍙凤細" + existingTicket.getTicketNo() + "锛夛紝璇蜂娇鐢ㄨ拷鍔犲鐞嗚褰曟帴鍙?); + // 工单已存在,不允许重复创建,抛出异常提示使用追加处理记录接口 + throw new NflgException(STATE.BusinessError, "该任务已存在工单(工单编号:" + existingTicket.getTicketNo() + "),请使用追加处理记录接口"); } - // 鏌ヨ妫€娴嬭鍒? + // 查询检测规则 QmsPdiDetectionRules rules = pdiDetectionRulesService.getById(taskRecord.getDetectionRulesId()); if (Objects.isNull(rules)) { - throw new NflgException(STATE.BusinessError, "PDI妫€娴嬭鍒欎笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PDI检测规则不存在"); } - // 鏍规嵁 inspectionType 鐢熸垚宸ュ崟鏍囬 + // 根据 inspectionType 生成工单标题 String ticketTitle; if (Objects.equals(rules.getInspectionType(), 0)) { - // 鏂板搧锛氭満鍨嬬紪鍙?鏈哄彴鍙?璁㈠崟缂栧彿-鍑哄巶妫€楠?妫€娴嬬増鏈彿 + // 新品:机型编号-机台号-订单编号-出厂检验-检测版本号 ticketTitle = StrUtil.join("-", rules.getModelNo(), taskRecord.getDeviceNo(), - taskRecord.getOrderNo(), "鍑哄巶妫€楠?, rules.getInspectionVersion()); + taskRecord.getOrderNo(), "出厂检验", rules.getInspectionVersion()); } else { - // 搴撳瓨锛氭満鍨嬬紪鍙?璁㈠崟缂栧彿-搴撳瓨妫€楠?妫€娴嬬増鏈彿 + // 库存:机型编号-订单编号-库存检验-检测版本号 ticketTitle = StrUtil.join("-", rules.getModelNo(), - taskRecord.getOrderNo(), "搴撳瓨妫€楠?, rules.getInspectionVersion()); + taskRecord.getOrderNo(), "库存检验", rules.getInspectionVersion()); } - // 鏌ヨ璇ヤ换鍔$殑鎵€鏈変笉鍚堟牸椤癸紝姹囨€荤敓鎴恑ncidentDescription + // 查询该任务的所有不合格项,汇总生成incidentDescription String incidentDescription = ""; List allUnqualifiedResults = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, request.getTaskRecordId()) @@ -1218,23 +1218,23 @@ public class QmsIssueTicketControllerService { int index = 1; for (QmsPdiInspectionResults result : allUnqualifiedResults) { if (index > 1) { - descBuilder.append("锛?); + descBuilder.append(";"); } descBuilder.append(index).append(". "); - // 浣跨敤澶囨敞瀛楁浣滀负涓嶅悎鏍奸」鎻忚堪 + // 使用备注字段作为不合格项描述 descBuilder.append(result.getRemark() != null ? result.getRemark() : ""); index++; } incidentDescription = descBuilder.toString(); } - // 缁熻涓嶅悎鏍兼娴嬮」鏁伴噺 + // 统计不合格检测项数量 long unqualifiedCount = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, request.getTaskRecordId()) .eq(QmsPdiInspectionResults::getInspectionItemResults, false) .count(); - // 鑷姩鐢熸垚宸ュ崟缂栧彿 + // 自动生成工单编号 String ticketNo = basdeSerialNumberControllerService.generateSerialNumber(38); QmsIssueTicket entity = new QmsIssueTicket() @@ -1258,13 +1258,13 @@ public class QmsIssueTicketControllerService { issueTicketService.save(entity); - // 鍒涘缓宸ュ崟鎴愬姛鍚庯紝灏嗕换鍔$姸鎬佷粠3锛堝緟娴佽浆锛夋敼涓?锛堝凡瀹屾垚锛? + // 创建工单成功后,将任务状态从3(待流转)改为2(已完成) pdiTaskRecordService.lambdaUpdate() .eq(QmsPdiTaskRecord::getId, taskRecord.getId()) .set(QmsPdiTaskRecord::getInspectionEnable, 2) .update(); - // 鎸夊鐞嗕汉鍒嗙粍锛屽紓姝ユ柊澧炲伐鍗曞鐞嗚褰曞苟鎺ㄩ€佸緟鍔? + // 按处理人分组,异步新增工单处理记录并推送待办 Map> handlerToResultsMap = request.getHandlers().stream() .collect(Collectors.groupingBy( QmsIssueTicketPdiAddQO.HandlerItem::getHandlerUserId, @@ -1282,9 +1282,9 @@ public class QmsIssueTicketControllerService { } /** - * 鏂板PQC妫€娴嬪伐鍗? - * 宸ュ崟缂栧彿鑷姩鐢熸垚锛堝簭鍙?1锛夛紝鏉ユ簮绫诲瀷鍥哄畾涓?锛圥QC妫€娴嬩换鍔★級锛岀姸鎬侀粯璁や负0锛堝緟娴佽浆锛? - * 寮傛鏂板宸ュ崟澶勭悊璁板綍 + * 新增PQC检测工单 + * 工单编号自动生成(序号41),来源类型固定为3(PQC检测任务),状态默认为0(待流转) + * 异步新增工单处理记录 */ @Transactional(rollbackFor = Exception.class) public void addPqcTicket(@Valid QmsIssueTicketPqcAddQO request) { @@ -1295,16 +1295,16 @@ public class QmsIssueTicketControllerService { boolean containsSelf = request.getHandlers().stream() .anyMatch(h -> userId.equals(h.getHandlerUserId())); if (containsSelf) { - throw new NflgException(STATE.BusinessError, "涓嶈兘灏嗗伐鍗曞垎閰嶇粰鑷繁"); + throw new NflgException(STATE.BusinessError, "不能将工单分配给自己"); } QmsPqcTaskRecord taskRecord = pqcTaskRecordService.getById(request.getTaskRecordId()); if (Objects.isNull(taskRecord)) { - throw new NflgException(STATE.BusinessError, "PQC妫€娴嬩换鍔¤褰曚笉瀛樺湪"); + throw new NflgException(STATE.BusinessError, "PQC检测任务记录不存在"); } if (!Objects.equals(taskRecord.getStatus(), (short) 3)) { - throw new NflgException(STATE.BusinessError, "鍙湁宸插鏍哥殑PQC浠诲姟鎵嶈兘鍒涘缓宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只有已复核的PQC任务才能创建工单"); } QmsIssueTicket existingTicket = issueTicketService.lambdaQuery() @@ -1313,7 +1313,7 @@ public class QmsIssueTicketControllerService { .one(); if (existingTicket != null) { throw new NflgException(STATE.BusinessError, - "璇ヤ换鍔″凡瀛樺湪宸ュ崟锛堝伐鍗曠紪鍙凤細" + existingTicket.getTicketNo() + "锛夛紝璇蜂娇鐢ㄨ拷鍔犲鐞嗚褰曟帴鍙?); + "该任务已存在工单(工单编号:" + existingTicket.getTicketNo() + "),请使用追加处理记录接口"); } List requestedDetailIds = request.getHandlers().stream() @@ -1322,7 +1322,7 @@ public class QmsIssueTicketControllerService { .distinct() .collect(Collectors.toList()); if (requestedDetailIds.isEmpty()) { - throw new NflgException(STATE.BusinessError, "涓嶅悎鏍奸」涓嶈兘涓虹┖"); + throw new NflgException(STATE.BusinessError, "不合格项不能为空"); } List detailList = pqcTaskRecordDetailsService.lambdaQuery() @@ -1330,14 +1330,14 @@ public class QmsIssueTicketControllerService { .in(QmsPqcTaskRecordDetails::getId, requestedDetailIds) .list(); if (detailList.size() != requestedDetailIds.size()) { - throw new NflgException(STATE.BusinessError, "瀛樺湪鏃犳晥鐨勪笉鍚堟牸椤?); + throw new NflgException(STATE.BusinessError, "存在无效的不合格项"); } List unqualifiedDetails = detailList.stream() .filter(detail -> Boolean.FALSE.equals(detail.getReviewEnable())) .collect(Collectors.toList()); if (unqualifiedDetails.isEmpty()) { - throw new NflgException(STATE.BusinessError, "璇烽€夋嫨涓嶅悎鏍兼娴嬮」"); + throw new NflgException(STATE.BusinessError, "请选择不合格检测项"); } QmsPqcInspectionPoint point = pqcInspectionPointService.getById(taskRecord.getInspectionPointId()); @@ -1394,21 +1394,21 @@ public class QmsIssueTicketControllerService { } /** - * 閫氳繃鏉ユ枡妫€娴嬩换鍔D鍙戣捣IQC妫€娴嬩换鍔$被鍨嬭川閲忛棶棰樺伐鍗? - * 宸ュ崟缂栧彿鑷姩鐢熸垚锛屾潵婧愮被鍨嬪浐瀹氫负0锛圛QC妫€娴嬩换鍔★級锛岀姸鎬侀粯璁や负0锛堝緟娴佽浆锛? + * 通过来料检测任务ID发起IQC检测任务类型质量问题工单 + * 工单编号自动生成,来源类型固定为0(IQC检测任务),状态默认为0(待流转) */ @Transactional(rollbackFor = Exception.class) public void initiate(Long taskId) { - // 鏍¢獙浠诲姟鏄惁瀛樺湪 + // 校验任务是否存在 QmsIncomingInspectionTaskVO detail = incomingInspectionTaskControllerService.getDetail(taskId); VUtil.trueThrowBusinessError(issueTicketService.lambdaQuery().eq(QmsIssueTicket::getProjectNo, detail.getTaskNo()).exists()) - .throwMessage("璇ヤ换鍔″凡鐢熸垚璐ㄩ噺闂宸ュ崟"); + .throwMessage("该任务已生成质量问题工单"); Long userId = UserUtil.getUserId(); String userName = UserUtil.getUserName(); LocalDateTime now = LocalDateTime.now(); - // 鑷姩鐢熸垚宸ュ崟缂栧彿 + // 自动生成工单编号 String ticketNo = basdeSerialNumberControllerService.generateSerialNumber(36); QmsIssueTicket entity = new QmsIssueTicket() @@ -1432,7 +1432,7 @@ public class QmsIssueTicketControllerService { , detail.getMaterialNo(), detail.getStorageDays(), detail.getStandardVersion()) ); } else { - VUtil.trueThrowBusinessError(true).throwMessage("璇ユ娴嬬被鍨嬫湭瀹氫箟宸ュ崟鏍囬鐢熸垚鏂瑰紡"); + VUtil.trueThrowBusinessError(true).throwMessage("该检测类型未定义工单标题生成方式"); } List unqualifiedRecordItems = incomingInspectionTaskControllerService.getUnqualifiedRecordItems(taskId); @@ -1441,7 +1441,7 @@ public class QmsIssueTicketControllerService { unqualifiedRecordItemsMap.forEach((testStandard, items) -> { AtomicReference index = new AtomicReference<>(1); entity.setIncidentDescription(entity.getIncidentDescription() - + "妫€娴嬫爣鍑嗭細" + testStandard + "\n" + + "检测标准:" + testStandard + "\n" + items.stream() .map(item -> index.getAndSet(index.get() + 1) + ". " + item.getRemark() + "\n") .collect(Collectors.joining()) @@ -1453,7 +1453,7 @@ public class QmsIssueTicketControllerService { entity.setImageIds(StrUtil.join(",", images)); issueTicketService.save(entity); - // 娣诲姞寰呭姙 + // 添加待办 if (detail.getInspectionType() == 0) { if (StrUtil.isNotBlank(detail.getPurchaseGroup())) { List users = userService.lambdaQuery() @@ -1503,17 +1503,17 @@ public class QmsIssueTicketControllerService { int index = 1; for (QmsPqcTaskRecordDetails detail : detailList) { if (index > 1) { - descBuilder.append("锛?); + descBuilder.append(";"); } descBuilder.append(index).append(". "); QmsPqcInspectionPointItems item = itemMap.get(detail.getInspectionPointItemId()); if (item != null && StrUtil.isNotBlank(item.getInspectionContent())) { descBuilder.append(item.getInspectionContent()); } else { - descBuilder.append("PQC涓嶅悎鏍奸」"); + descBuilder.append("PQC不合格项"); } if (StrUtil.isNotBlank(detail.getReviewOpinion())) { - descBuilder.append("锛?).append(detail.getReviewOpinion()).append("锛?); + descBuilder.append("(").append(detail.getReviewOpinion()).append(")"); } index++; } @@ -1521,18 +1521,18 @@ public class QmsIssueTicketControllerService { } /** - * 鏌ヨ鏉ユ枡妫€娴嬩换鍔¤川閲忛棶棰樺伐鍗曡鎯? - * 鍖呭惈鍥剧墖鏂囦欢淇℃伅銆佹潵鏂欐娴嬩换鍔¤鎯呫€佹楠岃褰曪紙鍚瓙椤瑰拰鏍锋湰鏁版嵁锛? + * 查询来料检测任务质量问题工单详情 + * 包含图片文件信息、来料检测任务详情、检验记录(含子项和样本数据) */ public QmsIssueTicketDetailVO getIncomingInspectionTaskDetail(Long id) { QmsIssueTicket entity = issueTicketService.getById(id); if (Objects.isNull(entity)) { - throw new NflgException(STATE.BusinessError, "璐ㄩ噺闂宸ュ崟涓嶅瓨鍦?); + throw new NflgException(STATE.BusinessError, "质量问题工单不存在"); } QmsIssueTicketDetailVO vo = BeanUtil.copyProperties(entity, QmsIssueTicketDetailVO.class); - // 瑙f瀽鍥剧墖ID鍒楄〃骞舵煡璇㈡枃浠朵俊鎭? + // 解析图片ID列表并查询文件信息 if (StrUtil.isNotBlank(entity.getImageIds())) { List imageIdList = Arrays.stream(entity.getImageIds().split(",")) .filter(StrUtil::isNotBlank) @@ -1553,8 +1553,8 @@ public class QmsIssueTicketControllerService { } } - // 鏌ヨ鍏宠仈鐨勬潵鏂欐娴嬩换鍔¤鎯呭強妫€楠岃褰? - // 鏉ユ枡妫€娴嬩换鍔¤鎯? + // 查询关联的来料检测任务详情及检验记录 + // 来料检测任务详情 QmsIncomingInspectionTaskVO taskDetail = incomingInspectionTaskControllerService.getDetail(entity.getSourceId()); vo.setTaskDetail(taskDetail); @@ -1611,11 +1611,11 @@ public class QmsIssueTicketControllerService { } /** - * 鏌ヨPDI宸ュ崟璇︽儏 - * 杩斿洖宸ュ崟鍩烘湰淇℃伅鍙婂鐞嗚褰曘€佹帾鏂藉垪琛? + * 查询PDI工单详情 + * 返回工单基本信息及处理记录、措施列表 */ public QmsPdiTicketDetailVO getPdiTicketDetail(Long id) { -// // 鏌ヨ宸ュ崟鍩烘湰淇℃伅 +// // 查询工单基本信息 // QmsIssueTicket ticket = issueTicketService.getById(id); // QmsPdiTicketDetailVO vo = new QmsPdiTicketDetailVO(); // vo.setTicketNo(ticket.getTicketNo()); @@ -1627,38 +1627,38 @@ public class QmsIssueTicketControllerService { // vo.setCreator(ticket.getCreateUserName()); // vo.setCreateTime(ticket.getCreateTime()); // vo.setStatus(ticket.getStatus()); -// vo.setCompleteTime(ticket.getCompleteTime()); // 璁剧疆瀹屾垚鏃堕棿 +// vo.setCompleteTime(ticket.getCompleteTime()); // 设置完成时间 // -// // 鏌ヨ宸ュ崟绫诲瀷锛歅DI-鏂版満妫€娴?鎴?PDI-搴撳瓨妫€娴? +// // 查询工单类型:PDI-新机检测 或 PDI-库存检测 // if (ticket.getSourceId() != null) { // QmsPdiTaskRecord taskRecord = pdiTaskRecordService.getById(ticket.getSourceId()); // if (taskRecord != null && taskRecord.getDetectionRulesId() != null) { // QmsPdiDetectionRules detectionRules = pdiDetectionRulesService.getById(taskRecord.getDetectionRulesId()); // if (detectionRules != null && detectionRules.getInspectionType() != null) { -// String inspectionTypeStr = detectionRules.getInspectionType() == 0 ? "鏂版満妫€娴? : "搴撳瓨妫€娴?; +// String inspectionTypeStr = detectionRules.getInspectionType() == 0 ? "新机检测" : "库存检测"; // vo.setTicketType("PDI-" + inspectionTypeStr); // } // } // } // -// // 鏌ヨ澶勭悊璁板綍鍒楄〃 +// // 查询处理记录列表 // List processes = issueTicketProcessService.lambdaQuery() // .eq(QmsIssueTicketProcess::getIssueTicketId, id) // .list(); // -// // 鏋勫缓涓嶅悎鏍兼娴嬮」鍒楄〃锛堟瘡椤瑰叧鑱斿鐞嗕俊鎭級 +// // 构建不合格检测项列表(每项关联处理信息) // List inspectionItems = new ArrayList<>(); // String rootCause = null; // List temporaryMeasures = new ArrayList<>(); // List permanentMeasures = new ArrayList<>(); // // for (QmsIssueTicketProcess process : processes) { -// // 鎻愬彇鏍规湰鍘熷洜锛堝彇绗竴鏉★級 +// // 提取根本原因(取第一条) // if (rootCause == null && StrUtil.isNotBlank(process.getRootCause())) { // rootCause = process.getRootCause(); // } // -// // 鏌ヨ璇ュ鐞嗚褰曞叧鑱旂殑涓嶅悎鏍兼娴嬮」 +// // 查询该处理记录关联的不合格检测项 // if (StrUtil.isNotBlank(process.getTaskResultIds())) { // String[] taskIds = process.getTaskResultIds().split(","); // for (String taskId : taskIds) { @@ -1668,14 +1668,14 @@ public class QmsIssueTicketControllerService { // .eq(QmsPdiInspectionResults::getInspectionItemResults, false) // .list(); // -// // 鏀堕泦妫€娴嬮」ID锛堜粎type=0/1/3锛? +// // 收集检测项ID(仅type=0/1/3) // Set statusItemIds = unqualifiedResults.stream() // .filter(r -> r.getInspectionItemType() != null && r.getInspectionItemType() != 2) // .map(QmsPdiInspectionResults::getInspectionItemId) // .filter(Objects::nonNull) // .collect(Collectors.toSet()); // -// // 鏌ヨ妫€娴嬮」淇℃伅 +// // 查询检测项信息 // Map statusItemMap = new HashMap<>(); // if (!statusItemIds.isEmpty()) { // List statusItems = pdiStatusItemService.lambdaQuery() @@ -1685,7 +1685,7 @@ public class QmsIssueTicketControllerService { // .collect(Collectors.toMap(QmsPdiDetectionRulesStatusItem::getId, s -> s, (a, b) -> a)); // } // -// // 鏀堕泦绀轰緥鍥綢D +// // 收集示例图ID // Set exampleImageIds = statusItemMap.values().stream() // .map(QmsPdiDetectionRulesStatusItem::getInspectionImage) // .filter(StrUtil::isNotBlank) @@ -1694,7 +1694,7 @@ public class QmsIssueTicketControllerService { // .map(Long::valueOf) // .collect(Collectors.toSet()); // -// // 鏌ヨ绀轰緥鍥? +// // 查询示例图 // Map exampleImageMap = new HashMap<>(); // if (!exampleImageIds.isEmpty()) { // List records = fileUploadRecordService.lambdaQuery() @@ -1704,7 +1704,7 @@ public class QmsIssueTicketControllerService { // .collect(Collectors.toMap(FileUploadRecord::getId, r -> r, (a, b) -> a)); // } // -// // 鏌ヨ澶勭悊浜洪儴闂ㄤ俊鎭? +// // 查询处理人部门信息 // Long handlerDeptId = null; // String handlerDeptName = null; // if (process.getHandlerUserId() != null) { @@ -1737,13 +1737,13 @@ public class QmsIssueTicketControllerService { // itemVO.setInspectionTime(result.getInspectionTime()); // itemVO.setInspectionBy(result.getInspectionBy()); // -// // 濉厖妫€娴嬮」淇℃伅锛堜粎type=0/1/3锛? +// // 填充检测项信息(仅type=0/1/3) // if (result.getInspectionItemType() != null && result.getInspectionItemType() != 2) { // QmsPdiDetectionRulesStatusItem statusItem = finalStatusItemMap.get(result.getInspectionItemId()); // if (statusItem != null) { // itemVO.setComponentsDes(statusItem.getComponentsDes()); // itemVO.setInspectionContent(statusItem.getInspectionContent()); -// // 瑙f瀽绀轰緥鍥綰RL +// // 解析示例图URL // if (StrUtil.isNotBlank(statusItem.getInspectionImage())) { // String exampleUrl = Arrays.stream(statusItem.getInspectionImage().split(",")) // .filter(StrUtil::isNotBlank) @@ -1759,7 +1759,7 @@ public class QmsIssueTicketControllerService { // } // } // -// // 濉厖澶勭悊淇℃伅 +// // 填充处理信息 // itemVO.setHandlerUserId(process.getHandlerUserId()); // itemVO.setHandlerUserName(process.getHandlerUserName()); // itemVO.setHandlerDeptId(finalHandlerDeptId); @@ -1777,12 +1777,12 @@ public class QmsIssueTicketControllerService { // } // } // -// // 鏌ヨ鎺柦鍒楄〃锛屾寜鎺柦绫诲瀷鍖哄垎涓存椂/姘镐箙 +// // 查询措施列表,按措施类型区分临时/永久 // List measures = issueTicketProcessMeasureService.lambdaQuery() // .eq(QmsIssueTicketProcessMeasure::getIssueTicketProcessId, process.getId()) // .list(); // -// // 鏌ヨ瀛楀吀椤笽D +// // 查询字典项ID // Long temporaryTypeId = dictionaryItemService.getIdByCode("MeasureType", "TemporaryCorrectiveMeasures"); // Long permanentTypeId = dictionaryItemService.getIdByCode("MeasureType", "PermanentCorrectiveMeasures"); // @@ -1796,7 +1796,7 @@ public class QmsIssueTicketControllerService { // measureVO.setConfirmDate(measure.getConfirmDate()); // measureVO.setRemark(measure.getRemark()); // -// // 鏍规嵁measureTypeId鍖哄垎涓存椂鎺柦鍜屾案涔呮帾鏂? +// // 根据measureTypeId区分临时措施和永久措施 // if (measure.getMeasureTypeId() != null) { // if (measure.getMeasureTypeId().equals(temporaryTypeId)) { // temporaryMeasures.add(measureVO); @@ -1807,7 +1807,7 @@ public class QmsIssueTicketControllerService { // } // } // -// // 鏋勫缓澶勭悊浜轰俊鎭紙鎸夐儴闂ㄥ垎缁勶級 +// // 构建处理人信息(按部门分组) // Map> handlers = new HashMap<>(); // for (QmsIssueTicketProcess process : processes) { // if (process.getHandlerUserId() != null) { @@ -1831,7 +1831,7 @@ public class QmsIssueTicketControllerService { // vo.setTemporaryMeasures(temporaryMeasures); // vo.setPermanentMeasures(permanentMeasures); // -// // 鏋勫缓鐩稿叧浜哄憳绛惧瓧锛堟寜閮ㄩ棬锛屽彧杩斿洖宸插鎵圭殑锛? +// // 构建相关人员签字(按部门,只返回已审批的) // Map signatures = buildSignatures(processes); // vo.setSignatures(signatures); // @@ -1840,32 +1840,32 @@ public class QmsIssueTicketControllerService { } /** - * 鏌ヨ鏈汉鐨凱DI宸ュ崟璇︽儏 - * 鏍¢獙褰撳墠鐧诲綍浜轰负宸ュ崟鍒涘缓鑰咃紝鎴栧湪澶勭悊璁板綍涓负澶勭悊浜?瀹℃壒浜?涓婄骇棰嗗 - * 宸ュ崟鍒涘缓鑰呰繑鍥炲叏閮ㄦ娴嬮」锛屽叾浠栦汉浠呰繑鍥炶嚜宸变綔涓哄鐞嗕汉鐨勬娴嬮」 + * 查询本人的PDI工单详情 + * 校验当前登录人为工单创建者,或在处理记录中为处理人/审批人/上级领导 + * 工单创建者返回全部检测项,其他人仅返回自己作为处理人的检测项 */ public QmsPdiTicketMyDetailVO getMyPdiTicketDetail(Long id) { Long currentUserId = UserUtil.getUserId(); - // 鏌ヨ宸ュ崟鍩烘湰淇℃伅 + // 查询工单基本信息 QmsIssueTicket ticket = issueTicketService.getById(id); - // 濡傛灉宸ュ崟鐘舵€佹槸寰呮祦杞?0)锛屾洿鏂颁负澶勭悊涓?1) + // 如果工单状态是待流转(0),更新为处理中(1) if (ticket.getStatus() != null && ticket.getStatus() == 0) { issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, id) .set(QmsIssueTicket::getStatus, (short) 1) .update(); - ticket.setStatus((short) 1); // 鏇存柊鍐呭瓨涓殑鐘舵€? + ticket.setStatus((short) 1); // 更新内存中的状态 } - // 鍒ゆ柇鏄惁涓哄伐鍗曞垱寤鸿€? + // 判断是否为工单创建者 boolean isCreator = ticket.getCreateUserId() != null && ticket.getCreateUserId().equals(currentUserId); List processes = new ArrayList<>(); if (CollectionUtil.isNotEmpty(processes)) { - Long temporaryTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "涓存椂绾犳鎺柦"); - Long permanentTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "姘镐箙绾犳鎺柦"); + Long temporaryTypeId = dictionaryItemService.getId("工单解决措施", "临时纠正措施"); + Long permanentTypeId = dictionaryItemService.getId("工单解决措施", "永久纠正措施"); List processIds = processes.stream() .map(QmsIssueTicketProcess::getId) .filter(Objects::nonNull) @@ -1889,26 +1889,26 @@ public class QmsIssueTicketControllerService { } if (isCreator) { - // 宸ュ崟鍒涘缓鑰咃細杩斿洖鍏ㄩ儴澶勭悊璁板綍 + // 工单创建者:返回全部处理记录 processes = issueTicketProcessService.lambdaQuery() .eq(QmsIssueTicketProcess::getIssueTicketId, id) .list(); } else { - // 闈炲垱寤鸿€咃細浠呰繑鍥炶嚜宸变綔涓哄鐞嗕汉鐨勮褰? + // 非创建者:仅返回自己作为处理人的记录 processes = issueTicketProcessService.lambdaQuery() .eq(QmsIssueTicketProcess::getIssueTicketId, id) .eq(QmsIssueTicketProcess::getHandlerUserId, currentUserId) .list(); } - // 鏋勫缓杩斿洖VO - 宸ュ崟鍩烘湰淇℃伅 + // 构建返回VO - 工单基本信息 QmsPdiTicketMyDetailVO vo = new QmsPdiTicketMyDetailVO(); vo.setId(ticket.getId()); vo.setSourceType(ticket.getSourceType()); vo.setSourceId(ticket.getSourceId()); vo.setTicketNo(ticket.getTicketNo()); vo.setTicketTitle(ticket.getTicketTitle()); - vo.setProjectNo(ticket.getTicketNo()); // 宸ョ▼缂栧彿浣跨敤宸ュ崟缂栧彿 + vo.setProjectNo(ticket.getTicketNo()); // 工程编号使用工单编号 vo.setIncidentType(ticket.getIncidentType()); vo.setExceptionCode(ticket.getExceptionCode()); vo.setUnqualifiedQty(ticket.getUnqualifiedQty()); @@ -1932,52 +1932,52 @@ public class QmsIssueTicketControllerService { vo.setCreateTime(ticket.getCreateTime()); vo.setCreator(ticket.getCreateUserName()); - // 宸ュ崟绫诲瀷锛氭牴鎹畇ourceType杞崲 + // 工单类型:根据sourceType转换 if (ticket.getSourceType() != null) { switch (ticket.getSourceType()) { case 0: - vo.setTicketType("IQC妫€娴嬩换鍔?); + vo.setTicketType("IQC检测任务"); break; case 1: - vo.setTicketType("PDI妫€娴嬩换鍔?); + vo.setTicketType("PDI检测任务"); break; case 2: - vo.setTicketType("宸℃"); + vo.setTicketType("巡检"); break; default: - vo.setTicketType("鏈煡"); + vo.setTicketType("未知"); } } - // 鐢熸垚涓婚锛氭満鍨嬬紪鍙?璁㈠崟缂栧彿+鏂版満妫€娴?搴撳瓨妫€娴?妫€娴嬬増鏈彿锛堜粎PDI宸ュ崟锛? + // 生成主题:机型编号+订单编号+新机检测/库存检测+检测版本号(仅PDI工单) if (ticket.getSourceType() != null && ticket.getSourceType() == 1 && ticket.getSourceId() != null) { QmsPdiTaskRecord taskRecord = pdiTaskRecordService.getById(ticket.getSourceId()); if (taskRecord != null && taskRecord.getDetectionRulesId() != null) { QmsPdiDetectionRules detectionRules = pdiDetectionRulesService.getById(taskRecord.getDetectionRulesId()); if (detectionRules != null) { - String inspectionTypeStr = detectionRules.getInspectionType() != null && detectionRules.getInspectionType() == 0 ? "鏂版満妫€娴? : "搴撳瓨妫€娴?; + String inspectionTypeStr = detectionRules.getInspectionType() != null && detectionRules.getInspectionType() == 0 ? "新机检测" : "库存检测"; vo.setTicketTitle(detectionRules.getModelNo() + "-" + detectionRules.getOrderNo() + "-" + inspectionTypeStr + "-" + detectionRules.getInspectionVersion()); } } } - // 鏌ヨ褰撳墠鐧诲綍浜虹浉鍏崇殑妫€娴嬮」 + // 查询当前登录人相关的检测项 List inspectionItems = new ArrayList<>(); String rootCause = null; List temporaryMeasures = new ArrayList<>(); List permanentMeasures = new ArrayList<>(); - // 鏌ヨ瀛楀吀椤癸細涓存椂鎺柦鍜屾案涔呮帾鏂界殑绫诲瀷ID - Long temporaryTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "涓存椂绾犳鎺柦"); - Long permanentTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "姘镐箙绾犳鎺柦"); + // 查询字典项:临时措施和永久措施的类型ID + Long temporaryTypeId = dictionaryItemService.getId("工单解决措施", "临时纠正措施"); + Long permanentTypeId = dictionaryItemService.getId("工单解决措施", "永久纠正措施"); for (QmsIssueTicketProcess process : processes) { - // 鎻愬彇鏍规湰鍘熷洜 + // 提取根本原因 if (rootCause == null && StrUtil.isNotBlank(process.getRootCause())) { rootCause = process.getRootCause(); } - // 鏌ヨ澶勭悊璁板綍鍏宠仈鐨勪笉鍚堟牸妫€娴嬮」 + // 查询处理记录关联的不合格检测项 if (StrUtil.isNotBlank(process.getTaskResultIds())) { List resultIds = Arrays.stream(process.getTaskResultIds().split(",")) .filter(StrUtil::isNotBlank) @@ -1990,7 +1990,7 @@ public class QmsIssueTicketControllerService { .eq(QmsPdiInspectionResults::getInspectionItemResults, false) .list(); - // 鏌ヨ妫€娴嬭鍒欑姸鎬侀」锛堥儴浠舵弿杩般€佹鏌ュ唴瀹圭瓑锛? + // 查询检测规则状态项(部件描述、检查内容等) Map statusItemMap = new HashMap<>(); if (CollectionUtil.isNotEmpty(unqualifiedResults)) { List statusItemIds = unqualifiedResults.stream() @@ -2007,7 +2007,7 @@ public class QmsIssueTicketControllerService { } } - // 鏌ヨ鍥剧墖璇︽儏 + // 查询图片详情 Map fileUploadRecordMap = new HashMap<>(); List allImageIds = unqualifiedResults.stream() .filter(r -> StrUtil.isNotBlank(r.getInspectionItemImage())) @@ -2036,11 +2036,11 @@ public class QmsIssueTicketControllerService { itemVO.setInspectionTime(result.getInspectionTime()); itemVO.setInspectionBy(result.getInspectionBy()); - // 濉厖妫€娴嬮」淇℃伅锛堜粎type=0/1/3锛? + // 填充检测项信息(仅type=0/1/3) if (result.getInspectionItemType() != null && result.getInspectionItemType() != 2) { QmsPdiDetectionRulesStatusItem statusItem = statusItemMap.get(result.getInspectionItemId()); if (statusItem != null) { - // 閫氳繃componentsId鏌ヨ閮ㄤ欢鍚嶇О + // 通过componentsId查询部件名称 if (statusItem.getComponentsId() != null) { QmsPdiComponentAnagement component = pdiComponentAnagementService.getById(statusItem.getComponentsId()); if (component != null) { @@ -2063,7 +2063,7 @@ public class QmsIssueTicketControllerService { } } - // 瑙f瀽鐜板満涓婁紶鍥剧墖 + // 解析现场上传图片 if (StrUtil.isNotBlank(result.getInspectionItemImage())) { List imageDetails = Arrays.stream(result.getInspectionItemImage().split(",")) .filter(StrUtil::isNotBlank) @@ -2082,7 +2082,7 @@ public class QmsIssueTicketControllerService { itemVO.setInspectionItemImage(imageDetails); } - // 濉厖澶勭悊淇℃伅 + // 填充处理信息 itemVO.setHandlerUserId(process.getHandlerUserId()); itemVO.setHandlerUserName(process.getHandlerUserName()); itemVO.setProcessTime(process.getApprovalTime()); @@ -2092,7 +2092,7 @@ public class QmsIssueTicketControllerService { itemVO.setApprovalTime(process.getApprovalTime()); itemVO.setApprovalStatus(process.getApprovalStatus()); - // 鏌ヨ澶勭悊浜洪儴闂ㄤ俊鎭? + // 查询处理人部门信息 if (process.getHandlerUserId() != null) { UserInterior userInterior = userInteriorService.lambdaQuery() .eq(UserInterior::getUserId, process.getHandlerUserId()) @@ -2110,7 +2110,7 @@ public class QmsIssueTicketControllerService { } } - // 鏌ヨ鎺柦鍒楄〃 + // 查询措施列表 List measures = issueTicketProcessMeasureService.lambdaQuery() .eq(QmsIssueTicketProcessMeasure::getIssueTicketProcessId, process.getId()) .list(); @@ -2125,7 +2125,7 @@ public class QmsIssueTicketControllerService { measureVO.setConfirmDate(measure.getConfirmDate()); measureVO.setRemark(measure.getRemark()); - // 鏍规嵁measureTypeId鍖哄垎涓存椂鎺柦鍜屾案涔呮帾鏂? + // 根据measureTypeId区分临时措施和永久措施 if (measure.getMeasureTypeId() != null) { if (measure.getMeasureTypeId().equals(temporaryTypeId)) { temporaryMeasures.add(measureVO); @@ -2141,7 +2141,7 @@ public class QmsIssueTicketControllerService { vo.setTemporaryMeasures(temporaryMeasures); vo.setPermanentMeasures(permanentMeasures); - // 濉厖澶勭悊璁板綍鍒楄〃锛堝惈澶勭悊浜轰俊鎭級 + // 填充处理记录列表(含处理人信息) List processVOs = new ArrayList<>(); for (QmsIssueTicketProcess process : processes) { QmsPdiTicketMyDetailVO.ProcessVO pvo = new QmsPdiTicketMyDetailVO.ProcessVO(); @@ -2162,7 +2162,7 @@ public class QmsIssueTicketControllerService { pvo.setLeaderUserName(process.getLeaderUserName()); pvo.setLeaderApprovalTime(process.getLeaderApprovalTime()); - // 鏌ヨ璇ュ鐞嗚褰曠殑鎺柦鍒楄〃 + // 查询该处理记录的措施列表 List processMeasures = issueTicketProcessMeasureService.lambdaQuery() .eq(QmsIssueTicketProcessMeasure::getIssueTicketProcessId, process.getId()) .list(); @@ -2184,19 +2184,19 @@ public class QmsIssueTicketControllerService { } vo.setProcesses(processVOs); - // 鏋勫缓鐩稿叧浜哄憳绛惧瓧锛堟寜閮ㄩ棬锛屽彧杩斿洖宸插鎵圭殑锛? + // 构建相关人员签字(按部门,只返回已审批的) Map signatures = buildSignatures(processes); vo.setSignatures(signatures); - // === 鏉冮檺鍒ゆ柇锛歩sReview / isDispatch / isEdit / isShut === + // === 权限判断:isReview / isDispatch / isEdit / isShut === if (isCreator) { - // 鍒涘缓浜猴細isReview=false锛宨sEdit=false + // 创建人:isReview=false,isEdit=false vo.setIsReview(false); vo.setIsEdit(false); - // 鍒涘缓浜轰笖宸ュ崟鐘舵€佷负宸插畬鎴愭椂锛屾湁鍏抽棴鏉冮檺 + // 创建人且工单状态为已完成时,有关闭权限 vo.setIsShut(ticket.getStatus() != null && ticket.getStatus() == 2); - // isDispatch锛氭煡璇㈠叏閮ㄤ笉鍚堟牸椤癸紝鍒ゆ柇鏄惁閮藉凡琚湁鏁堝垎娲? + // isDispatch:查询全部不合格项,判断是否都已被有效分派 List allUnqualified = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, ticket.getSourceId()) .eq(QmsPdiInspectionResults::getInspectionItemResults, false) @@ -2205,36 +2205,36 @@ public class QmsIssueTicketControllerService { .map(QmsPdiInspectionResults::getId) .collect(Collectors.toSet()); - // 鏀堕泦鏈夋晥鍒嗘淳鐨勪笉鍚堟牸椤笽D锛堟帓闄ゅ鐞嗕汉/瀹℃壒浜洪┏鍥炵殑璁板綍锛? + // 收集有效分派的不合格项ID(排除处理人/审批人驳回的记录) Set effectivelyDispatched = new HashSet<>(); for (QmsIssueTicketProcess p : processes) { if (StrUtil.isBlank(p.getTaskResultIds())) continue; - // 澶勭悊浜?瀹℃壒浜洪┏鍥炵殑涓嶇畻鏈夋晥瑕嗙洊锛岄渶瑕佸垱寤轰汉閲嶆柊鍒嗘淳 + // 处理人/审批人驳回的不算有效覆盖,需要创建人重新分派 if (p.getApprovalStatus() != null && p.getApprovalStatus() == 1) continue; - // 棰嗗椹冲洖涓嶅奖鍝嶅垎娲炬潈闄愶紙鐢卞鐞嗕汉閲嶆柊鎻愪氦澶勭悊锛? + // 领导驳回不影响分派权限(由处理人重新提交处理) Arrays.stream(p.getTaskResultIds().split(",")) .filter(StrUtil::isNotBlank).map(String::trim).map(Long::valueOf) .forEach(effectivelyDispatched::add); } - // 鍏ㄩ儴涓嶅悎鏍奸」閮藉湪鏈夋晥鍒嗘淳闆嗗悎涓?鈫?isDispatch=false - // 鏈夋湭瑕嗙洊鐨勶紙浠庢湭鍒嗘淳 鎴?琚┏鍥炲悗鏈噸鏂板垎娲撅級鈫?isDispatch=true + // 全部不合格项都在有效分派集合中 → isDispatch=false + // 有未覆盖的(从未分派 或 被驳回后未重新分派)→ isDispatch=true vo.setIsDispatch(!allUnqualifiedIds.isEmpty() && !effectivelyDispatched.containsAll(allUnqualifiedIds)); } else { - // 闈炲垱寤轰汉锛歩sDispatch=false锛宨sShut=false + // 非创建人:isDispatch=false,isShut=false vo.setIsDispatch(false); vo.setIsShut(false); - // 鑾峰彇鍏ㄩ儴澶勭悊璁板綍鍒ゆ柇瑙掕壊 + // 获取全部处理记录判断角色 List allProcesses = issueTicketProcessService.lambdaQuery() .eq(QmsIssueTicketProcess::getIssueTicketId, id) .list(); - // 鍒ゆ柇鏄惁涓哄鐞嗕汉/瀹℃壒浜? + // 判断是否为处理人/审批人 boolean isHandler = allProcesses.stream() .anyMatch(p -> currentUserId.equals(p.getHandlerUserId()) || currentUserId.equals(p.getApprovalUserId())); - // 鍒ゆ柇鏄惁涓洪瀵硷細1.宸插湪process琛ㄨ褰曚簡leaderUserId 2.鎴栧綋鍓嶇敤鎴锋槸澶勭悊浜虹殑閮ㄩ棬璐熻矗浜? + // 判断是否为领导:1.已在process表记录了leaderUserId 2.或当前用户是处理人的部门负责人 boolean isLeader = allProcesses.stream() .anyMatch(p -> currentUserId.equals(p.getLeaderUserId())); if (!isLeader) { @@ -2254,23 +2254,23 @@ public class QmsIssueTicketControllerService { } if (isLeader) { - // 棰嗗锛氫粎鏈夊鏍告潈闄愶紝鏃犵紪杈戞潈闄? + // 领导:仅有审核权限,无编辑权限 vo.setIsReview(true); vo.setIsEdit(false); } else if (isHandler) { - // 澶勭悊浜?瀹℃壒浜? + // 处理人/审批人 boolean hasUnapproved = allProcesses.stream() .filter(p -> currentUserId.equals(p.getHandlerUserId()) || currentUserId.equals(p.getApprovalUserId())) .anyMatch(p -> p.getApprovalStatus() == null); vo.setIsReview(hasUnapproved); - // isEdit锛氭湭鎻愪氦锛坅pprovalStatus涓簄ull锛夋垨棰嗗椹冲洖锛坙eaderApprovalResult==1锛夋椂鏈夌紪杈戞潈闄? + // isEdit:未提交(approvalStatus为null)或领导驳回(leaderApprovalResult==1)时有编辑权限 boolean canEdit = allProcesses.stream() .filter(p -> currentUserId.equals(p.getHandlerUserId()) || currentUserId.equals(p.getApprovalUserId())) .anyMatch(p -> p.getApprovalStatus() == null || (p.getLeaderApprovalResult() != null && p.getLeaderApprovalResult() == 1)); vo.setIsEdit(canEdit); } else { - // 鍏朵粬瑙掕壊锛氭棤鏉冮檺 + // 其他角色:无权限 vo.setIsReview(false); vo.setIsEdit(false); } @@ -2280,39 +2280,34 @@ public class QmsIssueTicketControllerService { } /** - * 鏌ヨPQC宸ュ崟璇︽儏锛堟湰浜虹浉鍏筹級 - * 鏍¢獙褰撳墠鐧诲綍浜轰负鍒涘缓浜烘垨澶勭悊浜猴紝浠呰繑鍥炰笌鑷繁鐩稿叧鐨勬暟鎹? + * 查询PQC工单详情(本人相关) + * 校验当前登录人为创建人或处理人,仅返回与自己相关的数据 */ public QmsPqcTicketMyDetailVO getMyPqcTicketDetail(Long id) { Long currentUserId = UserUtil.getUserId(); String currentUserName = UserUtil.getUserName(); - // 1. 鏌ヨ宸ュ崟鍩烘湰淇℃伅 + // 1. 查询工单基本信息 QmsIssueTicket ticket = issueTicketService.getById(id); - VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 鏍¢獙宸ュ崟鏉ユ簮绫诲瀷涓篜QC + // 2. 校验工单来源类型为PQC if (!Objects.equals(ticket.getSourceType(), (short) 3)) { - throw new NflgException(STATE.BusinessError, "鍙兘鏌ヨPQC宸ュ崟"); + throw new NflgException(STATE.BusinessError, "只能查询PQC工单"); } - // 3. 鏍¢獙褰撳墠鐧诲綍浜烘槸鍚︿笌宸ュ崟鐩稿叧 - List allProcesses = issueTicketProcessService.lambdaQuery() - .eq(QmsIssueTicketProcess::getIssueTicketId, id) - .list(); + // 3. 校验当前登录人是否与工单相关 boolean isCreator = currentUserId.equals(ticket.getCreateUserId()); - List handlerProcesses = allProcesses.stream() - .filter(process -> currentUserId.equals(process.getHandlerUserId())) - .filter(process -> !Objects.equals(process.getApprovalStatus(), (short) 1)) - .collect(Collectors.toList()); - boolean isHandler = CollectionUtil.isNotEmpty(handlerProcesses); - List leaderProcesses = allProcesses.stream() - .filter(process -> isCurrentUserPqcProcessLeader(currentUserId, process)) - .collect(Collectors.toList()); - boolean isLeader = CollectionUtil.isNotEmpty(leaderProcesses); - VUtil.trueThrowBusinessError(!isCreator && !isHandler && !isLeader).throwMessage("鏃犳潈鏌ョ湅璇ュ伐鍗?); + boolean isHandler = false; + if (!isCreator) { + isHandler = issueTicketProcessService.lambdaQuery() + .eq(QmsIssueTicketProcess::getIssueTicketId, id) + .eq(QmsIssueTicketProcess::getHandlerUserId, currentUserId) + .count() > 0; + } + VUtil.trueThrowBusinessError(!isCreator && !isHandler).throwMessage("无权查看该工单"); - // 4. 鏋勫缓VO + // 4. 构建VO QmsPqcTicketMyDetailVO vo = new QmsPqcTicketMyDetailVO(); vo.setId(ticket.getId()); vo.setSourceType(ticket.getSourceType()); @@ -2335,7 +2330,7 @@ public class QmsIssueTicketControllerService { vo.setCreateTime(ticket.getCreateTime()); vo.setCreateUserName(ticket.getCreateUserName()); - // 5. 瑙f瀽宸ュ崟鍥剧墖 + // 5. 解析工单图片 if (StrUtil.isNotBlank(ticket.getImageIds())) { List imageIds = Arrays.stream(ticket.getImageIds().split(",")) .filter(StrUtil::isNotBlank) @@ -2359,7 +2354,7 @@ public class QmsIssueTicketControllerService { vo.setImages(images); } - // 6. 鏌ヨ闂璇︽儏锛堜笉鍚堟牸椤癸級 + // 6. 查询问题详情(不合格项) List issueDetails = new ArrayList<>(); List processes = isCreator ? issueTicketProcessService.lambdaQuery() @@ -2370,11 +2365,11 @@ public class QmsIssueTicketControllerService { .eq(QmsIssueTicketProcess::getHandlerUserId, currentUserId) .list(); - // 鏌ヨ褰撳墠鐧诲綍浜虹殑澶勭悊璁板綍 + // 查询当前登录人的处理记录 QmsIssueTicketProcess process = CollectionUtil.isEmpty(processes) ? null : processes.get(0); if (process != null && StrUtil.isNotBlank(process.getTaskResultIds())) { - // 瑙f瀽涓嶅悎鏍奸」ID + // 解析不合格项ID List taskResultIds = Arrays.stream(process.getTaskResultIds().split(",")) .filter(StrUtil::isNotBlank) .map(String::trim) @@ -2382,13 +2377,13 @@ public class QmsIssueTicketControllerService { .distinct() .collect(Collectors.toList()); - // 鏌ヨ妫€娴嬮」璇︽儏 + // 查询检测项详情 List details = pqcTaskRecordDetailsService.lambdaQuery() .in(QmsPqcTaskRecordDetails::getId, taskResultIds) .list(); if (CollectionUtil.isNotEmpty(details)) { - // 鎵归噺鏌ヨ妫€娴嬮」淇℃伅 + // 批量查询检测项信息 Set itemIds = details.stream() .map(QmsPqcTaskRecordDetails::getInspectionPointItemId) .filter(Objects::nonNull) @@ -2400,7 +2395,7 @@ public class QmsIssueTicketControllerService { .collect(Collectors.toMap(QmsPqcInspectionPointItems::getId, i -> i)); } - // 鎵归噺鏌ヨ妫€鏌ョ偣淇℃伅 + // 批量查询检查点信息 Set pointIds = details.stream() .map(QmsPqcTaskRecordDetails::getTaskId) .filter(Objects::nonNull) @@ -2423,7 +2418,7 @@ public class QmsIssueTicketControllerService { } } - // 鎵归噺鏌ヨ闄勪欢 + // 批量查询附件 Set allFileIds = new HashSet<>(); details.forEach(d -> { if (StrUtil.isNotBlank(d.getSelfTestAttachments())) { @@ -2446,12 +2441,12 @@ public class QmsIssueTicketControllerService { .collect(Collectors.toMap(FileUploadRecord::getId, f -> f)); } - // 缁勮闂璇︽儏 + // 组装问题详情 for (QmsPqcTaskRecordDetails detail : details) { QmsPqcTicketMyDetailVO.PqcIssueDetailVO issueVO = new QmsPqcTicketMyDetailVO.PqcIssueDetailVO(); issueVO.setTaskResultId(detail.getId()); - // 妫€娴嬮」淇℃伅 + // 检测项信息 QmsPqcInspectionPointItems item = itemMap.get(detail.getInspectionPointItemId()); if (item != null) { issueVO.setInspectionContent(item.getInspectionContent()); @@ -2459,32 +2454,32 @@ public class QmsIssueTicketControllerService { issueVO.setInspectionExampleImage(item.getInspectionImgUrl()); } - // 妫€鏌ョ偣鍚嶇О + // 检查点名称 QmsPqcTaskRecord task = taskMap.get(detail.getTaskId()); if (task != null) { QmsPqcInspectionPoint point = pointMap.get(task.getInspectionPointId()); if (point != null) { issueVO.setInspectionPointName(point.getInspectionPointName()); } - // 妫€娴嬩汉淇℃伅 + // 检测人信息 issueVO.setInspectorId(task.getSelfTesterId()); issueVO.setInspectorName(task.getSelfTesterName()); issueVO.setInspectionTime(task.getCompleteTime()); issueVO.setInspectionResult(task.getEnable()); } - // 妫€娴嬫暟鎹? + // 检测数据 issueVO.setSelfTestData(detail.getSelfTestData()); issueVO.setQcTestData(detail.getQcTestData()); - // 澶嶆牳鎰忚 + // 复核意见 issueVO.setReviewOpinion(detail.getReviewOpinion()); - // 闄勪欢 + // 附件 issueVO.setSelfTestFiles(parseFileList(detail.getSelfTestAttachments(), fileMap)); issueVO.setQcTestFiles(parseFileList(detail.getQcTestAttachments(), fileMap)); - // 澶勭悊浜轰俊鎭? + // 处理人信息 issueVO.setHandlerUserId(process.getHandlerUserId()); issueVO.setHandlerUserName(process.getHandlerUserName()); issueVO.setProcessTime(process.getApprovalTime()); @@ -2497,8 +2492,8 @@ public class QmsIssueTicketControllerService { } vo.setIssueDetails(buildPqcIssueDetails(processes)); if (CollectionUtil.isNotEmpty(processes)) { - Long temporaryTypeIdAll = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "涓存椂绾犳鎺柦"); - Long permanentTypeIdAll = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "姘镐箙绾犳鎺柦"); + Long temporaryTypeIdAll = dictionaryItemService.getId("工单解决措施", "临时纠正措施"); + Long permanentTypeIdAll = dictionaryItemService.getId("工单解决措施", "永久纠正措施"); List processIdsAll = processes.stream() .map(QmsIssueTicketProcess::getId) .filter(Objects::nonNull) @@ -2521,10 +2516,10 @@ public class QmsIssueTicketControllerService { } } - // 7. 鏌ヨ鎺柦鍒楄〃 + // 7. 查询措施列表 if (process != null) { - Long temporaryTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "涓存椂绾犳鎺柦"); - Long permanentTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "姘镐箙绾犳鎺柦"); + Long temporaryTypeId = dictionaryItemService.getId("工单解决措施", "临时纠正措施"); + Long permanentTypeId = dictionaryItemService.getId("工单解决措施", "永久纠正措施"); if (temporaryTypeId != null) { List temporaryMeasures = issueTicketProcessMeasureService.lambdaQuery() @@ -2543,25 +2538,25 @@ public class QmsIssueTicketControllerService { } } - // 8. 璁剧疆鏉冮檺瀛楁 + // 8. 设置权限字段 if (isCreator) { - // 鍒涘缓浜猴細 - // - isDispatch=true锛堢姸鎬?0鎴?鏃讹級 - // - isReview=true锛堢姸鎬?2鏃讹級 - // - isEdit=false锛堝垱寤轰汉鏃犵紪杈戞潈闄愶級 + // 创建人: + // - isDispatch=true(状态=0或1时) + // - isReview=true(状态=2时) + // - isEdit=false(创建人无编辑权限) vo.setIsDispatch(ticket.getStatus() != null && (ticket.getStatus() == 0 || ticket.getStatus() == 1)); vo.setIsReview(ticket.getStatus() != null && ticket.getStatus() == 2); vo.setIsEdit(false); } else if (isHandler && process != null) { - // 澶勭悊浜猴細 - // - isDispatch=false锛堝鐞嗕汉鏃犲垎娲炬潈闄愶級 - // - isReview=true锛堢姸鎬?1涓斿鎵圭姸鎬佷负绌烘椂锛? - // - isEdit=true锛堢姸鎬?1鏃讹級 + // 处理人: + // - isDispatch=false(处理人无分派权限) + // - isReview=true(状态=1且审批状态为空时) + // - isEdit=true(状态=1时) vo.setIsDispatch(false); vo.setIsReview(ticket.getStatus() != null && ticket.getStatus() == 1 && process.getApprovalStatus() == null); vo.setIsEdit(ticket.getStatus() != null && ticket.getStatus() == 1); } else { - // 鍏朵粬瑙掕壊锛氭棤鏉冮檺 + // 其他角色:无权限 vo.setIsDispatch(false); vo.setIsReview(false); vo.setIsEdit(false); @@ -2571,7 +2566,7 @@ public class QmsIssueTicketControllerService { } /** - * 瑙f瀽鏂囦欢鍒楄〃 + * 解析文件列表 */ private List buildPqcIssueDetails(List processes) { if (CollectionUtil.isEmpty(processes)) { @@ -2777,7 +2772,7 @@ public class QmsIssueTicketControllerService { } /** - * 杞崲鎺柦鍒楄〃 + * 转换措施列表 */ private List convertToMeasureVO(List measures) { if (CollectionUtil.isEmpty(measures)) { @@ -2799,20 +2794,20 @@ public class QmsIssueTicketControllerService { } /** - * 鏋勫缓鐩稿叧浜哄憳绛惧瓧锛堟寜閮ㄩ棬锛屽彧杩斿洖宸插鎵圭殑锛? - * @param processes 澶勭悊璁板綍鍒楄〃 - * @return 閮ㄩ棬绛惧瓧淇℃伅Map + * 构建相关人员签字(按部门,只返回已审批的) + * @param processes 处理记录列表 + * @return 部门签字信息Map */ private Map buildSignatures(List processes) { Map signatures = new HashMap<>(); for (QmsIssueTicketProcess process : processes) { - // 鍙繑鍥炲凡瀹℃壒鐨勮褰曪紙approvalStatus 涓嶄负 null锛? + // 只返回已审批的记录(approvalStatus 不为 null) if (process.getApprovalStatus() == null) { continue; } - // 鏌ヨ澶勭悊浜虹殑閮ㄩ棬淇℃伅 + // 查询处理人的部门信息 if (process.getHandlerUserId() != null) { UserInterior userInterior = userInteriorService.lambdaQuery() .eq(UserInterior::getUserId, process.getHandlerUserId()) @@ -2823,7 +2818,7 @@ public class QmsIssueTicketControllerService { if (department != null) { String deptName = department.getName(); - // 鏌ヨ閮ㄩ棬棰嗗 + // 查询部门领导 Department leaderDept = departmentService.getById(userInterior.getDeptId()); String leaderName = null; if (leaderDept != null && leaderDept.getHeadUserId() != null) { @@ -2833,16 +2828,16 @@ public class QmsIssueTicketControllerService { } } - // 濡傛灉棰嗗鏈鎵癸紝璺宠繃 + // 如果领导未审批,跳过 if (StrUtil.isBlank(leaderName)) { continue; } - // 鏋勫缓绛惧悕锛氬鍚嶏紙鐘舵€侊級 + // 构建签名:姓名(状态) String statusText = convertApprovalStatus(process.getApprovalStatus()); - String signature = leaderName + "锛? + statusText + "锛?; + String signature = leaderName + "(" + statusText + ")"; - // 鏋勫缓绛惧瓧淇℃伅 + // 构建签字信息 QmsPdiTicketMyDetailVO.SignatureInfo signatureInfo = new QmsPdiTicketMyDetailVO.SignatureInfo(); signatureInfo.setDeptName(deptName); signatureInfo.setApprovalOpinion(process.getApprovalOpinion()); @@ -2861,53 +2856,53 @@ public class QmsIssueTicketControllerService { } /** - * 杞崲瀹℃壒鐘舵€佷负鏂囨湰 - * @param status 瀹℃壒鐘舵€侊細0=閫氳繃锛?=椹冲洖锛?=閫€璐э紝3=鎶ュ簾锛?=缁翠慨锛?=鎸戦€変娇鐢紝6=璁╂浮浣跨敤 - * @return 鐘舵€佹枃鏈? + * 转换审批状态为文本 + * @param status 审批状态:0=通过,1=驳回,2=退货,3=报废,4=维修,5=挑选使用,6=让渡使用 + * @return 状态文本 */ private String convertApprovalStatus(Short status) { if (status == null) { - return "鏈鎵?; + return "未审批"; } switch (status) { case 0: - return "閫氳繃"; + return "通过"; case 1: - return "椹冲洖"; + return "驳回"; case 2: - return "閫€璐?; + return "退货"; case 3: - return "鎶ュ簾"; + return "报废"; case 4: - return "缁翠慨"; + return "维修"; case 5: - return "鎸戦€変娇鐢?; + return "挑选使用"; case 6: - return "璁╂浮浣跨敤"; + return "让渡使用"; default: - return "鏈煡"; + return "未知"; } } /** - * 鏌ヨ宸℃宸ュ崟璇︽儏 - * 杩斿洖宸ュ崟鍩烘湰淇℃伅銆佸浘鐗囧垪琛ㄣ€佸鐞嗕汉淇℃伅銆佺籂姝f帾鏂界瓑 + * 查询巡检工单详情 + * 返回工单基本信息、图片列表、处理人信息、纠正措施等 */ public QmsInspectionTicketDetailVO getInspectionTicketDetail(Long id) { - // 鏌ヨ宸ュ崟鍩烘湰淇℃伅 + // 查询工单基本信息 QmsIssueTicket ticket = issueTicketService.getById(id); if (Objects.isNull(ticket)) { - throw new NflgException(STATE.BusinessError, "宸℃宸ュ崟涓嶅瓨鍦?); + throw new NflgException(STATE.BusinessError, "巡检工单不存在"); } - // 鏍¢獙宸ュ崟鏉ユ簮绫诲瀷涓哄贰妫€ + // 校验工单来源类型为巡检 if (!Objects.equals(ticket.getSourceType(), (short) 2)) { - throw new NflgException(STATE.BusinessError, "璇ュ伐鍗曚笉鏄贰妫€宸ュ崟"); + throw new NflgException(STATE.BusinessError, "该工单不是巡检工单"); } QmsInspectionTicketDetailVO vo = new QmsInspectionTicketDetailVO(); - // 濉厖宸ュ崟鍩烘湰淇℃伅 + // 填充工单基本信息 vo.setId(ticket.getId()); vo.setTicketTitle(ticket.getTicketTitle()); vo.setProjectNo(ticket.getProjectNo()); @@ -2918,17 +2913,17 @@ public class QmsIssueTicketControllerService { vo.setImpactQuantity(ticket.getImpactQuantity()); vo.setDirectorId(ticket.getApprovalUserId()); vo.setStatus(ticket.getStatus()); - vo.setTicketType("宸℃"); + vo.setTicketType("巡检"); vo.setIncidentLocation(ticket.getIncidentLocation()); vo.setIncidentDescription(ticket.getIncidentDescription()); vo.setIncidentReason(ticket.getIncidentReason()); vo.setIncidentConsequence(ticket.getIncidentConsequence()); - // 濉厖璐熻矗浜哄鎵圭姸鎬佸拰鎰忚锛堟潵鑷伐鍗曡〃锛? + // 填充负责人审批状态和意见(来自工单表) vo.setResponsiblePersonApprovalStatus(ticket.getApprovalStatus()); vo.setResponsiblePersonApprovalComments(ticket.getApprovalOpinion()); - // 瑙f瀽鍥剧墖鍒楄〃 + // 解析图片列表 if (StrUtil.isNotBlank(ticket.getImageIds())) { List imageIds = Arrays.stream(ticket.getImageIds().split(",")) .filter(StrUtil::isNotBlank) @@ -2965,18 +2960,18 @@ public class QmsIssueTicketControllerService { vo.setImages(List.of()); } - // 鏌ヨ鎵€鏈夊鐞嗚褰? + // 查询所有处理记录 List processes = issueTicketProcessService.lambdaQuery() .eq(QmsIssueTicketProcess::getIssueTicketId, id) .list(); - // 杩囨护鎺夊鎵圭姸鎬佷负椹冲洖锛?锛夌殑澶勭悊璁板綍锛屼笉杩斿洖 + // 过滤掉审批状态为驳回(1)的处理记录,不返回 List validProcesses = processes.stream() .filter(p -> p.getApprovalStatus() == null || p.getApprovalStatus() != 1) .collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(validProcesses)) { - // 缁勮澶勭悊浜哄垪琛紙鎸夐儴闂ㄥ悎骞讹級 + // 组装处理人列表(按部门合并) Map> handlersByDept = new LinkedHashMap<>(); for (QmsIssueTicketProcess process : validProcesses) { if (StrUtil.isBlank(process.getHandlerUserName())) { @@ -3005,10 +3000,10 @@ public class QmsIssueTicketControllerService { } vo.setHandlers(handlers); - // 缁勮棰嗗鍒楄〃锛堜粎澶勭悊浜哄凡鎻愪氦銆侀瀵煎凡瀹℃壒鏃舵墠灞曠ず锛? + // 组装领导列表(仅处理人已提交、领导已审批时才展示) Map> leadersByDept = new LinkedHashMap<>(); for (QmsIssueTicketProcess process : validProcesses) { - // 棰嗗瀹℃壒鐘舵€佷负 null 琛ㄧず澶勭悊浜哄皻鏈彁浜わ紝涓嶅睍绀? + // 领导审批状态为 null 表示处理人尚未提交,不展示 if (process.getLeaderApprovalResult() == null || StrUtil.isBlank(process.getLeaderUserName())) { continue; } @@ -3024,13 +3019,13 @@ public class QmsIssueTicketControllerService { } } } - // 鎷兼帴棰嗗濮撳悕涓庡鎵规剰瑙? - String approvalText = process.getLeaderApprovalResult() == 0 ? "鍚屾剰" : "椹冲洖"; + // 拼接领导姓名与审批意见 + String approvalText = process.getLeaderApprovalResult() == 0 ? "同意" : "驳回"; String leaderDisplay; if (StrUtil.isNotBlank(process.getLeaderApprovalOpinion())) { - leaderDisplay = process.getLeaderUserName() + "锛? + approvalText + "锛? + process.getLeaderApprovalOpinion() + "锛?; + leaderDisplay = process.getLeaderUserName() + "(" + approvalText + ":" + process.getLeaderApprovalOpinion() + ")"; } else { - leaderDisplay = process.getLeaderUserName() + "锛? + approvalText + "锛?; + leaderDisplay = process.getLeaderUserName() + "(" + approvalText + ")"; } leadersByDept.computeIfAbsent(deptName, k -> new ArrayList<>()).add(leaderDisplay); } @@ -3043,15 +3038,15 @@ public class QmsIssueTicketControllerService { } vo.setLeaders(leaders); - // 濉厖鏍规湰鍘熷洜锛堝彇绗竴鏉″鐞嗚褰曪級 + // 填充根本原因(取第一条处理记录) QmsIssueTicketProcess firstProcess = validProcesses.get(0); if (StrUtil.isNotBlank(firstProcess.getRootCause())) { vo.setRootCause(firstProcess.getRootCause()); } - // 鏌ヨ绾犳鎺柦 - Long temporaryTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "涓存椂绾犳鎺柦"); - Long permanentTypeId = dictionaryItemService.getId("宸ュ崟瑙e喅鎺柦", "姘镐箙绾犳鎺柦"); + // 查询纠正措施 + Long temporaryTypeId = dictionaryItemService.getId("工单解决措施", "临时纠正措施"); + Long permanentTypeId = dictionaryItemService.getId("工单解决措施", "永久纠正措施"); List temporaryMeasures = new ArrayList<>(); List permanentMeasures = new ArrayList<>(); @@ -3070,7 +3065,7 @@ public class QmsIssueTicketControllerService { measureVO.setConfirmDate(measure.getConfirmDate()); measureVO.setRemark(measure.getRemark()); - // 鏍规嵁measureTypeId鍖哄垎涓存椂鎺柦鍜屾案涔呮帾鏂? + // 根据measureTypeId区分临时措施和永久措施 if (measure.getMeasureTypeId() != null) { if (measure.getMeasureTypeId().equals(temporaryTypeId)) { temporaryMeasures.add(measureVO); @@ -3084,33 +3079,33 @@ public class QmsIssueTicketControllerService { vo.setTemporaryMeasures(temporaryMeasures); vo.setPermanentMeasures(permanentMeasures); } else { - // 濡傛灉娌℃湁澶勭悊璁板綍锛岃缃┖鍒楄〃 + // 如果没有处理记录,设置空列表 vo.setHandlers(List.of()); vo.setLeaders(List.of()); vo.setTemporaryMeasures(List.of()); vo.setPermanentMeasures(List.of()); } - // === 鏉冮檺鍒ゆ柇锛歩sReview / isDispatch / isEdit === + // === 权限判断:isReview / isDispatch / isEdit === Long currentUserId = UserUtil.getUserId(); - // 鑾峰彇璇ュ伐鍗曞叏閮ㄥ鐞嗚褰曪紙鏉冮檺鍒ゆ柇鐢ㄥ叏閮ㄨ褰曪紝涓嶈繃婊わ級 + // 获取该工单全部处理记录(权限判断用全部记录,不过滤) List allProcesses = issueTicketProcessService.lambdaQuery() .eq(QmsIssueTicketProcess::getIssueTicketId, id) .list(); Short status = ticket.getStatus(); - // 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁涓鸿礋璐d汉锛堝伐鍗曡〃鐨?approvalUserId锛? + // 判断当前用户是否为负责人(工单表的 approvalUserId) boolean isResponsiblePerson = currentUserId.equals(ticket.getApprovalUserId()); - // 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁涓哄鐞嗕汉 + // 判断当前用户是否为处理人 QmsIssueTicketProcess myProcess = allProcesses.stream() .filter(p -> currentUserId.equals(p.getHandlerUserId())) .findFirst() .orElse(null); boolean isHandler = myProcess != null; - // 鍒ゆ柇鏄惁涓洪瀵硷細1.宸插湪process琛ㄨ褰曚簡leaderUserId 2.鎴栧綋鍓嶇敤鎴锋槸澶勭悊浜虹殑閮ㄩ棬璐熻矗浜? + // 判断是否为领导:1.已在process表记录了leaderUserId 2.或当前用户是处理人的部门负责人 boolean isLeader = allProcesses.stream() .anyMatch(p -> currentUserId.equals(p.getLeaderUserId())); if (!isLeader) { @@ -3129,47 +3124,47 @@ public class QmsIssueTicketControllerService { } } - // 璐熻矗浜烘潈闄愶細宸ュ崟鐘舵€佷负澶勭悊涓椂鏈夊鎵瑰拰鍒嗛厤鏉冮檺锛屾湁浜嗗鎵圭姸鎬佸悗澶卞幓瀹℃壒鏉冮檺 + // 负责人权限:工单状态为处理中时有审批和分配权限,有了审批状态后失去审批权限 if (isResponsiblePerson) { vo.setIsReview(status != null && status == 1 && ticket.getApprovalStatus() == null); vo.setIsDispatch(status != null && status == 1); vo.setIsEdit(false); vo.setIsShut(false); } - // 澶勭悊浜烘潈闄愶細鎷垮埌宸ュ崟鏃舵湁缂栬緫鍜屽鎵规潈闄愶紝鏈変簡瀹℃壒鐘舵€佸悗澶卞幓瀹℃壒鏉冮檺锛岄┏鍥炴椂澶卞幓缂栬緫鏉冮檺 + // 处理人权限:拿到工单时有编辑和审批权限,有了审批状态后失去审批权限,驳回时失去编辑权限 else if (isHandler) { Short handlerApprovalStatus = myProcess.getApprovalStatus(); vo.setIsReview(handlerApprovalStatus == null); if (handlerApprovalStatus != null && handlerApprovalStatus == 1) { - // 椹冲洖锛氬け鍘荤紪杈戞潈闄? + // 驳回:失去编辑权限 vo.setIsEdit(false); } else if (handlerApprovalStatus != null && handlerApprovalStatus == 0) { - // 閫氳繃锛氭寜涔嬪墠閫昏緫锛堥瀵兼湭瀹℃壒鏃跺彲缂栬緫锛? + // 通过:按之前逻辑(领导未审批时可编辑) boolean leaderNotApproved = myProcess.getLeaderApprovalResult() == null; vo.setIsEdit(leaderNotApproved); } else { - // 鏈彁浜わ細鏈夌紪杈戞潈闄? + // 未提交:有编辑权限 vo.setIsEdit(true); } vo.setIsDispatch(false); vo.setIsShut(false); } - // 棰嗗鏉冮檺锛氬彧鏈夊鏍告潈闄? + // 领导权限:只有审核权限 else if (isLeader) { vo.setIsReview(true); vo.setIsEdit(false); vo.setIsDispatch(false); vo.setIsShut(false); } - // 鍒涘缓浜烘潈闄? + // 创建人权限 else if (currentUserId.equals(ticket.getCreateUserId())) { vo.setIsReview(false); vo.setIsDispatch(status != null && status == 0); vo.setIsEdit(false); - // 鍒涘缓浜轰笖宸ュ崟鐘舵€佷负宸插畬鎴愭椂锛屾湁鍏抽棴鏉冮檺 + // 创建人且工单状态为已完成时,有关闭权限 vo.setIsShut(status != null && status == 2); } - // 鍏朵粬 + // 其他 else { vo.setIsReview(false); vo.setIsDispatch(false); @@ -3181,31 +3176,31 @@ public class QmsIssueTicketControllerService { } /** - * 鍒涘缓浜哄鏍稿伐鍗? - * 宸ュ崟鐘舵€佷负2锛堝凡瀹屾垚锛夋椂锛屽垱寤轰汉鍙互锛? - * - 鍏抽棴宸ュ崟锛歴tatus=3, createApproval=0 - * - 椹冲洖宸ュ崟锛歴tatus=1, createApproval=1, 閲嶇疆鎸囧畾澶勭悊浜虹殑瀹℃壒璁板綍 + * 创建人审核工单 + * 工单状态为2(已完成)时,创建人可以: + * - 关闭工单:status=3, createApproval=0 + * - 驳回工单:status=1, createApproval=1, 重置指定处理人的审批记录 */ @Transactional(rollbackFor = Exception.class) public void creatorReview(@Valid QmsIssueTicketCreatorReviewQO request) { - // 1. 鏍¢獙宸ュ崟瀛樺湪 + // 1. 校验工单存在 QmsIssueTicket ticket = issueTicketService.getById(request.getId()); - VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("宸ュ崟涓嶅瓨鍦?); + VUtil.trueThrowBusinessError(Objects.isNull(ticket)).throwMessage("工单不存在"); - // 2. 鏍¢獙褰撳墠鐢ㄦ埛涓哄伐鍗曞垱寤轰汉 + // 2. 校验当前用户为工单创建人 Long currentUserId = UserUtil.getUserId(); VUtil.trueThrowBusinessError(!currentUserId.equals(ticket.getCreateUserId())) - .throwMessage("鍙湁宸ュ崟鍒涘缓浜烘墠鑳藉鏍?); + .throwMessage("只有工单创建人才能审核"); - // 3. 鏍¢獙宸ュ崟鐘舵€佷负宸插畬鎴? + // 3. 校验工单状态为已完成 VUtil.trueThrowBusinessError(ticket.getStatus() != 2) - .throwMessage("鍙兘瀹℃牳鐘舵€佷负宸插畬鎴愮殑宸ュ崟"); + .throwMessage("只能审核状态为已完成的工单"); LocalDateTime now = LocalDateTime.now(); String currentUserName = UserUtil.getUserName(); if (request.getCreateApproval() == 0) { - // 鍏抽棴宸ュ崟 + // 关闭工单 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, ticket.getId()) .set(QmsIssueTicket::getStatus, (short) 3) @@ -3216,7 +3211,7 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, now) .update(); - // PDI宸ュ崟鍏抽棴鏃讹細鍒涘缓鏂颁换鍔″崟锛屽鍒跺唴瀹癸紝涓嶅悎鏍奸」鏀逛负鍚堟牸 + // PDI工单关闭时:创建新任务单,复制内容,不合格项改为合格 if (ticket.getSourceType() != null && ticket.getSourceType() == 1 && ticket.getSourceId() != null) { QmsPdiTaskRecord originalTask = createPdiRepairTask(ticket.getSourceId(), now); if (originalTask != null) { @@ -3225,19 +3220,19 @@ public class QmsIssueTicketControllerService { } } else if (request.getCreateApproval() == 1) { - // 椹冲洖宸ュ崟 - // 鏍¢獙锛歨andlers鍜屽鎵规剰瑙佷笉鑳戒负绌? + // 驳回工单 + // 校验:handlers和审批意见不能为空 VUtil.trueThrowBusinessError(request.getHandlers() == null || request.getHandlers().isEmpty()) - .throwMessage("椹冲洖鏃跺鐞嗕汉鍒楄〃涓嶈兘涓虹┖"); + .throwMessage("驳回时处理人列表不能为空"); VUtil.trueThrowBusinessError(StrUtil.isBlank(request.getCreateApprovalOpinion())) - .throwMessage("椹冲洖鏃跺鎵规剰瑙佷笉鑳戒负绌?); + .throwMessage("驳回时审批意见不能为空"); Long issueTicketId = ticket.getId(); List rejectUserIds = request.getHandlers().stream() .map(QmsIssueTicketCreatorReviewQO.RejectHandlerItem::getHandlerUserId) .collect(Collectors.toList()); - // 鏇存柊鎸囧畾澶勭悊浜虹殑璁板綍锛氶噸缃鎵圭姸鎬? + // 更新指定处理人的记录:重置审批状态 issueTicketProcessService.lambdaUpdate() .eq(QmsIssueTicketProcess::getIssueTicketId, issueTicketId) .in(QmsIssueTicketProcess::getHandlerUserId, rejectUserIds) @@ -3250,7 +3245,7 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicketProcess::getLeaderApprovalTime, null) .update(); - // 宸ュ崟鐘舵€佹敼鍥炲鐞嗕腑 + // 工单状态改回处理中 issueTicketService.lambdaUpdate() .eq(QmsIssueTicket::getId, issueTicketId) .set(QmsIssueTicket::getStatus, (short) 1) @@ -3261,7 +3256,7 @@ public class QmsIssueTicketControllerService { .set(QmsIssueTicket::getUpdateTime, now) .update(); - // 鎺ㄩ€佸緟鍔炵粰琚┏鍥炵殑澶勭悊浜? + // 推送待办给被驳回的处理人 for (Long userId : rejectUserIds) { QmsIssueTicketToDo todoItem = new QmsIssueTicketToDo() .setTicketId(issueTicketId) @@ -3269,19 +3264,19 @@ public class QmsIssueTicketControllerService { issueTicketToDoService.save(todoItem); } } else { - throw new NflgException(STATE.BusinessError, "瀹℃牳鎿嶄綔绫诲瀷鏃犳晥"); + throw new NflgException(STATE.BusinessError, "审核操作类型无效"); } } /** - * 灏嗛€楀彿鍒嗛殧鐨勫浘鐗嘔D瀛楃涓茶浆鎹负 FileDetailVO 鍒楄〃 + * 将逗号分隔的图片ID字符串转换为 FileDetailVO 列表 */ private List parseImageList(String imageIdsStr) { if (StrUtil.isBlank(imageIdsStr)) { return List.of(); } - // 鏀堕泦鎵€鏈夊浘鐗嘔D + // 收集所有图片ID Set imageIds = Arrays.stream(imageIdsStr.split(",")) .filter(StrUtil::isNotBlank) .map(String::trim) @@ -3292,16 +3287,16 @@ public class QmsIssueTicketControllerService { return List.of(); } - // 鏌ヨ鍥剧墖鏂囦欢淇℃伅 + // 查询图片文件信息 List records = fileUploadRecordService.lambdaQuery() .in(FileUploadRecord::getId, imageIds) .list(); - // 鏋勫缓 Map 淇濇寔椤哄簭 + // 构建 Map 保持顺序 Map imageMap = records.stream() .collect(Collectors.toMap(FileUploadRecord::getId, r -> r, (a, b) -> a)); - // 鎸夊師濮嬮『搴忚繑鍥? + // 按原始顺序返回 return Arrays.stream(imageIdsStr.split(",")) .filter(StrUtil::isNotBlank) .map(String::trim) @@ -3320,23 +3315,23 @@ public class QmsIssueTicketControllerService { } /** - * PDI宸ュ崟鍏抽棴鏃跺垱寤烘柊浠诲姟鍗? - * 澶嶅埗鍘熶换鍔″唴瀹癸紝灏嗕笉鍚堟牸椤规敼涓哄悎鏍? + * PDI工单关闭时创建新任务单 + * 复制原任务内容,将不合格项改为合格 */ private QmsPdiTaskRecord createPdiRepairTask(Long originalTaskId, LocalDateTime now) { - // 1. 鑾峰彇鍘熶换鍔? + // 1. 获取原任务 QmsPdiTaskRecord originalTask = pdiTaskRecordService.getById(originalTaskId); if (originalTask == null) { return null; } - // 2. 鍒涘缓鏂颁换鍔″崟 + // 2. 创建新任务单 QmsPdiTaskRecord newTask = new QmsPdiTaskRecord() .setTaskNo(basdeSerialNumberControllerService.generateSerialNumber(1)) .setDeviceNo(originalTask.getDeviceNo()) .setDetectionRulesId(originalTask.getDetectionRulesId()) - .setInspectionEnable(2) // 宸插畬鎴? - .setInspectionInspection(true) // 鍚堟牸 + .setInspectionEnable(2) // 已完成 + .setInspectionInspection(true) // 合格 .setAssistantId(originalTask.getAssistantId()) .setSubmissionTime(originalTask.getSubmissionTime()) .setRequiredCompletionTime(originalTask.getRequiredCompletionTime()) @@ -3350,7 +3345,7 @@ public class QmsIssueTicketControllerService { .setRelatedTaskId(originalTask.getId()); pdiTaskRecordService.save(newTask); - // 3. 澶嶅埗妫€楠岀粨鏋滐紝涓嶅悎鏍奸」鏀逛负鍚堟牸 + // 3. 复制检验结果,不合格项改为合格 List oldResults = pdiInspectionResultsService.lambdaQuery() .eq(QmsPdiInspectionResults::getTaskId, originalTaskId) .list(); @@ -3364,7 +3359,7 @@ public class QmsIssueTicketControllerService { .setInspectionItemId(old.getInspectionItemId()) .setInspectionItemType(old.getInspectionItemType()) .setInspectionItemImage(old.getInspectionItemImage()) - .setInspectionItemResults(true) // 鍏ㄩ儴鏀逛负鍚堟牸 + .setInspectionItemResults(true) // 全部改为合格 .setRemark(old.getRemark()) .setInspectorId(old.getInspectorId()) .setInspectionTime(old.getInspectionTime()) @@ -3374,7 +3369,7 @@ public class QmsIssueTicketControllerService { pdiInspectionResultsService.saveBatch(newResults); } - // 4. 澶嶅埗瑁呰溅鍓嶅浘鐗? + // 4. 复制装车前图片 List oldImages = pdiInspectionResultsLoadingImageService.lambdaQuery() .eq(QmsPdiInspectionResultsLoadingImage::getTaskId, originalTaskId) .list();