Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

Zimo 2 päivää sitten
vanhempi
commit
1df9946b64

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

@@ -22,12 +22,15 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotrddailyreport.vo.IotRdDai
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrhdailyreport.vo.*;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotrydailyreport.vo.IotRyDailyReportStatisticsVO;
+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.iotdailyreportfuel.IotDailyReportFuelDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotdailyreportfuel.IotDailyReportFuelDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojectinfo.IotProjectInfoDO;
 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.iotprojecttask.IotProjectTaskDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotprojecttaskattrs.IotTaskAttrModelProperty;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrddailyreport.IotRdDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotrhdailyreport.IotRhDailyReportDO;
+import cn.iocoder.yudao.module.pms.dal.mysql.IotDeviceMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
 import cn.iocoder.yudao.module.pms.dal.mysql.iotrhdailyreport.IotRhDailyReportMapper;
 import cn.iocoder.yudao.module.pms.service.iotdailyreportfuel.IotDailyReportFuelService;
 import cn.iocoder.yudao.module.pms.service.iotdailyreportfuel.IotDailyReportFuelService;
 import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
 import cn.iocoder.yudao.module.pms.service.iotprojectinfo.IotProjectInfoService;
@@ -42,6 +45,7 @@ import cn.iocoder.yudao.module.system.service.dict.DictDataService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
@@ -54,6 +58,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
 import java.text.DecimalFormat;
 import java.text.DecimalFormat;
 import java.time.LocalDateTime;
 import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Stream;
 import java.util.stream.Stream;
@@ -88,6 +93,8 @@ public class IotRhDailyReportController {
     private DictDataService dictDataService;
     private DictDataService dictDataService;
     @Resource
     @Resource
     private IotRhDailyReportMapper iotRhDailyReportMapper;
     private IotRhDailyReportMapper iotRhDailyReportMapper;
+    @Autowired
+    private IotDeviceMapper iotDeviceMapper;
 
 
     @PostMapping("/create")
     @PostMapping("/create")
     @Operation(summary = "创建瑞恒日报")
     @Operation(summary = "创建瑞恒日报")
@@ -465,14 +472,66 @@ public class IotRhDailyReportController {
                 pageReqVO.setTaskIds(taskIds);
                 pageReqVO.setTaskIds(taskIds);
             }
             }
         }
         }
+        // 统计设备利用率
+        Long deptId = pageReqVO.getDeptId();
+        // 项目部名称集合
+        Set<String> projectDeptNames = new HashSet<>();
+        // 项目部id集合
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key项目部id   value项目部名称
+        Map<Long, String> projectPair = new HashMap<>();
+        // key施工队伍id   value状态为LY的项目部id
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+        if (ObjUtil.isNotEmpty(deptId)) {
+            // 查询指定部门下所有子部门
+            Set<Long> childDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+            Map<Long, DeptDO> allDeptPair = deptService.getDeptMap(childDeptIds);
+            // 查询 瑞恒 所有设备 只统计包含 施工 状态设备的队伍
+            IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+            deviceReqVO.setDeptIds(new ArrayList<>(childDeptIds));
+            List<IotDeviceDO> allRhDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
+            // 包含设备的部门id集合
+            Set<Long> haveDeviceDeptIds = new HashSet<>();
+            if (CollUtil.isNotEmpty(allRhDevices)) {
+                // 筛选出包含设备的队伍部门集合
+                allRhDevices.forEach(device -> {
+                    haveDeviceDeptIds.add(device.getDeptId());
+                });
+            }
+            if (CollUtil.isNotEmpty(allDeptPair)) {
+                allDeptPair.forEach((departmentId, dept) -> {
+                    // 项目部 只统计 email = LY 的项目部的 设备利用率
+                    if ("2".equals(dept.getType()) && "LY".equals(dept.getEmail())) {
+                        projectDeptIds.add(departmentId);
+                        projectDeptNames.add(dept.getName());
+                        projectPair.put(departmentId, dept.getName());
+                    }
+                });
+                // 遍历所有部门 只筛选出有设备的队伍
+                allDeptPair.forEach((departmentId, dept) -> {
+                    // 不需要找出每个项目部下的队伍 根据筛选的日期和部门 统计数据
+                    if (projectPair.containsKey(dept.getParentId())) {
+                        // 获得队伍的上级项目部(LY状态的项目部)
+                        teamProjectIdPair.put(dept.getId(), dept.getParentId());
+                    }
+                });
+            }
+        }
+
         List<IotRhDailyReportDO> list = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO).getList();
         List<IotRhDailyReportDO> list = iotRhDailyReportService.getIotRhDailyReportPage(pageReqVO).getList();
         Map<String, BigDecimal> result = new HashMap<>();
         Map<String, BigDecimal> result = new HashMap<>();
         BigDecimal totalGasInjection = BigDecimal.ZERO;
         BigDecimal totalGasInjection = BigDecimal.ZERO;
         BigDecimal totalWaterInjection = BigDecimal.ZERO;
         BigDecimal totalWaterInjection = BigDecimal.ZERO;
         BigDecimal totalPowerConsumption = BigDecimal.ZERO;
         BigDecimal totalPowerConsumption = BigDecimal.ZERO;
         BigDecimal totalFuelConsumption = BigDecimal.ZERO;
         BigDecimal totalFuelConsumption = BigDecimal.ZERO;
+        double rate = 0.0;
+        Integer reportCount = 0;
         if (CollUtil.isNotEmpty(list)) {
         if (CollUtil.isNotEmpty(list)) {
             for (IotRhDailyReportDO report : list) {
             for (IotRhDailyReportDO report : list) {
+                // 统计出状态为 LY 的项目部下的施工队伍的日报数量
+                if (teamProjectIdPair.containsKey(report.getDeptId())) {
+                    ++reportCount;
+                }
                 BigDecimal dailyGasInjection = report.getDailyGasInjection();
                 BigDecimal dailyGasInjection = report.getDailyGasInjection();
                 BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
                 BigDecimal dailyWaterInjection = report.getDailyWaterInjection();
                 BigDecimal powerConsumption = report.getDailyPowerUsage();
                 BigDecimal powerConsumption = report.getDailyPowerUsage();
@@ -490,11 +549,33 @@ public class IotRhDailyReportController {
                     totalFuelConsumption = totalFuelConsumption.add(oilConsumption);
                     totalFuelConsumption = totalFuelConsumption.add(oilConsumption);
                 }
                 }
             }
             }
+            // 计算筛选时间范围内 指定部门的设备利用率
+            long daysCount = 0l;
+            if (ObjUtil.isNotEmpty(pageReqVO.getCreateTime()) && pageReqVO.getCreateTime().length >= 2) {
+                LocalDateTime start = pageReqVO.getCreateTime()[0];
+                LocalDateTime end = pageReqVO.getCreateTime()[1];
+                if (ObjUtil.isNotEmpty(start) && ObjUtil.isNotEmpty(end) && !end.isBefore(start)) {
+                    // 使用ChronoUnit.DAYS.between计算天数差,并+1包含首尾两天
+                    daysCount = ChronoUnit.DAYS.between(
+                            start.toLocalDate(),
+                            end.toLocalDate()
+                    ) + 1;
+                }
+            }
+            // 所有LY状态的项目部包含的队伍数量>0 并且 指定时间区间天数大于0
+            if (daysCount > 0 && teamProjectIdPair.size() > 0) {
+                // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum*daysCount)
+                // 计算设备利用率(处理除数为0的情况)
+                rate = new BigDecimal((double) reportCount / (teamProjectIdPair.size() * daysCount))
+                        .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                        .doubleValue();
+            }
             // 汇总 指定搜索时间段内的 累计注气量 累计注水量 累计用电量 累计油耗
             // 汇总 指定搜索时间段内的 累计注气量 累计注水量 累计用电量 累计油耗
             result.put("totalGasInjection", totalGasInjection);
             result.put("totalGasInjection", totalGasInjection);
             result.put("totalWaterInjection", totalWaterInjection);
             result.put("totalWaterInjection", totalWaterInjection);
             result.put("totalPowerConsumption", totalPowerConsumption);
             result.put("totalPowerConsumption", totalPowerConsumption);
             result.put("totalFuelConsumption", totalFuelConsumption);
             result.put("totalFuelConsumption", totalFuelConsumption);
+            result.put("utilizationRate", BigDecimal.valueOf(rate));
         }
         }
         return success(result);
         return success(result);
     }
     }

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

@@ -72,4 +72,7 @@ public class IotRhDailyReportStatisticsRespVO {
     private Integer zbTeamCount = 0;
     private Integer zbTeamCount = 0;
     @Schema(description = "驻地待命 队伍数量")
     @Schema(description = "驻地待命 队伍数量")
     private Integer zddmTeamCount = 0;
     private Integer zddmTeamCount = 0;
+
+    @Schema(description = "设备利用率")
+    private BigDecimal utilizationRate;
 }
 }

+ 3 - 3
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/stat/IotStaticController.java

@@ -1680,7 +1680,8 @@ public class IotStaticController {
         }
         }
         if (CollUtil.isNotEmpty(allDeptPair)) {
         if (CollUtil.isNotEmpty(allDeptPair)) {
             allDeptPair.forEach((deptId, dept) -> {
             allDeptPair.forEach((deptId, dept) -> {
-                if (dept.getName().contains("项目部") ) {
+                // 项目部
+                if ("2".equals(dept.getType())) {
                     projectDeptIds.add(deptId);
                     projectDeptIds.add(deptId);
                     projectDeptNames.add(dept.getName());
                     projectDeptNames.add(dept.getName());
                     projectPair.put(deptId, dept.getName());
                     projectPair.put(deptId, dept.getName());
@@ -1738,7 +1739,6 @@ public class IotStaticController {
                         }
                         }
                     });
                     });
                 }
                 }
-
             });
             });
             // 计算指定时间区间内包含的天数
             // 计算指定时间区间内包含的天数
             long daysCount;
             long daysCount;
@@ -1791,7 +1791,7 @@ public class IotStaticController {
                             if (currentTeamNum > 0 && daysCount > 0) {
                             if (currentTeamNum > 0 && daysCount > 0) {
                                 rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                 rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
                                         .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
                                         .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
-                                        .doubleValue();;
+                                        .doubleValue();
                             }
                             }
                         }
                         }
                         rateVo.setUtilizationRate(rate); // 存储计算结果
                         rateVo.setUtilizationRate(rate); // 存储计算结果

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

@@ -944,10 +944,10 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 result = statisticsByProjectDept(dailyReports, pageReqVO.getDeptId(), pageReqVO);
                 result = statisticsByProjectDept(dailyReports, pageReqVO.getDeptId(), pageReqVO);
             } else if ("2".equals(selectedDept.getType())) {
             } else if ("2".equals(selectedDept.getType())) {
                 // 以队伍为维度汇总数据
                 // 以队伍为维度汇总数据
-                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO);
             } else if ("3".equals(selectedDept.getType())) {
             } else if ("3".equals(selectedDept.getType())) {
                 // 显示单个队伍的汇总数据
                 // 显示单个队伍的汇总数据
-                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO);
             } else {
             } else {
                 // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
                 // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
                 // 以项目部为维度汇总数据
                 // 以项目部为维度汇总数据
@@ -1006,6 +1006,8 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         Map<Long, List<BigDecimal>> cumulativeNonProductionTimePair = new HashMap<>();
         Map<Long, List<BigDecimal>> cumulativeNonProductionTimePair = new HashMap<>();
         // key队伍id/项目部id   value非生产时效
         // key队伍id/项目部id   value非生产时效
         Map<Long, BigDecimal> cumulativeNonProductionPair = new HashMap<>();
         Map<Long, BigDecimal> cumulativeNonProductionPair = new HashMap<>();
+        // key队伍id/项目部id   value设备利用率
+        Map<Long, BigDecimal> deviceUtilizationPair = new HashMap<>();
 
 
         // 以项目部为维度统计数据
         // 以项目部为维度统计数据
         // 找到所有项目部与队伍的对应关系
         // 找到所有项目部与队伍的对应关系
@@ -1015,11 +1017,23 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         reqVO.setDeptIds(allRhChildDeptIds);
         reqVO.setDeptIds(allRhChildDeptIds);
         List<DeptDO> depts = deptService.getDeptList(reqVO);
         List<DeptDO> depts = deptService.getDeptList(reqVO);
 
 
+        // 包含设备的部门id集合
+        Set<Long> haveDeviceDeptIds = new HashSet<>();
+        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+        deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
+        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
+        if (CollUtil.isNotEmpty(devices)) {
+            // 筛选出包含设备的队伍部门集合
+            devices.forEach(device -> {
+                haveDeviceDeptIds.add(device.getDeptId());
+            });
+        }
+
         // 构建项目部映射和父子部门关系
         // 构建项目部映射和父子部门关系
         depts.forEach(dept -> {
         depts.forEach(dept -> {
             // 暂时过滤掉 欧洲项目部 克拉玛依项目部
             // 暂时过滤掉 欧洲项目部 克拉玛依项目部
-            if ("2".equals(dept.getType()) && dept.getId() != 352 && dept.getId() != 166) {
-                // 项目部
+            if ("2".equals(dept.getType()) && "LY".equals(dept.getEmail())) {
+                // 状态为LY的项目部 才统计设备利用率
                 projectDeptIds.add(dept.getId());
                 projectDeptIds.add(dept.getId());
                 projectDeptPair.put(dept.getId(), dept);
                 projectDeptPair.put(dept.getId(), dept);
             }
             }
@@ -1029,22 +1043,51 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             }
             }
             teamProjectIdPair.put(dept.getId(), dept.getParentId());
             teamProjectIdPair.put(dept.getId(), dept.getParentId());
         });
         });
+        // key项目部id   value项目部包含的队伍id集合
+        Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
+        // 筛选项目部下包含的队伍
+        depts.forEach(dept -> {
+            Long deptId = dept.getId();
+            Long parentId = dept.getParentId();
+            if (projectDeptIds.contains(parentId)) {
+                // 获得当前部门的上级项目部
+                projectDeptIds.forEach(projectDeptId -> {
+                    if (projectDeptId.equals(parentId) && haveDeviceDeptIds.contains(deptId)) {
+                        if (projectTeamPair.containsKey(projectDeptId)) {
+                            Set<Long> tempTeamIds = projectTeamPair.get(projectDeptId);
+                            tempTeamIds.add(deptId);
+                            projectTeamPair.put(projectDeptId, tempTeamIds);
+                        } else {
+                            Set<Long> tempTeamIds = new HashSet<>();
+                            tempTeamIds.add(deptId);
+                            projectTeamPair.put(projectDeptId, tempTeamIds);
+                        }
+                    }
+                });
+            }
+        });
 
 
         LocalDateTime[] createTime = pageReqVO.getCreateTime();
         LocalDateTime[] createTime = pageReqVO.getCreateTime();
+        List<Long> daysCounts = new ArrayList<>();
         // 如果 createTime 包含的时间是 1天则查询 这1天时间内的 队伍总数 施工队伍数量 施工准备队伍数量 驻地待命队伍数量
         // 如果 createTime 包含的时间是 1天则查询 这1天时间内的 队伍总数 施工队伍数量 施工准备队伍数量 驻地待命队伍数量
         if (ObjUtil.isNotEmpty(createTime)) {
         if (ObjUtil.isNotEmpty(createTime)) {
             LocalDateTime startTime = createTime[0];
             LocalDateTime startTime = createTime[0];
             LocalDateTime endTime = createTime[1];
             LocalDateTime endTime = createTime[1];
-            if (ObjUtil.isNotEmpty(startTime) && ObjUtil.isNotEmpty(endTime)) {
+            if (ObjUtil.isNotEmpty(startTime) && ObjUtil.isNotEmpty(endTime) && !endTime.isBefore(startTime)) {
+                // 查询时间区间包含的天数
+                // 使用ChronoUnit.DAYS.between计算天数差,并+1包含首尾两天
+                long daysCount = ChronoUnit.DAYS.between(
+                        startTime.toLocalDate(),
+                        endTime.toLocalDate()
+                ) + 1;
+                daysCounts.add(daysCount);
+
                 LocalDate startLocalDate = startTime.toLocalDate();
                 LocalDate startLocalDate = startTime.toLocalDate();
                 LocalDate endLocalDate = endTime.toLocalDate();
                 LocalDate endLocalDate = endTime.toLocalDate();
                 if (startLocalDate.isEqual(endLocalDate)) {
                 if (startLocalDate.isEqual(endLocalDate)) {
                     // 查询日期区间是 同一天
                     // 查询日期区间是 同一天
                     // 设置每个项目部下的队伍数量 只筛选 包含设备的队伍数量
                     // 设置每个项目部下的队伍数量 只筛选 包含设备的队伍数量
                     Set<Long> deviceDeptIds = new HashSet<>();
                     Set<Long> deviceDeptIds = new HashSet<>();
-                    IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
-                    deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
-                    List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
                     if (CollUtil.isNotEmpty(devices)) {
                     if (CollUtil.isNotEmpty(devices)) {
                         devices.forEach(device -> {
                         devices.forEach(device -> {
                             deviceDeptIds.add(device.getDeptId());
                             deviceDeptIds.add(device.getDeptId());
@@ -1101,6 +1144,9 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             }
             }
         }
         }
 
 
+        // 统计各项目部的设备利用率
+        // key项目部id     value项目部包含的队伍指定时间区域内日报数量
+        Map<Long, Integer> projectReportPair = new HashMap<>();
         // 查询指定部门下相关设备的产能
         // 查询指定部门下相关设备的产能
         // key队伍id   value队伍下相关设备产能
         // key队伍id   value队伍下相关设备产能
         Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
         Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
@@ -1108,6 +1154,21 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         // 累计计算各项指标
         // 累计计算各项指标
         if (CollUtil.isNotEmpty(dailyReports)) {
         if (CollUtil.isNotEmpty(dailyReports)) {
             dailyReports.forEach(report -> {
             dailyReports.forEach(report -> {
+                // 统计各项目部的日报数量
+                if (CollUtil.isNotEmpty(projectTeamPair)) {
+                    projectTeamPair.forEach((projectDeptId, teamDeptIds) -> {
+                        if (teamDeptIds.contains(report.getDeptId())) {
+                            // 项目部日报数量
+                            if (projectReportPair.containsKey(projectDeptId)) {
+                                Integer tempCount = projectReportPair.get(projectDeptId);
+                                projectReportPair.put(projectDeptId, ++tempCount);
+                            } else {
+                                projectReportPair.put(projectDeptId, 1);
+                            }
+                        }
+                    });
+                }
+
                 if (ObjUtil.isNotEmpty(report.getDeptId()) && teamProjectIdPair.containsKey(report.getDeptId())) {
                 if (ObjUtil.isNotEmpty(report.getDeptId()) && teamProjectIdPair.containsKey(report.getDeptId())) {
                     Long projectDeptId = teamProjectIdPair.get(report.getDeptId());
                     Long projectDeptId = teamProjectIdPair.get(report.getDeptId());
                     if (ObjUtil.isNotEmpty(projectDeptId) && projectDeptPair.containsKey(projectDeptId)) {
                     if (ObjUtil.isNotEmpty(projectDeptId) && projectDeptPair.containsKey(projectDeptId)) {
@@ -1156,6 +1217,26 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             }
             }
         }
         }
 
 
+        // 计算各项目部的平均设备利用率
+        if (CollUtil.isNotEmpty(projectTeamPair)) {
+            projectTeamPair.forEach((projectDeptId, resultTeamIds) -> {
+                double rate = 0.0;
+                Integer currentTeamNum = resultTeamIds.size();
+                if (projectReportPair.containsKey(projectDeptId)) {
+                    Integer reportCount = projectReportPair.getOrDefault(projectDeptId, 0);
+                    // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum * daysCount)
+                    // 计算设备利用率(处理除数为0的情况)
+                    if (currentTeamNum > 0 && CollUtil.isNotEmpty(daysCounts)) {
+                        long daysCount = daysCounts.get(0);
+                        rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
+                                .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                                .doubleValue();
+                        deviceUtilizationPair.put(projectDeptId, BigDecimal.valueOf(rate));
+                    }
+                }
+            });
+        }
+
         if (CollUtil.isNotEmpty(cumulativeNonProductionTimePair)) {
         if (CollUtil.isNotEmpty(cumulativeNonProductionTimePair)) {
             // 计算各项目部的平均时效
             // 计算各项目部的平均时效
             cumulativeNonProductionTimePair.forEach((projectDeptId, nonProductTimes) -> {
             cumulativeNonProductionTimePair.forEach((projectDeptId, nonProductTimes) -> {
@@ -1176,6 +1257,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             statistics.setProjectDeptName(dept.getName());
             statistics.setProjectDeptName(dept.getName());
             statistics.setSort(dept.getSort());
             statistics.setSort(dept.getSort());
             statistics.setType("2");
             statistics.setType("2");
+            statistics.setUtilizationRate(deviceUtilizationPair.get(deptId));
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(deptId));
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(deptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(deptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(deptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(deptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(deptId));
@@ -1323,10 +1405,11 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
     /**
     /**
      * 按 队伍 维度统计数据
      * 按 队伍 维度统计数据
      * @param dailyReports 日报数据列表
      * @param dailyReports 日报数据列表
-     * @param deptId 项目部ID 或 队伍id(塔河项目部 HY-A1)
+     * @param pageReqVO.deptId 项目部ID 或 队伍id(塔河项目部 HY-A1)
      * @return 队伍 维度统计结果列表
      * @return 队伍 维度统计结果列表
      */
      */
-    private List<IotRhDailyReportStatisticsRespVO> statisticsByProjectDepartment(List<IotRhDailyReportDO> dailyReports, Long deptId) {
+    private List<IotRhDailyReportStatisticsRespVO> statisticsByProjectDepartment(List<IotRhDailyReportDO> dailyReports,
+                                                                                 IotRhDailyReportPageReqVO pageReqVO) {
         List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
         List<IotRhDailyReportStatisticsRespVO> result = new ArrayList<>();
 
 
         Set<Long> projectDeptIds = new HashSet<>();
         Set<Long> projectDeptIds = new HashSet<>();
@@ -1353,33 +1436,83 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         Map<Long, List<BigDecimal>> cumulativeNonProductionTimePair = new HashMap<>();
         Map<Long, List<BigDecimal>> cumulativeNonProductionTimePair = new HashMap<>();
         // key队伍id/项目部id   value非生产时效
         // key队伍id/项目部id   value非生产时效
         Map<Long, BigDecimal> cumulativeNonProductionPair = new HashMap<>();
         Map<Long, BigDecimal> cumulativeNonProductionPair = new HashMap<>();
+        // key队伍id/项目部id   value设备利用率
+        Map<Long, BigDecimal> deviceUtilizationPair = new HashMap<>();
 
 
         // 以 队伍 为维度统计数据
         // 以 队伍 为维度统计数据
         // 找到所有项目部与队伍的对应关系
         // 找到所有项目部与队伍的对应关系
         // 查询指定根部门下的所有子部门
         // 查询指定根部门下的所有子部门
-        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
         DeptListReqVO reqVO = new DeptListReqVO();
         DeptListReqVO reqVO = new DeptListReqVO();
-        allRhChildDeptIds.add(deptId);  // 查询某支队伍
+        allRhChildDeptIds.add(pageReqVO.getDeptId());  // 查询某支队伍
         reqVO.setDeptIds(allRhChildDeptIds);
         reqVO.setDeptIds(allRhChildDeptIds);
         List<DeptDO> depts = deptService.getDeptList(reqVO);
         List<DeptDO> depts = deptService.getDeptList(reqVO);
 
 
+        // 筛选出状态为 LY 的项目部
+        depts.forEach(dept -> {
+            // 暂时过滤掉 欧洲项目部 克拉玛依项目部
+            if ("2".equals(dept.getType()) && "LY".equals(dept.getEmail())) {
+                // 状态为LY的项目部 才统计设备利用率
+                projectDeptIds.add(dept.getId());
+                projectDeptPair.put(dept.getId(), dept);
+            }
+        });
+
         // 构建项目部映射和父子部门关系
         // 构建项目部映射和父子部门关系
         depts.forEach(dept -> {
         depts.forEach(dept -> {
             if ("3".equals(dept.getType())) {
             if ("3".equals(dept.getType())) {
-                projectDeptIds.add(dept.getId());
                 teamDeptPair.put(dept.getId(), dept);
                 teamDeptPair.put(dept.getId(), dept);
             }
             }
             teamProjectIdPair.put(dept.getId(), dept.getParentId());
             teamProjectIdPair.put(dept.getId(), dept.getParentId());
         });
         });
 
 
+        // 包含设备的部门id集合
+        Set<Long> haveDeviceDeptIds = new HashSet<>();
+        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+        deviceReqVO.setDeptIds(new ArrayList<>(allRhChildDeptIds));
+        List<IotDeviceDO> devices = iotDeviceMapper.selectListAlone(deviceReqVO);
+        if (CollUtil.isNotEmpty(devices)) {
+            // 筛选出包含设备的队伍部门集合
+            devices.forEach(device -> {
+                haveDeviceDeptIds.add(device.getDeptId());
+            });
+        }
+
+        LocalDateTime[] createTime = pageReqVO.getCreateTime();
+        List<Long> daysCounts = new ArrayList<>();
+        // 如果 createTime 包含的时间是 1天则查询 这1天时间内的 队伍总数 施工队伍数量 施工准备队伍数量 驻地待命队伍数量
+        if (ObjUtil.isNotEmpty(createTime)) {
+            LocalDateTime startTime = createTime[0];
+            LocalDateTime endTime = createTime[1];
+            if (ObjUtil.isNotEmpty(startTime) && ObjUtil.isNotEmpty(endTime) && !endTime.isBefore(startTime)) {
+                // 查询时间区间包含的天数
+                // 使用ChronoUnit.DAYS.between计算天数差,并+1包含首尾两天
+                long daysCount = ChronoUnit.DAYS.between(
+                        startTime.toLocalDate(),
+                        endTime.toLocalDate()
+                ) + 1;
+                daysCounts.add(daysCount);
+            }
+        }
+
         // 查询指定部门下相关设备的产能
         // 查询指定部门下相关设备的产能
         // key队伍id   value队伍下相关设备产能
         // key队伍id   value队伍下相关设备产能
         Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
         Map<Long, BigDecimal> teamCapacityPair = queryCapacities(new ArrayList<>(allRhChildDeptIds));
-
+        // 统计各队伍的设备利用率
+        // key队伍id     value队伍指定时间区域内日报数量
+        Map<Long, Integer> teamReportPair = new HashMap<>();
         // 累计计算各项指标
         // 累计计算各项指标
         if (CollUtil.isNotEmpty(dailyReports)) {
         if (CollUtil.isNotEmpty(dailyReports)) {
             dailyReports.forEach(report -> {
             dailyReports.forEach(report -> {
                 if (ObjUtil.isNotEmpty(report.getDeptId())) {
                 if (ObjUtil.isNotEmpty(report.getDeptId())) {
+                    // 统计各个队伍的日报数量
+                    if (teamReportPair.containsKey(report.getDeptId())) {
+                        Integer tempCount = teamReportPair.get(report.getDeptId());
+                        teamReportPair.put(report.getDeptId(), ++tempCount);
+                    } else {
+                        teamReportPair.put(report.getDeptId(), 1);
+                    }
+
                     // 累计注气量
                     // 累计注气量
                     cumulativeGasInjectionPair.merge(report.getDeptId(), report.getDailyGasInjection(), BigDecimal::add);
                     cumulativeGasInjectionPair.merge(report.getDeptId(), report.getDailyGasInjection(), BigDecimal::add);
                     // 累计注水量
                     // 累计注水量
@@ -1432,6 +1565,23 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                     cumulativeNonProductionPair.put(teamId, nonProductionEfficiency);
                     cumulativeNonProductionPair.put(teamId, nonProductionEfficiency);
                 });
                 });
             }
             }
+
+            // 计算各队伍的平均设备利用率
+            if (CollUtil.isNotEmpty(teamReportPair)) {
+                teamReportPair.forEach((teamDeptId, reportCount) -> {
+                    double rate = 0.0;
+                    Integer currentTeamNum = 1;
+                        // 当前项目部 设备利用率 公式 reportCount/(currentTeamNum * daysCount)
+                        // 计算设备利用率(处理除数为0的情况)
+                        if (currentTeamNum > 0 && CollUtil.isNotEmpty(daysCounts)) {
+                            long daysCount = daysCounts.get(0);
+                            rate = new BigDecimal((double) reportCount / (currentTeamNum * daysCount))
+                                    .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                                    .doubleValue();
+                            deviceUtilizationPair.put(teamDeptId, BigDecimal.valueOf(rate));
+                        }
+                });
+            }
         }
         }
 
 
         // 生成返回的数据列表集合
         // 生成返回的数据列表集合
@@ -1441,6 +1591,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             statistics.setTeamName(dept.getName());
             statistics.setTeamName(dept.getName());
             statistics.setSort(dept.getSort());
             statistics.setSort(dept.getSort());
             statistics.setType("3");
             statistics.setType("3");
+            statistics.setUtilizationRate(deviceUtilizationPair.get(teamDeptId));
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(teamDeptId));
             statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.get(teamDeptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(teamDeptId));
             statistics.setCumulativeWaterInjection(cumulativeWaterInjectionPair.get(teamDeptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(teamDeptId));
             statistics.setCumulativePowerConsumption(cumulativePowerConsumptionPair.get(teamDeptId));