Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

Zimo 12 godzin temu
rodzic
commit
89acb9a897
19 zmienionych plików z 788 dodań i 67 usunięć
  1. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/constant/PmsConstants.java
  2. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotfivedailyreport/vo/IotFiveDailyReportRespVO.java
  3. 6 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotfivedailyreport/vo/IotFiveDailyReportSaveReqVO.java
  4. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskPageReqVO.java
  5. 20 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java
  6. 4 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportRespVO.java
  7. 13 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/IotRyDailyReportController.java
  8. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportRespVO.java
  9. 2 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapstock/IotSapStockController.java
  10. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotfivedailyreport/IotFiveDailyReportDO.java
  11. 4 3
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotprojecttask/IotProjectTaskMapper.java
  12. 161 6
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateFiveDailyReportOrderJob.java
  13. 10 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRyZjDailyReportOrderJob.java
  14. 7 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/message/PmsMessage.java
  15. 135 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotfivedailyreport/IotFiveDailyReportServiceImpl.java
  16. 19 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotprojecttaskplan/IotProjectTaskPlanServiceImpl.java
  17. 115 7
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportServiceImpl.java
  18. 162 39
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java
  19. 105 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportServiceImpl.java

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/constant/PmsConstants.java

@@ -43,4 +43,7 @@ public interface PmsConstants {
 
     // 物料领用单
     String MATERIAL_REQUISITION = "material-requisition";
+
+    // 生产异常消息提醒
+    String PRODUCTION_EXCEPTION = "production-exception";
 }

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotfivedailyreport/vo/IotFiveDailyReportRespVO.java

@@ -176,6 +176,14 @@ public class IotFiveDailyReportRespVO {
     @ExcelProperty("状态(2填写中 0待填写 1已完成)")
     private Integer status;
 
+    @Schema(description = "故障情况")
+    @ExcelProperty("故障情况")
+    private String malfunction;
+
+    @Schema(description = "故障误工h")
+    @ExcelProperty("故障误工h")
+    private BigDecimal faultDowntime;
+
     @Schema(description = "流程实例id", example = "187")
     @ExcelProperty("流程实例id")
     private String processInstanceId;

+ 6 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotfivedailyreport/vo/IotFiveDailyReportSaveReqVO.java

@@ -132,6 +132,12 @@ public class IotFiveDailyReportSaveReqVO {
     @Schema(description = "状态(2填写中 0待填写 1已完成)", example = "2")
     private Integer status;
 
+    @Schema(description = "故障情况")
+    private String malfunction;
+
+    @Schema(description = "故障误工h")
+    private BigDecimal faultDowntime;
+
     @Schema(description = "流程实例id", example = "187")
     private String processInstanceId;
 

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskPageReqVO.java

@@ -100,6 +100,9 @@ public class IotProjectTaskPageReqVO extends PageParam {
     @Schema(description = "定时任务标识 Y")
     private String jobFlag;
 
+    @Schema(description = "任务完工标识 Y")
+    private String finishFlag;
+
     @Schema(description = "platformGroup 集合")
     private List<String> platformGroups;
 

+ 20 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java

@@ -138,14 +138,29 @@ public class IotRhDailyReportController {
         if (ObjUtil.isEmpty(iotRhDailyReport)) {
             return success(null);
         }
+        Long deptId = iotRhDailyReport.getDeptId();
         // 查询当前日报关联的 部门下 增压机 的产能
-        BigDecimal capacity = iotRhDailyReportService.queryCapacity(iotRhDailyReport.getDeptId());
         IotRhDailyReportRespVO result = BeanUtils.toBean(iotRhDailyReport, IotRhDailyReportRespVO.class);
-        if (ObjUtil.isNotEmpty(iotRhDailyReport.getDeptId())) {
-            DeptDO dept = deptService.getDept(iotRhDailyReport.getDeptId());
+        if (ObjUtil.isNotEmpty(deptId)) {
+            DeptDO dept = deptService.getDept(deptId);
             result.setDeptName(dept.getName());
+            BigDecimal capacity = iotRhDailyReportService.queryCapacity(deptId);
+            result.setCapacity(capacity);
+
+            // 查询当前日报所属部门关联的任务井列表
+            Map<Long, String> deptWellNames = new HashMap<>();
+            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
+            taskReqVO.setCompanyId(157l);
+            taskReqVO.setJobFlag("Y");
+            taskReqVO.setDeptId(deptId);
+            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    deptWellNames.put(task.getId(), task.getWellName());
+                });
+                result.setRelatedTasks(deptWellNames);
+            }
         }
-        result.setCapacity(capacity);
         // 查询日报关联的项目 任务信息
         Long projectId = result.getProjectId();
         Long taskId = result.getTaskId();
@@ -158,6 +173,7 @@ public class IotRhDailyReportController {
             result.setTaskName(task.getWellName());
             result.setLocation(task.getLocation());
         }
+
         // 查询日报关联油耗记录
         IotDailyReportFuelPageReqVO reqVO = new IotDailyReportFuelPageReqVO();
         reqVO.setReportId(result.getId());

+ 4 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportRespVO.java

@@ -9,6 +9,7 @@ import lombok.Data;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 
 @Schema(description = "管理后台 - 瑞恒日报 Response VO")
 @Data
@@ -298,4 +299,7 @@ public class IotRhDailyReportRespVO {
 
     @Schema(description = "队伍下增压机 的设备型号")
     private String deviceNo;
+
+    @Schema(description = "当前日报所属部门关联的未完工任务井列表")
+    private Map<Long, String> relatedTasks;
 }

+ 13 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/IotRyDailyReportController.java

@@ -234,6 +234,19 @@ public class IotRyDailyReportController {
         }
         // 返回当前日报可以设置的任务井集合
         result.setWellNamePair(wellNamePair);
+        // 如果是录井1队 填写钻井日报模板 但是不需要填写进尺 system_dept_type.category
+        IotDeptTypePageReqVO deptTypeReqVO = new IotDeptTypePageReqVO();
+        deptTypeReqVO.setType("zj");
+        List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
+        if (CollUtil.isNotEmpty(deptTypes)) {
+            deptTypes.forEach(dept -> {
+                if (deptId.equals(dept.getDeptId()) && "lj".equals(dept.getCategory())) {
+                    // 当前队伍是录井1队 不需要填写 井深
+                    result.setFootageReadOnly(true);
+                }
+            });
+        }
+
         return success(result);
     }
 

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportRespVO.java

@@ -366,4 +366,7 @@ public class IotRyDailyReportRespVO {
 
     @Schema(description = "施工队伍排序值")
     private Integer teamSort;
+
+    @Schema(description = "是否填写井深进尺标识 true false")
+    private boolean footageReadOnly = false;
 }

+ 2 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotsapstock/IotSapStockController.java

@@ -145,11 +145,11 @@ public class IotSapStockController {
                             .filter(Objects::nonNull)
                             .reduce(BigDecimal.ZERO, BigDecimal::add);
 
-                    // 分组内累加总金额:数量、单价都不为空才计算金额
+                    // 分组内累加总金额:数量、单价都不为空才计算金额 直接使用总金额 使用 数量*单价会损失精度
                     BigDecimal groupTotalAmt = groupStocks.stream()
                             .filter(stock -> Objects.nonNull(stock.getQuantity())
                                     && Objects.nonNull(stock.getUnitPrice()))
-                            .map(stock -> stock.getQuantity().multiply(stock.getUnitPrice()))
+                            .map(stock -> stock.getTotalPrice())
                             .reduce(BigDecimal.ZERO, BigDecimal::add);
 
                     // 组装VO

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/dataobject/iotfivedailyreport/IotFiveDailyReportDO.java

@@ -190,6 +190,14 @@ public class IotFiveDailyReportDO extends BaseDO {
      * 状态(2填写中 0待填写 1已完成)
      */
     private Integer status;
+    /**
+     * 故障情况
+     */
+    private String malfunction;
+    /**
+     * 故障误工h
+     */
+    private BigDecimal faultDowntime;
     /**
      * 流程实例id
      */

+ 4 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotprojecttask/IotProjectTaskMapper.java

@@ -77,9 +77,10 @@ public interface IotProjectTaskMapper extends BaseMapperX<IotProjectTaskDO> {
         // 定时任务 如果是平台井 只生成主井号任务
         if (ObjUtil.isNotEmpty(reqVO.getJobFlag())) {
             wrapper.and(wq -> wq.ne(IotProjectTaskDO::getStatus, "wg"));
-                    /* .and(innerWq -> innerWq.eq(IotProjectTaskDO::getPlatformWell, 0)
-                    .or()
-                    .eq(IotProjectTaskDO::getPlatformWell, 1))); */
+        }
+        // 查询已经完工的任务
+        if (ObjUtil.isNotEmpty(reqVO.getFinishFlag())) {
+            wrapper.and(wq -> wq.eq(IotProjectTaskDO::getStatus, "wg"));
         }
         return selectList(wrapper);
     }

+ 161 - 6
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateFiveDailyReportOrderJob.java

@@ -1,8 +1,7 @@
 package cn.iocoder.yudao.module.pms.job.dailyreport;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.LocalDateTimeUtil;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.pms.constant.PmsConstants;
@@ -15,6 +14,7 @@ import cn.iocoder.yudao.module.pms.service.iotfivedailyreport.IotFiveDailyReport
 import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import lombok.extern.slf4j.Slf4j;
@@ -27,9 +27,9 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.util.*;
-import java.util.concurrent.CountDownLatch;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
 
 /**
@@ -53,7 +53,7 @@ public class CreateFiveDailyReportOrderJob implements JobHandler {
     @Resource
     private DeptService deptService;
 
-    @Override
+    /* @Override
     @TenantIgnore
     public String execute(String param) throws Exception {
 
@@ -78,7 +78,24 @@ public class CreateFiveDailyReportOrderJob implements JobHandler {
                 }
             });
         }
-        
+
+        // 查询5#国所有的 施工队伍 key部门id   value部门名称
+        Map<Long, String> teamPair = new HashMap<>();
+        Set<Long> allFiveChildDeptIds = deptService.getChildDeptIdListFromCache(388l);
+        if (CollUtil.isNotEmpty(allFiveChildDeptIds)) {
+            DeptListReqVO reqVO = new DeptListReqVO();
+            reqVO.setDeptIds(allFiveChildDeptIds);
+            List<DeptDO> fiveDepartments = deptService.getDeptList(reqVO);
+            if (CollUtil.isNotEmpty(fiveDepartments)) {
+                fiveDepartments.forEach(dept -> {
+                    if ("3".equals(dept.getType())) {
+                        // 组装队伍集合
+                        teamPair.put(dept.getId(), dept.getName());
+                    }
+                });
+            }
+        }
+
         // 查询 5#公司 相关的项目任务 根据每个任务的填报人进行工单生成和推送
         IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
         taskReqVO.setCompanyId(388l);
@@ -213,5 +230,143 @@ public class CreateFiveDailyReportOrderJob implements JobHandler {
             });
         }
         return "创建成功";
+    } */
+
+    @Override
+    @TenantIgnore
+    public String execute(String param) throws Exception {
+        LocalDate today = LocalDate.now();
+        IotFiveDailyReportPageReqVO reqVO = new IotFiveDailyReportPageReqVO();
+        reqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        // 1. 当天已有日报的去重集合
+        List<IotFiveDailyReportDO> allReports = iotFiveDailyReportService
+                .getIotFiveDailyReportPage(reqVO).getList();
+        Set<Long> existedTaskIds = new HashSet<>();
+        Set<Long> existedEmptyDeptIds = new HashSet<>();
+        for (IotFiveDailyReportDO report : allReports) {
+            if (report.getCreateTime().toLocalDate().equals(today)) {
+                if (report.getTaskId() != null) {
+                    existedTaskIds.add(report.getTaskId());
+                } else {
+                    existedEmptyDeptIds.add(report.getDeptId());
+                }
+            }
+        }
+
+        // 2. 获取所有施工队伍部门(type=3)并构建部门信息映射
+        Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(388L);
+        List<DeptDO> deptList = deptService.getDeptList(new DeptListReqVO().setDeptIds(childDeptIds));
+        Map<Long, DeptDO> deptMap = deptList.stream()
+                .filter(d -> "3".equals(d.getType()))
+                .collect(Collectors.toMap(DeptDO::getId, Function.identity()));
+
+        // 3. 查询所有非完工任务,构建 deptId → 任务列表 映射
+        IotProjectTaskPageReqVO taskReq = new IotProjectTaskPageReqVO();
+        taskReq.setCompanyId(388L);
+        taskReq.setJobFlag("Y");
+        List<IotProjectTaskDO> allTasks = iotProjectTaskService.projectTasks(taskReq);
+        Map<Long, List<IotProjectTaskDO>> deptTasksMap = new HashMap<>();
+        for (IotProjectTaskDO task : allTasks) {
+            if (CollUtil.isNotEmpty(task.getDeptIds())) {
+                for (Long deptId : task.getDeptIds()) {
+                    deptTasksMap.computeIfAbsent(deptId, k -> new ArrayList<>()).add(task);
+                }
+            }
+        }
+
+        // 4. 收集所有需要查询的用户ID(提前统一查询,避免循环内调用)
+        Set<Long> allUserIds = new HashSet<>();
+        for (IotProjectTaskDO task : allTasks) {
+            if (CollUtil.isNotEmpty(task.getResponsiblePerson())) {
+                allUserIds.addAll(task.getResponsiblePerson());
+            }
+        }
+        deptMap.values().forEach(d -> {
+            if (d.getLeaderUserId() != null) allUserIds.add(d.getLeaderUserId());
+        });
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(allUserIds);
+
+        // 5. 按部门生成日报
+        List<IotFiveDailyReportDO> newReports = new ArrayList<>();
+        for (Map.Entry<Long, DeptDO> entry : deptMap.entrySet()) {
+            Long deptId = entry.getKey();
+            DeptDO dept = entry.getValue();
+            List<IotProjectTaskDO> deptTasks = deptTasksMap.getOrDefault(deptId, Collections.emptyList());
+
+            if (CollUtil.isNotEmpty(deptTasks)) {
+                // 有任务 → 为每个未生成日报的任务创建日报
+                for (IotProjectTaskDO task : deptTasks) {
+                    if (!existedTaskIds.contains(task.getId()) && CollUtil.isNotEmpty(task.getResponsiblePerson())) {
+                        Long creatorId = new ArrayList<>(task.getResponsiblePerson()).get(0);
+                        newReports.add(buildReportWithTask(dept, task, creatorId, today));
+                    }
+                }
+            } else {
+                // 无任务 → 为该部门生成一份空日报(当天只生成一次)
+                if (!existedEmptyDeptIds.contains(deptId)) {
+                    Long creatorId = dept.getLeaderUserId();
+                    newReports.add(buildEmptyReport(dept, creatorId, today));
+                }
+            }
+        }
+
+        // 6. 批量保存
+        if (CollUtil.isNotEmpty(newReports)) {
+            iotFiveDailyReportService.batchAddDailyReports(newReports);
+        }
+
+        // 7. 异步发送消息(仅对有填报人的日报)
+        if (CollUtil.isNotEmpty(newReports)) {
+            Set<Long> creatorIds = newReports.stream()
+                    .map(r -> {
+                        try { return Long.valueOf(r.getCreator()); } catch (Exception e) { return null; }
+                    })
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toSet());
+            Map<Long, AdminUserRespDTO> creatorUserMap = adminUserApi.getUserMap(creatorIds);
+            for (IotFiveDailyReportDO report : newReports) {
+                Long creatorId = Long.valueOf(report.getCreator());
+                AdminUserRespDTO user = creatorUserMap.get(creatorId);
+                if (user != null && user.getMobile() != null) {
+                    pmsThreadPoolTaskExecutor.execute(() ->
+                            pmsMessage.sendMessage(report.getId(), report.getReportName(),
+                                    PmsConstants.DAILY_REPORT, creatorId, user.getMobile()));
+                }
+            }
+        }
+        return "创建成功";
+    }
+
+    // 创建关联任务的日报
+    private IotFiveDailyReportDO buildReportWithTask(DeptDO dept, IotProjectTaskDO task, Long creatorId, LocalDate today) {
+        IotFiveDailyReportDO report = new IotFiveDailyReportDO();
+        report.setDeptId(dept.getId());
+        report.setProjectId(task.getProjectId());
+        report.setTaskId(task.getId());
+        report.setDeviceIds(task.getDeviceIds());
+        report.setCreator(String.valueOf(creatorId));
+        fillCommonFields(report, dept, today);
+        return report;
     }
+
+    // 创建无任务的空日报
+    private IotFiveDailyReportDO buildEmptyReport(DeptDO dept, Long creatorId, LocalDate today) {
+        IotFiveDailyReportDO report = new IotFiveDailyReportDO();
+        report.setDeptId(dept.getId());
+        report.setCreator(creatorId != null ? String.valueOf(creatorId) : "0");
+        fillCommonFields(report, dept, today);
+        return report;
+    }
+
+    // 填充公共字段
+    private void fillCommonFields(IotFiveDailyReportDO report, DeptDO dept, LocalDate today) {
+        String deptName = dept.getName().split("~~")[0];
+        report.setReportName(deptName + "/" + today + "日报填报");
+        report.setStartTime(LocalTime.of(8, 0, 0));
+        report.setEndTime(LocalTime.of(8, 0, 0));
+        report.setConstructionStartDate(LocalDateTime.of(today, LocalTime.of(8, 0, 0)));
+        report.setConstructionEndDate(LocalDateTime.of(today.plusDays(1), LocalTime.of(8, 0, 0)));
+        report.setCreateTime(LocalDateTime.now());
+    }
+
 }

+ 10 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRyZjDailyReportOrderJob.java

@@ -85,6 +85,8 @@ public class CreateRyZjDailyReportOrderJob implements JobHandler {
         deptTypeReqVO.setType("zj");
         List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
         Set<Long> zjDeptIds = new HashSet<>();
+        // 包含设备但是也要生成空日报的队伍
+        Set<Long> zjContainsDeviceDeptIds = new HashSet<>();
         // 无设备 的部门id集合
         Set<Long> affiliatedDeptIds = new HashSet<>();
         // key部门id      value日报填报人id
@@ -108,6 +110,10 @@ public class CreateRyZjDailyReportOrderJob implements JobHandler {
                     usernames.add(deptType.getCreator());
                     deptUsernamePair.put(deptType.getDeptId(), deptType.getCreator());
                 }
+                // 包含设备的队伍也要生成空日报 录井1队
+                if (StrUtil.isNotBlank(deptType.getCategory())) {
+                    zjContainsDeviceDeptIds.add(deptType.getDeptId());
+                }
             });
             // 根据 用户账号 查询用户id 无设备队伍 日报填报人
             if (CollUtil.isNotEmpty(usernames)) {
@@ -142,7 +148,7 @@ public class CreateRyZjDailyReportOrderJob implements JobHandler {
                 }
             });
         }
-        // 查询瑞鹰所有队伍关联的设备 筛选出不包含任何设备的队伍
+        // 查询瑞鹰所有队伍关联的设备 筛选出不包含任何设备的队伍 包含设备的队伍 也需要生成日报 如 录井1队
         IotDevicePageReqVO reqVO = new IotDevicePageReqVO();
         reqVO.setDeptIds(new ArrayList<>(ryTeamDeptIds));
         List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(reqVO);
@@ -158,6 +164,9 @@ public class CreateRyZjDailyReportOrderJob implements JobHandler {
                 .filter(deptId -> !containsDeviceDeptIds.contains(deptId))
                 .collect(Collectors.toSet());
 
+        // 合并 包含设备设备但是也要生成空日报的队伍 录井1队
+        noDeviceZjDeptIds.addAll(zjContainsDeviceDeptIds);
+
         // 查询 无设备 钻井 队伍 日报列表
         IotRyDailyReportPageReqVO ryReqVO = new IotRyDailyReportPageReqVO();
         ryReqVO.setDeptIds(noDeviceZjDeptIds);

+ 7 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/message/PmsMessage.java

@@ -110,6 +110,11 @@ public class PmsMessage {
                 msg = "您有新的修井生产日报 " + name + "需要填报,请处理。"+"["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
             }
 
+            // 生产异常
+            if (PmsConstants.PRODUCTION_EXCEPTION.equals(businessType)) {
+                msg = "生产异常 \n" + name + "["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
+            }
+
             // 瑞鹰项目启动设备整改
             if (PmsConstants.RY_IMPROVE_DAILY_REPORT.equals(businessType)) {
                 msg = "您有新的项目启动设备整改日报 " + name + "需要填报,请处理。"+"["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
@@ -153,7 +158,8 @@ public class PmsMessage {
                 url=systemUrl + "dingding?id="+businessId+"&type="+businessType+"&userId="+userId;
             }
 
-            if (PmsConstants.FAILURE_NO_PASS.equals(businessType)||PmsConstants.ALARM_MESSAGE.equals(businessType)||PmsConstants.GENERATE_QHSE_CERT.equals(businessType)||PmsConstants.WEEK_ALARM_MESSAGE.equals(businessType)) {
+            if (PmsConstants.FAILURE_NO_PASS.equals(businessType) || PmsConstants.ALARM_MESSAGE.equals(businessType)
+                    || PmsConstants.GENERATE_QHSE_CERT.equals(businessType) || PmsConstants.WEEK_ALARM_MESSAGE.equals(businessType) || PmsConstants.PRODUCTION_EXCEPTION.equals(businessType)) {
                 //通知设备状态变更为观察使用
                 dingtalkSendApi.send(mobile, msg, "text",url,  title);
             } else {

+ 135 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotfivedailyreport/IotFiveDailyReportServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.constant.PmsConstants;
 import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotfivedailyreport.vo.IotFiveDailyReportStatisticsRespVO;
@@ -13,9 +14,19 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.iotfivedailyreport.IotFiveDail
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotfivedailyreport.IotFiveDailyReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
+import cn.iocoder.yudao.module.pms.message.PmsMessage;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import cn.iocoder.yudao.module.system.controller.admin.dept.vo.dept.DeptListReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
+import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import cn.iocoder.yudao.module.system.service.permission.RoleService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
@@ -25,9 +36,12 @@ import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_FIVE_DAILY_REPORT_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
 
 /**
  * 5#国日报 Service 实现类
@@ -44,6 +58,18 @@ public class IotFiveDailyReportServiceImpl implements IotFiveDailyReportService
     private DeptService deptService;
     @Resource
     private IotProjectTaskMapper iotProjectTaskMapper;
+    @Resource
+    private AdminUserService adminUserService;
+    @Resource
+    private RoleService roleService;
+    @Resource
+    private UserRoleMapper userRoleMapper;
+    @Resource
+    private AdminUserApi adminUserApi;
+    @Resource(name = PMS_THREAD_POOL_TASK_EXECUTOR)
+    private ThreadPoolTaskExecutor pmsThreadPoolTaskExecutor;
+    @Resource
+    private PmsMessage pmsMessage;
 
     @Override
     public Long createIotFiveDailyReport(IotFiveDailyReportSaveReqVO createReqVO) {
@@ -64,19 +90,128 @@ public class IotFiveDailyReportServiceImpl implements IotFiveDailyReportService
         updateObj.setStatus(1);
 
         Long taskId = updateReqVO.getTaskId();
+        Long deptId = updateObj.getDeptId();
         // 关联更新相关任务的 施工状态
         if (ObjUtil.isNotEmpty(taskId)) {
             IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
             if (ObjUtil.isNotEmpty(task)) {
                 task.setStatus(updateReqVO.getFiveStatus());
                 task.setRdStatus(updateReqVO.getFiveStatus());
+                Set<Long> deviceIds = task.getDeviceIds();
                 int num = iotProjectTaskMapper.updateById(task);
                 // 有可能重新选择任务井 根据taskId 查询相关的项目 projectId 重新赋值
                 updateObj.setProjectId(task.getProjectId());
+                updateObj.setDeviceIds(deviceIds);
             }
         }
+        // 查询当前日报关联的任务 带入任务关联的 设备id列表
 
         iotFiveDailyReportMapper.updateById(updateObj);
+        // 将生产异常情况 (npt 工程质量 > 0) 发送到拥有 生产异常通知 角色的人员
+        BigDecimal accidentTime = updateObj.getAccidentTime();
+        if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO) > 0) {
+
+            String companyName = "5#国";
+            BigDecimal day = accidentTime.divide(new BigDecimal("24"), 2, RoundingMode.HALF_UP);
+            String accidentDay = day + "T";
+            // 异常情况
+            String malfunction = StrUtil.blankToDefault(updateObj.getMalfunction(), "无");
+            DeptDO dept = deptService.getDept(deptId);
+            // 查询当前队伍的上级项目部
+            DeptDO projectDept = deptService.getDept(dept.getParentId());
+            // 队伍名称
+            String deptName = ObjUtil.isNotEmpty(dept) ? dept.getName() : StrUtil.EMPTY;
+            // 项目部名称
+            String projectDeptName = ObjUtil.isNotEmpty(projectDept) ? projectDept.getName() : StrUtil.EMPTY;
+
+            String wellName = "无";
+            if (ObjUtil.isNotEmpty(taskId)) {
+                IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
+                if (ObjUtil.isNotEmpty(task)) {
+                    wellName = task.getWellName();
+                }
+            }
+            // 当前处理进度 当日施工简报
+            String brief = StrUtil.blankToDefault(updateObj.getProductionStatus(), "无");
+            // 下步计划
+            String nextPlan = StrUtil.blankToDefault(updateObj.getNextPlan(), "无");
+            // 故障误工时间 accidentTime H
+
+            String PRODUCTION_EXCEPTION_MSG_TEMPLATE =
+                    "[公司]:{}\n" +
+                    "[项目部]:{}\n" +
+                    "[队伍]:{}\n" +
+                    "[井号]:{}\n" +
+                    "[故障描述]:{}\n" +
+                    "[当前处理进度]:{}\n" +
+                    "[下步处理计划]:{}\n" +
+                    "[累计误工时间]:{}\n";
+
+            String finalMsgTitle = StrUtil.format(PRODUCTION_EXCEPTION_MSG_TEMPLATE,
+                    companyName, projectDeptName, deptName, wellName,
+                    malfunction, brief, nextPlan, accidentDay
+            );
+
+            // 封装以上消息内容 发送到公司 角色 (生产异常通知)
+            // 查询瑞恒 157l 下具有以上角色的人员 查询集团(科瑞石油技术) 拥有以上角色的人员
+            Set<Long> userIds = new HashSet<>();
+            Set<Long> deptIds = new HashSet<>();
+            deptIds.add(388l);
+            List<AdminUserDO> companyUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(companyUsers)) {
+                companyUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            deptIds.clear();
+            deptIds.add(156l);
+            List<AdminUserDO> groupUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(groupUsers)) {
+                groupUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            RoleDO role = roleService.getRoleByCode("生产异常通知");
+            if (ObjUtil.isNotEmpty(role)) {
+                Set<Long> roleIds = new HashSet<>();
+                roleIds.add(role.getId());
+                List<UserRoleDO> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
+                if (CollUtil.isNotEmpty(userRoles)) {
+                    // 提取有审批角色的所有用户ID(去重+空值过滤)
+                    Set<Long> roleUserIds = userRoles.stream()
+                            .map(UserRoleDO::getUserId)
+                            .filter(Objects::nonNull) // 过滤空userId
+                            .collect(Collectors.toSet());
+                    // 计算两个集合的交集,得到最终目标用户ID
+                    Set<Long> targetUserIds = userIds.stream()
+                            .filter(roleUserIds::contains)
+                            .collect(Collectors.toSet());
+                    // 异步发送 站内信 钉钉消息
+                    if (CollUtil.isNotEmpty(targetUserIds)) {
+                        Map<Long, AdminUserRespDTO> users = adminUserApi.getUserMap(targetUserIds);
+                        // 给多个用户发送 相同 的 提醒消息
+                        if (CollUtil.isNotEmpty(users)) {
+                            // 生成消息提醒 标题内容
+                            CountDownLatch latch = new CountDownLatch(users.size());
+                            users.forEach((userId, user) -> {
+                                pmsThreadPoolTaskExecutor.execute(() -> {
+                                    try {
+                                        String mobile = user.getMobile();
+                                        // 没有手机号也发送站内信消息
+                                        if (StrUtil.isNotBlank(finalMsgTitle)) {
+                                            pmsMessage.sendMessage(updateObj.getId(), finalMsgTitle, PmsConstants.PRODUCTION_EXCEPTION,
+                                                    userId, mobile);
+                                        }
+                                    } finally {
+                                        latch.countDown();
+                                    }
+                                });
+                            });
+                        }
+                    }
+                }
+            }
+        }
     }
 
     @Override

+ 19 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotprojecttaskplan/IotProjectTaskPlanServiceImpl.java

@@ -61,14 +61,31 @@ public class IotProjectTaskPlanServiceImpl implements IotProjectTaskPlanService
     public Long createIotProjectTaskPlan(IotProjectTaskPlanSaveReqVO createReqVO) {
         // 插入
         IotProjectTaskPlanDO iotProjectTaskPlan = BeanUtils.toBean(createReqVO, IotProjectTaskPlanDO.class);
-        if (ObjUtil.isEmpty(createReqVO.getDeptId()) || ObjUtil.isEmpty(createReqVO.getStartTime())) {
+        Long deptId = createReqVO.getDeptId();
+        if (ObjUtil.isEmpty(deptId) || ObjUtil.isEmpty(createReqVO.getStartTime())) {
             throw exception(IOT_PROJECT_TASK_PLAN_NOT_EXISTS);
         }
         // 校验当前队伍部门 指定时间所属月份 是否已经存在 工作量计划记录
-        IotProjectTaskPlanDO existPlan = iotProjectTaskPlanMapper.selectOneByDeptIdAndMonth(createReqVO.getDeptId(), createReqVO.getStartTime(), createReqVO.getBusiness(), null);
+        IotProjectTaskPlanDO existPlan = iotProjectTaskPlanMapper.selectOneByDeptIdAndMonth(deptId, createReqVO.getStartTime(), createReqVO.getBusiness(), null);
         if (ObjUtil.isNotEmpty(existPlan)) {
             throw exception(IOT_PROJECT_TASK_PLAN_EXISTS);
         }
+        DeptDO companyDept = null;
+        int maxLoop = 15;
+        while (maxLoop-- > 0 && ObjUtil.isNotEmpty(deptId)) {
+            DeptDO dept = deptService.getDept(deptId);
+            if (ObjUtil.isEmpty(dept)) {
+                throw exception(IOT_PROJECT_TASK_PLAN_NOT_EXISTS);
+            }
+            if ("1".equals(dept.getType())) {
+                companyDept = dept;
+                break;
+            }
+            deptId = dept.getParentId();
+        }
+        if (ObjUtil.isNotEmpty(companyDept)) {
+            iotProjectTaskPlan.setCompanyId(companyDept.getId());
+        }
         iotProjectTaskPlanMapper.insert(iotProjectTaskPlan);
         // 返回
         return iotProjectTaskPlan.getId();

+ 115 - 7
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportServiceImpl.java

@@ -252,7 +252,11 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         }
         // 更新
         IotRdDailyReportDO updateObj = BeanUtils.toBean(updateReqVO, IotRdDailyReportDO.class);
-        // 如果是修改 非生产时间 ,则不必再发起审批
+
+        Long deptId = dailyReport.getDeptId();
+        Long taskId = dailyReport.getTaskId();
+
+        // 如果是修改 非生产时间 ,则不必再发起审批 生产运营部 维护 时效
         if (StrUtil.isBlank(updateReqVO.getNonProduct())) {
             // 正常填写4小时周报 不必设置日报状态为 已完成 可以每4小时填报1闪
             // updateObj.setStatus(1);
@@ -261,16 +265,119 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         } else {
             // 生产运营部填写了 非生产时间 施工简报 可以设置 日报状态为 已完成 不允许再次填报
             updateObj.setStatus(1);
-        }
-        // 如果 修改 了时效 只要保存 不管是否 填写了 非生产时间 都确认为已经 维护了 非生产时间
-        if (StrUtil.isNotBlank(updateReqVO.getNonProduct())) {
+            // 如果 修改 了时效 只要保存 不管是否 填写了 非生产时间 都确认为已经 维护了 非生产时间
             updateObj.setProcessInstanceId("2");
+
+            // 审核同意 将生产异常情况 (npt 工程质量) 发送到拥有 生产异常通知 角色的人员
+            BigDecimal accidentTime = dailyReport.getAccidentTime();
+            if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO) > 0) {
+                String companyName = "四川瑞都";
+                BigDecimal day = accidentTime.divide(new BigDecimal("24"), 2, RoundingMode.HALF_UP);
+                String accidentDay = day + "T";
+                // 异常情况
+                String malfunction = StrUtil.blankToDefault(dailyReport.getMalfunction(), "无");
+                DeptDO dept = deptService.getDept(deptId);
+                // 查询当前队伍的上级项目部
+                DeptDO projectDept = deptService.getDept(dept.getParentId());
+                // 队伍名称
+                String deptName = ObjUtil.isNotEmpty(dept) ? dept.getName() : StrUtil.EMPTY;
+                // 项目部名称
+                String projectDeptName = ObjUtil.isNotEmpty(projectDept) ? projectDept.getName() : StrUtil.EMPTY;
+                String wellName = "无";
+                if (ObjUtil.isNotEmpty(taskId)) {
+                    IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
+                    if (ObjUtil.isNotEmpty(task)) {
+                        wellName = task.getWellName();
+                    }
+                }
+                // 当前处理进度 当日施工简报
+                String brief = StrUtil.blankToDefault(dailyReport.getConstructionBrief(), "无");
+                // 下步计划
+                String nextPlan = StrUtil.blankToDefault(dailyReport.getNextPlan(), "无");
+                // 故障误工时间 accidentTime H
+
+                String PRODUCTION_EXCEPTION_MSG_TEMPLATE =
+                        "[公司]:{}\n" +
+                        "[项目部]:{}\n" +
+                        "[队伍]:{}\n" +
+                        "[井号]:{}\n" +
+                        "[故障描述]:{}\n" +
+                        "[当前处理进度]:{}\n" +
+                        "[下步处理计划]:{}\n" +
+                        "[累计误工时间]:{}\n";
+
+                String finalMsgTitle = StrUtil.format(PRODUCTION_EXCEPTION_MSG_TEMPLATE,
+                        companyName, projectDeptName, deptName, wellName,
+                        malfunction, brief, nextPlan, accidentDay
+                );
+
+                // 封装以上消息内容 发送到公司 角色 (生产异常通知)
+                // 查询瑞恒 157l 下具有以上角色的人员 查询集团(科瑞石油技术) 拥有以上角色的人员
+                Set<Long> userIds = new HashSet<>();
+                Set<Long> deptIds = new HashSet<>();
+                deptIds.add(163l);
+                List<AdminUserDO> companyUsers = adminUserService.getUserListByDeptIds(deptIds);
+                if (CollUtil.isNotEmpty(companyUsers)) {
+                    companyUsers.forEach(user -> {
+                        userIds.add(user.getId());
+                    });
+                }
+                deptIds.clear();
+                deptIds.add(156l);
+                List<AdminUserDO> groupUsers = adminUserService.getUserListByDeptIds(deptIds);
+                if (CollUtil.isNotEmpty(groupUsers)) {
+                    groupUsers.forEach(user -> {
+                        userIds.add(user.getId());
+                    });
+                }
+                RoleDO role = roleService.getRoleByCode("生产异常通知");
+                if (ObjUtil.isNotEmpty(role)) {
+                    Set<Long> roleIds = new HashSet<>();
+                    roleIds.add(role.getId());
+                    List<UserRoleDO> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
+                    if (CollUtil.isNotEmpty(userRoles)) {
+                        // 提取有审批角色的所有用户ID(去重+空值过滤)
+                        Set<Long> roleUserIds = userRoles.stream()
+                                .map(UserRoleDO::getUserId)
+                                .filter(Objects::nonNull) // 过滤空userId
+                                .collect(Collectors.toSet());
+                        // 计算两个集合的交集,得到最终目标用户ID
+                        Set<Long> targetUserIds = userIds.stream()
+                                .filter(roleUserIds::contains)
+                                .collect(Collectors.toSet());
+                        // 异步发送 站内信 钉钉消息
+                        if (CollUtil.isNotEmpty(targetUserIds)) {
+                            Map<Long, AdminUserRespDTO> users = adminUserApi.getUserMap(targetUserIds);
+                            // 给多个用户发送 相同 的 提醒消息
+                            if (CollUtil.isNotEmpty(users)) {
+                                // 生成消息提醒 标题内容
+                                CountDownLatch latch = new CountDownLatch(users.size());
+                                users.forEach((userId, user) -> {
+                                    pmsThreadPoolTaskExecutor.execute(() -> {
+                                        try {
+                                            String mobile = user.getMobile();
+                                            // 没有手机号也发送站内信消息
+                                            if (StrUtil.isNotBlank(finalMsgTitle)) {
+                                                pmsMessage.sendMessage(dailyReport.getId(), finalMsgTitle, PmsConstants.PRODUCTION_EXCEPTION,
+                                                        userId, mobile);
+                                            }
+                                        } finally {
+                                            latch.countDown();
+                                        }
+                                    });
+                                });
+                            }
+                        }
+                    }
+                }
+            }
         }
+
         iotRdDailyReportMapper.updateById(updateObj);
         // 同步更新日报关联任务的 施工状态
-        if (ObjUtil.isNotEmpty(dailyReport.getTaskId())) {
+        if (ObjUtil.isNotEmpty(taskId)) {
             // 查询任务记录 更新任务的施工状态
-            IotProjectTaskDO task = iotProjectTaskMapper.selectById(dailyReport.getTaskId());
+            IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
             if (ObjUtil.isNotEmpty(task)) {
                 task.setRdStatus(updateObj.getRdStatus());
                 task.setStatus(updateObj.getRdStatus());
@@ -2895,10 +3002,11 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         List<IotRdDailyReportDO> mainPlatformReports = new ArrayList<>();
         // 关联井日报
         List<IotRdDailyReportDO> relatePlatformReports = new ArrayList<>();
-        // 维护非生产时间标识 nonProduct
+        // 维护非生产时间标识 nonProduct 生产运营部维护时效
         AtomicReference<String> nonProduct = new AtomicReference<>(StrUtil.EMPTY);
         reports.forEach(report -> {
             if (StrUtil.isNotBlank(report.getNonProduct())) {
+                // 生产运营部维护时效
                 nonProduct.set(report.getNonProduct());
             }
             IotRdDailyReportDO updatedReport = updateIotRdDailyReport(report);

+ 162 - 39
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java

@@ -26,6 +26,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.iotcarzhbd.IotCarZhbdDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotdevicerunlog.IotDeviceRunLogDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotopeationfill.IotOpeationFillDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
@@ -33,6 +34,7 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotcarzhbd.IotCarZhbdMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotdailyreportfuel.IotDailyReportFuelMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotdevicerunlog.IotDeviceRunLogMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotprojectinfo.IotProjectInfoMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
 import cn.iocoder.yudao.module.pms.enums.common.FailureAuditStatusEnum;
@@ -132,6 +134,9 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
     private DictDataService dictDataService;
     @Resource
     private DeptMapper deptMapper;
+    @Resource
+    private IotProjectInfoMapper iotProjectInfoMapper;
+
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -164,7 +169,6 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         teams.add(currentDept[0]);
         // 查询增压机状态为非施工的小队
         List<IotDeviceDO> teamStatusL = iotOpeationFillMapper.selectDevStatusBatch(teams);
-        // System.out.println("无施工设备的队伍:" + currentDept.getName());
 
         // 设置 日报填写状态 审核状态
         iotRhDailyReport.setStatus(1);
@@ -173,8 +177,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
 
         // 根据日报的 施工队伍 deptId 查询队伍所在的 项目 任务
         // 根据日报的施工状态 更新 对应任务的 状态
-        Long taskId = Long.MIN_VALUE;
         Set<Long> deviceIds = new HashSet<>();
+
         IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
         reqVO.setDeptId(createReqVO.getDeptId());
         // 只筛选未施工完成的任务
@@ -189,22 +193,49 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         Set<String> zhbdCarIds = new HashSet<>();
         // 井号
         String wellName;
-        if (CollUtil.isNotEmpty(tasks)) {
-            // 只查询 未施工完成 的任务 随机获取1个 最好是保持 1个施工队伍只存在于1个任务中
-            IotProjectTaskDO task = tasks.get(0);
+
+        // 根据传参赋值 taskId 如果 createReqVO 传参对象中设置了 taskId 说明 填报人已经选择了 任务井 直接保存
+        Long existTaskId = createReqVO.getTaskId();
+        IotProjectTaskDO commonTask = null;
+        if (ObjUtil.isNotEmpty(existTaskId)) {
+            commonTask = iotProjectTaskMapper.selectById(existTaskId);
+        } else {
+            if (CollUtil.isNotEmpty(tasks)) {
+                // 只查询 未施工完成 的任务 随机获取1个 最好是保持 1个施工队伍只存在于1个任务中
+                commonTask = tasks.get(0);
+            } else {
+                // 当前队伍没有关联任务 查询当前部门关联的最新的完工任务 关联上 有可能是已经完工的空日报任务
+                reqVO.setDeptId(createReqVO.getDeptId());
+                // 只筛选未施工完成的任务
+                reqVO.setJobFlag(StrUtil.EMPTY);
+                reqVO.setFinishFlag("Y");
+                // 查询包含当前日报施工队伍的任务
+                List<IotProjectTaskDO> finishedTasks = iotProjectTaskMapper.selectList(reqVO);
+                if (CollUtil.isNotEmpty(finishedTasks)) {
+                    // 最新完工的任务位于列表第1个元素
+                    IotProjectTaskDO latestTask = finishedTasks.get(0);
+                    iotRhDailyReport.setProjectId(latestTask.getProjectId());
+                    iotRhDailyReport.setTaskId(latestTask.getId());
+                    wellName = latestTask.getWellName();
+                } else {
+                    wellName = StrUtil.EMPTY;
+                }
+            }
+        }
+
+        if (ObjUtil.isNotEmpty(commonTask)) {
             // 暂时只考虑1个施工队伍只属于1个任务
-            iotRhDailyReport.setProjectId(task.getProjectId());
-            iotRhDailyReport.setTaskId(task.getId());
-            taskId = task.getId();
-            wellName = task.getWellName();
+            iotRhDailyReport.setProjectId(commonTask.getProjectId());
+            iotRhDailyReport.setTaskId(commonTask.getId());
+            wellName = commonTask.getWellName();
             // 根据日报状态 查询 日报所属任务的状态
             if (ObjUtil.isNotEmpty(createReqVO.getConstructionStatus())) {
-                task.setStatus(createReqVO.getConstructionStatus());
+                commonTask.setStatus(createReqVO.getConstructionStatus());
                 // 更新任务状态
-                iotProjectTaskMapper.updateById(task);
+                iotProjectTaskMapper.updateById(commonTask);
             }
             // 查询任务的设备列表
-            deviceIds = task.getDeviceIds();
+            deviceIds = commonTask.getDeviceIds();
             IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
             deviceReqVO.setDeviceIds(new ArrayList<>(deviceIds));
             List<IotDeviceDO> carDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
@@ -253,8 +284,6 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             }
         } else {
             wellName = StrUtil.EMPTY;
-            // 当前队伍没有关联任务 不生成日报
-            // throw exception(IOT_PROJECT_TASK_NOT_RELATED);
         }
 
         // 查询当前队伍的运行记录 找到注水量 注水时间 赋值到日报的 注水时间
@@ -330,24 +359,6 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             });
         }
 
-        /* if (CollUtil.isNotEmpty(deptDevices)) {
-            deptDevices.forEach(device -> {
-                deviceCodes.add(device.getDeviceCode());
-            });
-            // 查询当前小队在运行记录填报结果表中 生产日报虚拟设备id 查询当年的日报
-            // 然后根据 虚拟设备id 在 rq_iot_device_run_log 表中查询 日报中填写的 当日注气量
-             List<IotOpeationFillDO> reports = iotOpeationFillMapper.selectReportsByYear(createReqVO.getDeptId(), LocalDateTime.now().getYear());
-            Set<Long> reportDeviceIds = new HashSet<>();
-            if (CollUtil.isNotEmpty(reports)) {
-                reports.forEach(report -> {
-                    reportDeviceIds.add(report.getDeviceId());
-                });
-                // 累计注气量
-                BigDecimal currentYearFillContentSum = iotDeviceRunLogMapper.selectCurrentYearFillContentSum(createReqVO.getDeptId(), reportDeviceIds);
-                iotRhDailyReport.setTotalGasInjection(currentYearFillContentSum);
-            }
-        } */
-
         BigDecimal capacity = queryCapacity(createReqVO.getDeptId());
         // 计算运行时效 当日注气量/产能
         if (ObjUtil.isNotEmpty(createReqVO.getDailyGasInjection()) && (capacity.compareTo(BigDecimal.ZERO)>0)) {
@@ -371,9 +382,9 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         if (ObjUtil.isEmpty(existReport)) {
             // 新增日报记录 如果是 无施工设备的队伍 status auditStatus 需要单独处理
             if (CollUtil.isNotEmpty(teamStatusL)) {
-                // 自动生成的日报 设置 填报完成 审批通过
-                iotRhDailyReport.setStatus(1);
-                iotRhDailyReport.setAuditStatus(20);
+                // 20260731 修改成 生成的空日报需要再次填报 确认并审核
+                iotRhDailyReport.setStatus(0);
+                iotRhDailyReport.setAuditStatus(0);
                 // 如果是自动生成的日报 需要根据规则设备 非生产时间
                 // 设备状态为 "动迁" 时,系统生成的日报里面,非生产时间内的 "生产配合"(relocation_time) 时间为24小时;
                 // 设备状态为 "完工" 时,系统生成的日报里面,非生产时间内的 "待命"(winter_break_time) 时间为24小时
@@ -512,6 +523,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             Long parentId = currentDept[0].getParentId();
             if (ObjUtil.isNotEmpty(parentId)) {
                 AtomicReference<DeptDO> projectDept = new AtomicReference<>();
+                String finalWellName = wellName;
                 DataPermissionUtils.executeIgnore(() -> {
                     projectDept.set(deptService.getDept(parentId));
                     if (ObjUtil.isNotEmpty(projectDept) && "2".equals(projectDept.get().getType())) {
@@ -546,8 +558,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                                         if (CollUtil.isNotEmpty(users)) {
                                             // 生成消息提醒标题 部门名称-井号
                                             String msgTitle = currentDept[0].getName();
-                                            if (StrUtil.isNotBlank(wellName)) {
-                                                msgTitle = StrUtil.join("-", msgTitle, wellName);
+                                            if (StrUtil.isNotBlank(finalWellName)) {
+                                                msgTitle = StrUtil.join("-", msgTitle, finalWellName);
                                             }
                                             CountDownLatch latch = new CountDownLatch(users.size());
                                             String finalMsgTitle = msgTitle;
@@ -837,11 +849,11 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         IotRhDailyReportDO dailyReport = validateIotRhDailyReportExists(updateReqVO.getId());
         dailyReport.setAuditStatus(updateReqVO.getAuditStatus());
         dailyReport.setOpinion(updateReqVO.getOpinion());
+        Long deptId = dailyReport.getDeptId();
+        Long taskId = dailyReport.getTaskId();
         if (SupplierAuditStatusEnum.REJECT.getStatus().equals(updateReqVO.getAuditStatus())) {
             dailyReport.setStatus(0);
             // 审批拒绝后需要向 日报填报人 发送消息提醒 每个队伍暂时只有1人 随机取1人
-            Long deptId = dailyReport.getDeptId();
-            Long taskId = dailyReport.getTaskId();
             DeptDO dept = deptService.getDept(deptId);
             // 消息标题
             String msgTitle = dept.getName();
@@ -864,6 +876,117 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 }
             }
         }
+        // 审核同意 将生产异常情况 (npt 工程质量) 发送到拥有 生产异常通知 角色的人员
+        BigDecimal accidentTime = dailyReport.getAccidentTime();
+        if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO) > 0) {
+
+            String companyName = "瑞恒兴域";
+            BigDecimal day = accidentTime.divide(new BigDecimal("24"), 2, RoundingMode.HALF_UP);
+            String accidentDay = day + "T";
+            // 异常情况
+            String malfunction = StrUtil.blankToDefault(dailyReport.getMalfunction(), "无");
+            Long projectId = dailyReport.getProjectId();
+            DeptDO dept = deptService.getDept(deptId);
+            // 查询当前队伍的上级项目部
+            DeptDO projectDept = deptService.getDept(dept.getParentId());
+            // 队伍名称
+            String deptName = ObjUtil.isNotEmpty(dept) ? dept.getName() : StrUtil.EMPTY;
+            // 项目部名称
+            String projectDeptName = ObjUtil.isNotEmpty(projectDept) ? projectDept.getName() : StrUtil.EMPTY;
+            String contract = "无";
+            if (ObjUtil.isNotEmpty(projectId)) {
+                IotProjectInfoDO project = iotProjectInfoMapper.selectById(projectId);
+                if (ObjUtil.isNotEmpty(project)) {
+                    contract = project.getContractName();
+                }
+            }
+            String wellName = "无";
+            if (ObjUtil.isNotEmpty(taskId)) {
+                IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
+                if (ObjUtil.isNotEmpty(task)) {
+                    wellName = task.getWellName();
+                }
+            }
+            // 当前处理进度 当日施工简报
+            String brief = StrUtil.blankToDefault(dailyReport.getProductionStatus(), "无");
+            // 下步计划
+            String nextPlan = StrUtil.blankToDefault(dailyReport.getNextPlan(), "无");
+            // 故障误工时间 accidentTime H
+            String PRODUCTION_EXCEPTION_MSG_TEMPLATE =
+                    "[公司]:{}\n" +
+                    "[项目部]:{}\n" +
+                    "[队伍]:{}\n" +
+                    "[井号]:{}\n" +
+                    "[故障描述]:{}\n" +
+                    "[当前处理进度]:{}\n" +
+                    "[下步处理计划]:{}\n" +
+                    "[累计误工时间]:{}\n";
+
+            String finalMsgTitle = StrUtil.format(PRODUCTION_EXCEPTION_MSG_TEMPLATE,
+                    companyName, projectDeptName, deptName, wellName,
+                    malfunction, brief, nextPlan, accidentDay
+            );
+
+            // 封装以上消息内容 发送到公司 角色 (生产异常通知)
+            // 查询瑞恒 157l 下具有以上角色的人员 查询集团(科瑞石油技术) 拥有以上角色的人员
+            Set<Long> userIds = new HashSet<>();
+            Set<Long> deptIds = new HashSet<>();
+            deptIds.add(157l);
+            List<AdminUserDO> companyUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(companyUsers)) {
+                companyUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            deptIds.clear();
+            deptIds.add(156l);
+            List<AdminUserDO> groupUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(groupUsers)) {
+                groupUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            RoleDO role = roleService.getRoleByCode("生产异常通知");
+            if (ObjUtil.isNotEmpty(role)) {
+                Set<Long> roleIds = new HashSet<>();
+                roleIds.add(role.getId());
+                List<UserRoleDO> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
+                if (CollUtil.isNotEmpty(userRoles)) {
+                    // 提取有审批角色的所有用户ID(去重+空值过滤)
+                    Set<Long> roleUserIds = userRoles.stream()
+                            .map(UserRoleDO::getUserId)
+                            .filter(Objects::nonNull) // 过滤空userId
+                            .collect(Collectors.toSet());
+                    // 计算两个集合的交集,得到最终目标用户ID
+                    Set<Long> targetUserIds = userIds.stream()
+                            .filter(roleUserIds::contains)
+                            .collect(Collectors.toSet());
+                    // 异步发送 站内信 钉钉消息
+                    if (CollUtil.isNotEmpty(targetUserIds)) {
+                        Map<Long, AdminUserRespDTO> users = adminUserApi.getUserMap(targetUserIds);
+                        // 给多个用户发送 相同 的 提醒消息
+                        if (CollUtil.isNotEmpty(users)) {
+                            // 生成消息提醒 标题内容
+                            CountDownLatch latch = new CountDownLatch(users.size());
+                            users.forEach((userId, user) -> {
+                                pmsThreadPoolTaskExecutor.execute(() -> {
+                                    try {
+                                        String mobile = user.getMobile();
+                                        // 没有手机号也发送站内信消息
+                                        if (StrUtil.isNotBlank(finalMsgTitle)) {
+                                            pmsMessage.sendMessage(dailyReport.getId(), finalMsgTitle, PmsConstants.PRODUCTION_EXCEPTION,
+                                                    userId, mobile);
+                                        }
+                                    } finally {
+                                        latch.countDown();
+                                    }
+                                });
+                            });
+                        }
+                    }
+                }
+            }
+        }
         // 更新瑞恒日报审核状态
         iotRhDailyReportMapper.updateById(dailyReport);
     }

+ 105 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportServiceImpl.java

@@ -945,11 +945,11 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
         dailyReport.setAuditStatus(updateReqVO.getAuditStatus());
         dailyReport.setOpinion(updateReqVO.getOpinion());
         dailyReport.setConstructionBrief(updateReqVO.getConstructionBrief());
+        Long deptId = dailyReport.getDeptId();
+        Long taskId = dailyReport.getTaskId();
         if (SupplierAuditStatusEnum.REJECT.getStatus().equals(updateReqVO.getAuditStatus())) {
             dailyReport.setStatus(0);
             // 审批拒绝后需要向 日报填报人 发送消息提醒 驳回到日报创建人
-            Long deptId = dailyReport.getDeptId();
-            Long taskId = dailyReport.getTaskId();
             DeptDO dept = deptService.getDept(deptId);
             // 当前日报创建人
             String creator = dailyReport.getCreator();
@@ -983,6 +983,109 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
                 }
             }
         }
+        // 审核同意 将生产异常情况 (npt 工程质量) 发送到拥有 生产异常通知 角色的人员
+        BigDecimal accidentTime = dailyReport.getAccidentTime();
+        if (ObjUtil.isNotEmpty(accidentTime) && accidentTime.compareTo(BigDecimal.ZERO) > 0) {
+
+            String companyName = "瑞鹰国际";
+            BigDecimal day = accidentTime.divide(new BigDecimal("24"), 2, RoundingMode.HALF_UP);
+            String accidentDay = day + "T";
+            // 异常情况
+            String malfunction = StrUtil.blankToDefault(dailyReport.getMalfunction(), "无");
+            DeptDO dept = deptService.getDept(deptId);
+            // 查询当前队伍的上级项目部
+            DeptDO projectDept = deptService.getDept(dept.getParentId());
+            // 队伍名称
+            String deptName = ObjUtil.isNotEmpty(dept) ? dept.getName() : StrUtil.EMPTY;
+            // 项目部名称
+            String projectDeptName = ObjUtil.isNotEmpty(projectDept) ? projectDept.getName() : StrUtil.EMPTY;
+            String wellName = "无";
+            if (ObjUtil.isNotEmpty(taskId)) {
+                IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
+                if (ObjUtil.isNotEmpty(task)) {
+                    wellName = task.getWellName();
+                }
+            }
+            // 当前处理进度 当日施工简报
+            String brief = StrUtil.blankToDefault(dailyReport.getConstructionBrief(), "无");
+            // 下步计划
+            String nextPlan = StrUtil.blankToDefault(dailyReport.getNextPlan(), "无");
+            // 故障误工时间 accidentTime H
+            String PRODUCTION_EXCEPTION_MSG_TEMPLATE =
+                    "[公司]:{}\n" +
+                    "[项目部]:{}\n" +
+                    "[队伍]:{}\n" +
+                    "[井号]:{}\n" +
+                    "[故障描述]:{}\n" +
+                    "[当前处理进度]:{}\n" +
+                    "[下步处理计划]:{}\n" +
+                    "[累计误工时间]:{}\n";
+
+            String finalMsgTitle = StrUtil.format(PRODUCTION_EXCEPTION_MSG_TEMPLATE,
+                    companyName, projectDeptName, deptName, wellName,
+                    malfunction, brief, nextPlan, accidentDay
+            );
+
+            // 封装以上消息内容 发送到公司 角色 (生产异常通知)
+            // 查询瑞鹰 158l 下具有以上角色的人员 查询集团(科瑞石油技术) 拥有以上角色的人员
+            Set<Long> userIds = new HashSet<>();
+            Set<Long> deptIds = new HashSet<>();
+            deptIds.add(158l);
+            List<AdminUserDO> companyUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(companyUsers)) {
+                companyUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            deptIds.clear();
+            deptIds.add(156l);
+            List<AdminUserDO> groupUsers = adminUserService.getUserListByDeptIds(deptIds);
+            if (CollUtil.isNotEmpty(groupUsers)) {
+                groupUsers.forEach(user -> {
+                    userIds.add(user.getId());
+                });
+            }
+            RoleDO role = roleService.getRoleByCode("生产异常通知");
+            if (ObjUtil.isNotEmpty(role)) {
+                Set<Long> roleIds = new HashSet<>();
+                roleIds.add(role.getId());
+                List<UserRoleDO> userRoles = userRoleMapper.selectListByRoleIds(roleIds);
+                if (CollUtil.isNotEmpty(userRoles)) {
+                    // 提取有审批角色的所有用户ID(去重+空值过滤)
+                    Set<Long> roleUserIds = userRoles.stream()
+                            .map(UserRoleDO::getUserId)
+                            .filter(Objects::nonNull) // 过滤空userId
+                            .collect(Collectors.toSet());
+                    // 计算两个集合的交集,得到最终目标用户ID
+                    Set<Long> targetUserIds = userIds.stream()
+                            .filter(roleUserIds::contains)
+                            .collect(Collectors.toSet());
+                    // 异步发送 站内信 钉钉消息
+                    if (CollUtil.isNotEmpty(targetUserIds)) {
+                        Map<Long, AdminUserRespDTO> users = adminUserApi.getUserMap(targetUserIds);
+                        // 给多个用户发送 相同 的 提醒消息
+                        if (CollUtil.isNotEmpty(users)) {
+                            // 生成消息提醒 标题内容
+                            CountDownLatch latch = new CountDownLatch(users.size());
+                            users.forEach((userId, user) -> {
+                                pmsThreadPoolTaskExecutor.execute(() -> {
+                                    try {
+                                        String mobile = user.getMobile();
+                                        // 没有手机号也发送站内信消息
+                                        if (StrUtil.isNotBlank(finalMsgTitle)) {
+                                            pmsMessage.sendMessage(dailyReport.getId(), finalMsgTitle, PmsConstants.PRODUCTION_EXCEPTION,
+                                                    userId, mobile);
+                                        }
+                                    } finally {
+                                        latch.countDown();
+                                    }
+                                });
+                            });
+                        }
+                    }
+                }
+            }
+        }
         // 更新瑞恒日报审核状态
         iotRyDailyReportMapper.updateById(dailyReport);
     }