Bläddra i källkod

pms 瑞恒 看板 生产动态列表 3个主要项目部 生产动态展示所有区域的队伍设备套数

zhangcl 1 dag sedan
förälder
incheckning
095fc4b095

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

@@ -593,6 +593,12 @@ public class IotRyDailyReportController {
         Map<String, String> constructStatusPair = new HashMap<>();
         // 修井 key施工状态数据字典value   value施工状态数据字典label
         Map<String, String> repairStatusPair = new HashMap<>();
+
+        // key部门设备属性数据字典value   value部门设备属性数据字典label
+        Map<String, String> deviceAttributesPair = new HashMap<>();
+        // key部门id   value部门设备属性数据字典label
+        Map<Long, String> deptIdDeviceAttributesPair = new HashMap<>();
+
         // key日报id   value生产动态明细
         Map<Long, List<IotRyDailyReportDetailRespVO>> reportDetailsPair = new HashMap<>();
 
@@ -602,6 +608,8 @@ public class IotRyDailyReportController {
         List<DictDataDO> repairStatusDictData = dictDataService.getDictDataListByDictType("repairStatus");
         // 非生产时间原因 字典数据
         List<DictDataDO> nptReasonDictData = dictDataService.getDictDataListByDictType("ryNptReason");
+        // 部门设备属性 字典数据
+        List<DictDataDO> deviceAttributesDictData = dictDataService.getDictDataListByDictType("rq_iot_device_attributes");
 
         if (CollUtil.isNotEmpty(nptReasonDictData)) {
             nptReasonDictData.forEach(data -> {
@@ -620,6 +628,22 @@ public class IotRyDailyReportController {
                 repairStatusPair.put(data.getValue(), data.getLabel());
             });
         }
+        // 部门设备属性
+        if (CollUtil.isNotEmpty(deviceAttributesDictData)) {
+            deviceAttributesDictData.forEach(data -> {
+                deviceAttributesPair.put(data.getValue(), data.getLabel());
+            });
+        }
+
+        if (CollUtil.isNotEmpty(deptMap)) {
+            deptMap.forEach((deptId, dept) -> {
+                String deviceAttributes = dept.getDeviceAttributes();
+                if (StrUtil.isNotBlank(deviceAttributes) && deviceAttributesPair.containsKey(deviceAttributes)) {
+                    String attributesLabel = deviceAttributesPair.get(deviceAttributes);
+                    deptIdDeviceAttributesPair.put(deptId, attributesLabel);
+                }
+            });
+        }
 
         // 查询瑞鹰下所有部门 施工队伍及对应的项目部
         Set<Long> deptIds = deptService.getChildDeptIdListFromCache(158l);
@@ -776,6 +800,8 @@ public class IotRyDailyReportController {
             }
             // 2.1 拼接部门信息
             findAndThen(deptMap, reportVO.getDeptId(), dept -> reportVO.setDeptName(dept.getName()));
+            // 部门设备属性
+            findAndThen(deptIdDeviceAttributesPair, reportVO.getDeptId(), deviceAttributes -> reportVO.setDeviceAttributes(deviceAttributes));
             // 队伍排序值
             findAndThen(teamSortPair, reportVO.getDeptId(), sort -> reportVO.setTeamSort(sort));
             // 设置项目部排序值

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

@@ -380,4 +380,8 @@ public class IotRyDailyReportRespVO {
     @Schema(description = "修井 施工状态 对应的数据字典 label")
     @ExcelProperty("修井 施工状态 label")
     private String repairStatusName;
+
+    @Schema(description = "部门设备属性 自有/租赁/合作")
+    @ExcelProperty("设备属性")
+    private String deviceAttributes;
 }

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

@@ -3135,6 +3135,9 @@ public class IotStaticController {
         Set<String> projectDeptNames = new HashSet<>();
         Set<Long> projectDeptIds = new HashSet<>();
 
+        // 可用的部门id集合
+        Set<Long> availableDeptIds = new HashSet<>();
+
         // 查询钻井部门 修井 部门
         // 钻井或修井部门 队伍
         List<Long> zjOrXjDeptIds = new ArrayList<>();
@@ -3142,6 +3145,7 @@ public class IotStaticController {
         List<IotDeptTypeDO> deptTypes = iotDeptTypeMapper.selectList(deptTypeReqVO);
         if (CollUtil.isNotEmpty(deptTypes)) {
             deptTypes.forEach(dept -> {
+                // 有的队伍不需要计入队伍总数
                 if (!"no".equals(dept.getUpdater())) {
                     zjOrXjDeptIds.add(dept.getDeptId());
                 }
@@ -3165,6 +3169,10 @@ public class IotStaticController {
                     // 队伍
                     crewIds.add(dept.getId());
                 }
+                // 过滤掉禁用的部门
+                if (0 == dept.getStatus()) {
+                    availableDeptIds.add(deptId);
+                }
             });
             // 遍历所有部门
             allDeptPair.forEach((deptId, dept) -> {
@@ -3199,6 +3207,15 @@ public class IotStaticController {
         List<IotRyDailyReportDO> dailyReports = iotRyDailyReportMapper.dailyReports(reqVO);
         // key项目部id     value项目部包含的队伍指定时间区域内日报数量
         Map<Long, Integer> projectReportPair = new HashMap<>();
+        // 总日报数量
+        Integer totalReportCount = 0;
+        // 总队伍数量
+        Integer totalTeamCount = 0;
+        // 查询时间区间内的天数
+        long daysCount;
+        // 公司总的设备利用率
+        double totalRate;
+        List<Double> totalRates = new ArrayList<>();
         if (CollUtil.isNotEmpty(dailyReports)) {
             // 整理出每个项目部下的队伍填报的日报数量
             dailyReports.forEach(report -> {
@@ -3217,7 +3234,6 @@ public class IotStaticController {
 
             });
             // 计算指定时间区间内包含的天数
-            long daysCount;
             if (ObjUtil.isNotEmpty(reqVO.getCreateTime()) && reqVO.getCreateTime().length >= 2) {
                 LocalDateTime start = reqVO.getCreateTime()[0];
                 LocalDateTime end = reqVO.getCreateTime()[1];
@@ -3262,8 +3278,32 @@ public class IotStaticController {
                     rates.add(rateVo);
                 });
             }
+
+            // 公司总日报数 = 各项目部日报数之和
+            totalReportCount = projectReportPair.values().stream()
+                    .mapToInt(Integer::intValue)
+                    .sum();
+            // 公司总队伍数 = 各项目部队伍数之和
+            totalTeamCount = projectTeamPair.values().stream()
+                    .mapToInt(Set::size)
+                    .sum();
+            if (totalTeamCount > 0) {
+                totalRate = new BigDecimal((double) totalReportCount / (totalTeamCount * daysCount))
+                        .setScale(4, RoundingMode.HALF_UP)  // 保留4位小数,四舍五入
+                        .doubleValue();
+                totalRates.add(totalRate);
+            }
         }
         rates.sort(Comparator.comparingDouble(ProjectUtilizationRateVo::getUtilizationRate).reversed());
+        // 公司总的设备利用率,追加到列表最后。
+        ProjectUtilizationRateVo totalVo = new ProjectUtilizationRateVo();
+        totalVo.setProjectDeptId(null); // 或 0L,按前端约定
+        totalVo.setProjectDeptName("总计");
+        totalVo.setTeamCount(totalTeamCount);
+        if (CollUtil.isNotEmpty(totalRates)) {
+            totalVo.setUtilizationRate(totalRates.get(0));
+        }
+        rates.add(totalVo);
         return success(rates);
     }
 

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

@@ -1139,8 +1139,11 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
         // key队伍id   value队伍名称
         Map<Long, String> teamPair = new HashMap<>();
 
-        // key项目部id   value项目部包含的队伍id集合
+        // key项目部id   value项目部包含的队伍id集合 包含主设备的队伍
         Map<Long, Set<Long>> projectTeamPair = new HashMap<>();
+        // key项目部id   value项目部包含的队伍id集合 所有队伍
+        Map<Long, Set<Long>> projectTeamsPair = new HashMap<>();
+
         // key项目部id   value项目部包含的队伍集合
         Map<Long, Set<DeptDO>> projectDepartmentPair = new HashMap<>();
         // 队伍id 集合
@@ -1210,16 +1213,47 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
             });
             // 遍历所有部门 只筛选出有设备的队伍
             allDeptPair.forEach((deptId, dept) -> {
+                if (!"3".equals(dept.getType())) {
+                    return;
+                }
+
+                Long parentId = dept.getParentId();
+                if (ObjUtil.isEmpty(parentId) || !projectPair.containsKey(parentId)) {
+                    return;
+                }
+
+                // 所有队伍只挂到自己的直接父项目部
+                projectTeamsPair.computeIfAbsent(parentId, k -> new HashSet<>()).add(deptId);
+                teamIdProjectIdPair.put(deptId, parentId);
+
+                // 有主设备的队伍
+                if (haveDeviceDeptIds.contains(deptId)) {
+                    projectTeamPair.computeIfAbsent(parentId, k -> new HashSet<>()).add(deptId);
+                    teamProjectIdPair.put(deptId, parentId);
+                    projectSortedTeamIdPair.computeIfAbsent(parentId, k -> new ArrayList<>()).add(deptId);
+                }
                 // 找出每个项目部下的队伍
-                if (projectPair.containsKey(dept.getParentId())) {
+                /* if (projectPair.containsKey(dept.getParentId())) {
                     // 获得当前部门的上级项目部
                     projectPair.forEach((projectDeptId, projectDeptName) -> {
+                        // 项目部下所有队伍
+                        if (projectTeamsPair.containsKey(projectDeptId)) {
+                            Set<Long> teamIds = projectTeamsPair.get(projectDeptId);
+                            teamIds.add(deptId);
+                            projectTeamsPair.put(projectDeptId, teamIds);
+                        } else {
+                            Set<Long> teamIds = new HashSet<>();
+                            teamIds.add(deptId);
+                            projectTeamsPair.put(projectDeptId, teamIds);
+                        }
+
+                        // 项目部下包含主设备的队伍
                         if (projectDeptId.equals(dept.getParentId()) && haveDeviceDeptIds.contains(deptId) && teamDepartmentIds.contains(deptId)) {
                             // 项目部下各队伍id列表初始化
                             projectSortedTeamIdPair
                                     .computeIfAbsent(dept.getParentId(), k -> new ArrayList<>())
                                     .add(deptId);
-
+                            // 项目部下包含主设备的队伍
                             if (projectTeamPair.containsKey(projectDeptId)) {
                                 Set<Long> teamIds = projectTeamPair.get(projectDeptId);
                                 teamIds.add(deptId);
@@ -1237,7 +1271,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                             teamIdProjectIdPair.put(dept.getId(), dept.getParentId());
                         }
                     });
-                }
+                } */
             });
 
             // 对每个项目部下的队伍ID列表,根据队伍的 sort 字段正序排序
@@ -1402,6 +1436,32 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                     location = taskLocationPair.get(reportTaskId);
                 }
 
+                // 日报关联的任务井id
+                Long taskId = report.getTaskId();
+
+                if (CollUtil.isNotEmpty(projectTeamsPair)) {
+                    for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamsPair.entrySet()) {
+                        Long projectDeptId = longSetEntry.getKey();
+                        Set<Long> teamDeptIds = longSetEntry.getValue();
+                        if (teamDeptIds.contains(deptId)) {
+                            // 以施工区域为维度统计 队伍总数 施工队伍数 准备队伍数 待命队伍数量
+                            String taskLocation = StrUtil.EMPTY;
+                            if (ObjUtil.isNotEmpty(taskId) && taskLocationPair.containsKey(taskId)) {
+                                taskLocation = taskLocationPair.get(taskId);
+                            }
+                            // 项目部下 施工区域内 队伍总数量
+                            if (StrUtil.isNotBlank(taskLocation)) {
+                                // 总队伍(去重)
+                                projectLocationTeamSet
+                                        .computeIfAbsent(projectDeptId, k -> new HashMap<>())
+                                        .computeIfAbsent(taskLocation, k -> new HashSet<>())
+                                        .add(deptId);
+                            }
+                        }
+                    }
+                }
+
+
                 if (CollUtil.isNotEmpty(projectTeamPair)) {
                     for (Map.Entry<Long, Set<Long>> longSetEntry : projectTeamPair.entrySet()) {
                         Long projectDeptId = longSetEntry.getKey();
@@ -1409,20 +1469,19 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
 
                         if (teamDeptIds.contains(deptId)) {
                             // 以施工区域为维度统计 队伍总数 施工队伍数 准备队伍数 待命队伍数量
-                            Long taskId = report.getTaskId();
                             String taskLocation = StrUtil.EMPTY;
                             if (ObjUtil.isNotEmpty(taskId) && taskLocationPair.containsKey(taskId)) {
                                 taskLocation = taskLocationPair.get(taskId);
                             }
 
                             // 项目部下 施工区域内 队伍总数量
-                            if (StrUtil.isNotBlank(taskLocation)) {
+                            /* if (StrUtil.isNotBlank(taskLocation)) {
                                 // 总队伍(去重)
                                 projectLocationTeamSet
                                         .computeIfAbsent(projectDeptId, k -> new HashMap<>())
                                         .computeIfAbsent(taskLocation, k -> new HashSet<>())
                                         .add(deptId);
-                            }
+                            } */
 
                             if (dailyGasInjection.compareTo(BigDecimal.ZERO) > 0 || dailyWaterInjection.compareTo(BigDecimal.ZERO) > 0) {
                                 // 项目部日报数量 20260608 统计 注气量 or 注水量 > 0 的日报数量
@@ -1878,7 +1937,7 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                 rate.setConstructionDays((ObjUtil.isNotEmpty(rate.getConstructionDays()) ? rate.getConstructionDays() : 0) + mergeConstructionDays.get());
             }
 
-            Map<String, Map<String, List<String>>> locationMap = productionMap.get(rate.getProjectDeptId());
+            /* Map<String, Map<String, List<String>>> locationMap = productionMap.get(rate.getProjectDeptId());
             // 组装各项目部 按照施工区域维度统计 的 队伍数量 生产动态明细
             if (locationMap != null && !locationMap.isEmpty() && !specialProjectIds.contains(rate.getProjectDeptId())) {
                 Map<String, Set<Long>> teamMap = projectLocationTeamSet.getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());
@@ -1912,6 +1971,69 @@ public class IotRhDailyReportServiceImpl implements IotRhDailyReportService {
                     }
                 }
                 rate.setProductionSummary(sb.toString());
+            } */
+
+            if (!specialProjectIds.contains(rate.getProjectDeptId())) {
+                Map<String, Set<Long>> teamMap = projectLocationTeamSet
+                        .getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());
+
+                Map<String, Set<Long>> sgTeamMap = projectLocationSgTeamSet
+                        .getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());
+
+                // productionMap 只表示:有“非生产时间和=24H”的井动态,不是区域全集
+                Map<String, Map<String, List<String>>> locationMap = productionMap
+                        .getOrDefault(rate.getProjectDeptId(), Collections.emptyMap());
+
+                // 关键:以区域统计全集为准,而不是只遍历 locationMap.keySet()
+                Set<String> locations = new TreeSet<>();
+                locations.addAll(teamMap.keySet());
+                locations.addAll(sgTeamMap.keySet());
+                locations.addAll(locationMap.keySet()); // 防止有动态但统计集合缺失
+
+                if (!locations.isEmpty()) {
+                    StringBuilder sb = new StringBuilder();
+
+                    for (String location : locations) {
+                        int total = teamMap.getOrDefault(location, Collections.emptySet()).size();
+                        int sg = sgTeamMap.getOrDefault(location, Collections.emptySet()).size();
+                        int zb = Math.max(total - sg, 0);
+
+                        // 无论有没有“非生产时间和=24H”,区域统计行都输出
+                        sb.append(location)
+                                .append(":施工").append(sg)
+                                .append("套设备,准备").append(zb)
+                                .append("套设备(共").append(total).append("套设备)\n");
+
+                        // 没有该区域的 24H 非生产动态时,只输出上面区域统计行
+                        Map<String, List<String>> wellMap = locationMap.get(location);
+                        if (wellMap == null || wellMap.isEmpty()) {
+                            continue;
+                        }
+
+                        List<String> sortedWells = new ArrayList<>(wellMap.keySet());
+                        Collections.sort(sortedWells);
+
+                        for (String well : sortedWells) {
+                            List<String> dynamics = wellMap.get(well);
+                            List<String> nonEmptyDynamics = dynamics == null
+                                    ? Collections.emptyList()
+                                    : dynamics.stream()
+                                    .filter(s -> s != null && !s.trim().isEmpty())
+                                    .collect(Collectors.toList());
+
+                            if (nonEmptyDynamics.isEmpty()) {
+                                sb.append(well).append(",;\n");
+                            } else {
+                                sb.append(well)
+                                        .append(",")
+                                        .append(String.join(";", nonEmptyDynamics))
+                                        .append(";\n");
+                            }
+                        }
+                    }
+
+                    rate.setProductionSummary(sb.toString());
+                }
             }
         });
         // 删除projectDeptId为166的对象 克拉玛依项目部