ソースを参照

pms 瑞都日报汇总 设备利用率 逻辑调整

zhangcl 5 日 前
コミット
0d65d42139

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

@@ -1044,12 +1044,13 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         List<IotRdDailyReportStatisticsRespVO> result = new ArrayList<>();
         // 不分页统计所有数据
         Set<Long> ids = new HashSet<>();
-        if (Objects.nonNull(pageReqVO.getDeptId())) {
-            ids = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
-            // 找到所有子部门对象集合
-            ids.add(pageReqVO.getDeptId());
-            pageReqVO.setDeptIds(ids);
+        if (ObjUtil.isEmpty(pageReqVO.getDeptId())) {
+            pageReqVO.setDeptId(163l);
         }
+        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<>();
@@ -1073,10 +1074,10 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                 result = statisticsByProjectDept(dailyReports, pageReqVO.getDeptId(), pageReqVO);
             } else if ("2".equals(selectedDept.getType())) {
                 // 以队伍为维度汇总数据
-                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO);
             } else if ("3".equals(selectedDept.getType())) {
                 // 显示单个队伍的汇总数据
-                result = statisticsByProjectDepartment(dailyReports, pageReqVO.getDeptId());
+                result = statisticsByProjectDepartment(dailyReports, pageReqVO);
             } else {
                 // 点击的部门没有类型 判断部门下的是否包含 项目部类型部门 新疆分公司
                 // 以项目部为维度汇总数据
@@ -1143,31 +1144,9 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             });
         }
 
-        // 查询瑞都所有 A B 类设备 计算总的设备利用率
-        Set<Long> abDeviceCategoryIds = new HashSet<>();
-        // 查询所有瑞都产品类别包含 A B 类
-        /* IotProductClassifyListReqVO deviceCategoryReqVO = new IotProductClassifyListReqVO();
-        List<IotProductClassifyDO> allDeviceCategories = iotProductClassifyMapper.selectList(deviceCategoryReqVO);
-        if (CollUtil.isNotEmpty(allDeviceCategories)) {
-            allDeviceCategories.forEach(category -> {
-                if ("A".equals(category.getRemark())) {
-                    abDeviceCategoryIds.add(category.getId());
-                }
-            });
-        } */
         // 查询瑞都所有查询到的设备
         // 过滤掉 封存 的 压裂 连油 主设备
         Set<Long> abDeviceIds = new HashSet<>();
-        /* IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
-        deviceReqVO.setDeptIds(new ArrayList<>(ids));
-        List<IotDeviceDO> rdDevices = iotDeviceMapper.selectListAlone(deviceReqVO);
-        if (CollUtil.isNotEmpty(rdDevices)) {
-            rdDevices.forEach(device -> {
-                if (abDeviceCategoryIds.contains(device.getAssetClass())) {
-                    abDeviceIds.add(device.getId());
-                }
-            });
-        } */
 
         // 20260604 修改设备利用率统计逻辑 统计 压裂 连油 主设备 rq_iot_device_associate
         // 队伍日报中关联的主设备数量 /(队伍下所有主设备数量-封存设备数量)
@@ -1203,19 +1182,46 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             });
         }
 
+        // 计算指定时间区间内包含的天数
+        long daysCount;
+        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;
+            } else {
+                daysCount = 0L;
+            }
+        } else {
+            daysCount = 0L;
+        }
+
         // 日报涉及到的施工设备id集合
         Set<Long> reportDeviceIds = new HashSet<>();
+        // 日报小到的施工主设备id集合
+        List<Long> reportMainDeviceIds = new ArrayList<>();
 
         List<IotRdDailyReportDO> dailyReports = iotRdDailyReportMapper.dailyReports(pageReqVO);
         // 累加所有日报的 工作量 数据 油耗 桥塞 趟数 井数...
         if (CollUtil.isNotEmpty(dailyReports)) {
             // 筛选出所有日报关联的任务集合
-
             dailyReports.forEach(report -> {
-                // 筛选出日报中施工的 设备id集合
-                if (CollUtil.isNotEmpty(report.getDeviceIds())) {
-                    reportDeviceIds.addAll(report.getDeviceIds());
+                // 筛选出日报中施工的 主设备id 集合
+                Set<Long> currentReportDeviceIds = report.getDeviceIds();
+                if (CollUtil.isNotEmpty(currentReportDeviceIds)) {
+                    // 筛选出属于 abDeviceIds 的设备 ID,全部加入 reportMainDeviceIds(不去重)
+                    currentReportDeviceIds.stream()
+                            .filter(abDeviceIds::contains)
+                            .forEach(reportMainDeviceIds::add);
                 }
+                /* if (CollUtil.isNotEmpty(report.getDeviceIds())) {
+                    reportDeviceIds.addAll(report.getDeviceIds());
+                } */
                 BigDecimal dailyFuel = report.getDailyFuel();
                 dailyFuel = ObjUtil.isEmpty(dailyFuel) ? BigDecimal.ZERO : dailyFuel;
                 if (cumulativeFuelsPair.containsKey("cumulativeFuels")) {
@@ -1340,9 +1346,9 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     }
                 }
             });
-            // 指定时间范围内 日报中所有施工的设备数量/总设备数量 (A B类)
+            // 指定时间范围内 日报中所有施工的设备数量/总设备数量*N天 (A B类)
             // abDeviceIds所有AB类设备  reportDeviceIds日报中用到的所有设备 交集求出日报中使用到的AB类设备
-            if (CollUtil.isNotEmpty(abDeviceIds) && CollUtil.isNotEmpty(reportDeviceIds)) {
+            if (CollUtil.isNotEmpty(abDeviceIds) && CollUtil.isNotEmpty(reportMainDeviceIds)) {
                 // 1. 求交集:实际使用的A B类设备
                 Set<Long> utilizedDeviceIds = reportDeviceIds.stream()
                         .filter(abDeviceIds::contains)
@@ -1350,8 +1356,8 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                 // 2. 计算设备利用率(实际使用设备数 / 总设备数)
                 BigDecimal deviceUtilization = BigDecimal.ZERO;
                 // 转换为BigDecimal进行计算,保留4位小数
-                deviceUtilization = BigDecimal.valueOf(utilizedDeviceIds.size())
-                        .divide(BigDecimal.valueOf(abDeviceIds.size()), 4, RoundingMode.HALF_UP);
+                deviceUtilization = BigDecimal.valueOf(reportMainDeviceIds.size())
+                        .divide(BigDecimal.valueOf(abDeviceIds.size() * daysCount), 4, RoundingMode.HALF_UP);
                 IotRdDailyReportStatisticsRespVO utilizationResp = new IotRdDailyReportStatisticsRespVO();
                 utilizationResp.setUtilizationRate(deviceUtilization);
                 utilizationResp.setDeptName("utilizationRate");
@@ -1524,6 +1530,9 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         });
         // key项目部id   value 日报中A+B类设备id集合
         Map<Long, Set<Long>> projectReportABDeviceIdPair = new HashMap<>();
+        // key项目部id   value 日报中A+B类设备id集合(不去重)
+        Map<Long, List<Long>> projectReportABDeviceIdsPair = new HashMap<>();
+
         // key项目部id   value A+B类设备id集合
         Map<Long, Set<Long>> projectABDeviceIdPair = new HashMap<>();
 
@@ -1609,6 +1618,25 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             });
         }
 
+        // 计算指定时间区间内包含的天数
+        long daysCount;
+        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;
+            } else {
+                daysCount = 0L;
+            }
+        } else {
+            daysCount = 0L;
+        }
+
         // 累计计算各项 工作量
         if (CollUtil.isNotEmpty(dailyReports)) {
             dailyReports.forEach(report -> {
@@ -1629,14 +1657,14 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                                 .filter(deviceId -> !fcMainDeviceIds.contains(deviceId)) // 过滤掉 封存的主设备
                                 .collect(Collectors.toSet()) // 收集为新的Set集合
                                 : Collections.emptySet(); // 任意集合为空则返回空Set(避免返回null)
-                        if (projectReportABDeviceIdPair.containsKey(projectId)) {
-                            Set<Long> tempDeviceIds = projectReportABDeviceIdPair.get(projectId);
+                        if (projectReportABDeviceIdsPair.containsKey(projectId)) {
+                            List<Long> tempDeviceIds = projectReportABDeviceIdsPair.get(projectId);
                             tempDeviceIds.addAll(crossDeviceIds);
-                            projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
+                            projectReportABDeviceIdsPair.put(projectId, tempDeviceIds);
                         } else {
-                            Set<Long> tempDeviceIds = new HashSet<>();
+                            List<Long> tempDeviceIds = new ArrayList<>();
                             tempDeviceIds.addAll(crossDeviceIds);
-                            projectReportABDeviceIdPair.put(projectId, tempDeviceIds);
+                            projectReportABDeviceIdsPair.put(projectId, tempDeviceIds);
                         }
                     }
                 }
@@ -1806,21 +1834,21 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                 }
             });
             // 计算每个项目部的设备利用率 施工的设备数量/设备总数量
-            // 队伍日报中关联的主设备数量/(队伍下所有主设备数量-封存设备数量)
+            // 队伍日报中关联的主设备数量(不去重)/(队伍下所有主设备数量-封存设备数量)*N天
             if (CollUtil.isNotEmpty(projectABDeviceIdPair)) {
                 projectABDeviceIdPair.forEach((projectDeptId, deviceIds) -> {
                     // 项目部下所有压裂连油主设备
                     Integer projectDeviceCount = deviceIds.size();
                     // 项目部日报中施工的压裂连油主设备
                     Integer reportDeviceCount = 0;
-                    if (projectReportABDeviceIdPair.containsKey(projectDeptId)) {
-                        Set<Long> reportDeviceIds = projectReportABDeviceIdPair.get(projectDeptId);
+                    if (projectReportABDeviceIdsPair.containsKey(projectDeptId)) {
+                        List<Long> reportDeviceIds = projectReportABDeviceIdsPair.get(projectDeptId);
                         reportDeviceCount = reportDeviceIds.size();
                     }
                     double rate = 0.0;
                     // 计算设备利用率(处理除数为0的情况)
-                    if (projectDeviceCount > 0 && reportDeviceCount > 0) {
-                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount))
+                    if (projectDeviceCount > 0 && reportDeviceCount > 0 && daysCount > 0) {
+                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount * daysCount))
                                 .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
                                 .doubleValue();;
                     } else {
@@ -1869,10 +1897,10 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
     /**
      * 按 队伍 维度统计 汇总 数据
      * @param dailyReports 日报数据列表
-     * @param deptId 项目部ID 或 队伍id
+     * @param pageReqVO (deptId)项目部ID 或 队伍id
      * @return 队伍 维度统计结果列表
      */
-    private List<IotRdDailyReportStatisticsRespVO> statisticsByProjectDepartment(List<IotRdDailyReportDO> dailyReports, Long deptId) {
+    private List<IotRdDailyReportStatisticsRespVO> statisticsByProjectDepartment(List<IotRdDailyReportDO> dailyReports, IotRdDailyReportPageReqVO pageReqVO) {
         List<IotRdDailyReportStatisticsRespVO> result = new ArrayList<>();
 
         Set<Long> teamDeptIds = new HashSet<>();
@@ -1908,10 +1936,10 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
         // 以 队伍 为维度统计数据
         // 找到所有项目部与队伍的对应关系
         // 查询指定根部门下的所有子部门
-        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(deptId);
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
         DeptListReqVO reqVO = new DeptListReqVO();
         // 查询某支队伍 或 所属项目部的信息
-        allRhChildDeptIds.add(deptId);
+        allRhChildDeptIds.add(pageReqVO.getDeptId());
         reqVO.setDeptIds(allRhChildDeptIds);
         List<DeptDO> depts = deptService.getDeptList(reqVO);
 
@@ -1940,21 +1968,12 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                 }
             });
         }
-        // 查询瑞都所有 A B 类设备 计算总的设备利用率
-        Set<Long> abDeviceCategoryIds = new HashSet<>();
-        // 查询所有瑞都产品类别包含 A B 类
-        /* IotProductClassifyListReqVO deviceCategoryReqVO = new IotProductClassifyListReqVO();
-        List<IotProductClassifyDO> allDeviceCategories = iotProductClassifyMapper.selectList(deviceCategoryReqVO);
-        if (CollUtil.isNotEmpty(allDeviceCategories)) {
-            allDeviceCategories.forEach(category -> {
-                if ("A".equals(category.getRemark())) {
-                    abDeviceCategoryIds.add(category.getId());
-                }
-            });
-        } */
 
         // key队伍id   value 日报中A+B类设备id集合
         Map<Long, Set<Long>> teamReportABDeviceIdPair = new HashMap<>();
+        // key队伍id   value 日报中A+B类设备id集合(不去重)
+        Map<Long, List<Long>> teamReportABDeviceIdsPair = new HashMap<>();
+
         // key队伍id   value A+B类设备id集合
         Map<Long, Set<Long>> teamABDeviceIdPair = new HashMap<>();
 
@@ -2013,6 +2032,23 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
             });
         }
 
+        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);
+            }
+        }
+
         // 累计计算 工作量
         if (CollUtil.isNotEmpty(dailyReports)) {
             dailyReports.forEach(report -> {
@@ -2030,14 +2066,14 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                                 .filter(deviceId -> !fcMainDeviceIds.contains(deviceId)) // 过滤掉 封存的主设备
                                 .collect(Collectors.toSet()) // 收集为新的Set集合
                                 : Collections.emptySet(); // 任意集合为空则返回空Set(避免返回null)
-                        if (teamReportABDeviceIdPair.containsKey(report.getDeptId())) {
-                            Set<Long> tempDeviceIds = teamReportABDeviceIdPair.get(report.getDeptId());
+                        if (teamReportABDeviceIdsPair.containsKey(report.getDeptId())) {
+                            List<Long> tempDeviceIds = teamReportABDeviceIdsPair.get(report.getDeptId());
                             tempDeviceIds.addAll(crossDeviceIds);
-                            teamReportABDeviceIdPair.put(report.getDeptId(), tempDeviceIds);
+                            teamReportABDeviceIdsPair.put(report.getDeptId(), tempDeviceIds);
                         } else {
-                            Set<Long> tempDeviceIds = new HashSet<>();
+                            List<Long> tempDeviceIds = new ArrayList<>();
                             tempDeviceIds.addAll(crossDeviceIds);
-                            teamReportABDeviceIdPair.put(report.getDeptId(), tempDeviceIds);
+                            teamReportABDeviceIdsPair.put(report.getDeptId(), tempDeviceIds);
                         }
                     }
                 }
@@ -2181,21 +2217,21 @@ public class IotRdDailyReportServiceImpl implements IotRdDailyReportService {
                     }
                 }
             });
-            // 计算每个队伍的设备利用率 施工的设备数量/设备总数量
+            // 计算每个队伍的设备利用率 (日报中施工的设备数量) / (主设备总数量)*N天
             if (CollUtil.isNotEmpty(teamABDeviceIdPair)) {
                 teamABDeviceIdPair.forEach((teamDeptId, deviceIds) -> {
                     // 队伍下所有AB类设备
                     Integer projectDeviceCount = deviceIds.size();
                     // 队伍日报中施工的AB类设备
                     Integer reportDeviceCount = 0;
-                    if (teamReportABDeviceIdPair.containsKey(teamDeptId)) {
-                        Set<Long> reportDeviceIds = teamReportABDeviceIdPair.get(teamDeptId);
+                    if (teamReportABDeviceIdsPair.containsKey(teamDeptId)) {
+                        List<Long> reportDeviceIds = teamReportABDeviceIdsPair.get(teamDeptId);
                         reportDeviceCount = reportDeviceIds.size();
                     }
                     double rate = 0.0;
                     // 计算设备利用率(处理除数为0的情况)
-                    if (projectDeviceCount > 0 && reportDeviceCount > 0) {
-                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount))
+                    if (projectDeviceCount > 0 && reportDeviceCount > 0 && CollUtil.isNotEmpty(daysCounts)) {
+                        rate = new BigDecimal((double) reportDeviceCount / (projectDeviceCount * daysCounts.get(0)))
                                 .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
                                 .doubleValue();;
                     } else {