Browse Source

Merge remote-tracking branch 'origin/master'

Zimo 1 tuần trước cách đây
mục cha
commit
1424a1f717

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotdeviceallotlog/IotDeviceAllotLogServiceImpl.java

@@ -37,6 +37,7 @@ import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_DEVICE_ALLOT_LOG_NOT_EXISTS;
+import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstant.IOT_MAINTAIN_RUNNING_EXISTS;
 import static cn.iocoder.yudao.module.pms.framework.config.MultiThreadConfiguration.PMS_THREAD_POOL_TASK_EXECUTOR;
 
 /**
@@ -176,6 +177,10 @@ public class IotDeviceAllotLogServiceImpl implements IotDeviceAllotLogService {
             }
 
         });
+        // 判断是否有正在进行的 维修工单 如果为false,不能调拨
+        if (!iotMaintainService.ifFinished(changedDeviceIds)) {
+            throw exception(IOT_MAINTAIN_RUNNING_EXISTS);
+        }
         if (CollUtil.isNotEmpty(deviceAllotLogs)) {
             iotDeviceAllotLogMapper.insertBatch(deviceAllotLogs);
         }

+ 246 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotprojecttaskplan/IotProjectTaskPlanServiceImpl.java

@@ -188,7 +188,7 @@ public class IotProjectTaskPlanServiceImpl implements IotProjectTaskPlanService
         DeptDO selectedDept = deptService.getDept(pageReqVO.getDeptId());
         if ("0".equals(selectedDept.getType())) {
             // 选中集团 查询所有公司的汇总数据
-            // result = statisticsByCompany(plans, pageReqVO);
+            result = statisticsByCompany(plans, pageReqVO);
         } else if ("1".equals(selectedDept.getType())) {
             // 选中公司 查询公司下所有项目部的汇总数据
             result = statisticsByProjectDept(plans, pageReqVO);
@@ -214,6 +214,251 @@ public class IotProjectTaskPlanServiceImpl implements IotProjectTaskPlanService
         return result;
     }
 
+    /**
+     * 按专业公司维度 汇总 统计数据
+     * @param plans 月度计划工作量列表
+     * @param pageReqVO 包含根部门ID(如 156L为 集团 根部门,或其他公司级部门ID)
+     * @return 公司维度统计结果列表
+     */
+    private List<IotProjectTaskPlanStatisticsRespVO> statisticsByCompany(List<IotProjectTaskPlanDO> plans, IotProjectTaskPlanPageReqVO pageReqVO) {
+        List<IotProjectTaskPlanStatisticsRespVO> result = new ArrayList<>();
+
+        Set<Long> projectDeptIds = new HashSet<>();
+        // key公司id    value公司级部门
+        Map<Long, DeptDO> companyDeptPair = new HashMap<>();
+        // key项目部id    value项目部名称
+        Map<Long, DeptDO> projectDeptPair = new HashMap<>();
+        // key部门id   value部门parentId
+        Map<Long, Long> teamProjectIdPair = new HashMap<>();
+        // key队伍id    value队伍部门
+        Map<Long, DeptDO> teamDeptPair = new HashMap<>();
+
+        // key公司id   value累计 注气量(万方)
+        Map<Long, BigDecimal> cumulativeGasInjectionPair = new HashMap<>();
+        // key公司id   value累计 进尺(米)
+        Map<Long, BigDecimal> cumulativeFootagePair = new HashMap<>();
+        // key公司id   value累计 井次(井)    修井 井下 连油 井次
+        Map<Long, BigDecimal> cumulativeWellCountPair = new HashMap<>();
+        // key公司id   value累计 压裂(层)    瑞都压裂层  5#国压裂层
+        Map<Long, BigDecimal> cumulativeFracLayerPair = new HashMap<>();
+        // key公司id   value业务类型
+        Map<Long, String> projectBusinessPair = new HashMap<>();
+
+        // 月度统计(公司 -> 年月 -> 统计值)
+        Map<Long, Map<String, MonthlyStats>> projectMonthStatsMap = new HashMap<>();
+
+        //  计划工作量 项目业务类型 key字典键值     value字典标签
+        Map<String, String> workloadPlanDictPair = new HashMap<>();
+
+        // key项目业务类型     value项目部id集合
+        Map<String, Set<Long>> projectBizPair = new HashMap<>();
+
+        // 队伍id 集合
+        Set<Long> teamIds = new HashSet<>();
+
+        // 查询3个专业公司的所有子部门 组装队伍与公司的关联关系
+        Set<Long> allRhChildDeptIds = deptService.getChildDeptIdListFromCache(157l);
+        Set<Long> allRyChildDeptIds = deptService.getChildDeptIdListFromCache(158l);
+        Set<Long> allRdChildDeptIds = deptService.getChildDeptIdListFromCache(163l);
+        Set<Long> allFiveChildDeptIds = deptService.getChildDeptIdListFromCache(388l);
+        // 公司ID -> 公司全部下属子部门集合
+        Map<Long, Set<Long>> companyAllChildDeptMap = new HashMap<>(4);
+        companyAllChildDeptMap.put(157L, allRhChildDeptIds);
+        companyAllChildDeptMap.put(158L, allRyChildDeptIds);
+        companyAllChildDeptMap.put(163L, allRdChildDeptIds);
+        companyAllChildDeptMap.put(388L, allFiveChildDeptIds);
+
+        // 以项目部为维度统计数据
+        // 找到所有项目部与队伍的对应关系
+        // 查询指定根部门下的所有子部门
+        Set<Long> allJtChildDeptIds = deptService.getChildDeptIdListFromCache(pageReqVO.getDeptId());
+        DeptListReqVO reqVO = new DeptListReqVO();
+        reqVO.setDeptIds(allJtChildDeptIds);
+        List<DeptDO> departments = deptService.getDeptList(reqVO);
+
+        // 查询 计划工作量 项目业务类型 项目业务(注气/钻井/修井/压裂/连油/井下)
+        List<DictDataDO> workloadPlanBizData = dictDataService.getDictDataListByDictType("rq_iot_workload_plan_biz");
+        if (CollUtil.isNotEmpty(workloadPlanBizData)) {
+            workloadPlanBizData.forEach(tech -> {
+                String label = tech.getLabel();
+                workloadPlanDictPair.put(tech.getValue(), label);
+                // 设置每个项目部的业务类型
+                String projectDeptIdsStr = tech.getRemark();
+                if (StrUtil.isNotBlank(projectDeptIdsStr)) {
+                    // 数据格式 234,124,832
+                    // 逗号分割、转Long、过滤空字符串、收集到Set
+                    Set<Long> deptIdSet = StrUtil.splitTrim(projectDeptIdsStr, ",")
+                            .stream()
+                            .filter(StrUtil::isNotBlank)
+                            .map(Long::valueOf)
+                            .collect(Collectors.toSet());
+
+                    // 存入map:存在则合并集合,不存在则新建
+                    projectBizPair.computeIfAbsent(label, k -> new HashSet<>()).addAll(deptIdSet);
+                }
+            });
+        }
+
+        // 构建项目部映射和父子部门关系
+        departments.forEach(dept -> {
+            if ("1".equals(dept.getType()) && dept.getStatus() == 0) {
+                // 公司
+                companyDeptPair.put(dept.getId(), dept);
+            }
+            if ("2".equals(dept.getType())) {
+                // 项目部
+                projectDeptIds.add(dept.getId());
+                projectDeptPair.put(dept.getId(), dept);
+            }
+            if ("3".equals(dept.getType())) {
+                // 队伍
+                teamIds.add(dept.getId());
+                teamDeptPair.put(dept.getId(), dept);
+            }
+            // 所有部门与上级部门的 id 对应关系
+            teamProjectIdPair.put(dept.getId(), dept.getParentId());
+
+        });
+        // 遍历 计划工作量列表 以公司为维度组装 工作量数据
+        plans.forEach(plan -> {
+            Long teamDeptId = plan.getDeptId();
+            BigDecimal gasInjection = ObjUtil.isNotEmpty(plan.getPlanGasInjection()) ? plan.getPlanGasInjection() : BigDecimal.ZERO;
+            BigDecimal footage = ObjUtil.isNotEmpty(plan.getPlanFootage()) ? plan.getPlanFootage() : BigDecimal.ZERO;
+            BigDecimal wellTrips = ObjUtil.isNotEmpty(plan.getPlanWellTrips()) ? plan.getPlanWellTrips() : BigDecimal.ZERO;
+            BigDecimal layers = ObjUtil.isNotEmpty(plan.getPlanLayers()) ? plan.getPlanLayers() : BigDecimal.ZERO;
+            String business = plan.getBusiness();
+            if (ObjUtil.isNotEmpty(teamDeptId) && teamProjectIdPair.containsKey(teamDeptId)) {
+                // 公司id
+                Long companyDeptId = 0l;
+                // 判断当前队伍所属的专业公司
+                if (allRhChildDeptIds.contains(teamDeptId)) {
+                    // 瑞恒公司下的队伍
+                    companyDeptId = 157l;
+                } else if (allRyChildDeptIds.contains(teamDeptId)) {
+                    // 瑞鹰公司下的队伍
+                    companyDeptId = 158l;
+                } else if (allRdChildDeptIds.contains(teamDeptId)) {
+                    // 瑞都公司下的队伍
+                    companyDeptId = 163l;
+                } else {
+                    // 5#国的队伍
+                    companyDeptId = 388l;
+                }
+                if (ObjUtil.isNotEmpty(companyDeptId) && (companyDeptId > 0)) {
+                    // 累计注气量
+                    cumulativeGasInjectionPair.compute(companyDeptId, (k, v) -> ObjUtil.isEmpty(v) ? gasInjection : v.add(gasInjection));
+                    // 累计进尺
+                    cumulativeFootagePair.compute(companyDeptId, (k, v) -> ObjUtil.isEmpty(v) ? footage : v.add(footage));
+                    // 累计井次
+                    cumulativeWellCountPair.compute(companyDeptId, (k, v) -> ObjUtil.isEmpty(v) ? wellTrips : v.add(wellTrips));
+                    // 累计压裂层
+                    cumulativeFracLayerPair.compute(companyDeptId, (k, v) -> ObjUtil.isEmpty(v) ? layers : v.add(layers));
+                    // 工作量业务类型
+                    if (StrUtil.isNotBlank(business) && workloadPlanDictPair.containsKey(business)) {
+                        projectBusinessPair.put(companyDeptId, workloadPlanDictPair.get(business));
+                    }
+                }
+
+                // 按照 年 月 汇总统计 计划工作量 如 2025-03
+                LocalDateTime startTime = plan.getStartTime();
+                if (ObjUtil.isNotEmpty(startTime)) {
+                    // 提取出时间中的 年 月
+                    Integer year = startTime.getYear();
+                    Integer month = startTime.getMonthValue();
+                    String uniqueKey = StrUtil.join("-", year, month);
+                    // 统计各公司下包含的按照 yyyy-MM 统计的各项工作量
+                    // 获取该公司的月度Map
+                    Map<String, MonthlyStats> monthMap = projectMonthStatsMap.computeIfAbsent(companyDeptId, k -> new HashMap<>());
+                    // 获取该年月的统计对象
+                    MonthlyStats stats = monthMap.computeIfAbsent(uniqueKey, k -> new MonthlyStats());
+                    // 累加
+                    stats.gasInjection = stats.gasInjection.add(gasInjection);
+                    stats.footage = stats.footage.add(footage);
+                    stats.wellCount = stats.wellCount.add(wellTrips);
+                    stats.fracLayer = stats.fracLayer.add(layers);
+                }
+            }
+        });
+
+        // 组装查询时间区间内包含的 年 月
+        LocalDateTime[] startTimeArr = pageReqVO.getStartTime();
+        if (ObjUtil.isEmpty(startTimeArr)) {
+            return result;
+        }
+        if (startTimeArr.length < 1) {
+            return result;
+        }
+        List<String> allMonths = generateMonthRange(startTimeArr[0], startTimeArr[1]);
+
+        // 生成返回的数据列表集合
+        companyDeptPair.forEach((deptId, dept) -> {
+            IotProjectTaskPlanStatisticsRespVO statistics = new IotProjectTaskPlanStatisticsRespVO();
+            statistics.setCompanyId(deptId);
+            statistics.setCompanyName(dept.getName());
+            statistics.setSort(dept.getSort());
+            statistics.setType("1");
+            statistics.setCumulativeGasInjection(cumulativeGasInjectionPair.getOrDefault(deptId, BigDecimal.ZERO));
+            statistics.setCumulativeFootage(cumulativeFootagePair.getOrDefault(deptId, BigDecimal.ZERO));
+            statistics.setCumulativeWellCount(cumulativeWellCountPair.getOrDefault(deptId, BigDecimal.ZERO));
+            statistics.setCumulativeFracLayer(cumulativeFracLayerPair.getOrDefault(deptId, BigDecimal.ZERO));
+
+            // 设置每个公司的 业务类型
+            Set<Long> companyChildDepts = companyAllChildDeptMap.getOrDefault(deptId, Collections.emptySet());
+            List<String> bizNameList = projectBizPair.entrySet().stream()
+                    .filter(entry -> CollUtil.isNotEmpty(entry.getValue())
+                            && CollUtil.intersection(entry.getValue(), companyChildDepts).size() > 0)
+                    .map(Map.Entry::getKey)
+                    .distinct()
+                    .collect(Collectors.toList());
+            String businessName = bizNameList.isEmpty() ? StrUtil.EMPTY : CollUtil.join(bizNameList, ",");
+            statistics.setBusiness(businessName);
+
+            // 处理月度明细
+            Map<String, MonthlyStats> existingMonthMap = projectMonthStatsMap.get(deptId);
+            List<IotProjectTaskPlanStatisticsItemRespVO> items = new ArrayList<>();
+            if (allMonths.isEmpty()) {
+                // 无时间范围时,仅输出已有的月度(兼容原逻辑)
+                if (CollUtil.isNotEmpty(existingMonthMap)) {
+                    items = existingMonthMap.entrySet().stream()
+                            .sorted(Map.Entry.comparingByKey())
+                            .map(entry -> {
+                                IotProjectTaskPlanStatisticsItemRespVO item = new IotProjectTaskPlanStatisticsItemRespVO();
+                                item.setYearMonth(entry.getKey());
+                                MonthlyStats ms = entry.getValue();
+                                item.setCumulativeGasInjection(ms.gasInjection);
+                                item.setCumulativeFootage(ms.footage);
+                                item.setCumulativeWellCount(ms.wellCount);
+                                item.setCumulativeFracLayer(ms.fracLayer);
+                                return item;
+                            })
+                            .collect(Collectors.toList());
+                }
+            } else {
+                // ★ 补全所有月份
+                for (String month : allMonths) {
+                    MonthlyStats stats = CollUtil.isNotEmpty(existingMonthMap) ? existingMonthMap.get(month) : null;
+                    if (stats == null) {
+                        stats = new MonthlyStats(); // 默认所有字段为 0
+                    }
+                    IotProjectTaskPlanStatisticsItemRespVO item = new IotProjectTaskPlanStatisticsItemRespVO();
+                    item.setYearMonth(month);
+                    item.setCumulativeGasInjection(stats.gasInjection);
+                    item.setCumulativeFootage(stats.footage);
+                    item.setCumulativeWellCount(stats.wellCount);
+                    item.setCumulativeFracLayer(stats.fracLayer);
+                    items.add(item);
+                }
+            }
+
+            if (!items.isEmpty()) {
+                statistics.setItems(items);
+            }
+
+            result.add(statistics);
+        });
+
+        return result;
+    }
 
     /**
      * 按项目部维度 汇总 统计数据