Ver Fonte

pms 生产运营双周会 数据汇总页面 工作量汇总

zhangcl há 3 dias atrás
pai
commit
d69d67bfa9

+ 558 - 22
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotoperationmeeting/IotOperationMeetingServiceImpl.java

@@ -525,6 +525,33 @@ public class IotOperationMeetingServiceImpl implements IotOperationMeetingServic
         if (CollUtil.isEmpty(summarizedDetails)) {
             return resultMeetings;
         }
+
+        // 计算本期各公司财务数据集合
+        // key公司id   value本期次公司本期收入
+        Map<Long, BigDecimal> currentRevenuePair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentRevenue, BigDecimal::add)));
+        // key公司id   value本期次公司累计收入
+        Map<Long, BigDecimal> currentTotalRevenuePair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCumulativeRevenue, BigDecimal::add)));
+        // key公司id   value本期次公司本期挂账
+        Map<Long, BigDecimal> currentOnAccountPair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentOnAccount, BigDecimal::add)));
+        // key公司id   value本期次公司累计挂账
+        Map<Long, BigDecimal> currentTotalOnAccountPair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCumulativeOnAccount, BigDecimal::add)));
+        // key公司id   value本期次公司本期回款
+        Map<Long, BigDecimal> currentPaymentPair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentPayment, BigDecimal::add)));
+        // key公司id   value本期次公司累计回款
+        Map<Long, BigDecimal> currentTotalPaymentPair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                        Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCumulativePayment, BigDecimal::add)));
+
         Set<Long> companyIds = new HashSet<>();
         // key会议id   value当前会议/公司下的项目明细
         Map<Long, List<IotOperationMeetingDetailDO>> companyMeetingIdDetailPair = new HashMap<>();
@@ -546,9 +573,108 @@ public class IotOperationMeetingServiceImpl implements IotOperationMeetingServic
                 nonCumulativeDeptIds.add(name.getId());
             }
         });
+        // key专业公司id   value专业公司计划注气量累加
+        Map<Long, BigDecimal> companyPlanGasInjectionPair = new HashMap<>();
+        // key专业公司id   value专业公司实际注气量累加
+        Map<Long, BigDecimal> companyActualGasInjectionPair = new HashMap<>();
+        // key专业公司id   value专业公司累计注气量累加
+        Map<Long, BigDecimal> companyCumulativeGasInjectionPair = new HashMap<>();
+
+        // 上期次会议 key专业公司id   value专业公司投运设备数量累加
+        Map<Long, BigDecimal> beforeCompanyInServiceDeviceNumPair = new HashMap<>();
+        // 上期次会议 key专业公司id   value专业公司施工设备数量累加
+        Map<Long, BigDecimal> beforeCompanyConstructionDeviceNumPair = new HashMap<>();
+
+        // key专业公司id   value专业公司投运设备数量累加
+        Map<Long, BigDecimal> companyInServiceDeviceNumPair = new HashMap<>();
+        // key专业公司id   value专业公司施工设备数量累加
+        Map<Long, BigDecimal> companyConstructionDeviceNumPair = new HashMap<>();
+
+        // key专业公司id   value专业公司各项目计划进尺累加
+        Map<Long, BigDecimal> companyPlanFootagePair = new HashMap<>();
+        // key专业公司id   value专业公司各项目实际进尺累加
+        Map<Long, BigDecimal> companyActualFootagePair = new HashMap<>();
+        // key专业公司id   value专业公司各项目累计进尺累加
+        Map<Long, BigDecimal> companyCumulativeFootagePair = new HashMap<>();
+
+        // key专业公司id   value专业公司各项目计划井次累加
+        Map<Long, BigDecimal> companyPlanWellTripsPair = new HashMap<>();
+        // key专业公司id   value专业公司各项目实际井次累加
+        Map<Long, BigDecimal> companyActualWellTripsPair = new HashMap<>();
+        // key专业公司id   value专业公司各项目累计井次累加
+        Map<Long, BigDecimal> companyCumulativeWellTripsPair = new HashMap<>();
+
+        // key专业公司id   value专业公司各项目计划层数累加
+        Map<Long, BigDecimal> companyPlanLayersPair = new HashMap<>();
+        // key专业公司id   value专业公司各项目实际层数累加
+        Map<Long, BigDecimal> companyActualLayersPair = new HashMap<>();
+        // key专业公司id   value专业公司各项目累计层数累加
+        Map<Long, BigDecimal> companyCumulativeLayersPair = new HashMap<>();
+
+        // key部门id   value当前会议/公司下的项目明细
+        Map<Long, List<IotOperationMeetingDetailDO>> companyDeptIdDetailPair = summarizedDetails.stream()
+                .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId));
+        if (CollUtil.isEmpty(companyDeptIdDetailPair)) {
+            return resultMeetings;
+        }
+        companyDeptIdDetailPair.forEach((deptId, details) -> {
+            // key专业公司id    details公司各项目明细
+            if (CollUtil.isNotEmpty(details)) {
+                details.forEach(detail -> {
+                    // 组装细分的工作量
+                    List<IotTaskAttrModelProperty> properties = detail.getExtProperty();
+                    if (CollUtil.isNotEmpty(properties)) {
+                        // 公共属性 投运设备 施工设备
+                        BigDecimal inServiceDeviceNum = getActualValue(properties, "inServiceDeviceNum");
+                        BigDecimal constructionDeviceNum = getActualValue(properties, "constructionDeviceNum");
+                        companyInServiceDeviceNumPair.merge(deptId, inServiceDeviceNum, BigDecimal::add);
+                        companyConstructionDeviceNumPair.merge(deptId, constructionDeviceNum, BigDecimal::add);
+                        // 163 瑞都
+                        // 388 5#公司
+                        if (Long.valueOf(157).equals(deptId)) {
+                            // 157 瑞恒 计划注气 实际注气 累计注气 总设备利用率及环比 总注气量完成比
+                            BigDecimal planGasInjection = getActualValue(properties, "planGasInjection");
+                            BigDecimal actualGasInjection = getActualValue(properties, "actualGasInjection");
+                            BigDecimal cumulativeGasInjection = getActualValue(properties, "cumulativeGasInjection");
+                            companyPlanGasInjectionPair.merge(deptId, planGasInjection, BigDecimal::add);
+                            companyActualGasInjectionPair.merge(deptId, actualGasInjection, BigDecimal::add);
+                            companyCumulativeGasInjectionPair.merge(deptId, cumulativeGasInjection, BigDecimal::add);
+                        }
+                        if (Long.valueOf(158).equals(deptId)) {
+                            // 158 瑞鹰 计划进尺 实际进尺 完成比 累计进尺 总设备利用率及环比 计划井次 实际井次 完成比 累计井次
+                            BigDecimal planFootage = getActualValue(properties, "planFootage");
+                            BigDecimal actualFootage = getActualValue(properties, "actualFootage");
+                            BigDecimal cumulativeFootage = getActualValue(properties, "cumulativeFootage");
+                            companyPlanFootagePair.merge(deptId, planFootage, BigDecimal::add);
+                            companyActualFootagePair.merge(deptId, actualFootage, BigDecimal::add);
+                            companyCumulativeFootagePair.merge(deptId, cumulativeFootage, BigDecimal::add);
+                        }
+                        if (Long.valueOf(163).equals(deptId)) {
+                            // 163 瑞都 计划层数 实际层数 完成比 累计层数 总设备利用率及环比 计划井次 实际井次 完成比 累计井次
+                            BigDecimal planLayers = getActualValue(properties, "planLayers");
+                            BigDecimal actualLayers = getActualValue(properties, "actualLayers");
+                            BigDecimal cumulativeLayers = getActualValue(properties, "cumulativeLayers");
+                            companyPlanLayersPair.merge(deptId, planLayers, BigDecimal::add);
+                            companyActualLayersPair.merge(deptId, actualLayers, BigDecimal::add);
+                            companyCumulativeLayersPair.merge(deptId, cumulativeLayers, BigDecimal::add);
+                        }
+                        if (Long.valueOf(163).equals(deptId) || Long.valueOf(158).equals(deptId)) {
+                            // 瑞都 瑞鹰 同时具备 井次属性
+                            BigDecimal planWellTrips = getActualValue(properties, "planWellTrips");
+                            BigDecimal actualWellTrips = getActualValue(properties, "actualWellTrips");
+                            BigDecimal cumulativeWellTrips = getActualValue(properties, "cumulativeWellTrips");
+                            companyPlanWellTripsPair.merge(deptId, planWellTrips, BigDecimal::add);
+                            companyActualWellTripsPair.merge(deptId, actualWellTrips, BigDecimal::add);
+                            companyCumulativeWellTripsPair.merge(deptId, cumulativeWellTrips, BigDecimal::add);
+                        }
+                    }
+                });
+            }
+        });
+
         summarizedDetails.forEach(detail -> {
             meetingIds.add(detail.getMeetingId());
-            if (companyMeetingIdDetailPair.containsKey(detail.getMeetingId())) {
+            /* if (companyMeetingIdDetailPair.containsKey(detail.getMeetingId())) {
                 List<IotOperationMeetingDetailDO> tempDetails = companyMeetingIdDetailPair.get(detail.getMeetingId());
                 tempDetails.add(detail);
                 companyMeetingIdDetailPair.put(detail.getMeetingId(), tempDetails);
@@ -556,7 +682,9 @@ public class IotOperationMeetingServiceImpl implements IotOperationMeetingServic
                 List<IotOperationMeetingDetailDO> tempDetails = new ArrayList<>();
                 tempDetails.add(detail);
                 companyMeetingIdDetailPair.put(detail.getMeetingId(), tempDetails);
-            }
+            } */
+            companyMeetingIdDetailPair.computeIfAbsent(detail.getMeetingId(), k -> new ArrayList<>()).add(detail);
+
         });
         // 根据 meetingIds 集合查询各会议的汇总信息(需要集团支持事项)
         IotOperationMeetingPageReqVO meetingReqVO = new IotOperationMeetingPageReqVO();
@@ -577,16 +705,43 @@ public class IotOperationMeetingServiceImpl implements IotOperationMeetingServic
         beforeReqVO.setYear(year);
         beforeReqVO.setSort(reqVO.getSort() - 1);
         List<IotOperationMeetingDetailDO> beforeSummarizedDetails = iotOperationMeetingDetailMapper.summarizedProjectDetails(beforeReqVO);
-        if (CollUtil.isNotEmpty(beforeSummarizedDetails)) {
-            // 如果上期次存在数据 才比较 财务数据 环比
-            beforeSummarizedDetails.forEach(detail -> {
-                beforeCompanyIds.add(detail.getDeptId());
-            });
-        }
         // 组装每个专业公司各项目的累加财务数据 本期 收入 挂账 回款 并计算 环比
-        Map<Long, BigDecimal> revenuePair = new HashMap<>();
-
+        if (CollUtil.isNotEmpty(beforeSummarizedDetails)) {
+            // 先以公司为单位 组装每个专业公司 的项目明细 然后再组装各专业公司的工作量细化数据
+            Map<Long, List<IotOperationMeetingDetailDO>> beforeCompanyDeptIdDetailPair = beforeSummarizedDetails.stream()
+                    .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId));
+            if (CollUtil.isNotEmpty(beforeCompanyDeptIdDetailPair)) {
+                beforeCompanyDeptIdDetailPair.forEach((deptId, details) -> {
+                    // key专业公司id    details公司各项目明细
+                    if (CollUtil.isNotEmpty(details)) {
+                        details.forEach(detail -> {
+                            // 组装细分的工作量
+                            List<IotTaskAttrModelProperty> properties = detail.getExtProperty();
+                            if (CollUtil.isNotEmpty(properties)) {
+                                // 公共属性 投运设备 施工设备
+                                BigDecimal inServiceDeviceNum = getActualValue(properties, "inServiceDeviceNum");
+                                BigDecimal constructionDeviceNum = getActualValue(properties, "constructionDeviceNum");
+                                beforeCompanyInServiceDeviceNumPair.merge(deptId, inServiceDeviceNum, BigDecimal::add);
+                                beforeCompanyConstructionDeviceNumPair.merge(deptId, constructionDeviceNum, BigDecimal::add);
+                            }
+                        });
+                    }
+                });
+            }
+            // key公司id   value上一期次公司本期收入
+            Map<Long, BigDecimal> beforeRevenuePair = beforeSummarizedDetails.stream()
+                    .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                            Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentRevenue, BigDecimal::add)));
+            // key公司id   value上一期次公司本期挂账
+            Map<Long, BigDecimal> beforeOnAccountPair = beforeSummarizedDetails.stream()
+                    .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                            Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentOnAccount, BigDecimal::add)));
+            // key公司id   value上一期次公司本期回款
+            Map<Long, BigDecimal> beforePaymentPair = beforeSummarizedDetails.stream()
+                    .collect(Collectors.groupingBy(IotOperationMeetingDetailDO::getDeptId,
+                            Collectors.reducing(BigDecimal.ZERO, IotOperationMeetingDetailDO::getCurrentPayment, BigDecimal::add)));
 
+        }
 
         // 组装每个会议的需要集团支持的事项
         Map<Long, IotOperationMeetingDO> supportPair = new HashMap<>();
@@ -602,32 +757,413 @@ public class IotOperationMeetingServiceImpl implements IotOperationMeetingServic
         companyMeetingIdDetailPair.values().forEach(list ->
                 list.sort(Comparator.comparingInt(detail ->
                         deptSortMap.getOrDefault(detail.getDeptId(), Integer.MAX_VALUE))));
-        // 排序后的会议项目明细列表
-        LinkedHashMap<Long, List<IotOperationMeetingDetailDO>> sortedMeetingDetails = companyMeetingIdDetailPair.entrySet().stream()
-                .sorted(Comparator.comparingInt(e -> deptSortMap.getOrDefault(e.getKey(), Integer.MAX_VALUE)))
-                .collect(Collectors.toMap(
-                        Map.Entry::getKey,
-                        Map.Entry::getValue,
-                        (v1, v2) -> v1,
-                        LinkedHashMap::new));
+
         companyMeetingIdDetailPair.forEach((meetingId, details) -> {
+            // 各专业公司会议 工作量扩展属性集合
+            List<IotTaskAttrModelProperty> companyExtProperties = new ArrayList<>();
             // meetingId会议id   details各专业公司的会议明细
             IotOperationMeetingRespVO tempMeeting = new IotOperationMeetingRespVO();
             if (supportPair.containsKey(meetingId)) {
                 IotOperationMeetingDO existMeeting = supportPair.get(meetingId);
-                tempMeeting.setDeptId(existMeeting.getDeptId());
+                Long deptId = existMeeting.getDeptId();
+                tempMeeting.setDeptId(deptId);
                 tempMeeting.setSupport(existMeeting.getSupport());
                 tempMeeting.setMeetingSeries(existMeeting.getMeetingSeries());
                 tempMeeting.setMeetingDate(existMeeting.getMeetingDate());
-                if (companyPair.containsKey(existMeeting.getDeptId())) {
-                    tempMeeting.setCompanyName(companyPair.get(existMeeting.getDeptId()));
+                if (companyPair.containsKey(deptId)) {
+                    tempMeeting.setCompanyName(companyPair.get(deptId));
                 }
                 // 判断公司的财务数据是否需要累计 新业务开发 非洲地区 中东地区 3个公司不累计
-                if (nonCumulativeDeptIds.contains(existMeeting.getDeptId())) {
+                if (nonCumulativeDeptIds.contains(deptId)) {
                     tempMeeting.setCumulative(false);
                 } else {
                     tempMeeting.setCumulative(true);
                 }
+                // 上期收入
+                BigDecimal beforeRevenue = CollUtil.isEmpty(beforeSummarizedDetails) ? BigDecimal.ZERO :
+                        beforeSummarizedDetails.stream()
+                                .filter(d -> deptId.equals(d.getDeptId()))
+                                .map(IotOperationMeetingDetailDO::getCurrentRevenue)
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                // 设置 各专业公司 财务数据汇总
+                if (currentRevenuePair.containsKey(deptId)) {
+                    BigDecimal currentRevenue = currentRevenuePair.get(deptId);
+                    // 本期收入
+                    tempMeeting.setCurrentRevenue(currentRevenue);
+                    // 计算本期收入 环比 (本期收入-上期收入)/上期收入
+                    if (beforeRevenue.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal revenuePeriodOnPeriod = currentRevenue.subtract(beforeRevenue).divide(beforeRevenue, 4, RoundingMode.HALF_UP);
+                        tempMeeting.setRevenuePeriodOnPeriod(revenuePeriodOnPeriod);
+                    }
+                }
+                tempMeeting.setBeforeRevenue(beforeRevenue);
+                if (currentTotalRevenuePair.containsKey(deptId)) {
+                    // 本期收入 累计
+                    tempMeeting.setCumulativeRevenue(currentTotalRevenuePair.get(deptId));
+                }
+                // 上期挂账
+                BigDecimal beforeOnAccount = CollUtil.isEmpty(beforeSummarizedDetails) ? BigDecimal.ZERO :
+                        beforeSummarizedDetails.stream()
+                                .filter(d -> deptId.equals(d.getDeptId()))
+                                .map(IotOperationMeetingDetailDO::getCurrentOnAccount)
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                if (currentOnAccountPair.containsKey(deptId)) {
+                    BigDecimal currentOnAccount = currentOnAccountPair.get(deptId);
+                    // 本期挂账
+                    tempMeeting.setCurrentOnAccount(currentOnAccount);
+                    // 计算本期挂账 环比 (本期挂账-上期挂账)/上期挂账
+                    if (beforeOnAccount.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal onAccountPeriodOnPeriod = currentOnAccount.subtract(beforeOnAccount).divide(beforeOnAccount, 4, RoundingMode.HALF_UP);
+                        tempMeeting.setOnAccountPeriodOnPeriod(onAccountPeriodOnPeriod);
+                    }
+                }
+                tempMeeting.setBeforeOnAccount(beforeOnAccount);
+                if (currentTotalOnAccountPair.containsKey(deptId)) {
+                    // 本期挂账 累计
+                    tempMeeting.setCumulativeOnAccount(currentTotalOnAccountPair.get(deptId));
+                }
+                // 上期回款
+                BigDecimal beforePayment = CollUtil.isEmpty(beforeSummarizedDetails) ? BigDecimal.ZERO :
+                        beforeSummarizedDetails.stream()
+                                .filter(d -> deptId.equals(d.getDeptId()))
+                                .map(IotOperationMeetingDetailDO::getCurrentPayment)
+                                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                if (currentPaymentPair.containsKey(deptId)) {
+                    // 本期回款
+                    BigDecimal currentPayment = currentPaymentPair.get(deptId);
+                    tempMeeting.setCurrentPayment(currentPayment);
+                    // 计算回款 环比 (本期回款-上期回款)/上期回款
+                    if (beforePayment.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal paymentPeriodOnPeriod = currentPayment.subtract(beforePayment).divide(beforePayment, 4, RoundingMode.HALF_UP);
+                        tempMeeting.setPaymentPeriodOnPeriod(paymentPeriodOnPeriod);
+                    }
+                }
+                tempMeeting.setBeforePayment(beforePayment);
+                if (currentTotalPaymentPair.containsKey(deptId)) {
+                    // 本期回款 累计
+                    tempMeeting.setCumulativePayment(currentTotalPaymentPair.get(deptId));
+                }
+                // 设置各专业公司的工作量细化数据
+                // 瑞恒 注气量 细化数据
+                if (companyPlanGasInjectionPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty planGasProperty = new IotTaskAttrModelProperty();
+                    planGasProperty.setName("计划注气量");
+                    planGasProperty.setAccessMode("r");
+                    planGasProperty.setRequired(1);
+                    planGasProperty.setSort(1);
+                    planGasProperty.setUnit("万方");
+                    planGasProperty.setDataType("double");
+                    planGasProperty.setIdentifier("planGasInjection");
+                    planGasProperty.setActualValue(companyPlanGasInjectionPair.get(deptId).toString());
+                    planGasProperty.setMaxValue(StrUtil.EMPTY);
+                    planGasProperty.setMinValue(StrUtil.EMPTY);
+                    planGasProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(planGasProperty);
+                }
+                if (companyActualGasInjectionPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty actualGasProperty = new IotTaskAttrModelProperty();
+                    actualGasProperty.setName("实际注气量");
+                    actualGasProperty.setAccessMode("r");
+                    actualGasProperty.setRequired(1);
+                    actualGasProperty.setSort(2);
+                    actualGasProperty.setUnit("万方");
+                    actualGasProperty.setDataType("double");
+                    actualGasProperty.setIdentifier("actualGasInjection");
+                    actualGasProperty.setActualValue(companyActualGasInjectionPair.get(deptId).toString());
+                    actualGasProperty.setMaxValue(StrUtil.EMPTY);
+                    actualGasProperty.setMinValue(StrUtil.EMPTY);
+                    actualGasProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(actualGasProperty);
+                }
+                if (companyCumulativeGasInjectionPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty cumulativeGasProperty = new IotTaskAttrModelProperty();
+                    cumulativeGasProperty.setName("累计注气量");
+                    cumulativeGasProperty.setAccessMode("r");
+                    cumulativeGasProperty.setRequired(1);
+                    cumulativeGasProperty.setSort(4);
+                    cumulativeGasProperty.setUnit("万方");
+                    cumulativeGasProperty.setDataType("double");
+                    cumulativeGasProperty.setIdentifier("cumulativeGasInjection");
+                    cumulativeGasProperty.setActualValue(companyCumulativeGasInjectionPair.get(deptId).toString());
+                    cumulativeGasProperty.setMaxValue(StrUtil.EMPTY);
+                    cumulativeGasProperty.setMinValue(StrUtil.EMPTY);
+                    cumulativeGasProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(cumulativeGasProperty);
+                }
+                // 注气量完成比
+                if (companyActualGasInjectionPair.containsKey(deptId) && companyPlanGasInjectionPair.containsKey(deptId)) {
+                    BigDecimal actualGasInjection = companyActualGasInjectionPair.get(deptId);
+                    BigDecimal planGasInjection = companyPlanGasInjectionPair.get(deptId);
+                    if (planGasInjection.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal gasCompletionRatio = actualGasInjection.divide(planGasInjection, 4, RoundingMode.HALF_UP);
+                        IotTaskAttrModelProperty gasCompletionRatioProperty = new IotTaskAttrModelProperty();
+                        gasCompletionRatioProperty.setName("注气完成比");
+                        gasCompletionRatioProperty.setAccessMode("r");
+                        gasCompletionRatioProperty.setRequired(1);
+                        gasCompletionRatioProperty.setSort(3);
+                        gasCompletionRatioProperty.setUnit("%");
+                        gasCompletionRatioProperty.setDataType("double");
+                        gasCompletionRatioProperty.setIdentifier("gasCompletionRatio");
+                        gasCompletionRatioProperty.setActualValue(gasCompletionRatio.toString());
+                        gasCompletionRatioProperty.setMaxValue(StrUtil.EMPTY);
+                        gasCompletionRatioProperty.setMinValue(StrUtil.EMPTY);
+                        gasCompletionRatioProperty.setDefaultValue(StrUtil.EMPTY);
+                        companyExtProperties.add(gasCompletionRatioProperty);
+                    }
+                }
+
+                // 瑞鹰 进尺 井次 细化数据
+                if (companyPlanFootagePair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty planFootageProperty = new IotTaskAttrModelProperty();
+                    planFootageProperty.setName("计划进尺");
+                    planFootageProperty.setAccessMode("r");
+                    planFootageProperty.setRequired(1);
+                    planFootageProperty.setSort(1);
+                    planFootageProperty.setUnit("m");
+                    planFootageProperty.setDataType("double");
+                    planFootageProperty.setIdentifier("planFootage");
+                    planFootageProperty.setActualValue(companyPlanFootagePair.get(deptId).toString());
+                    planFootageProperty.setMaxValue(StrUtil.EMPTY);
+                    planFootageProperty.setMinValue(StrUtil.EMPTY);
+                    planFootageProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(planFootageProperty);
+                }
+                if (companyActualFootagePair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty actualFootageProperty = new IotTaskAttrModelProperty();
+                    actualFootageProperty.setName("实际进尺");
+                    actualFootageProperty.setAccessMode("r");
+                    actualFootageProperty.setRequired(1);
+                    actualFootageProperty.setSort(2);
+                    actualFootageProperty.setUnit("m");
+                    actualFootageProperty.setDataType("double");
+                    actualFootageProperty.setIdentifier("actualFootage");
+                    actualFootageProperty.setActualValue(companyActualFootagePair.get(deptId).toString());
+                    actualFootageProperty.setMaxValue(StrUtil.EMPTY);
+                    actualFootageProperty.setMinValue(StrUtil.EMPTY);
+                    actualFootageProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(actualFootageProperty);
+                }
+                if (companyCumulativeFootagePair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty cumulativeFootageProperty = new IotTaskAttrModelProperty();
+                    cumulativeFootageProperty.setName("累计进尺");
+                    cumulativeFootageProperty.setAccessMode("r");
+                    cumulativeFootageProperty.setRequired(1);
+                    cumulativeFootageProperty.setSort(4);
+                    cumulativeFootageProperty.setUnit("m");
+                    cumulativeFootageProperty.setDataType("double");
+                    cumulativeFootageProperty.setIdentifier("cumulativeFootage");
+                    cumulativeFootageProperty.setActualValue(companyCumulativeFootagePair.get(deptId).toString());
+                    cumulativeFootageProperty.setMaxValue(StrUtil.EMPTY);
+                    cumulativeFootageProperty.setMinValue(StrUtil.EMPTY);
+                    cumulativeFootageProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(cumulativeFootageProperty);
+                }
+                // 进尺完成比
+                if (companyActualFootagePair.containsKey(deptId) && companyPlanFootagePair.containsKey(deptId)) {
+                    BigDecimal actualFootage = companyActualFootagePair.get(deptId);
+                    BigDecimal planFootage = companyPlanFootagePair.get(deptId);
+                    if (planFootage.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal footageCompletionRatio = actualFootage.divide(planFootage, 4, RoundingMode.HALF_UP);
+                        IotTaskAttrModelProperty footageCompletionRatioProperty = new IotTaskAttrModelProperty();
+                        footageCompletionRatioProperty.setName("进尺完成比");
+                        footageCompletionRatioProperty.setAccessMode("r");
+                        footageCompletionRatioProperty.setRequired(1);
+                        footageCompletionRatioProperty.setSort(3);
+                        footageCompletionRatioProperty.setUnit("%");
+                        footageCompletionRatioProperty.setDataType("double");
+                        footageCompletionRatioProperty.setIdentifier("footageCompletionRatio");
+                        footageCompletionRatioProperty.setActualValue(footageCompletionRatio.toString());
+                        footageCompletionRatioProperty.setMaxValue(StrUtil.EMPTY);
+                        footageCompletionRatioProperty.setMinValue(StrUtil.EMPTY);
+                        footageCompletionRatioProperty.setDefaultValue(StrUtil.EMPTY);
+                        companyExtProperties.add(footageCompletionRatioProperty);
+                    }
+                }
+                // 瑞鹰 瑞都 井次
+                if (companyPlanWellTripsPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty planWellTripsProperty = new IotTaskAttrModelProperty();
+                    planWellTripsProperty.setName("计划井次");
+                    planWellTripsProperty.setAccessMode("r");
+                    planWellTripsProperty.setRequired(1);
+                    planWellTripsProperty.setSort(5);
+                    planWellTripsProperty.setUnit("井");
+                    planWellTripsProperty.setDataType("double");
+                    planWellTripsProperty.setIdentifier("planWellTrips");
+                    planWellTripsProperty.setActualValue(companyPlanWellTripsPair.get(deptId).toString());
+                    planWellTripsProperty.setMaxValue(StrUtil.EMPTY);
+                    planWellTripsProperty.setMinValue(StrUtil.EMPTY);
+                    planWellTripsProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(planWellTripsProperty);
+                }
+                if (companyActualWellTripsPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty actualWellTripsProperty = new IotTaskAttrModelProperty();
+                    actualWellTripsProperty.setName("实际井次");
+                    actualWellTripsProperty.setAccessMode("r");
+                    actualWellTripsProperty.setRequired(1);
+                    actualWellTripsProperty.setSort(6);
+                    actualWellTripsProperty.setUnit("井");
+                    actualWellTripsProperty.setDataType("double");
+                    actualWellTripsProperty.setIdentifier("actualWellTrips");
+                    actualWellTripsProperty.setActualValue(companyActualWellTripsPair.get(deptId).toString());
+                    actualWellTripsProperty.setMaxValue(StrUtil.EMPTY);
+                    actualWellTripsProperty.setMinValue(StrUtil.EMPTY);
+                    actualWellTripsProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(actualWellTripsProperty);
+                }
+                if (companyCumulativeWellTripsPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty cumulativeWellTripsProperty = new IotTaskAttrModelProperty();
+                    cumulativeWellTripsProperty.setName("累计井次");
+                    cumulativeWellTripsProperty.setAccessMode("r");
+                    cumulativeWellTripsProperty.setRequired(1);
+                    cumulativeWellTripsProperty.setSort(8);
+                    cumulativeWellTripsProperty.setUnit("井");
+                    cumulativeWellTripsProperty.setDataType("double");
+                    cumulativeWellTripsProperty.setIdentifier("cumulativeWellTrips");
+                    cumulativeWellTripsProperty.setActualValue(companyCumulativeWellTripsPair.get(deptId).toString());
+                    cumulativeWellTripsProperty.setMaxValue(StrUtil.EMPTY);
+                    cumulativeWellTripsProperty.setMinValue(StrUtil.EMPTY);
+                    cumulativeWellTripsProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(cumulativeWellTripsProperty);
+                }
+                // 井次完成比
+                if (companyActualWellTripsPair.containsKey(deptId) && companyPlanWellTripsPair.containsKey(deptId)) {
+                    BigDecimal actualWellTrips = companyActualWellTripsPair.get(deptId);
+                    BigDecimal planWellTrips = companyPlanWellTripsPair.get(deptId);
+                    if (planWellTrips.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal wellTripsCompletionRatio = actualWellTrips.divide(planWellTrips, 4, RoundingMode.HALF_UP);
+                        IotTaskAttrModelProperty wellTripsCompletionRatioProperty = new IotTaskAttrModelProperty();
+                        wellTripsCompletionRatioProperty.setName("井次完成比");
+                        wellTripsCompletionRatioProperty.setAccessMode("r");
+                        wellTripsCompletionRatioProperty.setRequired(1);
+                        wellTripsCompletionRatioProperty.setSort(7);
+                        wellTripsCompletionRatioProperty.setUnit("%");
+                        wellTripsCompletionRatioProperty.setDataType("double");
+                        wellTripsCompletionRatioProperty.setIdentifier("wellTripsCompletionRatio");
+                        wellTripsCompletionRatioProperty.setActualValue(wellTripsCompletionRatio.toString());
+                        wellTripsCompletionRatioProperty.setMaxValue(StrUtil.EMPTY);
+                        wellTripsCompletionRatioProperty.setMinValue(StrUtil.EMPTY);
+                        wellTripsCompletionRatioProperty.setDefaultValue(StrUtil.EMPTY);
+                        companyExtProperties.add(wellTripsCompletionRatioProperty);
+                    }
+                }
+
+                // 5#公司 瑞都 层数
+                if (companyPlanLayersPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty planLayersProperty = new IotTaskAttrModelProperty();
+                    planLayersProperty.setName("计划层数");
+                    planLayersProperty.setAccessMode("r");
+                    planLayersProperty.setRequired(1);
+                    planLayersProperty.setSort(1);
+                    planLayersProperty.setUnit("层");
+                    planLayersProperty.setDataType("double");
+                    planLayersProperty.setIdentifier("planLayers");
+                    planLayersProperty.setActualValue(companyPlanLayersPair.get(deptId).toString());
+                    planLayersProperty.setMaxValue(StrUtil.EMPTY);
+                    planLayersProperty.setMinValue(StrUtil.EMPTY);
+                    planLayersProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(planLayersProperty);
+                }
+                if (companyActualLayersPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty actualLayersProperty = new IotTaskAttrModelProperty();
+                    actualLayersProperty.setName("实际层数");
+                    actualLayersProperty.setAccessMode("r");
+                    actualLayersProperty.setRequired(1);
+                    actualLayersProperty.setSort(2);
+                    actualLayersProperty.setUnit("层");
+                    actualLayersProperty.setDataType("double");
+                    actualLayersProperty.setIdentifier("actualLayers");
+                    actualLayersProperty.setActualValue(companyActualLayersPair.get(deptId).toString());
+                    actualLayersProperty.setMaxValue(StrUtil.EMPTY);
+                    actualLayersProperty.setMinValue(StrUtil.EMPTY);
+                    actualLayersProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(actualLayersProperty);
+                }
+                if (companyCumulativeLayersPair.containsKey(deptId)) {
+                    IotTaskAttrModelProperty cumulativeLayersProperty = new IotTaskAttrModelProperty();
+                    cumulativeLayersProperty.setName("累计层数");
+                    cumulativeLayersProperty.setAccessMode("r");
+                    cumulativeLayersProperty.setRequired(1);
+                    cumulativeLayersProperty.setSort(4);
+                    cumulativeLayersProperty.setUnit("层");
+                    cumulativeLayersProperty.setDataType("double");
+                    cumulativeLayersProperty.setIdentifier("cumulativeLayers");
+                    cumulativeLayersProperty.setActualValue(companyCumulativeLayersPair.get(deptId).toString());
+                    cumulativeLayersProperty.setMaxValue(StrUtil.EMPTY);
+                    cumulativeLayersProperty.setMinValue(StrUtil.EMPTY);
+                    cumulativeLayersProperty.setDefaultValue(StrUtil.EMPTY);
+                    companyExtProperties.add(cumulativeLayersProperty);
+                }
+                // 层数完成比
+                if (companyActualLayersPair.containsKey(deptId) && companyPlanLayersPair.containsKey(deptId)) {
+                    BigDecimal actualLayers = companyActualLayersPair.get(deptId);
+                    BigDecimal planLayers = companyPlanLayersPair.get(deptId);
+                    if (planLayers.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal layersCompletionRatio = actualLayers.divide(planLayers, 4, RoundingMode.HALF_UP);
+                        IotTaskAttrModelProperty layersCompletionRatioProperty = new IotTaskAttrModelProperty();
+                        layersCompletionRatioProperty.setName("层数完成比");
+                        layersCompletionRatioProperty.setAccessMode("r");
+                        layersCompletionRatioProperty.setRequired(1);
+                        layersCompletionRatioProperty.setSort(3);
+                        layersCompletionRatioProperty.setUnit("%");
+                        layersCompletionRatioProperty.setDataType("double");
+                        layersCompletionRatioProperty.setIdentifier("layersCompletionRatio");
+                        layersCompletionRatioProperty.setActualValue(layersCompletionRatio.toString());
+                        layersCompletionRatioProperty.setMaxValue(StrUtil.EMPTY);
+                        layersCompletionRatioProperty.setMinValue(StrUtil.EMPTY);
+                        layersCompletionRatioProperty.setDefaultValue(StrUtil.EMPTY);
+                        companyExtProperties.add(layersCompletionRatioProperty);
+                    }
+                }
+
+                if (companyInServiceDeviceNumPair.containsKey(deptId) && companyConstructionDeviceNumPair.containsKey(deptId)) {
+                    // 各专业公司共用属性 设备利用率 施工设备/投运设备
+                    BigDecimal inServiceDeviceNum = companyInServiceDeviceNumPair.get(deptId);
+                    BigDecimal constructionDeviceNum = companyConstructionDeviceNumPair.get(deptId);
+                    if (inServiceDeviceNum.compareTo(BigDecimal.ZERO) > 0) {
+                        BigDecimal utilizationRate = constructionDeviceNum.divide(inServiceDeviceNum, 4, RoundingMode.HALF_UP);
+                        IotTaskAttrModelProperty utilizationRateProperty = new IotTaskAttrModelProperty();
+                        utilizationRateProperty.setName("设备利用率");
+                        utilizationRateProperty.setAccessMode("r");
+                        utilizationRateProperty.setRequired(1);
+                        utilizationRateProperty.setSort(3);
+                        utilizationRateProperty.setUnit("%");
+                        utilizationRateProperty.setDataType("double");
+                        utilizationRateProperty.setIdentifier("utilizationRate");
+                        utilizationRateProperty.setActualValue(utilizationRate.toString());
+                        utilizationRateProperty.setMaxValue(StrUtil.EMPTY);
+                        utilizationRateProperty.setMinValue(StrUtil.EMPTY);
+                        utilizationRateProperty.setDefaultValue(StrUtil.EMPTY);
+                        companyExtProperties.add(utilizationRateProperty);
+                        // 设备利用率 环比 (本期-上期)/上期
+                        if (beforeCompanyInServiceDeviceNumPair.containsKey(deptId) && beforeCompanyConstructionDeviceNumPair.containsKey(deptId)) {
+                            // 计算上期会议 对应专业公司的设备利用率
+                            BigDecimal beforeInServiceDeviceNum = beforeCompanyInServiceDeviceNumPair.get(deptId);
+                            BigDecimal beforeConstructionDeviceNum = beforeCompanyConstructionDeviceNumPair.get(deptId);
+                            if (beforeInServiceDeviceNum.compareTo(BigDecimal.ZERO) > 0) {
+                                BigDecimal beforeUtilizationRate = beforeConstructionDeviceNum.divide(beforeInServiceDeviceNum, 4, RoundingMode.HALF_UP);
+                                if (beforeUtilizationRate.compareTo(BigDecimal.ZERO) > 0) {
+                                    BigDecimal periodOnPeriod = utilizationRate.subtract(beforeUtilizationRate).divide(beforeUtilizationRate, 4, RoundingMode.HALF_UP);
+                                    IotTaskAttrModelProperty periodOnPeriodProperty = new IotTaskAttrModelProperty();
+                                    periodOnPeriodProperty.setName("环比");
+                                    periodOnPeriodProperty.setAccessMode("r");
+                                    periodOnPeriodProperty.setRequired(1);
+                                    periodOnPeriodProperty.setSort(8);
+                                    periodOnPeriodProperty.setUnit("%");
+                                    periodOnPeriodProperty.setDataType("double");
+                                    periodOnPeriodProperty.setIdentifier("periodOnPeriod");
+                                    periodOnPeriodProperty.setActualValue(periodOnPeriod.toString());
+                                    periodOnPeriodProperty.setMaxValue(StrUtil.EMPTY);
+                                    periodOnPeriodProperty.setMinValue(StrUtil.EMPTY);
+                                    periodOnPeriodProperty.setDefaultValue(StrUtil.EMPTY);
+                                    companyExtProperties.add(periodOnPeriodProperty);
+                                }
+                            }
+                        }
+                    }
+
+                }
+                // 设置各专业公司的工作量汇总数据
+                tempMeeting.setExtProperty(companyExtProperties);
                 List<IotOperationMeetingDetailRespVO> meetingDetails = BeanUtils.toBean(details, IotOperationMeetingDetailRespVO.class);
                 tempMeeting.setDetails(meetingDetails);
                 resultMeetings.add(tempMeeting);