From 993095c3d36d62e52aaa6cb229c309231205f343 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期一, 19 十月 2026 17:11:52 +0800
Subject: [PATCH] feat(qualityMonitor): 实现质量监控检验任务完整流程 - 新增年度质量监控计划创建、提交审核及按年度查询接口 - 新增质量监控检验任务下发、查询及取消接口 - 新增质量监控检验评价提交与批准/退回流程 - 在检验订单中增加任务来源和质量监控明细ID字段 - 增加质控任务认领、原始记录填写、提交、复核等环节的权限校验 - 质控任务复核通过后发送评价通知给指定评价人 - 质控任务不生成检验报告,由评价环节完成归档 - 新增从已复核质控原始记录读取检测数据和上下文信息的方法 - 增加标准方法验证中实时查看所选设备校准证书的功能 - 补充质量监控计划明细的模板ID规范化及字段校验逻辑 - 在样品查询SQL中关联质控明细表返回任务来源和评价状态

---
 inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
index 50d6ad8..9e811fd 100644
--- a/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
+++ b/inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
@@ -49,6 +49,7 @@
 import com.ruoyi.inspect.util.ReportSignaturePictureUtils;
 import com.ruoyi.inspect.vo.InsOrderPlanTaskSwitchVo;
 import com.ruoyi.inspect.vo.InsOrderPlanVO;
+import com.ruoyi.inspect.vo.QualityMonitorRawContext;
 import com.ruoyi.inspect.vo.InsSampleUserVO;
 import com.ruoyi.performance.mapper.AuxiliaryOutputWorkingHoursMapper;
 import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
@@ -223,6 +224,10 @@
     public boolean claimInsOrderPlan(InsOrderPlanDTO entity) {
         if (Objects.isNull(entity)) {
             return false;
+        }
+        InsOrder claimOrder = insOrderMapper.selectById(entity.getInsSampleId());
+        if (claimOrder != null && "QUALITY_MONITOR".equals(claimOrder.getTaskSource())) {
+            throw new ErrorException("璐ㄩ噺鐩戞帶浠诲姟鐢辫鍒掓寚瀹氭娴嬪憳锛屼笉鑳借棰�");
         }
         Integer userId = SecurityUtils.getUserId().intValue();
         InsSampleUser insSampleUser = new InsSampleUser(entity.getInsSampleId().intValue(), userId, 0, entity.getSonLaboratory());
@@ -612,6 +617,16 @@
     public void saveTemplateContext(SaveTemplateContextDto dto) {
         if (dto.getOrderId() == null || dto.getSampleId() == null || dto.getTemplateId() == null) {
             throw new ErrorException("璁㈠崟銆佹牱鍝佸拰妯℃澘涓嶈兘涓虹┖");
+        }
+        InsOrder sourceOrder = insOrderMapper.selectById(dto.getOrderId());
+        if (sourceOrder != null && "QUALITY_MONITOR".equals(sourceOrder.getTaskSource())
+                && !Objects.equals(sourceOrder.getState(), 1)) {
+            throw new ErrorException("宸插彇娑堢殑璐ㄩ噺鐩戞帶浠诲姟涓嶈兘濉啓鍘熷璁板綍");
+        }
+        if (sourceOrder != null && "QUALITY_MONITOR".equals(sourceOrder.getTaskSource())
+                && !Objects.equals(SecurityUtils.getUserId().intValue(),
+                    insOrderMapper.selectQualityMonitorInspectorId(dto.getOrderId()))) {
+            throw new ErrorException("鍙湁璁″垝鎸囧畾鐨勬娴嬪憳鍙互濉啓璐ㄩ噺鐩戞帶鍘熷璁板綍");
         }
         InsSample sample = insSampleMapper.selectById(dto.getSampleId());
         if (sample == null || !Objects.equals(sample.getInsOrderId(), dto.getOrderId())) {
@@ -1027,6 +1042,10 @@
     //浜ゆ帴
     @Override
     public int upPlanUser(Integer userId, Integer orderId, String sonLaboratory) {
+        InsOrder handoffOrder = insOrderMapper.selectById(orderId);
+        if (handoffOrder != null && "QUALITY_MONITOR".equals(handoffOrder.getTaskSource())) {
+            throw new ErrorException("璐ㄩ噺鐩戞帶浠诲姟妫�娴嬪憳鐢辫鍒掓寚瀹氾紝涓嶈兘鐩存帴浜ゆ帴");
+        }
         InsSampleUser insSampleUser = new InsSampleUser();
         insSampleUser.setUserId(userId);
         insSampleUser.setInsSampleId(orderId);
@@ -1211,6 +1230,23 @@
         InsOrder order = insOrderMapper.selectOne(Wrappers.<InsOrder>lambdaQuery()
                 .eq(InsOrder::getId, orderId)
                 .last("FOR UPDATE"));
+        if (order == null) throw new ErrorException("妫�楠屼换鍔′笉瀛樺湪");
+        if ("QUALITY_MONITOR".equals(order.getTaskSource()) && !Objects.equals(order.getState(), 1)) {
+            throw new ErrorException("宸插彇娑堢殑璐ㄩ噺鐩戞帶浠诲姟涓嶈兘鎻愪氦");
+        }
+        if ("QUALITY_MONITOR".equals(order.getTaskSource())
+                && (verifyUser == null || userMapper.selectById(verifyUser) == null)) {
+            throw new ErrorException("璇烽�夋嫨璐ㄩ噺鐩戞帶浠诲姟澶嶆牳浜�");
+        }
+        if ("QUALITY_MONITOR".equals(order.getTaskSource())
+                && Objects.equals(verifyUser, insOrderMapper.selectQualityMonitorInspectorId(orderId))) {
+            throw new ErrorException("妫�娴嬪憳涓嶈兘澶嶆牳鑷繁鐨勮川閲忕洃鎺у師濮嬭褰�");
+        }
+        if ("QUALITY_MONITOR".equals(order.getTaskSource())
+                && !Objects.equals(SecurityUtils.getUserId().intValue(),
+                    insOrderMapper.selectQualityMonitorInspectorId(orderId))) {
+            throw new ErrorException("鍙湁璁″垝鎸囧畾鐨勬娴嬪憳鍙互鎻愪氦璐ㄩ噺鐩戞帶浠诲姟");
+        }
         boolean isInspectionReport = Objects.equals(INSPECTION_REPORT, reportType);
         registerInsResults = isInspectionReport && Boolean.TRUE.equals(registerInsResults);
         // 1. 濮旀墭缂栧彿鍏ㄥ眬鍞竴锛屾彁浜ゅ鏍告椂鍐嶆鏍¢獙锛岄槻姝㈠苟鍙戞垨鍘嗗彶鏁版嵁缁曡繃鐢熸垚鏍¢獙銆�
@@ -1675,11 +1711,25 @@
         if (orderId == null || laboratory == null || type == null) {
             throw new ErrorException("澶嶆牳鍙傛暟涓嶅畬鏁�");
         }
+        InsOrder verifyOrder = insOrderMapper.selectById(orderId);
+        if (verifyOrder == null) throw new ErrorException("妫�楠屼换鍔′笉瀛樺湪");
+        if ("QUALITY_MONITOR".equals(verifyOrder.getTaskSource()) && !Objects.equals(verifyOrder.getState(), 1)) {
+            throw new ErrorException("宸插彇娑堢殑璐ㄩ噺鐩戞帶浠诲姟涓嶈兘澶嶆牳");
+        }
         ensureDirectTemplateOrderState(orderId);
         InsOrderState currentState = insOrderStateMapper.selectOne(Wrappers.<InsOrderState>lambdaQuery()
                 .eq(InsOrderState::getInsOrderId, orderId)
                 .eq(InsOrderState::getLaboratory, laboratory)
                 .last("limit 1"));
+        if ("QUALITY_MONITOR".equals(verifyOrder.getTaskSource())
+                && (currentState == null || currentState.getVerifyUser() == null
+                    || !Objects.equals(SecurityUtils.getUserId().intValue(), currentState.getVerifyUser()))) {
+            throw new ErrorException("鍙湁鎻愪氦鏃舵寚瀹氱殑澶嶆牳浜哄彲浠ュ鏍歌川閲忕洃鎺т换鍔�");
+        }
+        if ("QUALITY_MONITOR".equals(verifyOrder.getTaskSource()) && Objects.equals(type, 1)
+                && currentState != null && Objects.equals(currentState.getInsState(), 5)) {
+            return 1;
+        }
         InsReport existingReport = insReportMapper.selectOne(Wrappers.<InsReport>lambdaQuery()
                 .eq(InsReport::getInsOrderId, orderId)
                 .last("limit 1"));
@@ -1738,6 +1788,24 @@
             insOrderMapper.update(null, Wrappers.<InsOrder>lambdaUpdate()
                     .eq(InsOrder::getId, orderId)
                     .set(InsOrder::getInsState, 5));
+
+            // 璐ㄩ噺鐩戞帶浠诲姟鍙繚鐣欏師濮嬭褰曪紝鍚庣画鐢辫川閲忕洃鎺ц瘎浠峰畬鎴愬綊妗c��
+            if ("QUALITY_MONITOR".equals(order.getTaskSource())) {
+                Integer evaluatorId = insOrderMapper.selectQualityMonitorEvaluatorId(orderId);
+                if (evaluatorId != null) {
+                    InformationNotification notice = new InformationNotification();
+                    notice.setCreateUser(insProductMapper.selectUserById(SecurityUtils.getUserId().intValue()).get("name"));
+                    notice.setSenderId(SecurityUtils.getUserId().intValue());
+                    notice.setConsigneeId(evaluatorId);
+                    notice.setMessageType("2");
+                    notice.setTheme("璐ㄩ噺鐩戞帶璇勪环閫氱煡");
+                    notice.setContent("璐ㄩ噺鐩戞帶浠诲姟 " + order.getEntrustCode() + " 鐨勫師濮嬭褰曞凡澶嶆牳锛岃濉啓璇勪环璁板綍");
+                    notice.setViewStatus(false);
+                    notice.setJumpPath(MenuJumpPathConstants.QUALITY_MONITOR);
+                    informationNotificationService.addInformationNotification(notice);
+                }
+                return 1;
+            }
 
             // 妫�楠屼汉鍛樻彁浜ゅ鏍告椂涓嶇敓鎴愭姤鍛婏紱鍏ㄩ儴璇曢獙瀹ゅ鏍搁�氳繃鍚庣敓鎴愭姤鍛娿��
             if (report == null || StringUtils.isBlank(report.getUrl())) {
@@ -2009,6 +2077,10 @@
      * @param orderId
      */
     private void generateReport(Integer orderId, Integer reportType, Integer writeUserId) {
+        InsOrder sourceOrder = insOrderMapper.selectById(orderId);
+        if (sourceOrder != null && "QUALITY_MONITOR".equals(sourceOrder.getTaskSource())) {
+            throw new ErrorException("璐ㄩ噺鐩戞帶妫�楠屼换鍔′笉鐢熸垚鎶ュ憡");
+        }
         /*鏍峰搧涓嬬殑椤圭洰鍙鏈変竴涓」鐩笉鍚堟牸鍒欐楠岀粨鏋滀负0,鍚﹀垯涓�1*/
         //杩欓噷鐨刬nsSamples鏄鍗曚笅鐨勬墍鏈夋牱鍝佸寘鎷�("/")
         List<InsSample> insSamples = insSampleMapper.selectList(Wrappers.<InsSample>lambdaQuery().eq(InsSample::getInsOrderId, orderId));
@@ -3774,6 +3846,40 @@
     /**
      * 鏂拌仛鐩寸粦妯℃澘璁㈠崟锛氭ā鏉夸腑姣忎竴涓�滃鍑哄�尖�濇壒娉ㄩ兘瀵瑰簲鎶ュ憡涓殑涓�鏉℃娴嬮」鐩��
      */
+    @Override
+    public List<Map<String, String>> getQualityMonitorRawResults(Integer orderId) {
+        requireReviewedQualityMonitorOrder(orderId);
+        return buildTemplateDetectionResultRows(orderId);
+    }
+
+    @Override
+    public QualityMonitorRawContext getQualityMonitorRawContext(Integer orderId) {
+        requireReviewedQualityMonitorOrder(orderId);
+        QualityMonitorRawContext context = new QualityMonitorRawContext();
+        List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
+                Wrappers.<InsOrderStandardTemplate>lambdaQuery()
+                        .eq(InsOrderStandardTemplate::getInsOrderId, orderId)
+                        .orderByAsc(InsOrderStandardTemplate::getSort, InsOrderStandardTemplate::getId));
+        context.setDetectionDates(snapshots.stream().map(InsOrderStandardTemplate::getDetectionTime)
+                .filter(Objects::nonNull).distinct().sorted().collect(Collectors.toList()));
+        List<Integer> deviceIds = insOrderTemplateDeviceMapper.selectDeviceIdsByOrderId(orderId);
+        if (CollectionUtils.isNotEmpty(deviceIds)) {
+            context.setDevices(insOrderMapper.selectDeviceListByIds(new LinkedHashSet<>(deviceIds)));
+        }
+        return context;
+    }
+
+    private void requireReviewedQualityMonitorOrder(Integer orderId) {
+        InsOrder order = insOrderMapper.selectById(orderId);
+        if (order == null || !"QUALITY_MONITOR".equals(order.getTaskSource())
+                || !Objects.equals(order.getInsState(), 5)) {
+            throw new ErrorException("璐ㄦ帶浠诲姟鍘熷璁板綍澶嶆牳閫氳繃鍚庢墠鑳借鍙栨娴嬫暟鎹�");
+        }
+        Long pendingCount = insOrderStateMapper.selectCount(Wrappers.<InsOrderState>lambdaQuery()
+                .eq(InsOrderState::getInsOrderId, orderId).ne(InsOrderState::getInsState, 5));
+        if (pendingCount > 0) throw new ErrorException("璐ㄦ帶浠诲姟浠嶆湁鏈鏍哥殑鍘熷璁板綍");
+    }
+
     private List<Map<String, String>> buildTemplateDetectionResultRows(Integer orderId) {
         List<InsOrderStandardTemplate> snapshots = insOrderStandardTemplateService.list(
                 Wrappers.<InsOrderStandardTemplate>lambdaQuery()

--
Gitblit v1.9.3