Эх сурвалжийг харах

Merge remote-tracking branch 'origin/master'

lipenghui 5 өдөр өмнө
parent
commit
4024cd526c
18 өөрчлөгдсөн 516 нэмэгдсэн , 60 устгасан
  1. 1 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/constant/PmsConstants.java
  2. 2 2
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/IotProjectTaskController.java
  3. 6 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotprojecttask/vo/IotProjectTaskPageReqVO.java
  4. 18 14
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java
  5. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportPageReqVO.java
  6. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportRespVO.java
  7. 13 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportStatisticsRespVO.java
  8. 18 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportTaskPeriodVO.java
  9. 53 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java
  10. 8 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotprojecttask/IotProjectTaskMapper.java
  11. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrddailyreport/IotRdDailyReportMapper.java
  12. 51 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRdDailyReportOrderJob.java
  13. 3 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/message/PmsMessage.java
  14. 57 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotprojecttask/IotProjectTaskServiceImpl.java
  15. 1 1
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportService.java
  16. 248 29
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportServiceImpl.java
  17. 13 2
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotProjectTaskMapper.xml
  18. 10 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotRdDailyReportMapper.xml

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

@@ -13,6 +13,7 @@ public interface PmsConstants {
     String GENERATE_OPERATE_TEMPLATE = "generate-operate";
 
     String DAILY_REPORT = "rdDailyReport";
+    String DAILY_REPORT_APPROVAL = "rdReportApproval";
 
     String MAINTAIN_OUT = "maintainOut";
     String MAINTAIN_OUT_TEMPLATE = "maintain-out";

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

@@ -113,6 +113,7 @@ public class IotProjectTaskController {
         // 循环每个任务 找到任务 关联的平台井
         if (CollUtil.isNotEmpty(pagedTasks)) {
             pagedTasks.forEach(task -> {
+                // 查询任务主井及关联井的扩展属性 组装 工作量集合 extProperty dropdownList
                 String platformGroup = task.getPlatformGroup();
                 if (StrUtil.isNotBlank(platformGroup)) {
                     // 根据 platformGroup 查询关联的平台井
@@ -125,6 +126,7 @@ public class IotProjectTaskController {
                         tempPlatform.setId(groupTask.getId());
                         tempPlatform.setWellName(groupTask.getWellName());
                         tempPlatform.setWorkloadDesign(groupTask.getWorkloadDesign());
+                        tempPlatform.setExtProperty(groupTask.getExtProperty());
                         platforms.add(tempPlatform);
                     });
                     platformWellPair.put(task.getId(), platforms);
@@ -144,8 +146,6 @@ public class IotProjectTaskController {
     public CommonResult<PageResult<IotProjectTaskRespVO>> getTaskList( IotProjectTaskPageReqVO pageReqVO) {
         Set<Long> idList = new HashSet<>();
         PageResult<IotProjectTaskDO> taskList = iotProjectTaskService.taskList(pageReqVO, idList);
-        // 设置每个任务的施工队伍
-
         return success(new PageResult<>(buildProjectTaskList(taskList.getList()), taskList.getTotal()));
     }
 

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

@@ -97,4 +97,10 @@ public class IotProjectTaskPageReqVO extends PageParam {
     @Schema(description = "定时任务标识 Y")
     private String jobFlag;
 
+    @Schema(description = "platformGroup 集合")
+    private List<String> platformGroups;
+
+    @Schema(description = "平台井标识 Y N")
+    private String platformFlag;
+
 }

+ 18 - 14
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/IotRdDailyReportController.java

@@ -171,6 +171,8 @@ public class IotRdDailyReportController {
             dailyReportVO.setContractName(project.getContractName());
             dailyReportVO.setManufactureName(project.getManufactureName());
             dailyReportVO.setCompanyId(project.getDeptId());
+            // 虚拟项目标识
+            dailyReportVO.setVirtualProject(project.getContractSubject());
         }
         // 查询日报对应的任务信息
         if (ObjUtil.isNotEmpty(dailyReport.getTaskId())) {
@@ -222,6 +224,7 @@ public class IotRdDailyReportController {
         if (1 == dailyReport.getPlatformWell()) {
             IotProjectTaskPageReqVO pageReqVO = new IotProjectTaskPageReqVO();
             pageReqVO.setPlatformGroup(dailyReport.getTaskPlatform());
+            pageReqVO.setJobFlag("Y");
             List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(pageReqVO);
             // 查询相同平台井组关联的 日报
             IotRdDailyReportPageReqVO reportReqVO  = new IotRdDailyReportPageReqVO();
@@ -278,22 +281,23 @@ public class IotRdDailyReportController {
             List<IotProjectTaskPlatformVO> platforms = new ArrayList<>();
             if (CollUtil.isNotEmpty(tasks)) {
                 tasks.forEach(task -> {
-                    IotProjectTaskPlatformVO platform = new IotProjectTaskPlatformVO();
-                    platform.setId(task.getId());
-                    platform.setWellName(task.getWellName());
-                    platform.setWorkloadDesign(task.getWorkloadDesign());
+                    // 只有生成了主井关联井日报才能在查询平台井详情直接列表中出现
                     if (reportPair.containsKey(task.getId())) {
+                        IotProjectTaskPlatformVO platform = new IotProjectTaskPlatformVO();
+                        platform.setId(task.getId());
+                        platform.setWellName(task.getWellName());
+                        platform.setWorkloadDesign(task.getWorkloadDesign());
                         platform.setReportId(reportPair.get(task.getId()));
+                        if (platformPair.containsKey(task.getId())) {
+                            IotProjectTaskPlatformVO tempPlatform = platformPair.get(task.getId());
+                            platform.setRdStatus(tempPlatform.getRdStatus());
+                            platform.setRdStatusLabel(tempPlatform.getRdStatusLabel());
+                            platform.setTechniqueIds(tempPlatform.getTechniqueIds());
+                            platform.setTechniqueNames(tempPlatform.getTechniqueNames());
+                            platform.setExtProperty(tempPlatform.getExtProperty());
+                        }
+                        platforms.add(platform);
                     }
-                    if (platformPair.containsKey(task.getId())) {
-                        IotProjectTaskPlatformVO tempPlatform = platformPair.get(task.getId());
-                        platform.setRdStatus(tempPlatform.getRdStatus());
-                        platform.setRdStatusLabel(tempPlatform.getRdStatusLabel());
-                        platform.setTechniqueIds(tempPlatform.getTechniqueIds());
-                        platform.setTechniqueNames(tempPlatform.getTechniqueNames());
-                        platform.setExtProperty(tempPlatform.getExtProperty());
-                    }
-                    platforms.add(platform);
                 });
                 dailyReportVO.setPlatforms(platforms);
             }
@@ -544,7 +548,7 @@ public class IotRdDailyReportController {
                         if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                             tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
                         }
-                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()))) {
+                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()) || "当日混砂".equals(attr.getName()))) {
                             tempTotalMixSand = tempTotalMixSand.add(actualValue);
                         }
                     }

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

@@ -29,6 +29,9 @@ public class IotRdDailyReportPageReqVO extends PageParam {
     @Schema(description = "项目id", example = "32587")
     private Long projectId;
 
+    @Schema(description = "平台井标识 2非平台井 1平台井 0默认值", example = "2")
+    private Integer platformWell;
+
     @Schema(description = "平台井组", example = "463e3996-be48-4758-8229-c1351cbf3e37")
     private String platformGroup;
 

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

@@ -290,4 +290,7 @@ public class IotRdDailyReportRespVO {
     @Schema(description = "平台井列表", example = "[]")
     @ExcelProperty("平台井列表")
     private List<IotProjectTaskPlatformVO> platforms;
+
+    @Schema(description = "虚拟项目标识", example = "Y N")
+    private String virtualProject;
 }

+ 13 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportStatisticsRespVO.java

@@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 import java.util.List;
 
 @Schema(description = "管理后台 - 瑞都日报 统计 Response VO")
@@ -41,6 +42,14 @@ public class IotRdDailyReportStatisticsRespVO {
     @ExcelProperty("井号")
     private String wellName;
 
+    @Schema(description = "施工周期 天")
+    @ExcelProperty("施工周期 天")
+    private String period;
+
+    @Schema(description = "施工状态")
+    @ExcelProperty("施工状态")
+    private String rdStatus;
+
     @Schema(description = "施工工艺 多个逗号分隔")
     @ExcelProperty("施工工艺")
     private String techniques;
@@ -53,6 +62,10 @@ public class IotRdDailyReportStatisticsRespVO {
     @ExcelProperty("已完成工作量")
     private BigDecimal finishedWorkload;
 
+    @Schema(description = "任务创建时间")
+    @ExcelProperty("任务创建时间")
+    private LocalDateTime createTime;
+
     @Schema(description = "工作量明细")
     @ExcelProperty("工作量明细")
     private List<IotRdDailyReportStatisticsItemVO> items;

+ 18 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrddailyreport/vo/IotRdDailyReportTaskPeriodVO.java

@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - 瑞都日报 任务施工周期 Response VO")
+@Data
+public class IotRdDailyReportTaskPeriodVO {
+
+    @Schema(description = "任务id", example = "123")
+    private Long taskId;
+
+    @Schema(description = "工作量", example = "2")
+    private String startDate;
+
+    @Schema(description = "单位")
+    private String endDate;
+}

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

@@ -135,6 +135,59 @@ public class IotRhDailyReportController {
         return success(new PageResult<>(buildRhDailyReports(pageResult.getList()), pageResult.getTotal()));
     }
 
+    @GetMapping("/totalWorkload")
+    @Operation(summary = "累计工作量统计")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
+    public CommonResult<Map<String, BigDecimal>> totalWorkload(@Valid IotRhDailyReportPageReqVO pageReqVO) {
+        // 查询所有数据不分页
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        // 根据查询参数筛选出 符合条件 的记录id 再传入 分页查询
+        Set<Long> projectIds = new HashSet<>();
+        Set<Long> taskIds = new HashSet<>();
+        if (StrUtil.isNotBlank(pageReqVO.getContractName())) {
+            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
+            reqVO.setContractName(pageReqVO.getContractName());
+            List<IotProjectInfoDO> projects = iotProjectInfoService.getIotProjectInfos(reqVO);
+            if (CollUtil.isNotEmpty(projects)) {
+                projects.forEach(project -> {
+                    projectIds.add(project.getId());
+                });
+                pageReqVO.setProjectIds(projectIds);
+            }
+        }
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName())) {
+            IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
+            reqVO.setSearchKey(pageReqVO.getTaskName());
+            List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(reqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    taskIds.add(task.getId());
+                });
+                pageReqVO.setTaskIds(taskIds);
+            }
+        }
+        List<IotRhDailyReportDO> list = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO).getList();
+        Map<String, BigDecimal> result = new HashMap<>();
+        BigDecimal totalGasInjection = BigDecimal.ZERO;
+        BigDecimal totalWaterInjection = BigDecimal.ZERO;
+        if (CollUtil.isNotEmpty(list)) {
+            for (IotRhDailyReportDO report : list) {
+                BigDecimal dailyGasInjection = report.getDailyGasInjection();
+                BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
+                if (ObjUtil.isNotEmpty(dailyGasInjection)) {
+                    totalGasInjection = totalGasInjection.add(dailyGasInjection);
+                }
+                if (ObjUtil.isNotEmpty(dailyWaterInjection)) {
+                    totalWaterInjection = totalWaterInjection.add(dailyWaterInjection);
+                }
+            }
+            // 汇总 指定搜索时间段内的 累计注气量 累计注水量
+            result.put("totalGasInjection", totalGasInjection);
+            result.put("totalWaterInjection", totalWaterInjection);
+        }
+        return success(result);
+    }
+
     @GetMapping("/rhDailyReportStatistics")
     @Operation(summary = "按照日期查询瑞恒日报统计数据 已填报 未填报 数量")
     @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")

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

@@ -91,21 +91,24 @@ public interface IotProjectTaskMapper extends BaseMapperX<IotProjectTaskDO> {
         }
         // 定时任务 如果是平台井 只生成主井号任务
         if (ObjUtil.isNotEmpty(reqVO.getJobFlag())) {
-            wrapper.and(wq -> wq.eq(IotProjectTaskDO::getPlatformWell, 0)
+            wrapper.and(wq -> wq.ne(IotProjectTaskDO::getStatus, "wg"));
+                    /* .and(innerWq -> innerWq.eq(IotProjectTaskDO::getPlatformWell, 0)
                     .or()
-                    .eq(IotProjectTaskDO::getPlatformWell, 1));
+                    .eq(IotProjectTaskDO::getPlatformWell, 1))); */
         }
         return selectList(wrapper);
     }
 
-    IPage<IotProjectTaskDO> taskList(IPage<IotProjectTaskPageReqVO> page,
+    IPage<IotProjectTaskDO> taskList(IPage<?> page,
                                      @Param("companyId") Long companyId,
                                      @Param("manufactureName") String manufactureName,
                                      @Param("contractName") String contractName,
                                      @Param("contractCode") String contractCode,
                                      @Param("wellName") String wellName,
                                      @Param("createTime") LocalDateTime[] createTime,
-                                     @Param("deptIds") Collection<Long> deptIds
+                                     @Param("deptIds") Collection<Long> deptIds,
+                                     @Param("projectIds") Collection<Long> projectIds,
+                                     @Param("platformFlag") String platformFlag
     );
 
     /**
@@ -119,6 +122,7 @@ public interface IotProjectTaskMapper extends BaseMapperX<IotProjectTaskDO> {
                 .likeIfPresent(IotProjectTaskDO::getWellName, reqVO.getWellName())
                 .eqIfPresent(IotProjectTaskDO::getWellType, reqVO.getWellType())
                 .eqIfPresent(IotProjectTaskDO::getPlatformGroup, reqVO.getPlatformGroup())
+                .inIfPresent(IotProjectTaskDO::getPlatformGroup, reqVO.getPlatformGroups())
                 .eqIfPresent(IotProjectTaskDO::getLocation, reqVO.getLocation())
                 .eqIfPresent(IotProjectTaskDO::getTechnique, reqVO.getTechnique())
                 .eqIfPresent(IotProjectTaskDO::getWorkloadDesign, reqVO.getWorkloadDesign())

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrddailyreport/IotRdDailyReportMapper.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportTaskPeriodVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -77,6 +78,7 @@ public interface IotRdDailyReportMapper extends BaseMapperX<IotRdDailyReportDO>
                 .inIfPresent(IotRdDailyReportDO::getDeptId, reqVO.getDeptIds())
                 .eqIfPresent(IotRdDailyReportDO::getProjectId, reqVO.getProjectId())
                 .inIfPresent(IotRdDailyReportDO::getProjectId, reqVO.getProjectIds())
+                .eqIfPresent(IotRdDailyReportDO::getPlatformWell, reqVO.getPlatformWell())
                 .eqIfPresent(IotRdDailyReportDO::getPlatformGroup, reqVO.getPlatformGroup())
                 .eqIfPresent(IotRdDailyReportDO::getTaskId, reqVO.getTaskId())
                 .inIfPresent(IotRdDailyReportDO::getTaskId, reqVO.getTaskIds())
@@ -172,4 +174,10 @@ public interface IotRdDailyReportMapper extends BaseMapperX<IotRdDailyReportDO>
      * @param reqVO 查询条件
      */
     List<IotRdDailyReportDO> selectListGrouped(@Param("reqVO") IotRdDailyReportPageReqVO reqVO);
+
+    /**
+     * 瑞都日报 关联的任务 施工周期
+     */
+    List<IotRdDailyReportTaskPeriodVO> taskConstructionPeriod();
+
 }

+ 51 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/dailyreport/CreateRdDailyReportOrderJob.java

@@ -89,13 +89,59 @@ public class CreateRdDailyReportOrderJob implements JobHandler {
         // 平台井任务只生成主井号任务 关联井在日报中聚合处理
         IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
         taskReqVO.setCompanyId(163l);
-        taskReqVO.setJobFlag(StrUtil.EMPTY);
+        taskReqVO.setJobFlag("Y");
         List<IotProjectTaskDO> tasks = iotProjectTaskService.projectTasks(taskReqVO);
+        // 平台井任务关联了3口井,其中2口井已经完工,1口井还在施工,平台井任务需要定时生成日报
+        // 从任务列表中筛选出 (platformWell=0或platformGroup有值)的记录,并进一步找到 platformGroup有值的记录 对应的‘主井记录’生成日报
+        List<IotProjectTaskDO> qualifiedTasks = new ArrayList<>();
+        Set<String> platformGroups = new HashSet<>();
+        // 未施工完成的任务id集合
+        Set<Long> unfinishedTaskIds = new HashSet<>();
+        // key平台井标识platformGroup    value平台井platformWell=1时的taskId
+        Map<String, IotProjectTaskDO> mainWellTaskPair = new HashMap<>();
+        if (CollUtil.isNotEmpty(tasks)) {
+            tasks.forEach(task -> {
+                // 非平台井任务 直接生成日报
+                qualifiedTasks.add(task);
+                if (StrUtil.isNotBlank(task.getPlatformGroup())) {
+                    platformGroups.add(task.getPlatformGroup());
+                    if (1 == task.getPlatformWell()) {
+                        mainWellTaskPair.put(task.getPlatformGroup(), task);
+                    }
+                }
+                // 生成所有所有未施工完成的任务id集合
+                unfinishedTaskIds.add(task.getId());
+            });
+            // 找出 关联井未施工完成 但是主井已经施工完成的记录 同步生成主井日报
+
+            // 查询出 platformGroups 对应的任务,找到主井记录
+            if (CollUtil.isNotEmpty(platformGroups)) {
+                IotProjectTaskPageReqVO platformTaskReqVO = new IotProjectTaskPageReqVO();
+                platformTaskReqVO.setPlatformGroups(new ArrayList<>(platformGroups));
+                List<IotProjectTaskDO> platformTasks = iotProjectTaskService.projectTasks(platformTaskReqVO);
+                if (CollUtil.isNotEmpty(platformTasks)) {
+                    // platformTasks 可能同时包含 主井 关联井 有的已经施工完成 有的未施工完成
+                    // 已经施工完成的关联井不再生成日报
+                    // 未施工完成的关联井需要和相关主井一起生成日报
+                    platformTasks.forEach(task -> {
+                        /* if (2 == task.getPlatformWell() && !"wg".equals(task.getStatus())
+                                && mainWellTaskPair.containsKey(task.getPlatformGroup()) && !unfinishedTaskIds.contains(task.getId())) {
+                            qualifiedTasks.add(mainWellTaskPair.get(task.getPlatformGroup()));
+                        } */
+                        if (1 == task.getPlatformWell() && "wg".equals(task.getStatus())
+                                && !mainWellTaskPair.containsKey(task.getPlatformGroup()) && !unfinishedTaskIds.contains(task.getId())) {
+                            qualifiedTasks.add(task);
+                        }
+                    });
+                }
+            }
+        }
+
         Set<Long> userIds = new HashSet<>();
         List<IotRdDailyReportDO> reports = new ArrayList<>();
         Map<Long, Long> taskSubmitterPair = new HashMap<>();
-        if (CollUtil.isNotEmpty(tasks)) {
-            tasks.forEach(task -> {
+        if (CollUtil.isNotEmpty(qualifiedTasks)) {
+            qualifiedTasks.forEach(task -> {
                 // 查询当前任务的 工单填报人
                 Set<Long> submitterIds = task.getSubmitter();
                 if (CollUtil.isNotEmpty(submitterIds)) {
@@ -115,7 +161,8 @@ public class CreateRdDailyReportOrderJob implements JobHandler {
             }
             Map<Long, DeptDO> deptPair = deptService.getDeptMap(deptIds);
             // 以任务为维度 生成瑞都日报 部门为任务配置的工单填报人对应的部门
-            tasks.forEach(task -> {
+            // todo 任务填报人列表中 如果有人属于队伍上 则 设置日报deptId=队伍id 这样项目部填报人也能看到日报
+            qualifiedTasks.forEach(task -> {
                 if (!taskIds.contains(task.getId()) && CollUtil.isNotEmpty(task.getSubmitter())) {
                     // 生成当天的日报
                     IotRdDailyReportDO report = new IotRdDailyReportDO();

+ 3 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/message/PmsMessage.java

@@ -82,6 +82,9 @@ public class PmsMessage {
             if (PmsConstants.DAILY_REPORT.equals(businessType)) {
                 msg = "您有新的生产日报 " + name + ",请处理。"+"["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
             }
+            if (PmsConstants.DAILY_REPORT_APPROVAL.equals(businessType)) {
+                msg = "您有新的生产日报 " + name + "需要审批,请处理。"+"["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
+            }
             if (PmsConstants.GENERATE_OPERATION.equals(businessType)) {
                 msg = "您有新的运行记录工单 " + name + ",请处理。"+"["+ DateUtil.format(new Date(),"yyyy-MM-dd hh:mm:ss")+"]";
             }

+ 57 - 4
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotprojecttask/IotProjectTaskServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskSaveReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
@@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskD
 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.service.iotprojectinfo.IotProjectInfoService;
+import cn.iocoder.yudao.module.supplier.service.product.SupplierService;
 import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -41,6 +43,8 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
     @Resource
     private IotProjectInfoService iotProjectInfoService;
 
+    @Resource
+    private SupplierService iotSupplierService;
     @Resource
     private IotProjectInfoMapper iotProjectInfoMapper;
 
@@ -95,10 +99,23 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
         // 如果是瑞都的平台井,使用已有的 platformGroup 关联平台井多个任务
         AtomicBoolean platformWell = new AtomicBoolean(false);
         AtomicReference<String> platformGroup = new AtomicReference<>(StrUtil.EMPTY);
+        String uuid = StrUtil.uuid();
+        // 是否是从已有的非平台井 转换成 平台井
+        AtomicBoolean transferFlag = new AtomicBoolean(false);
         list.forEach(task -> {
+            // 如果 设置为 平台井后 task.getPlatformGroup() 为空 说明是非平台井修改成平台井的情况
+            // 此时需要 重新生成 platformGroup
+            if (StrUtil.isNotBlank(task.getPlatformGroup())) {
+                platformGroup.set(task.getPlatformGroup());
+            }
             if (1 == task.getPlatformWell()) {
                 platformWell.set(true);
-                platformGroup.set(task.getPlatformGroup());
+                if (StrUtil.isBlank(task.getPlatformGroup())) {
+                    transferFlag.set(true);
+                }
+            } else {
+                // 可能之前设置过平台井 然后又取消 这里需要 删除主井外的关联井
+                // 并清空 主井 的 platformGroup
             }
         });
         // 查询系统中已有的关联平台井 保存时入参集合中没有的平台井 需要删除掉
@@ -116,16 +133,29 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
             iotProjectInfoService.saveDictData(saveReqVO.getDictType(), updateObj.getLocation());
             if (ObjUtil.isEmpty(updateObj.getId())) {
                 // 新增加的任务 瑞都平台井
-                updateObj.setPlatformGroup(platformGroup.get());
+                if (transferFlag.get()) {
+                    updateObj.setPlatformGroup(uuid);
+                } else {
+                    updateObj.setPlatformGroup(platformGroup.get());
+                }
                 tobeAddedTasks.add(updateObj);
             } else {
+                // 更新现有的井任务
+                if (!platformWell.get()) {
+                    // 非平台井 设置 platformWell = 0 兼容 之前是平台井然后再取消选中的情况
+                    updateObj.setPlatformGroup(StrUtil.EMPTY);
+                }
+                if (transferFlag.get()) {
+                    // 非平台井 设置 platformWell = 0 兼容 之前是平台井然后再取消选中的情况
+                    updateObj.setPlatformGroup(uuid);
+                }
                 taskDOS.add(updateObj);
             }
             if (ObjUtil.isNotEmpty(saveReqVO.getId())) {
                 currentTaskIds.add(saveReqVO.getId());
             }
         }
-        // 找到需要删除的 平台井任务
+        // 找到需要 删除 的 平台井任务
         if (StrUtil.isNotBlank(platformGroup.get())) {
             IotProjectTaskPageReqVO reqVO = new IotProjectTaskPageReqVO();
             reqVO.setPlatformGroup(platformGroup.get());
@@ -138,6 +168,11 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
                         tobeDeletedTasks.add(task);
                         deletedTaskIds.add(task.getId());
                     }
+                    if (2 == task.getPlatformWell() && !platformWell.get()) {
+                        // 取消平台井设置时 主井的关联井也需要删除
+                        tobeDeletedTasks.add(task);
+                        deletedTaskIds.add(task.getId());
+                    }
                 });
             }
         }
@@ -201,6 +236,22 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
                 departmentIds.add(dept.getId());
             });
         }
+        // 客户名称模板搜索
+        Set<Long> projectIds = new HashSet<>();
+        if (StrUtil.isNotBlank(vo.getManufactureName())) {
+            IotProjectInfoPageReqVO reqVO = new IotProjectInfoPageReqVO();
+            reqVO.setManufactureName(vo.getManufactureName());
+            List<IotProjectInfoDO> matchedProjects = iotProjectInfoMapper.selectList(reqVO);
+            if (CollUtil.isNotEmpty(matchedProjects)) {
+                matchedProjects.forEach(project -> {
+                    projectIds.add(project.getId());
+                });
+            } else {
+                // 返回空数据
+                return new PageResult<>(new ArrayList<>(), 0l);
+            }
+        }
+
         IPage<IotProjectTaskDO> taskDOIPage = iotProjectTaskMapper.taskList(Page.of(vo.getPageNo(), vo.getPageSize()),
                 vo.getCompanyId(),
                 vo.getManufactureName(),
@@ -208,7 +259,9 @@ public class IotProjectTaskServiceImpl implements IotProjectTaskService {
                 vo.getContractCode(),
                 vo.getWellName(),
                 vo.getCreateTime(),
-                departmentIds);
+                departmentIds,
+                projectIds,
+                vo.getPlatformFlag());
         return new PageResult<>(taskDOIPage.getRecords(), taskDOIPage.getTotal());
     }
 

+ 1 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrddailyreport/IotRdDailyReportService.java

@@ -29,7 +29,7 @@ public interface IotRdDailyReportService {
      *
      * @param updateReqVO 更新信息
      */
-    void updateIotRdDailyReport(@Valid IotRdDailyReportSaveReqVO updateReqVO);
+    IotRdDailyReportDO updateIotRdDailyReport(@Valid IotRdDailyReportSaveReqVO updateReqVO);
 
     /**
      * 审批瑞都日报

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

@@ -5,13 +5,11 @@ import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 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.iotattachment.vo.IotAttachmentSaveReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojectinfo.vo.IotProjectInfoPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportPageReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportSaveReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportStatisticsItemVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportStatisticsRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotattachment.IotAttachmentDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
@@ -23,24 +21,40 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrddailyreport.IotRdDailyReportMapper;
 import cn.iocoder.yudao.module.pms.enums.AttachmentCategoryEnum;
 import cn.iocoder.yudao.module.pms.enums.AttachmentTypeEnum;
+import cn.iocoder.yudao.module.pms.message.PmsMessage;
 import cn.iocoder.yudao.module.supplier.enums.common.SupplierAuditStatusEnum;
+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.dal.dataobject.dept.DeptDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictDataDO;
+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.dict.DictDataService;
+import cn.iocoder.yudao.module.system.service.permission.RoleService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import com.google.common.collect.ImmutableMap;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+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.framework.common.util.collection.CollectionUtils.convertList;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_PROJECT_TASK_NOT_EXISTS;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_RD_DAILY_REPORT_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
 
 /**
  * 瑞都日报 Service 实现类
@@ -63,6 +77,18 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
     private DictDataService dictDataService;
     @Resource
     private DeptService deptService;
+    @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 createIotRdDailyReport(IotRdDailyReportSaveReqVO createReqVO) {
@@ -74,9 +100,17 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
     }
 
     @Override
-    public void updateIotRdDailyReport(IotRdDailyReportSaveReqVO updateReqVO) {
+    public IotRdDailyReportDO updateIotRdDailyReport(IotRdDailyReportSaveReqVO updateReqVO) {
         // 校验存在
-        validateIotRdDailyReportExists(updateReqVO.getId());
+        IotRdDailyReportDO dailyReport = validateIotRdDailyReportExists(updateReqVO.getId());
+        // 如果 endTime = 24:00 转换成 23:59:59 否则会引发异常 Parse [2025-11-22 24:00] with format [yyyy-MM-dd HH:mm] error!
+        String endTime = updateReqVO.getEndTime();
+        if (StrUtil.isNotBlank(endTime)) {
+            String[] timeAttr = endTime.split(":");
+            if ("24".equals(timeAttr[0])) {
+                updateReqVO.setEndTime("23:59:59");
+            }
+        }
         // 更新
         IotRdDailyReportDO updateObj = BeanUtils.toBean(updateReqVO, IotRdDailyReportDO.class);
         // 设置 日报填写状态 保存 已完成
@@ -118,6 +152,10 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     "type", AttachmentTypeEnum.EXTERNAL_RENTAL.getCode()
             ));
         }
+        updateObj.setReportName(dailyReport.getReportName());
+        updateObj.setPlatformWell(dailyReport.getPlatformWell());
+        updateObj.setPlatformGroup(dailyReport.getPlatformGroup());
+        return updateObj;
     }
 
     @Override
@@ -141,9 +179,13 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             if (ObjUtil.isNotEmpty(taskId)) {
                 // 查找关联的任务 更新任务的 施工状态
                 IotProjectTaskDO task = iotProjectTaskMapper.selectById(taskId);
-                task.setStatus(updateReqVO.getRdStatus());
-                task.setRdStatus(updateReqVO.getRdStatus());
-                iotProjectTaskMapper.updateById(task);
+                if (!"wg".equals(task.getStatus()) && StrUtil.isNotBlank(task.getRdStatus())) {
+                    // 兼容平台井关联的任务已经完工,没有填报数据,但是关联井没有完工的情况
+                    // 此时没有填写日报数据主井任务不必更新状态
+                    task.setStatus(updateReqVO.getRdStatus());
+                    task.setRdStatus(updateReqVO.getRdStatus());
+                    iotProjectTaskMapper.updateById(task);
+                }
                 // 如果是平台井 且 关联井也设置了 施工状态 也要同步更新关联井任务的施工状态
                 if (1 == platformWell) {
                     // key平台井关联井的任务taskId   value平台井关联井的任务施工状态数据字典value
@@ -296,12 +338,17 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         Map<Long, String> projectPair = new HashMap<>();
         //  key任务id     value任务井号
         Map<Long, String> taskPair = new HashMap<>();
+        //  key任务id     value任务施工状态
+        Map<Long, String> taskStatusPair = new HashMap<>();
         //  施工工艺 key字典键值     value字典标签
         Map<String, String> techniqueDictPair = new HashMap<>();
         //  key任务id     value任务工作量
         Map<Long, BigDecimal> taskWorkloadPair = new HashMap<>();
         //  key任务id     value任务工艺名称
         Map<Long, String> taskTechniquePair = new HashMap<>();
+        // key任务id   value任务的施工周期天数
+        Map<Long, String> taskPeriodPair = new HashMap<>();
+
         if (CollUtil.isNotEmpty(dailyReports)) {
             // 遍历日报 找到每个日报关联的任务的 施工队伍
             List<Long> taskIds = convertList(dailyReports, IotRdDailyReportDO::getTaskId);
@@ -309,6 +356,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             // 查询所有任务关联的队伍信息 如果任务选择了多个队伍 队伍名称逗号分隔
             // key任务id      value任务选择的施工队伍名称集合
             Map<Long, String> taskDeptNamePair = new HashMap<>();
+            // key任务id      value任务创建时间集合
+            Map<Long, LocalDateTime> taskCreateTimePair = new HashMap<>();
             // key任务id      value任务选择的施工队伍对应的项目部名称集合
             Map<Long, String> taskProjectDeptPair = new HashMap<>();
             IotProjectTaskPageReqVO relatedTaskReqVO = new IotProjectTaskPageReqVO();
@@ -363,6 +412,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             if (CollUtil.isNotEmpty(tasks)) {
                 tasks.forEach(task -> {
                     taskPair.put(task.getId(), task.getWellName());
+                    taskStatusPair.put(task.getId(), task.getStatus());
+                    taskCreateTimePair.put(task.getId(), task.getCreateTime());
                     // 获取所有任务的工作量数据
                     taskWorkloadPair.put(task.getId(), new BigDecimal(task.getWorkloadDesign()));
                     if (techniqueDictPair.containsKey(task.getTechnique())) {
@@ -371,6 +422,46 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     }
                 });
             }
+
+            // 查询所有日报关联任务的施工周期
+            List<IotRdDailyReportTaskPeriodVO> taskPeriods = iotRdDailyReportMapper.taskConstructionPeriod();
+            if (CollUtil.isNotEmpty(taskPeriods)) {
+                // 定义日期格式化器,匹配"yyyy-MM-dd HH:mm:ss"格式
+                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                taskPeriods.forEach(period -> {
+                    // 如果 startDate endDate 都存在 计算施工周期天数 考虑到日报审批后才会更新任务状态
+                    // 所以计算任务施工周期时 要筛选出施工完成的任务
+                    String taskStatus = StrUtil.EMPTY;
+                    if (taskStatusPair.containsKey(period.getTaskId())) {
+                        taskStatus = taskStatusPair.get(period.getTaskId());
+                    }
+                    if (StrUtil.isNotBlank(period.getStartDate()) && StrUtil.isNotBlank(period.getEndDate()) && "wg".equals(taskStatus)) {
+                        // 计算 startDate endDate 之间的差值
+                        try {
+                            // 1. 解析日期字符串为LocalDateTime
+                            LocalDateTime startLdt = LocalDateTime.parse(period.getStartDate(), dtf);
+                            LocalDateTime endLdt = LocalDateTime.parse(period.getEndDate(), dtf);
+
+                            // 2. 截断时分秒,仅保留日期部分
+                            LocalDate startDate = startLdt.toLocalDate();
+                            LocalDate endDate = endLdt.toLocalDate();
+
+                            // 3. 计算日期差值(天),+1满足「同一天算1天」的规则
+                            long daysDiff = ChronoUnit.DAYS.between(startDate, endDate);
+                            long constructionDays = daysDiff + 1;
+
+                            // 4. 存入任务-施工周期映射(key=任务ID,value=天数字符串)
+                            taskPeriodPair.put(period.getTaskId(), String.valueOf(constructionDays));
+                        } catch (Exception e) {
+                            // 解析失败时默认周期为1天(可根据业务调整,也可记录日志)
+                            taskPeriodPair.put(period.getTaskId(), "1");
+                            // 可选:添加日志打印
+                            // log.error("解析任务施工周期日期失败,taskId={}, startDate={}, endDate={}", period.getTaskId(), period.getStartDate(), period.getEndDate(), e);
+                        }
+                    }
+                });
+            }
+
             // 设置 小队 任务已经完成的工作量集合 (按照不同的单位统计任务的不同工作量)
             // key任务井id      value队伍工作量数据
             Map<Long, BigDecimal> bridgePlugPair = new HashMap<>();
@@ -385,6 +476,7 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             dailyReports.forEach(report -> {
                 // 设置每个任务的工作量数据  单位相同的工作量值作合并处理
                 List<IotTaskAttrModelProperty> taskAttrs = report.getExtProperty();
+                Long taskId = report.getTaskId();
                 // 暂存不同单位的工作量属性值
                 BigDecimal tempTotalBridgePlug = BigDecimal.ZERO;               // 桥塞(个数)
                 BigDecimal tempTotalRunCount = BigDecimal.ZERO;                 // 趟数
@@ -411,8 +503,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         if ("个数".equals(unit)) {
                             // 钻可溶桥塞  钻复合桥塞
                             tempTotalBridgePlug = tempTotalBridgePlug.add(actualValue);
-                            if (bridgePlugPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempBridgePlug = bridgePlugPair.get(report.getDeptId());
+                            if (bridgePlugPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempBridgePlug = bridgePlugPair.get(report.getTaskId());
                                 bridgePlugPair.put(report.getTaskId(), tempTotalBridgePlug.add(tempBridgePlug));
                             } else {
                                 bridgePlugPair.put(report.getTaskId(), tempTotalBridgePlug);
@@ -420,8 +512,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         }
                         if ("趟数".equals(unit)) {
                             tempTotalRunCount = tempTotalRunCount.add(actualValue);
-                            if (runCountPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempRunCount = runCountPair.get(report.getDeptId());
+                            if (runCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempRunCount = runCountPair.get(report.getTaskId());
                                 runCountPair.put(report.getTaskId(), tempTotalRunCount.add(tempRunCount));
                             } else {
                                 runCountPair.put(report.getTaskId(), tempTotalRunCount);
@@ -429,8 +521,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         }
                         if ("小时".equals(unit)) {
                             tempTotalHourCount = tempTotalHourCount.add(actualValue);
-                            if (hourCountPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempHourCount = hourCountPair.get(report.getDeptId());
+                            if (hourCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempHourCount = hourCountPair.get(report.getTaskId());
                                 hourCountPair.put(report.getTaskId(), tempTotalHourCount.add(tempHourCount));
                             } else {
                                 hourCountPair.put(report.getTaskId(), tempTotalHourCount);
@@ -440,8 +532,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                             // 将 actualValue 换算成 H
                             BigDecimal hours = actualValue.multiply(new BigDecimal("24"));
                             tempTotalHourCount = tempTotalHourCount.add(hours);
-                            if (hourCountPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempHourCount = hourCountPair.get(report.getDeptId());
+                            if (hourCountPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempHourCount = hourCountPair.get(report.getTaskId());
                                 hourCountPair.put(report.getTaskId(), tempTotalHourCount.add(tempHourCount));
                             } else {
                                 hourCountPair.put(report.getTaskId(), tempTotalHourCount);
@@ -449,8 +541,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         }
                         if ("方".equals(unit)) {
                             tempTotalWaterVolume = tempTotalWaterVolume.add(actualValue);
-                            if (waterVolumePair.containsKey(report.getDeptId())) {
-                                BigDecimal tempWaterVolume = waterVolumePair.get(report.getDeptId());
+                            if (waterVolumePair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWaterVolume = waterVolumePair.get(report.getTaskId());
                                 waterVolumePair.put(report.getTaskId(), tempTotalWaterVolume.add(tempWaterVolume));
                             } else {
                                 waterVolumePair.put(report.getTaskId(), tempTotalWaterVolume);
@@ -458,8 +550,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         }
                         if ("井数".equals(unit)) {
                             tempTotalCumulativeWorkingWell = tempTotalCumulativeWorkingWell.add(actualValue);
-                            if (cumulativeWorkingWellPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempWorkingWell = cumulativeWorkingWellPair.get(report.getDeptId());
+                            if (cumulativeWorkingWellPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWorkingWell = cumulativeWorkingWellPair.get(report.getTaskId());
                                 cumulativeWorkingWellPair.put(report.getTaskId(), tempTotalCumulativeWorkingWell.add(tempWorkingWell));
                             } else {
                                 cumulativeWorkingWellPair.put(report.getTaskId(), tempTotalCumulativeWorkingWell);
@@ -468,8 +560,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         if ("段数".equals(unit)) {
                             // 累计施工层
                             tempTotalCumulativeWorkingLayers = tempTotalCumulativeWorkingLayers.add(actualValue);
-                            if (cumulativeWorkingLayersPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempWorkingLayer = cumulativeWorkingLayersPair.get(report.getDeptId());
+                            if (cumulativeWorkingLayersPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempWorkingLayer = cumulativeWorkingLayersPair.get(report.getTaskId());
                                 cumulativeWorkingLayersPair.put(report.getTaskId(), tempTotalCumulativeWorkingLayers.add(tempWorkingLayer));
                             } else {
                                 cumulativeWorkingLayersPair.put(report.getTaskId(), tempTotalCumulativeWorkingLayers);
@@ -477,17 +569,18 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                         }
                         if ("台次".equals(unit) && "当日泵车台次".equals(attr.getName())) {
                             tempTotalPumpTrips = tempTotalPumpTrips.add(actualValue);
-                            if (pumpTripsPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempPumpTrips = pumpTripsPair.get(report.getDeptId());
+                            if (pumpTripsPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempPumpTrips = pumpTripsPair.get(report.getTaskId());
                                 pumpTripsPair.put(report.getTaskId(), tempTotalPumpTrips.add(tempPumpTrips));
                             } else {
                                 pumpTripsPair.put(report.getTaskId(), tempTotalPumpTrips);
                             }
                         }
-                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName()))) {
+                        if ("台次".equals(unit) && ("当日仪表/混砂".equals(attr.getName())
+                                || "当日混砂".equals(attr.getName()) || "当日仪表".equals(attr.getName()))) {
                             tempTotalMixSand = tempTotalMixSand.add(actualValue);
-                            if (mixSandPair.containsKey(report.getDeptId())) {
-                                BigDecimal tempMixSand = mixSandPair.get(report.getDeptId());
+                            if (mixSandPair.containsKey(report.getTaskId())) {
+                                BigDecimal tempMixSand = mixSandPair.get(report.getTaskId());
                                 mixSandPair.put(report.getTaskId(), tempTotalMixSand.add(tempMixSand));
                             } else {
                                 mixSandPair.put(report.getTaskId(), tempTotalMixSand);
@@ -517,9 +610,13 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     /* if (teamDeptPair.containsKey(deptId)) {
                         uniqueReport.setDeptName(teamDeptPair.get(deptId));
                     } */
+                    uniqueReport.setTaskId(taskId);
                     if (taskDeptNamePair.containsKey(taskId)) {
                         uniqueReport.setDeptName(taskDeptNamePair.get(taskId));
                     }
+                    if (taskCreateTimePair.containsKey(taskId)) {
+                        uniqueReport.setCreateTime(taskCreateTimePair.get(taskId));
+                    }
                     /* if (teamProjectPair.containsKey(deptId)) {
                         Long parentId = teamProjectPair.get(deptId);
                         if (projectDeptPair.containsKey(parentId)) {
@@ -535,6 +632,12 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     if (taskPair.containsKey(taskId)) {
                         uniqueReport.setWellName(taskPair.get(taskId));
                     }
+                    if (taskPeriodPair.containsKey(taskId)) {
+                        uniqueReport.setPeriod(taskPeriodPair.get(taskId));
+                    }
+                    if (taskStatusPair.containsKey(taskId)) {
+                        uniqueReport.setRdStatus(taskStatusPair.get(taskId));
+                    }
                     if (taskTechniquePair.containsKey(taskId)) {
                         uniqueReport.setTechniques(taskTechniquePair.get(taskId));
                     }
@@ -604,6 +707,13 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                 });
             }
         }
+        // 将 result 集合按照 集合中元素的 属性 创建时间 倒序排列
+        if (CollUtil.isNotEmpty(result)) {
+            result.sort(Comparator.comparing(
+                    IotRdDailyReportStatisticsRespVO::getCreateTime,
+                    Comparator.nullsLast(Comparator.reverseOrder())
+            ));
+        }
         return result;
     }
 
@@ -612,9 +722,118 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         if (CollUtil.isEmpty(reports)) {
             throw exception(IOT_RD_DAILY_REPORT_NOT_EXISTS);
         }
+        // 需要发送提醒消息的日报对象
+        List<IotRdDailyReportDO> tobeSendMsgReports = new ArrayList<>();
+        // 主井日报
+        List<IotRdDailyReportDO> mainPlatformReports = new ArrayList<>();
+        // 关联井日报
+        List<IotRdDailyReportDO> relatePlatformReports = new ArrayList<>();
         reports.forEach(report -> {
-            updateIotRdDailyReport(report);
+            IotRdDailyReportDO updatedReport = updateIotRdDailyReport(report);
+            // 标识当前任务井是 普通井 或 平台井主井 关联的任务审批人发送提醒消息
+            if (1 == updatedReport.getPlatformWell() || 0 == updatedReport.getPlatformWell()) {
+                tobeSendMsgReports.add(updatedReport);
+            }
+            // 记录关联井集合
+            if (2 == updatedReport.getPlatformWell()) {
+                relatePlatformReports.add(updatedReport);
+            }
+            // 记录平台井主井集合
+            if (1 == updatedReport.getPlatformWell()) {
+                mainPlatformReports.add(updatedReport);
+            }
         });
+
+        // 兼容平台井任务 主井任务已经施工完成 但是关联井仍在施工的情况 此时 平台井 下拉列表中 选择不到主井
+        // 此时应该同步修改主井任务的 填写状态 审批状态
+        if (CollUtil.isNotEmpty(relatePlatformReports) && CollUtil.isEmpty(mainPlatformReports)) {
+            // 找到关联井对应的主井 并把 主井 添加到 准备发送消息提醒的集合 tobeSendMsgReports
+            IotRdDailyReportDO randomRelatedReport = relatePlatformReports.get(0);
+            String platformGroup = randomRelatedReport.getPlatformGroup();
+            // 根据 platformGroup 找到主井日报
+            IotRdDailyReportPageReqVO reqVO = new IotRdDailyReportPageReqVO();
+            reqVO.setPlatformGroup(platformGroup);
+            reqVO.setPlatformWell(1);
+            List<IotRdDailyReportDO> mainWellReports = iotRdDailyReportMapper.dailyReports(reqVO);
+            if (CollUtil.isNotEmpty(mainWellReports)) {
+                IotRdDailyReportDO mainWellReport = mainWellReports.get(0);
+                // 设置 日报审批状态为 审批中 auditStatus = 10
+                mainWellReport.setAuditStatus(10);
+                // 设置 日报填写状态 保存 已完成
+                mainWellReport.setStatus(1);
+                iotRdDailyReportMapper.updateById(mainWellReport);
+            }
+        }
+
+        // 考虑到平台井的情况 只向有审批权限的人发送一次 钉钉提醒及站内信
+        // 任务为平台井时 只向主井的任务的 填报人所属部门或上级项目部下 有审批权限的人 发送消息提醒
+        if (CollUtil.isNotEmpty(tobeSendMsgReports)) {
+            Set<Long> deptIds = new HashSet<>();
+            IotRdDailyReportDO tobeSendMsgReport = tobeSendMsgReports.get(0);
+            Long deptId = tobeSendMsgReport.getDeptId();
+            DeptDO dept = deptService.getDept(deptId);
+            if (ObjUtil.isNotEmpty(dept)) {
+                deptIds.add(dept.getId());
+                String type = dept.getType();
+                // 类型(公司级1 项目部2 队伍3)
+                // 如果当前部门是 队伍 查找上级 项目部
+                if ("3".equals(type)) {
+                    DeptDO projectDept = deptService.getDept(dept.getParentId());
+                    if (ObjUtil.isNotEmpty(projectDept)) {
+                        deptIds.add(projectDept.getId());
+                    }
+                }
+                // 查找当前部门及项目下有审批权限的人员 role 项目部日报审批RD
+                List<AdminUserDO> receivedMsgUsers = adminUserService.getUserListByDeptIds(deptIds);
+                //
+                if (CollUtil.isNotEmpty(receivedMsgUsers)) {
+                    Set<Long> userIds = new HashSet<>();
+                    receivedMsgUsers.forEach(user -> {
+                        userIds.add(user.getId());
+                    });
+                    RoleDO role = roleService.getRoleByCode("项目部日报审批RD");
+                    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(mobile) && StrUtil.isNotBlank(tobeSendMsgReport.getReportName())) {
+                                                    pmsMessage.sendMessage(tobeSendMsgReport.getId(), tobeSendMsgReport.getReportName(), PmsConstants.DAILY_REPORT_APPROVAL,
+                                                            userId, mobile);
+                                                }
+                                            } finally {
+                                                latch.countDown();
+                                            }
+                                        });
+                                    });
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 
     @Override

+ 13 - 2
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotProjectTaskMapper.xml

@@ -18,8 +18,7 @@
         <result column="contract_code" property="contractCode" />
     </resultMap>
 
-    <select id="taskList" parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO"
-    resultMap="IotProjectTaskResultMap">
+    <select id="taskList" resultMap="IotProjectTaskResultMap">
         select
         a.id,
         a.project_id,
@@ -45,6 +44,12 @@
         <if test="companyId != null and companyId != ''">
         and a.dept_id = #{companyId}
         </if>
+        <if test='platformFlag != null and platformFlag == "Y"'>
+            and a.platform_well = 1
+        </if>
+        <if test='platformFlag != null and platformFlag == "N"'>
+            and a.platform_well = 0
+        </if>
         <if test="manufactureName != null  and manufactureName != ''">
         and b.manufacture_name like concat('%', #{manufactureName}, '%')
         </if>
@@ -73,6 +78,12 @@
                 #{deptId}
             </foreach>
         </if>
+        <if test="projectIds != null and !projectIds.isEmpty()">
+            AND a.project_id IN
+            <foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
+                #{projectId}
+            </foreach>
+        </if>
         ORDER BY a.id DESC
     </select>
 

+ 10 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotRdDailyReportMapper.xml

@@ -81,4 +81,14 @@
         ORDER BY g.min_start_date ASC
     </select>
 
+    <select id="taskConstructionPeriod" resultType="cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDailyReportTaskPeriodVO">
+        SELECT
+            task_id taskId,
+            MIN(construction_start_date) AS startDate,
+            MIN(CASE WHEN rd_status = 'wg' THEN construction_start_date ELSE NULL END) AS endDate
+        FROM rq_iot_rd_daily_report
+        WHERE deleted = b'0'
+        GROUP BY task_id;
+    </select>
+
 </mapper>