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