Sfoglia il codice sorgente

Merge branch 'reportStatistics'

zhangcl 1 giorno fa
parent
commit
51eea7d72b
11 ha cambiato i file con 1173 aggiunte e 9 eliminazioni
  1. 46 5
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/IotRhDailyReportController.java
  2. 67 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrhdailyreport/vo/IotRhDailyReportStatisticsRespVO.java
  3. 138 4
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/IotRyDailyReportController.java
  4. 71 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotrydailyreport/vo/IotRyDailyReportStatisticsRespVO.java
  5. 11 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrhdailyreport/IotRhDailyReportMapper.java
  6. 129 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotZHBDController.java
  7. 8 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportService.java
  8. 259 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportServiceImpl.java
  9. 9 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportService.java
  10. 394 0
      yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportServiceImpl.java
  11. 41 0
      yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/iotprojecttask/IotRhDailyReportMapper.xml

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

@@ -12,10 +12,7 @@ import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 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.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportRespVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportStatisticsVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
 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.iotprojecttaskattrs.IotTaskAttrModelProperty;
@@ -135,6 +132,41 @@ public class IotRhDailyReportController {
         return success(new PageResult<>(buildRhDailyReports(pageResult.getList()), pageResult.getTotal()));
     }
 
+    @GetMapping("/statistics")
+    @Operation(summary = "获得瑞恒日报汇总统计")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
+    public CommonResult<List<IotRhDailyReportStatisticsRespVO>> statistics(@Valid IotRhDailyReportPageReqVO pageReqVO) {
+        List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
+        // 根据查询参数筛选出 符合条件 的记录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<IotRhDailyReportStatisticsRespVO> statistics = iotRhDailyReportService.statistics(pageReqVO);
+        result.addAll(statistics);
+        return success(result);
+    }
+
     @GetMapping("/totalWorkload")
     @Operation(summary = "累计工作量统计")
     @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
@@ -170,20 +202,29 @@ public class IotRhDailyReportController {
         Map<String, BigDecimal> result = new HashMap<>();
         BigDecimal totalGasInjection = BigDecimal.ZERO;
         BigDecimal totalWaterInjection = BigDecimal.ZERO;
+        BigDecimal totalPowerConsumption = BigDecimal.ZERO;
+        BigDecimal totalFuelConsumption = BigDecimal.ZERO;
         if (CollUtil.isNotEmpty(list)) {
             for (IotRhDailyReportDO report : list) {
                 BigDecimal dailyGasInjection = report.getDailyGasInjection();
                 BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
+                BigDecimal powerConsumption = report.getDailyPowerUsage();
                 if (ObjUtil.isNotEmpty(dailyGasInjection)) {
                     totalGasInjection = totalGasInjection.add(dailyGasInjection);
                 }
                 if (ObjUtil.isNotEmpty(dailyWaterInjection)) {
                     totalWaterInjection = totalWaterInjection.add(dailyWaterInjection);
                 }
+                if (ObjUtil.isNotEmpty(powerConsumption)) {
+                    totalPowerConsumption = totalPowerConsumption.add(powerConsumption);
+                }
+
             }
-            // 汇总 指定搜索时间段内的 累计注气量 累计注水量
+            // 汇总 指定搜索时间段内的 累计注气量 累计注水量 累计用电量 累计油耗
             result.put("totalGasInjection", totalGasInjection);
             result.put("totalWaterInjection", totalWaterInjection);
+            result.put("totalPowerConsumption", totalPowerConsumption);
+            result.put("totalFuelConsumption", totalFuelConsumption);
         }
         return success(result);
     }

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

@@ -0,0 +1,67 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 瑞恒日报 汇总统计 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRhDailyReportStatisticsRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13853")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "项目部id", example = "125")
+    @ExcelProperty("项目部id")
+    private Long projectDeptId;
+
+    @Schema(description = "队伍id", example = "125")
+    @ExcelProperty("队伍id")
+    private Long teamId;
+
+    @Schema(description = "项目部名称", example = "塔河项目部")
+    @ExcelProperty("项目部名称")
+    private String projectDeptName;
+
+    @Schema(description = "队伍名称", example = "HY-A1")
+    @ExcelProperty("队伍名称")
+    private String teamName;
+
+    @Schema(description = "任务id", example = "15678")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @Schema(description = "排序", example = "1")
+    @ExcelProperty("排序")
+    private Integer sort;
+
+    @Schema(description = "部门类型(公司级1 项目部2 队伍3)", example = "1")
+    @ExcelProperty("部门类型(公司级1 项目部2 队伍3)")
+    private String type;
+
+    @Schema(description = "累计注气量(方)")
+    @ExcelProperty("累计注气量(方)")
+    private BigDecimal cumulativeGasInjection = BigDecimal.ZERO;
+
+    @Schema(description = "累计注气量(方)")
+    @ExcelProperty("累计注气量(方)")
+    private BigDecimal cumulativeWaterInjection = BigDecimal.ZERO;
+
+    @Schema(description = "累计用电量(kWh)")
+    @ExcelProperty("累计用电量(kWh)")
+    private BigDecimal cumulativePowerConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "累计油耗(吨)")
+    @ExcelProperty("累计油耗(吨)")
+    private BigDecimal cumulativeFuelConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "运行时效")
+    @ExcelProperty("运行时效")
+    private BigDecimal transitTime = BigDecimal.ZERO;
+
+}

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

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -11,10 +12,7 @@ import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 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.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportRespVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportSaveReqVO;
-import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.*;
 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.iotprojecttaskattrs.IotTaskAttrModelProperty;
@@ -128,6 +126,41 @@ public class IotRyDailyReportController {
         return success(new PageResult<>(buildRyDailyReports(pageResult.getList()), pageResult.getTotal()));
     }
 
+    @GetMapping("/statistics")
+    @Operation(summary = "获得瑞鹰日报汇总统计")
+    @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
+    public CommonResult<List<IotRyDailyReportStatisticsRespVO>> statistics(@Valid IotRyDailyReportPageReqVO pageReqVO) {
+        List<IotRyDailyReportStatisticsRespVO> result = new ArrayList<>();
+        // 根据查询参数筛选出 符合条件 的记录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<IotRyDailyReportStatisticsRespVO> statistics = iotRyDailyReportService.statistics(pageReqVO);
+        result.addAll(statistics);
+        return success(result);
+    }
+
     /**
      * 瑞恒日报分页 设置关联查询信息
      * @param reports
@@ -269,6 +302,107 @@ public class IotRyDailyReportController {
         });
     }
 
+    @GetMapping("/totalWorkload")
+    @Operation(summary = "累计工作量统计")
+    @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:query')")
+    public CommonResult<Map<String, BigDecimal>> totalWorkload(@Valid IotRyDailyReportPageReqVO 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<IotRyDailyReportDO> list = iotRyDailyReportService.getIotRyDailyReportPage(pageReqVO).getList();
+        Map<String, BigDecimal> result = new HashMap<>();
+        // 总进尺
+        BigDecimal totalFootage = BigDecimal.ZERO;
+        // 总用电量
+        BigDecimal totalPowerConsumption = BigDecimal.ZERO;
+        // 总油耗
+        BigDecimal totalFuelConsumption = BigDecimal.ZERO;
+        // key队伍id      value施工井数
+        BigDecimal constructionWells = BigDecimal.ZERO;
+        // key队伍id      value完工井数
+        BigDecimal completedWells = BigDecimal.ZERO;
+        // key施工队伍id    value施工井数量
+        Map<Long, Integer> totalTasksPair = new HashMap<>();
+        // key施工队伍id    value完工井数量
+        Map<Long, Integer> completedTasksPair = new HashMap<>();
+        List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportService.countRepairTasksByDept();
+        if (CollUtil.isNotEmpty(repairDeptTasks)) {
+            repairDeptTasks.forEach(task -> {
+                totalTasksPair.put(task.getDeptId(), task.getTotalTaskCount());
+                completedTasksPair.put(task.getDeptId(), task.getCompletedTaskCount());
+            });
+        }
+        if (CollUtil.isNotEmpty(list)) {
+            for (IotRyDailyReportDO report : list) {
+                BigDecimal dailyFootage = report.getDailyFootage();
+                BigDecimal powerConsumption = report.getDailyPowerUsage();
+                BigDecimal fuelConsumption = report.getDailyFuel();
+                if (ObjUtil.isNotEmpty(dailyFootage)) {
+                    totalFootage = totalFootage.add(dailyFootage);
+                }
+                if (ObjUtil.isNotEmpty(powerConsumption)) {
+                    totalPowerConsumption = totalPowerConsumption.add(powerConsumption);
+                }
+                if (ObjUtil.isNotEmpty(fuelConsumption)) {
+                    totalFuelConsumption = totalFuelConsumption.add(fuelConsumption);
+                }
+            }
+            // 汇总 指定搜索时间段内的 总进尺  累计用电量 累计油耗
+            if ("1".equals(pageReqVO.getProjectClassification())) {
+                // 钻井日报
+                result.put("totalFootage", totalFootage);
+            } else if ("2".equals(pageReqVO.getProjectClassification())) {
+                // 修井日报 总施工井数 完工井数 取日报记录中的最大值
+                result.put("totalFootage", totalFootage);
+            }
+            // 施工井数
+            if (CollUtil.isNotEmpty(totalTasksPair)) {
+                for (Integer wellCount : totalTasksPair.values()) {
+                    constructionWells = constructionWells.add(new BigDecimal(wellCount));
+                }
+            }
+            // 完工井数
+            if (CollUtil.isNotEmpty(completedTasksPair)) {
+                for (Integer wellCount : completedTasksPair.values()) {
+                    completedWells = completedWells.add(new BigDecimal(wellCount));
+                }
+            }
+            // 累计用电量
+            result.put("totalPowerConsumption", totalPowerConsumption);
+            // 累计油耗
+            result.put("totalFuelConsumption", totalFuelConsumption);
+            // 累计施工井数
+            result.put("constructionWells", constructionWells);
+            // 累计完工井数
+            result.put("completedWells", completedWells);
+        }
+        return success(result);
+    }
+
     @GetMapping("/export-excel")
     @Operation(summary = "导出瑞鹰日报 Excel")
     @PreAuthorize("@ss.hasPermission('pms:iot-ry-daily-report:export')")

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

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Schema(description = "管理后台 - 瑞鹰日报 汇总统计 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotRyDailyReportStatisticsRespVO {
+
+    @Schema(description = "主键id", requiredMode = Schema.RequiredMode.REQUIRED, example = "13853")
+    @ExcelProperty("主键id")
+    private Long id;
+
+    @Schema(description = "项目部id", example = "125")
+    @ExcelProperty("项目部id")
+    private Long projectDeptId;
+
+    @Schema(description = "队伍id", example = "125")
+    @ExcelProperty("队伍id")
+    private Long teamId;
+
+    @Schema(description = "项目部名称", example = "新疆项目部")
+    @ExcelProperty("项目部名称")
+    private String projectDeptName;
+
+    @Schema(description = "队伍名称", example = "小修20队")
+    @ExcelProperty("队伍名称")
+    private String teamName;
+
+    @Schema(description = "任务id", example = "15678")
+    @ExcelProperty("任务id")
+    private Long taskId;
+
+    @Schema(description = "排序", example = "1")
+    @ExcelProperty("排序")
+    private Integer sort;
+
+    @Schema(description = "部门类型(公司级1 项目部2 队伍3)", example = "1")
+    @ExcelProperty("部门类型(公司级1 项目部2 队伍3)")
+    private String type;
+
+    @Schema(description = "累计进尺(m)")
+    @ExcelProperty("累计进尺(m)")
+    private BigDecimal cumulativeFootage = BigDecimal.ZERO;
+
+    @Schema(description = "累计施工井数")
+    @ExcelProperty("累计施工井数")
+    private Integer cumulativeConstructWells = 0;
+
+    @Schema(description = "累计完工井数")
+    @ExcelProperty("累计完工井数")
+    private Integer cumulativeCompletedWells = 0;
+
+    @Schema(description = "累计用电量(kWh)")
+    @ExcelProperty("累计用电量(kWh)")
+    private BigDecimal cumulativePowerConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "累计油耗(吨)")
+    @ExcelProperty("累计油耗(吨)")
+    private BigDecimal cumulativeFuelConsumption = BigDecimal.ZERO;
+
+    @Schema(description = "运行时效")
+    @ExcelProperty("运行时效")
+    private BigDecimal transitTime = BigDecimal.ZERO;
+
+}

+ 11 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotrhdailyreport/IotRhDailyReportMapper.java

@@ -38,6 +38,17 @@ public interface IotRhDailyReportMapper extends BaseMapperX<IotRhDailyReportDO>
                                              @Param("taskIds") Collection<Long> taskIds,
                                              @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
 
+    /**
+     * 瑞恒日报汇总统计
+     * @param page
+     * @param reqVO
+     * @param projectIds
+     * @return
+     */
+    IPage<IotRhDailyReportDO> rhReportStatistics(IPage<IotRhDailyReportDO> page, @Param("reqVO") IotRhDailyReportPageReqVO reqVO,
+                                             @Param("taskIds") Collection<Long> taskIds,
+                                             @Param("projectIds") Collection<Long> projectIds, @Param("deptIds") Collection<Long> deptIds);
+
     default PageResult<IotRhDailyReportDO> selectPage(IotRhDailyReportPageReqVO reqVO) {
         // 检查contractName不为空但projectIds为空的情况
         if (StrUtil.isNotBlank(reqVO.getContractName()) && (CollUtil.isEmpty(reqVO.getProjectIds()))) {

+ 129 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/job/IotZHBDController.java

@@ -0,0 +1,129 @@
+package cn.iocoder.yudao.module.pms.job;
+
+import cn.hutool.json.JSONObject;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportRespVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.TDDeviceMapper;
+import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapper;
+import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
+import cn.iocoder.yudao.module.pms.service.iotprojecttask.IotProjectTaskService;
+import cn.iocoder.yudao.module.pms.service.iotrhdailyreport.IotRhDailyReportService;
+import cn.iocoder.yudao.module.system.service.dept.DeptService;
+import cn.iocoder.yudao.module.system.service.dict.DictDataService;
+import com.alibaba.fastjson.JSON;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.http.HttpHeaders;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "中航北斗")
+@RestController
+@RequestMapping("/pms/iot-zhbd")
+@Validated
+public class IotZHBDController {
+
+    @Resource
+    private IotRhDailyReportService iotRhDailyReportService;
+    @Resource
+    private DeptService deptService;
+    @Resource
+    private IotProjectInfoService iotProjectInfoService;
+    @Resource
+    private IotProjectTaskService iotProjectTaskService;
+    @Resource
+    private DictDataService dictDataService;
+
+    private static final String ID = "NjI1LjUyNS42ODg";
+    private static final String SECRET = "3897865b70d7bf29fcca5029147f7d0a";
+    private static final String TOKEN_URL = "https://zhbdgps.cn/video/webapi/user/login";
+    private static final String LOCATION_URL="https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
+    private static final String parameter = "lng,lat,today_distance,distance,todayoil,totaloil,online,oil1,oil2,oil3,oil4,vehicle_name";
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+    @Autowired
+    private RestTemplate restTemplate;
+    @Autowired
+    private IotOpeationFillMapper zhbdmapper;
+    @Autowired
+    private TDDeviceMapper deviceMapper;
+    @Autowired
+    private IotDeviceMapper iotDeviceMapper;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建瑞恒日报")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:create')")
+    public CommonResult<Long> createIotRhDailyReport(@Valid @RequestBody IotRhDailyReportSaveReqVO createReqVO) {
+        return success(iotRhDailyReportService.createIotRhDailyReport(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新瑞恒日报")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:update')")
+    public CommonResult<Boolean> updateIotRhDailyReport(@Valid @RequestBody IotRhDailyReportSaveReqVO updateReqVO) {
+        iotRhDailyReportService.updateIotRhDailyReport(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除瑞恒日报")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:delete')")
+    public CommonResult<Boolean> deleteIotRhDailyReport(@RequestParam("id") Long id) {
+        iotRhDailyReportService.deleteIotRhDailyReport(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得车辆油耗")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('pms:iot-rh-daily-report:query')")
+    public CommonResult<IotRhDailyReportRespVO> getIotRhDailyReport(@RequestParam("id") Long id) {
+        IotRhDailyReportRespVO result = new IotRhDailyReportRespVO();
+
+        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
+        if (StringUtils.isBlank(zhbdtoken)) {
+            Map<String, String> map = new HashMap<>();
+            map.put("id", ID);
+            map.put("secret", SECRET);
+            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
+            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
+                com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
+                zhbdtoken = jsonObject.get("token").toString();
+                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
+            }
+        }
+        // 1. 设置请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.add("Authorization", zhbdtoken); // 添加自定义头信息
+        // headers.addHeader("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
+        headers.add("Content-Type", "application/json");
+        headers.add("Accept", "*/*");
+        headers.add("Host", "zhbdgps.cn");
+        headers.add("Connection", "keep-alive");
+        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+        params.add("client_ids", "8203");
+        params.add("vehicle_ids", "8203");
+        return success(result);
+    }
+
+}

+ 8 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrhdailyreport/IotRhDailyReportService.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pms.service.iotrhdailyreport;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportStatisticsRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportStatisticsVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 
@@ -56,6 +57,13 @@ public interface IotRhDailyReportService {
      */
     PageResult<IotRhDailyReportDO> getIotRhDailyReportPage(IotRhDailyReportPageReqVO pageReqVO);
 
+    /**
+     * 瑞恒日报汇总统计
+     *
+     * @param pageReqVO 列表查询
+     * @return 瑞恒日报汇总统计
+     */
+    List<IotRhDailyReportStatisticsRespVO> statistics(IotRhDailyReportPageReqVO pageReqVO);
 
     /**
      * 按照日期查询瑞恒日报统计数据 已填报 未填报 数量

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

@@ -3,12 +3,14 @@ package cn.iocoder.yudao.module.pms.service.iotrhdailyreport;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
 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.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceProperty;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportStatisticsRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportStatisticsVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
@@ -21,6 +23,7 @@ import cn.iocoder.yudao.module.pms.dal.mysql.iotopeationfill.IotOpeationFillMapp
 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;
+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.dict.DictTypeDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
@@ -366,6 +369,262 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         return new PageResult<>(page.getRecords(), page.getTotal());
     }
 
+    @Override
+    public List<IotRhDailyReportStatisticsRespVO> statistics(IotRhDailyReportPageReqVO pageReqVO) {
+        List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
+        // 不分页统计所有数据
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            // 找到所有子部门对象集合
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // 检查contractName不为空但projectIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getContractName()) && (CollUtil.isEmpty(pageReqVO.getProjectIds()))) {
+            return new ArrayList<>();
+        }
+        // 检查taskName不为空但taskIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && (CollUtil.isEmpty(pageReqVO.getTaskIds()))) {
+            return new ArrayList<>();
+        }
+        IPage<IotRhDailyReportDO> page = iotRhDailyReportMapper.rhReportStatistics(
+                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO,
+                pageReqVO.getTaskIds(), pageReqVO.getProjectIds(), ids);
+        List<IotRhDailyReportDO> dailyReports = page.getRecords();
+
+        // 默认显示所有项目部的汇总数据(新疆分公司也展示 下属各项目部的数据)
+        // 点击项目部 显示 下属队伍的数据
+        // 首先判断点击的部门是属于 公司 还是 队伍 如果没有点击任何部门 默认查询所有项目部数据
+        if (ObjUtil.isEmpty(pageReqVO.getDeptId())) {
+            result = statisticsByProjectDept(dailyReports, 157L);
+        } else {
+            // 判断点击的组织树中的部门类型 类型(公司级1 项目部2 队伍3)
+            DeptDO selectedDept = deptService.getDept(pageReqVO.getDeptId());
+            if ("1".equals(selectedDept.getType())) {
+                // 以项目部为维度汇总数据
+                result = statisticsByProjectDept(dailyReports, pageReqVO.getDeptId());
+            } else if ("2".equals(selectedDept.getType())) {
+                // 以队伍为维度汇总数据
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+            } else if ("3".equals(selectedDept.getType())) {
+                // 显示单个队伍的汇总数据
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+            } else {
+                // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
+                // 以项目部为维度汇总数据
+                result = statisticsByProjectDept(dailyReports, pageReqVO.getDeptId());
+            }
+        }
+        // 根据result集合内对象的 sort 属性正序排列 sort 类型为 integer 类型
+        if (CollUtil.isNotEmpty(result)) {
+            result.sort(Comparator.comparing(
+                    IotRhDailyReportStatisticsRespVO::getSort,
+                    Comparator.nullsLast(Comparator.naturalOrder())
+            ));
+        }
+        return result;
+    }
+
+    /**
+     * 按项目部维度统计数据
+     * @param dailyReports 日报数据列表
+     * @param rootDeptId 根部门ID(如157L为瑞恒根部门,或其他公司级部门ID)
+     * @return 项目部维度统计结果列表
+     */
+    private List<IotRhDailyReportStatisticsRespVO> statisticsByProjectDept(List<IotRhDailyReportDO> dailyReports, Long rootDeptId) {
+        List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // key队伍id/项目部id   value累计注气量
+        Map<Long, BigDecimal> cumulativeGasInjectionPair = new HashMap<>();
+        // key队伍id/项目部id   value累计注水量
+        Map<Long, BigDecimal> cumulativeWaterInjectionPair = new HashMap<>();
+        // key队伍id/项目部id   value累计用电
+        Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的总产能
+        Map<Long, BigDecimal> cumulativeCapacityPair = new HashMap<>();
+        // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
+        Map<Long, BigDecimal> cumulativeTransitTimePair = new HashMap<>();
+
+        // 以项目部为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(rootDeptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            if ("2".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                projectDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // 查询指定部门下相关设备的产能
+        // key队伍id   value队伍下相关设备产能
+        Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if (ObjUtil.isNotEmpty(report.getDeptId()) && teamProjectIdPair.containsKey(report.getDeptId())) {
+                    Long projectDeptId = teamProjectIdPair.get(report.getDeptId());
+                    if (ObjUtil.isNotEmpty(projectDeptId) && projectDeptPair.containsKey(projectDeptId)) {
+                        // 累计注气量
+                        cumulativeGasInjectionPair.merge(projectDeptId, report.getDailyGasInjection(), BigDecimal::add);
+                        // 累计注水量
+                        cumulativeWaterInjectionPair.merge(projectDeptId, report.getDailyWaterInjection(), BigDecimal::add);
+                        // 累计用电量
+                        cumulativePowerConsumptionPair.merge(projectDeptId, report.getDailyPowerUsage(), BigDecimal::add);
+                        if (teamCapacityPair.containsKey(report.getDeptId())) {
+                            BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
+                            cumulativeCapacityPair.merge(projectDeptId, tempCapacity, BigDecimal::add);
+                        }
+                    }
+                }
+            });
+            // 根据 累计注气量 累计产能 计算指定项目部下的平均产能
+            if (CollUtil.isNotEmpty(cumulativeGasInjectionPair) && CollUtil.isNotEmpty(cumulativeCapacityPair)) {
+                cumulativeGasInjectionPair.forEach((projectDeptId, cumulativeGasInjection) -> {
+                    if (cumulativeCapacityPair.containsKey(projectDeptId)) {
+                        BigDecimal tempCapacity = cumulativeCapacityPair.get(projectDeptId);
+                        if (tempCapacity.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指定项目部的累计运行时效
+                            BigDecimal tempTransitTime = cumulativeGasInjection.divide(tempCapacity, 4, RoundingMode.HALF_UP);
+                            cumulativeTransitTimePair.put(projectDeptId, tempTransitTime);
+                        } else {
+                            cumulativeTransitTimePair.put(projectDeptId, BigDecimal.ZERO);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 生成返回的数据列表集合
+        projectDeptPair.forEach((deptId, dept) -> {
+            IotRhDailyReportStatisticsRespVO statistics = new IotRhDailyReportStatisticsRespVO();
+            statistics.setProjectDeptId(deptId);
+            statistics.setProjectDeptName(dept.getName());
+            statistics.setSort(dept.getSort());
+            statistics.setType("2");
+            statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(deptId));
+            statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(deptId));
+            statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(deptId));
+            statistics.setTransitTime(cumulativeTransitTimePair.get(deptId));
+            result.add(statistics);
+        });
+
+        return result;
+    }
+
+    /**
+     * 按 队伍 维度统计数据
+     * @param dailyReports 日报数据列表
+     * @param deptId 项目部ID 或 队伍id(塔河项目部 HY-A1)
+     * @return 队伍 维度统计结果列表
+     */
+    private List<IotRhDailyReportStatisticsRespVO> statisticsByProjectDepartment(List<IotRhDailyReportDO> dailyReports, Long deptId) {
+        List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key队伍id    value队伍名称
+        Map<Long, DeptDO> teamDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // key队伍id   value累计注气量
+        Map<Long, BigDecimal> cumulativeGasInjectionPair = new HashMap<>();
+        // key队伍id   value累计注水量
+        Map<Long, BigDecimal> cumulativeWaterInjectionPair = new HashMap<>();
+        // key队伍id   value累计用电
+        Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的总产能
+        Map<Long, BigDecimal> cumulativeCapacityPair = new HashMap<>();
+        // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
+        Map<Long, BigDecimal> cumulativeTransitTimePair = new HashMap<>();
+
+        // 以 队伍 为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        allRhChildDeptIds.add(deptId);  // 查询某支队伍
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            if ("3".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                teamDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // 查询指定部门下相关设备的产能
+        // key队伍id   value队伍下相关设备产能
+        Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if (ObjUtil.isNotEmpty(report.getDeptId())) {
+                    // 累计注气量
+                    cumulativeGasInjectionPair.merge(report.getDeptId(), report.getDailyGasInjection(), BigDecimal::add);
+                    // 累计注水量
+                    cumulativeWaterInjectionPair.merge(report.getDeptId(), report.getDailyWaterInjection(), BigDecimal::add);
+                    // 累计用电量
+                    cumulativePowerConsumptionPair.merge(report.getDeptId(), report.getDailyPowerUsage(), BigDecimal::add);
+                    if (teamCapacityPair.containsKey(report.getDeptId())) {
+                        BigDecimal tempCapacity = teamCapacityPair.get(report.getDeptId());
+                        cumulativeCapacityPair.merge(report.getDeptId(), tempCapacity, BigDecimal::add);
+                    }
+                }
+            });
+            // 根据 累计注气量 累计产能 计算指定队伍下的平均产能
+            if (CollUtil.isNotEmpty(cumulativeGasInjectionPair) && CollUtil.isNotEmpty(cumulativeCapacityPair)) {
+                cumulativeGasInjectionPair.forEach((teamDeptId, cumulativeGasInjection) -> {
+                    if (cumulativeCapacityPair.containsKey(teamDeptId)) {
+                        BigDecimal tempCapacity = cumulativeCapacityPair.get(teamDeptId);
+                        if (tempCapacity.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指定队伍的累计运行时效
+                            BigDecimal tempTransitTime = cumulativeGasInjection.divide(tempCapacity, 4, RoundingMode.HALF_UP);
+                            cumulativeTransitTimePair.put(teamDeptId, tempTransitTime);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 生成返回的数据列表集合
+        teamDeptPair.forEach((teamDeptId, dept) -> {
+            IotRhDailyReportStatisticsRespVO statistics = new IotRhDailyReportStatisticsRespVO();
+            statistics.setTeamId(teamDeptId);
+            statistics.setTeamName(dept.getName());
+            statistics.setSort(dept.getSort());
+            statistics.setType("3");
+            statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(teamDeptId));
+            statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(teamDeptId));
+            statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(teamDeptId));
+            statistics.setTransitTime(cumulativeTransitTimePair.get(teamDeptId));
+            result.add(statistics);
+        });
+
+        return result;
+    }
+
     @Override
     public List<IotRhDailyReportStatisticsVO> rhDailyReportStatistics(IotRhDailyReportPageReqVO reqVO) {
         if (reqVO.getCreateTime().length == 0) {

+ 9 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotrydailyreport/IotRyDailyReportService.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pms.service.iotrydailyreport;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
 
@@ -112,4 +113,12 @@ public interface IotRyDailyReportService {
      * @return 按部门统计任务数量
      */
     List<IotRyDailyReportTaskCountVO> countDateRigTasksByDepartment();
+
+    /**
+     * 瑞鹰日报汇总统计
+     *
+     * @param pageReqVO 列表查询
+     * @return 瑞恒日报汇总统计
+     */
+    List<IotRyDailyReportStatisticsRespVO> statistics(IotRyDailyReportPageReqVO pageReqVO);
 }

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

@@ -3,20 +3,25 @@ package cn.iocoder.yudao.module.pms.service.iotrydailyreport;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjUtil;
 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.controller.admin.iotdevicecategorytemplateattrs.vo.IotDeviceProperty;
 import cn.iocoder.yudao.module.pms.controller.admin.iotprojecttask.vo.IotProjectTaskPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportTaskCountVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttask.IotProjectTaskDO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrydailyreport.IotRyDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotprojecttask.IotProjectTaskMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrydailyreport.IotRyDailyReportMapper;
+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.dict.DictTypeDO;
 import cn.iocoder.yudao.module.system.service.dept.DeptService;
 import cn.iocoder.yudao.module.system.service.dict.DictTypeService;
@@ -28,11 +33,13 @@ import org.springframework.validation.annotation.Validated;
 import javax.annotation.Resource;
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 
 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.*;
 
 
@@ -288,4 +295,391 @@ public class IotRyDailyReportServiceImpl implements IotRyDailyReportService {
         return iotRyDailyReportMapper.countDateRigTasksByDepartment();
     }
 
+    @Override
+    public List<IotRyDailyReportStatisticsRespVO> statistics(IotRyDailyReportPageReqVO pageReqVO) {
+        List<IotRyDailyReportStatisticsRespVO> result = new ArrayList<>();
+        // 不分页统计所有数据
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        Set<Long> ids = new HashSet<>();
+        if (Objects.nonNull(pageReqVO.getDeptId())) {
+            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+            // 找到所有子部门对象集合
+            ids.add(pageReqVO.getDeptId());
+            pageReqVO.setDeptIds(ids);
+        }
+        // 检查contractName不为空但projectIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getContractName()) && (CollUtil.isEmpty(pageReqVO.getProjectIds()))) {
+            return new ArrayList<>();
+        }
+        // 检查taskName不为空但taskIds为空的情况
+        if (StrUtil.isNotBlank(pageReqVO.getTaskName()) && (CollUtil.isEmpty(pageReqVO.getTaskIds()))) {
+            return new ArrayList<>();
+        }
+        PageResult<IotRyDailyReportDO> page = iotRyDailyReportMapper.selectPage(pageReqVO);
+        List<IotRyDailyReportDO> dailyReports = page.getList();
+
+        // 默认显示所有项目部的汇总数据
+        // 点击项目部 显示 下属队伍的数据
+        // 首先判断点击的部门是属于 公司 还是 队伍 如果没有点击任何部门 默认查询所有项目部数据
+        if (ObjUtil.isEmpty(pageReqVO.getDeptId())) {
+            result = statisticsByProjectDept(pageReqVO, dailyReports, 158L);
+        } else {
+            // 判断点击的组织树中的部门类型 类型(公司级1 项目部2 队伍3)
+            DeptDO selectedDept = deptService.getDept(pageReqVO.getDeptId());
+            if ("1".equals(selectedDept.getType())) {
+                // 以项目部为维度汇总数据
+                result = statisticsByProjectDept(pageReqVO, dailyReports, pageReqVO.getDeptId());
+            } else if ("2".equals(selectedDept.getType())) {
+                // 以队伍为维度汇总数据
+                result = statisticsByProjectDepartment(pageReqVO, dailyReports, pageReqVO.getDeptId());
+            } else if ("3".equals(selectedDept.getType())) {
+                // 显示单个队伍的汇总数据
+                result = statisticsByProjectDepartment(pageReqVO, dailyReports, pageReqVO.getDeptId());
+            } else {
+                // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
+                // 以项目部为维度汇总数据
+                result = statisticsByProjectDept(pageReqVO, dailyReports, pageReqVO.getDeptId());
+            }
+        }
+        // 根据result集合内对象的 sort 属性正序排列 sort 类型为 integer 类型
+        if (CollUtil.isNotEmpty(result)) {
+            result.sort(Comparator.comparing(
+                    IotRyDailyReportStatisticsRespVO::getSort,
+                    Comparator.nullsLast(Comparator.naturalOrder())
+            ));
+        }
+        return result;
+    }
+
+    /**
+     * 按项目部维度统计数据
+     * @param pageReqVO 日报查询对象
+     * @param dailyReports 日报数据列表
+     * @param rootDeptId 根部门ID(如158L为 瑞鹰 根部门,或其他公司级部门ID)
+     * @return 项目部维度统计结果列表  钻井 修井
+     */
+    private List<IotRyDailyReportStatisticsRespVO> statisticsByProjectDept(IotRyDailyReportPageReqVO pageReqVO,
+                                                                           List<IotRyDailyReportDO> dailyReports, Long rootDeptId) {
+        List<IotRyDailyReportStatisticsRespVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // key队伍id/项目部id   value累计进尺
+        Map<Long, BigDecimal> cumulativeFootagePair = new HashMap<>();
+        // key队伍id/项目部id   value累计用电
+        Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value累计油耗
+        Map<Long, BigDecimal> cumulativeFuelConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的施工井数
+        Map<Long, Integer> cumulativeConstructWellsPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的完工井数
+        Map<Long, Integer> cumulativeCompletedWellsPair = new HashMap<>();
+        // key队伍id/项目部id   value生产时间(H)
+        Map<Long, BigDecimal> cumulativeProductTimePair = new HashMap<>();
+        // key队伍id/项目部id   value额定生产时间(H)
+        Map<Long, BigDecimal> cumulativeRatedTimePair = new HashMap<>();
+        // key队伍id/项目部id   value累计运行时效   累计注气量/累计产能
+        Map<Long, BigDecimal> cumulativeTransitTimePair = new HashMap<>();
+
+        // 以项目部为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(rootDeptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            // 筛选出所有项目部
+            if ("2".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                projectDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // key施工队伍id    value施工井数量
+        Map<Long, Integer> totalTasksPair = new HashMap<>();
+        // key施工队伍id    value完工井数量
+        Map<Long, Integer> completedTasksPair = new HashMap<>();
+        // key任务id   value额定生产时间
+        Map<Long, BigDecimal> taskRatedProductionTimePair = new HashMap<>();
+        if ("2".equals(pageReqVO.getProjectClassification())) {
+            // 查询修井 累计施工井数 累计完工井数
+            List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportMapper.countRepairTasksByDept();
+            if (CollUtil.isNotEmpty(repairDeptTasks)) {
+                repairDeptTasks.forEach(task -> {
+                    totalTasksPair.put(task.getDeptId(), task.getTotalTaskCount());
+                    completedTasksPair.put(task.getDeptId(), task.getCompletedTaskCount());
+                });
+
+            }
+            // 计算 运行时效 累计生产时间/累计额定生产时间
+            // 查询日报关联的任务信息
+            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
+            taskReqVO.setTaskIds(convertList(dailyReports, IotRyDailyReportDO::getTaskId));
+            List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(taskReqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
+                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
+                        if (CollUtil.isNotEmpty(taskAttrs)) {
+                            // 找到 额定生产时间 属性 对应的值
+                            taskAttrs.forEach(attr -> {
+                                if ("额定生产时间".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
+                                    taskRatedProductionTimePair.put(task.getId(), new BigDecimal(attr.getActualValue()));
+                                }
+                            });
+                        }
+                    }
+                });
+            }
+        }
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if (ObjUtil.isNotEmpty(report.getDeptId()) && teamProjectIdPair.containsKey(report.getDeptId())) {
+                    Long projectDeptId = teamProjectIdPair.get(report.getDeptId());
+                    if (ObjUtil.isNotEmpty(projectDeptId) && projectDeptPair.containsKey(projectDeptId)) {
+                        // 累计进尺
+                        cumulativeFootagePair.merge(projectDeptId, report.getDailyFootage(), BigDecimal::add);
+                        // 累计用电量
+                        cumulativePowerConsumptionPair.merge(projectDeptId, report.getDailyPowerUsage(), BigDecimal::add);
+                        // 累计油耗
+                        cumulativeFuelConsumptionPair.merge(projectDeptId, report.getDailyFuel(), BigDecimal::add);
+                        // 统计各项目部的 累计施工井数 累计完工井数 取每个井任务的最大值 而不是累加
+                        /* if (totalTasksPair.containsKey(report.getDeptId())) {
+                            Integer tempCount = totalTasksPair.get(report.getDeptId());
+                            cumulativeConstructWellsPair.merge(projectDeptId, tempCount, Integer::sum);
+                        }
+                        if (completedTasksPair.containsKey(report.getDeptId())) {
+                            Integer tempCompleteCount = completedTasksPair.get(report.getDeptId());
+                            cumulativeCompletedWellsPair.merge(projectDeptId, tempCompleteCount, Integer::sum);
+                        } */
+                        // 额定生产时间
+                        if (taskRatedProductionTimePair.containsKey(report.getTaskId())) {
+                            BigDecimal ratedTime = taskRatedProductionTimePair.get(report.getTaskId());
+                            cumulativeRatedTimePair.merge(projectDeptId, ratedTime, BigDecimal::add);
+                        }
+                        // 生产时间
+                        cumulativeProductTimePair.merge(projectDeptId, report.getProductionTime(), BigDecimal::add);
+                    }
+                }
+            });
+            // 筛选每个队伍对应的项目部 设置每个项目部的 累计施工井数 累计完工井数 totalTasksPair   completedTasksPair
+            if (CollUtil.isNotEmpty(totalTasksPair)) {
+                totalTasksPair.forEach((teamDeptId, taskCount) -> {
+                    if (teamProjectIdPair.containsKey(teamDeptId)) {
+                        // 项目部id
+                        Long projectDeptId = teamProjectIdPair.get(teamDeptId);
+                        cumulativeConstructWellsPair.merge(projectDeptId, taskCount, Integer::sum);
+                    }
+                });
+            }
+            if (CollUtil.isNotEmpty(completedTasksPair)) {
+                completedTasksPair.forEach((teamDeptId, taskCount) -> {
+                    if (teamProjectIdPair.containsKey(teamDeptId)) {
+                        // 项目部id
+                        Long projectDeptId = teamProjectIdPair.get(teamDeptId);
+                        cumulativeCompletedWellsPair.merge(projectDeptId, taskCount, Integer::sum);
+                    }
+                });
+            }
+
+            // 计算项目部对应的 运行时效
+            if (CollUtil.isNotEmpty(cumulativeProductTimePair) && CollUtil.isNotEmpty(cumulativeRatedTimePair)) {
+                cumulativeProductTimePair.forEach((projectDeptId, productionTime) -> {
+                    if (cumulativeRatedTimePair.containsKey(projectDeptId)) {
+                        BigDecimal tempRatedTime = cumulativeRatedTimePair.get(projectDeptId);
+                        if (tempRatedTime.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指定项目部的 累计额定生产时间
+                            BigDecimal tempTransitTime = productionTime.divide(tempRatedTime, 4, RoundingMode.HALF_UP);
+                            cumulativeTransitTimePair.put(projectDeptId, tempTransitTime);
+                        } else {
+                            cumulativeTransitTimePair.put(projectDeptId, BigDecimal.ZERO);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 生成返回的数据列表集合
+        projectDeptPair.forEach((deptId, dept) -> {
+            IotRyDailyReportStatisticsRespVO statistics = new IotRyDailyReportStatisticsRespVO();
+            statistics.setProjectDeptId(deptId);
+            statistics.setProjectDeptName(dept.getName());
+            statistics.setSort(dept.getSort());
+            statistics.setType("2");
+            statistics.setCumulativeFootage(cumulativeFootagePair.get(deptId));
+            statistics.setCumulativeConstructWells(cumulativeConstructWellsPair.get(deptId));
+            statistics.setCumulativeCompletedWells(cumulativeCompletedWellsPair.get(deptId));
+            statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(deptId));
+            statistics.setCumulativeFuelConsumption(cumulativeFuelConsumptionPair.get(deptId));
+            statistics.setTransitTime(cumulativeTransitTimePair.get(deptId));
+            result.add(statistics);
+        });
+
+        return result;
+    }
+
+    /**
+     * 按 队伍 维度统计数据
+     * @param pageReqVO 日报数据请求对象
+     * @param dailyReports 日报数据列表
+     * @param deptId 项目部ID 或 队伍id(塔河项目部 HY-A1)
+     * @return 队伍 维度统计结果列表
+     */
+    private List<IotRyDailyReportStatisticsRespVO> statisticsByProjectDepartment(IotRyDailyReportPageReqVO pageReqVO,
+                                                                                 List<IotRyDailyReportDO> dailyReports, Long deptId) {
+        List<IotRyDailyReportStatisticsRespVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key队伍id    value队伍名称
+        Map<Long, DeptDO> teamDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+
+        // key队伍id/项目部id   value累计进尺
+        Map<Long, BigDecimal> cumulativeFootagePair = new HashMap<>();
+        // key队伍id   value累计用电
+        Map<Long, BigDecimal> cumulativePowerConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value累计油耗
+        Map<Long, BigDecimal> cumulativeFuelConsumptionPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的施工井数
+        Map<Long, Integer> cumulativeConstructWellsPair = new HashMap<>();
+        // key队伍id/项目部id   value对应项目部的完工井数
+        Map<Long, Integer> cumulativeCompletedWellsPair = new HashMap<>();
+        // key队伍id/项目部id   value生产时间(H)
+        Map<Long, BigDecimal> cumulativeProductTimePair = new HashMap<>();
+        // key队伍id/项目部id   value额定生产时间(H)
+        Map<Long, BigDecimal> cumulativeRatedTimePair = new HashMap<>();
+        // key队伍id   value累计运行时效   累计注气量/累计产能
+        Map<Long, BigDecimal> cumulativeTransitTimePair = new HashMap<>();
+
+        // 以 队伍 为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+        DeptListReqVO reqVO = new DeptListReqVO();
+        allRhChildDeptIds.add(deptId);  // 查询某支队伍
+        reqVO.setDeptIds(allRhChildDeptIds);
+        List<DeptDO> depts = deptService.getDeptList(reqVO);
+
+        // 构建项目部映射和父子部门关系
+        depts.forEach(dept -> {
+            if ("3".equals(dept.getType())) {
+                projectDeptIds.add(dept.getId());
+                teamDeptPair.put(dept.getId(), dept);
+            }
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+        });
+
+        // key施工队伍id    value施工井数量
+        Map<Long, Integer> totalTasksPair = new HashMap<>();
+        // key施工队伍id    value完工井数量
+        Map<Long, Integer> completedTasksPair = new HashMap<>();
+        // key任务id   value额定生产时间
+        Map<Long, BigDecimal> taskRatedProductionTimePair = new HashMap<>();
+        if ("2".equals(pageReqVO.getProjectClassification())) {
+            // 查询修井 累计施工井数 累计完工井数
+            List<IotRyDailyReportTaskCountVO> repairDeptTasks = iotRyDailyReportMapper.countRepairTasksByDept();
+            if (CollUtil.isNotEmpty(repairDeptTasks)) {
+                repairDeptTasks.forEach(task -> {
+                    totalTasksPair.put(task.getDeptId(), task.getTotalTaskCount());
+                    completedTasksPair.put(task.getDeptId(), task.getCompletedTaskCount());
+                });
+
+            }
+            // 计算 运行时效 累计生产时间/累计额定生产时间
+            // 查询日报关联的任务信息
+            IotProjectTaskPageReqVO taskReqVO = new IotProjectTaskPageReqVO();
+            taskReqVO.setTaskIds(convertList(dailyReports, IotRyDailyReportDO::getTaskId));
+            List<IotProjectTaskDO> tasks = iotProjectTaskMapper.selectList(taskReqVO);
+            if (CollUtil.isNotEmpty(tasks)) {
+                tasks.forEach(task -> {
+                    if (CollUtil.isNotEmpty(task.getExtProperty())) {
+                        List<IotTaskAttrModelProperty> taskAttrs = task.getExtProperty();
+                        if (CollUtil.isNotEmpty(taskAttrs)) {
+                            // 找到 额定生产时间 属性 对应的值
+                            taskAttrs.forEach(attr -> {
+                                if ("额定生产时间".equals(attr.getName()) && StrUtil.isNotBlank(attr.getActualValue())) {
+                                    taskRatedProductionTimePair.put(task.getId(), new BigDecimal(attr.getActualValue()));
+                                }
+                            });
+                        }
+                    }
+                });
+            }
+        }
+
+        // 累计计算各项指标
+        if (CollUtil.isNotEmpty(dailyReports)) {
+            dailyReports.forEach(report -> {
+                if (ObjUtil.isNotEmpty(report.getDeptId())) {
+                    // 累计进尺
+                    cumulativeFootagePair.merge(report.getDeptId(), report.getDailyFootage(), BigDecimal::add);
+                    // 累计油耗
+                    cumulativeFuelConsumptionPair.merge(report.getDeptId(), report.getDailyFuel(), BigDecimal::add);
+                    // 累计用电量
+                    cumulativePowerConsumptionPair.merge(report.getDeptId(), report.getDailyPowerUsage(), BigDecimal::add);
+                    // 统计各项目部的 累计施工井数 累计完工井数
+                    /* if (totalTasksPair.containsKey(report.getDeptId())) {
+                        Integer tempCount = totalTasksPair.get(report.getDeptId());
+                        cumulativeConstructWellsPair.put(report.getDeptId(), tempCount);
+                    }
+                    if (completedTasksPair.containsKey(report.getDeptId())) {
+                        Integer tempCompleteCount = completedTasksPair.get(report.getDeptId());
+                        cumulativeCompletedWellsPair.put(report.getDeptId(), tempCompleteCount);
+                    } */
+                    // 额定生产时间
+                    if (taskRatedProductionTimePair.containsKey(report.getTaskId())) {
+                        BigDecimal ratedTime = taskRatedProductionTimePair.get(report.getTaskId());
+                        cumulativeRatedTimePair.merge(report.getDeptId(), ratedTime, BigDecimal::add);
+                    }
+                    // 生产时间
+                    cumulativeProductTimePair.merge(report.getDeptId(), report.getProductionTime(), BigDecimal::add);
+                }
+            });
+            // 根据 累计注气量 累计产能 计算指定队伍下的平均产能
+            if (CollUtil.isNotEmpty(cumulativeProductTimePair) && CollUtil.isNotEmpty(cumulativeRatedTimePair)) {
+                cumulativeProductTimePair.forEach((teamDeptId, productionTime) -> {
+                    if (cumulativeRatedTimePair.containsKey(teamDeptId)) {
+                        BigDecimal tempRatedTime = cumulativeRatedTimePair.get(teamDeptId);
+                        if (tempRatedTime.compareTo(BigDecimal.ZERO) > 0) {
+                            // 指定队伍的累计运行时效
+                            BigDecimal tempTransitTime = productionTime.divide(tempRatedTime, 4, RoundingMode.HALF_UP);
+                            cumulativeTransitTimePair.put(teamDeptId, tempTransitTime);
+                        }
+                    }
+                });
+            }
+        }
+
+        // 生成返回的数据列表集合
+        teamDeptPair.forEach((teamDeptId, dept) -> {
+            IotRyDailyReportStatisticsRespVO statistics = new IotRyDailyReportStatisticsRespVO();
+            statistics.setTeamId(teamDeptId);
+            statistics.setTeamName(dept.getName());
+            statistics.setSort(dept.getSort());
+            statistics.setType("3");
+            statistics.setCumulativeFootage(cumulativeFootagePair.get(teamDeptId));
+            statistics.setCumulativeConstructWells(totalTasksPair.get(teamDeptId));
+            statistics.setCumulativeCompletedWells(completedTasksPair.get(teamDeptId));
+            statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(teamDeptId));
+            statistics.setCumulativeFuelConsumption(cumulativeFuelConsumptionPair.get(teamDeptId));
+            statistics.setTransitTime(cumulativeTransitTimePair.get(teamDeptId));
+            result.add(statistics);
+        });
+
+        return result;
+    }
+
 }

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

@@ -194,4 +194,45 @@
             CAST( REGEXP_REPLACE ( d.`name`, '[^0-9]+', '' ) AS UNSIGNED ) ASC;
     </select>
 
+    <!-- 瑞恒日报汇总统计 -->
+    <select id="rhReportStatistics" resultMap="BaseResultMap"
+            parameterType="cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.IotRhDailyReportPageReqVO">
+        SELECT
+        *
+        FROM
+        rq_iot_rh_daily_report rdr
+        INNER JOIN system_dept d ON d.id = rdr.dept_id
+        WHERE
+        rdr.deleted = 0
+        AND rdr.dept_id IS NOT NULL
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND rdr.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="projectIds != null and projectIds.size &gt; 0">
+            AND rdr.project_id IN
+            <foreach collection="projectIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="taskIds != null and taskIds.size &gt; 0">
+            AND rdr.task_id IN
+            <foreach collection="taskIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="reqVO.createTime != null and reqVO.createTime.length > 0">
+            <!-- 处理“开始时间”(数组第1位,如 createTime[0] = 2024-01-01 00:00:00) -->
+            <if test="reqVO.createTime[0] != null">
+                AND rdr.create_time &gt;= #{reqVO.createTime[0]}
+            </if>
+            <!-- 处理“结束时间”(数组第2位,如 createTime[1] = 2024-01-31 23:59:59) -->
+            <if test="reqVO.createTime.length > 1 and reqVO.createTime[1] != null">
+                AND rdr.create_time &lt;= #{reqVO.createTime[1]}
+            </if>
+        </if>
+    </select>
+
 </mapper>