From e7faf1e13cccfcde861b55f8d5afcd4f4f342440 Mon Sep 17 00:00:00 2001 From: tangwei Date: Wed, 3 Jun 2026 14:48:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=9F=E6=80=81=E6=B5=81=E9=87=8F?= =?UTF-8?q?=E8=BE=BE=E6=A0=87=E7=8E=87=E5=B0=8F=E6=97=B6=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?(=E4=BA=8C=E7=BA=A7=E9=A1=B5=E9=9D=A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eq/controller/EngEqDataController.java | 7 + .../eq/entity/vo/EngEqHourIntervalVo.java | 137 +++++ .../qgc_eng/eq/service/EngEqDataService.java | 3 + .../eq/service/impl/EngEqDataServiceImpl.java | 487 +++++++++++++++++- 4 files changed, 633 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqHourIntervalVo.java diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java index ce3f64d0..092e4be2 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/controller/EngEqDataController.java @@ -3,6 +3,7 @@ package com.yfd.platform.qgc_eng.eq.controller; import com.yfd.platform.common.DataSourceLoadOptionsBase; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.config.ResponseResult; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo; @@ -39,6 +40,12 @@ public class EngEqDataController { return ResponseResult.successData(engEqDataService.getIntervalKendoListCust(dataSourceRequest)); } + @PostMapping("/interval/qgc/hour/GetKendoListCust") + @Operation(summary = "生态流量达标率小时统计(二级页面)") + public ResponseResult getQgcHourKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) { + return ResponseResult.successData(engEqDataService.getQgcHourKendoListCust(dataSourceRequest)); + } + @PostMapping("/interval/qgc/getQgcStaticData") @Operation(summary = "生态流量达标率区间范围统计(一级页面)") public ResponseResult getQgcStaticData(@RequestBody DataSourceRequest dataSourceRequest) { diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqHourIntervalVo.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqHourIntervalVo.java new file mode 100644 index 00000000..fcc87f1e --- /dev/null +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/entity/vo/EngEqHourIntervalVo.java @@ -0,0 +1,137 @@ +package com.yfd.platform.qgc_eng.eq.entity.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@Schema(description = "生态流量达标率小时统计") +public class EngEqHourIntervalVo { + + @Schema(description = "电站编码") + private String stcd; + + @Schema(description = "电站名称") + private String stnm; + + @Schema(description = "工程名称") + private String ennm; + + @Schema(description = "站类") + private String sttp; + + @Schema(description = "站类编码") + private String sttpCode; + + @Schema(description = "基地编码") + private String baseId; + + @Schema(description = "基地名称") + private String baseName; + + @Schema(description = "基地流域编码") + private String hbrvcd; + + @Schema(description = "基地流域名称") + private String hbrvcdName; + + @Schema(description = "行政区名称") + private String addvcdName; + + @Schema(description = "经度") + private BigDecimal lgtd; + + @Schema(description = "纬度") + private BigDecimal lttd; + + @Schema(description = "高程") + private BigDecimal dtmel; + + @Schema(description = "装机容量") + private BigDecimal ttpwr; + + @Schema(description = "正常蓄水位") + private BigDecimal normz; + + @Schema(description = "多年平均流量") + private BigDecimal avq; + + @Schema(description = "是否接入") + private Integer dtin; + + @Schema(description = "环保数据接入状态") + private Integer dtinEnv; + + @Schema(description = "工程规模") + private Integer prsc; + + @Schema(description = "建设状态分类") + private Integer bldsttCcode; + + @Schema(description = "入库流量") + private BigDecimal qi; + + @Schema(description = "出库流量") + private BigDecimal qo; + + @Schema(description = "生态流量") + private BigDecimal qec; + + @Schema(description = "坝上水位") + private BigDecimal rz; + + @Schema(description = "生态流量达标率") + private BigDecimal qecRate; + + @Schema(description = "水利部生态流量达标率") + private BigDecimal mwrRate; + + @Schema(description = "多年平均生态流量达标率") + private BigDecimal avqRate; + + @Schema(description = "环保部区间") + private String qecInterval; + + @Schema(description = "水利部区间") + private String mwrInterval; + + @Schema(description = "多年平均区间") + private String avqInterval; + + @Schema(description = "环保部锚点状态") + private String anchoPointState; + + @Schema(description = "水利部锚点状态") + private String mwrPointState; + + @Schema(description = "多年平均锚点状态") + private String avqPointState; + + @Schema(description = "入库流量合计") + private BigDecimal qiSum; + + @Schema(description = "出库流量合计") + private BigDecimal qoSum; + + @Schema(description = "补水总量") + private BigDecimal fillWater; + + @Schema(description = "标题名称") + private String titleName; + + @Schema(description = "生态类型") + private String eqtp; + + @Schema(description = "基地排序") + private Integer baseStepSort; + + @Schema(description = "流域排序") + private Integer rvcdStepSort; + + @Schema(description = "电站排序") + private Integer rstcdStepSort; + + @Schema(description = "站点排序") + private Integer siteStepSort; +} diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java index 2932c505..9e3e7031 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/EngEqDataService.java @@ -2,6 +2,7 @@ package com.yfd.platform.qgc_eng.eq.service; import com.yfd.platform.common.DataSourceRequest; import com.yfd.platform.common.DataSourceResult; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqVmsstbprptVo; @@ -15,6 +16,8 @@ public interface EngEqDataService { DataSourceResult getIntervalKendoListCust(DataSourceRequest dataSourceRequest); + DataSourceResult getQgcHourKendoListCust(DataSourceRequest dataSourceRequest); + QgcQecStaticVo getQgcStaticData(DataSourceRequest dataSourceRequest, String type); DataSourceResult getWbsbList(DataSourceRequest dataSourceRequest); diff --git a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java index 1d251c5c..b0aed9b3 100644 --- a/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java +++ b/backend/src/main/java/com/yfd/platform/qgc_eng/eq/service/impl/EngEqDataServiceImpl.java @@ -12,6 +12,7 @@ import com.yfd.platform.common.MicroservicDynamicSQLMapper; import com.yfd.platform.common.enums.QecIntervalEnum; import com.yfd.platform.common.enums.ShowEnum; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqDataVo; +import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqHourIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqIntervalVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqRateCountVo; import com.yfd.platform.qgc_eng.eq.entity.vo.EngEqStaticIntervalVo; @@ -61,6 +62,15 @@ public class EngEqDataServiceImpl implements EngEqDataService { return queryIntervalGroupList(dataSourceRequest, loadOptions); } + @Override + public DataSourceResult getQgcHourKendoListCust(DataSourceRequest dataSourceRequest) { + DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest(); + if (CollUtil.isEmpty(dataSourceRequest == null ? null : dataSourceRequest.getGroup())) { + return queryHourIntervalDetailList(dataSourceRequest, loadOptions); + } + return queryHourIntervalGroupList(dataSourceRequest, loadOptions); + } + @Override public QgcQecStaticVo getQgcStaticData(DataSourceRequest dataSourceRequest, String type) { List intervalList = queryStaticIntervals(dataSourceRequest, type); @@ -248,6 +258,473 @@ public class EngEqDataServiceImpl implements EngEqDataService { return result; } + private DataSourceResult queryHourIntervalDetailList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + Map paramMap = new HashMap<>(); + int[] indexHolder = new int[]{0}; + String viewSql = buildHourIntervalViewSql(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, indexHolder); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(buildHourDetailSelectSql(dataSourceRequest == null ? null : dataSourceRequest.getSelect())) + .append(" FROM (") + .append(viewSql) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildHourFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, indexHolder); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + if (CollUtil.isNotEmpty(dataSourceRequest == null ? null : dataSourceRequest.getAggregate()) + && "average".equalsIgnoreCase(dataSourceRequest.getAggregate().get(0).getAggregate())) { + return buildHourIntervalAggregateResult(dataSourceRequest, sql.toString(), paramMap); + } + + sql.append(buildHourDetailOrderBySql(dataSourceRequest == null ? null : dataSourceRequest.getSort())); + Page page = loadOptions == null ? null : QgcQueryWrapperUtil.buildPage(loadOptions, loadOptions.getSkip(), loadOptions.getTake()); + List list = microservicDynamicSQLMapper.pageAllListWithResultType(page, sql.toString(), paramMap, EngEqHourIntervalVo.class); + postProcessHourIntervalList(list); + + DataSourceResult result = new DataSourceResult<>(); + result.setData(list); + result.setTotal(page != null ? page.getTotal() : list.size()); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult queryHourIntervalGroupList(DataSourceRequest dataSourceRequest, + DataSourceLoadOptionsBase loadOptions) { + List groups = dataSourceRequest.getGroup(); + GroupingInfo[] groupInfos = loadOptions == null ? new GroupingInfo[0] : loadOptions.getGroup(); + Map paramMap = new HashMap<>(); + int[] indexHolder = new int[]{0}; + String viewSql = buildHourIntervalViewSql(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, indexHolder); + + List selectItems = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapHourColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + selectItems.add(column + " AS " + descriptor.getField().toUpperCase()); + selectItems.add("COUNT(*) AS COUNT_" + descriptor.getField().toUpperCase()); + if (CollUtil.isNotEmpty(descriptor.getAggregates())) { + for (DataSourceRequest.AggregateDescriptor aggregate : descriptor.getAggregates()) { + String aggregateColumn = mapHourColumn(aggregate.getField()); + if (StrUtil.isBlank(aggregateColumn) || StrUtil.isBlank(aggregate.getAggregate())) { + continue; + } + selectItems.add(buildAggregateSql(aggregate.getAggregate(), aggregateColumn, aggregate.getField())); + } + } + } + if (selectItems.isEmpty()) { + selectItems.add("t.STCD AS STCD"); + selectItems.add("COUNT(*) AS COUNT_STCD"); + } + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT ") + .append(String.join(", ", selectItems)) + .append(" FROM (") + .append(viewSql) + .append(") t WHERE 1 = 1 "); + + String filterSql = buildHourFilterCondition(dataSourceRequest == null ? null : dataSourceRequest.getFilter(), paramMap, indexHolder); + if (StrUtil.isNotBlank(filterSql)) { + sql.append(" AND ").append(filterSql).append(" "); + } + + List groupByColumns = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapHourColumn(descriptor.getField()); + if (StrUtil.isNotBlank(column)) { + groupByColumns.add(column); + } + } + if (!groupByColumns.isEmpty()) { + sql.append(" GROUP BY ").append(String.join(", ", groupByColumns)).append(" "); + } + sql.append(buildHourGroupOrderBySql(groups)); + + List> rows = microservicDynamicSQLMapper.pageAllList(null, sql.toString(), paramMap); + DataSourceResult result = new DataSourceResult<>(); + if (Boolean.TRUE.equals(dataSourceRequest.getGroupResultFlat())) { + result.setData((List) (List) new GroupHelper().faltGroup(rows, Arrays.asList(groupInfos))); + } else { + result.setData((List) (List) new GroupHelper().group(rows, Arrays.asList(groupInfos))); + } + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private DataSourceResult buildHourIntervalAggregateResult(DataSourceRequest dataSourceRequest, + String sourceSql, + Map paramMap) { + List aggregateItems = new ArrayList<>(); + for (DataSourceRequest.AggregateDescriptor item : dataSourceRequest.getAggregate()) { + if (item == null || !"average".equalsIgnoreCase(item.getAggregate())) { + continue; + } + String column = mapHourColumn(item.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + aggregateItems.add("AVG(" + column + ") AS " + item.getField()); + } + if (aggregateItems.isEmpty()) { + DataSourceResult emptyResult = new DataSourceResult<>(); + emptyResult.setData(new ArrayList<>()); + emptyResult.setTotal(0L); + emptyResult.setAggregates(new HashMap<>()); + return emptyResult; + } + + String sql = "SELECT " + String.join(", ", aggregateItems) + " FROM (" + sourceSql + ")"; + List> list = microservicDynamicSQLMapper.pageAllList(null, sql, paramMap); + DataSourceResult result = new DataSourceResult<>(); + result.setData((List) (List) list); + result.setTotal(0L); + result.setAggregates(new HashMap<>()); + return result; + } + + private void postProcessHourIntervalList(List list) { + if (CollUtil.isEmpty(list)) { + return; + } + for (EngEqHourIntervalVo item : list) { + if (item == null) { + continue; + } + if (item.getQiSum() != null && item.getQoSum() != null) { + item.setFillWater(item.getQoSum().subtract(item.getQiSum())); + } + item.setTitleName(item.getEnnm()); + item.setEqtp("QEC"); + } + } + + private String buildHourIntervalViewSql(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + boolean hasDtinFilter = CollUtil.isNotEmpty(findFilterValues(filter, "dtin")); + String validTimeFilter = buildIntervalTmFilterCondition(filter, "valid.TM", paramMap, indexHolder, 0); + return "SELECT " + + "eng.STCD AS stcd, " + + "eng.ENNM AS stnm, " + + "eng.ENNM AS ennm, " + + "'ENG' AS sttp, " + + "'ENG' AS sttpCode, " + + "eng.BASE_ID AS baseId, " + + "hb.BASENAME AS baseName, " + + "eng.HBRVCD AS hbrvcd, " + + "hbrv.HBRVNM AS hbrvcdName, " + + "addv.ADDVNM AS addvcdName, " + + "eng.LGTD AS lgtd, " + + "eng.LTTD AS lttd, " + + "eng.ELEV AS dtmel, " + + "CAST(NULL AS NUMBER(18,6)) AS ttpwr, " + + "CAST(NULL AS NUMBER(18,6)) AS normz, " + + "eng.AVQ AS avq, " + + "eng.DTIN AS dtin, " + + "eng.DTIN_ENV AS dtinEnv, " + + "eng.PRSC AS prsc, " + + "eng.BLDSTT_CODE AS bldsttCcode, " + + "runAgg.QI AS qi, " + + "runAgg.QO AS qo, " + + "runAgg.QEC AS qec, " + + "runAgg.RZ AS rz, " + + buildIntervalRateDisplaySql("met.QEC_RATE") + " AS qecRate, " + + buildIntervalRateDisplaySql("met.MWR_RATE") + " AS mwrRate, " + + buildIntervalRateDisplaySql("met.AVQ_RATE") + " AS avqRate, " + + buildStaticIntervalSql("met.QEC_RATE", "met.QR", "qecNoRule.STCD", false) + " AS qecInterval, " + + buildStaticIntervalSql("met.MWR_RATE", "met.MQR", "mwrNoRule.STCD", false) + " AS mwrInterval, " + + buildStaticIntervalSql("met.AVQ_RATE", "met.AQR", "eng.AVQ", true) + " AS avqInterval, " + + buildHourPointStateSql("met.QEC_RATE") + " AS anchoPointState, " + + buildHourPointStateSql("met.MWR_RATE") + " AS mwrPointState, " + + buildHourPointStateSql("met.AVQ_RATE") + " AS avqPointState, " + + "runAgg.QI_SUM AS qiSum, " + + "runAgg.QO_SUM AS qoSum, " + + "CAST(NULL AS NUMBER(18,6)) AS fillWater, " + + "CAST(NULL AS VARCHAR2(255)) AS titleName, " + + "CAST(NULL AS VARCHAR2(20)) AS eqtp, " + + "NVL(hb.ORDER_INDEX, 999999) AS baseStepSort, " + + "NVL(along.ORDER_INDEX, 999999) AS rvcdStepSort, " + + "NVL(rstSort.SORT, 999999) AS rstcdStepSort, " + + "NVL(siteSort.SORT, 999999) AS siteStepSort " + + "FROM SD_ENGINFO_B_H eng " + + "LEFT JOIN SD_HYDROBASE hb ON hb.BASEID = eng.BASE_ID AND NVL(hb.IS_DELETED, 0) = 0 " + + "LEFT JOIN SD_HBRV_DIC hbrv ON hbrv.HBRVCD = eng.HBRVCD AND hbrv.BASEID = eng.BASE_ID " + + " AND NVL(hbrv.IS_DELETED, 0) = 0 AND NVL(hbrv.ENABLED, 1) = 1 " + + "LEFT JOIN SD_ADDVCD_DIC addv ON addv.ADDVCD = eng.ADDVCD " + + "LEFT JOIN MS_ALONG_B along ON along.RVCD = eng.HBRVCD AND along.CODE = 'common' AND NVL(along.IS_DELETED, 0) = 0 " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") rstSort ON rstSort.RVCD = eng.HBRVCD AND rstSort.STCD = eng.STCD " + + "LEFT JOIN ( " + + " SELECT det.SORT, cfg.RVCD, det.STCD " + + " FROM MS_ALONGDET_B det " + + " INNER JOIN MS_ALONG_B cfg ON det.ALONG_ID = cfg.ID " + + " WHERE NVL(det.IS_DELETED, 0) = 0 AND NVL(cfg.IS_DELETED, 0) = 0 AND cfg.CODE = 'common' " + + ") siteSort ON siteSort.RVCD = eng.HBRVCD AND siteSort.STCD = eng.STCD " + + "LEFT JOIN (" + buildHourMetricSourceSql(filter, paramMap, indexHolder, 0) + ") met ON met.STCD = eng.STCD " + + "LEFT JOIN (" + buildHourRunSourceSql(filter, paramMap, indexHolder, 0) + ") runAgg ON runAgg.STCD = eng.STCD " + + "LEFT JOIN (" + buildStaticRuleSql("EQMN") + ") qecNoRule ON qecNoRule.STCD = eng.STCD " + + "LEFT JOIN (" + buildStaticRuleSql("EQMNMWR") + ") mwrNoRule ON mwrNoRule.STCD = eng.STCD " + + "WHERE NVL(eng.IS_DELETED, 0) = 0 " + + " AND NVL(eng.BLDSTT_CODE, 0) = 2 " + + (hasDtinFilter ? "" : " AND NVL(eng.DTIN, 0) = 1 ") + + " AND EXISTS (SELECT 1 FROM SD_QEC_R valid WHERE valid.STCD = eng.STCD AND NVL(valid.IS_DELETED, 0) = 0" + + (StrUtil.isNotBlank(validTimeFilter) ? " AND " + validTimeFilter : "") + + ")"; + } + + private String buildHourMetricSourceSql(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + int yearOffset) { + return buildStaticAggregateSql("hour", filter, paramMap, indexHolder, yearOffset); + } + + private String buildHourRunSourceSql(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + int yearOffset) { + String timeFilter = buildIntervalTmFilterCondition(filter, "run.TM", paramMap, indexHolder, yearOffset); + return "SELECT run.STCD, " + + "AVG(run.QI) AS QI, " + + "AVG(run.QO) AS QO, " + + "AVG(run.QEC) AS QEC, " + + "AVG(run.RZ) AS RZ, " + + "SUM(run.QI) AS QI_SUM, " + + "SUM(run.QO) AS QO_SUM " + + "FROM SD_HYDROPW_R run " + + "WHERE NVL(run.IS_DELETED, 0) = 0 " + + (StrUtil.isNotBlank(timeFilter) ? " AND " + timeFilter : "") + + " GROUP BY run.STCD"; + } + + private String buildHourPointStateSql(String rateColumn) { + return "CASE " + + "WHEN " + rateColumn + " IS NULL AND eng.PRSC = 1 THEN 'eef_1_none' " + + "WHEN " + rateColumn + " >= 95 AND eng.PRSC = 1 THEN 'eef_1_1' " + + "WHEN " + rateColumn + " >= 90 AND " + rateColumn + " < 95 AND eng.PRSC = 1 THEN 'eef_1_2' " + + "WHEN " + rateColumn + " >= 80 AND " + rateColumn + " < 90 AND eng.PRSC = 1 THEN 'eef_1_3' " + + "WHEN " + rateColumn + " < 80 AND eng.PRSC = 1 THEN 'eef_1_4' " + + "WHEN " + rateColumn + " IS NULL AND eng.PRSC IN (2, 3) THEN 'eef_2_none' " + + "WHEN " + rateColumn + " >= 95 AND eng.PRSC IN (2, 3) THEN 'eef_2_1' " + + "WHEN " + rateColumn + " >= 90 AND " + rateColumn + " < 95 AND eng.PRSC IN (2, 3) THEN 'eef_2_2' " + + "WHEN " + rateColumn + " >= 80 AND " + rateColumn + " < 90 AND eng.PRSC IN (2, 3) THEN 'eef_2_3' " + + "WHEN " + rateColumn + " < 80 AND eng.PRSC IN (2, 3) THEN 'eef_2_4' " + + "END"; + } + + private String buildHourDetailSelectSql(List selectFields) { + Map columns = hourFieldColumns(); + List selected = new ArrayList<>(); + if (CollUtil.isEmpty(selectFields)) { + selected.addAll(columns.values()); + } else { + for (String field : selectFields) { + String column = columns.get(field); + if (StrUtil.isNotBlank(column)) { + selected.add(column); + } + } + if (selected.isEmpty()) { + selected.addAll(columns.values()); + } + } + return String.join(", ", selected); + } + + private Map hourFieldColumns() { + Map columns = new LinkedHashMap<>(); + columns.put("stcd", "t.stcd AS stcd"); + columns.put("stnm", "t.stnm AS stnm"); + columns.put("ennm", "t.ennm AS ennm"); + columns.put("sttp", "t.sttp AS sttp"); + columns.put("sttpCode", "t.sttpCode AS sttpCode"); + columns.put("baseId", "t.baseId AS baseId"); + columns.put("baseName", "t.baseName AS baseName"); + columns.put("hbrvcd", "t.hbrvcd AS hbrvcd"); + columns.put("hbrvcdName", "t.hbrvcdName AS hbrvcdName"); + columns.put("addvcdName", "t.addvcdName AS addvcdName"); + columns.put("lgtd", "t.lgtd AS lgtd"); + columns.put("lttd", "t.lttd AS lttd"); + columns.put("dtmel", "t.dtmel AS dtmel"); + columns.put("ttpwr", "t.ttpwr AS ttpwr"); + columns.put("normz", "t.normz AS normz"); + columns.put("avq", "t.avq AS avq"); + columns.put("dtin", "t.dtin AS dtin"); + columns.put("dtinEnv", "t.dtinEnv AS dtinEnv"); + columns.put("prsc", "t.prsc AS prsc"); + columns.put("bldsttCcode", "t.bldsttCcode AS bldsttCcode"); + columns.put("qi", "t.qi AS qi"); + columns.put("qo", "t.qo AS qo"); + columns.put("qec", "t.qec AS qec"); + columns.put("rz", "t.rz AS rz"); + columns.put("qecRate", "t.qecRate AS qecRate"); + columns.put("mwrRate", "t.mwrRate AS mwrRate"); + columns.put("avqRate", "t.avqRate AS avqRate"); + columns.put("qecInterval", "t.qecInterval AS qecInterval"); + columns.put("mwrInterval", "t.mwrInterval AS mwrInterval"); + columns.put("avqInterval", "t.avqInterval AS avqInterval"); + columns.put("anchoPointState", "t.anchoPointState AS anchoPointState"); + columns.put("mwrPointState", "t.mwrPointState AS mwrPointState"); + columns.put("avqPointState", "t.avqPointState AS avqPointState"); + columns.put("qiSum", "t.qiSum AS qiSum"); + columns.put("qoSum", "t.qoSum AS qoSum"); + columns.put("fillWater", "t.fillWater AS fillWater"); + columns.put("titleName", "t.titleName AS titleName"); + columns.put("eqtp", "t.eqtp AS eqtp"); + columns.put("baseStepSort", "t.baseStepSort AS baseStepSort"); + columns.put("rvcdStepSort", "t.rvcdStepSort AS rvcdStepSort"); + columns.put("rstcdStepSort", "t.rstcdStepSort AS rstcdStepSort"); + columns.put("siteStepSort", "t.siteStepSort AS siteStepSort"); + return columns; + } + + private String buildHourFilterCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + if (filter == null) { + return ""; + } + if (StrUtil.isNotBlank(filter.getField())) { + if ("tm".equalsIgnoreCase(filter.getField())) { + return ""; + } + return buildHourLeafCondition(filter, paramMap, indexHolder); + } + if (CollUtil.isEmpty(filter.getFilters())) { + return ""; + } + List conditions = new ArrayList<>(); + for (DataSourceRequest.FilterDescriptor child : filter.getFilters()) { + String childSql = buildHourFilterCondition(child, paramMap, indexHolder); + if (StrUtil.isNotBlank(childSql)) { + conditions.add("(" + childSql + ")"); + } + } + if (conditions.isEmpty()) { + return ""; + } + String logic = "or".equalsIgnoreCase(filter.getLogic()) ? " OR " : " AND "; + return String.join(logic, conditions); + } + + private String buildHourLeafCondition(DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder) { + String column = mapHourColumn(filter.getField()); + if (StrUtil.isBlank(column)) { + return ""; + } + return buildGenericCondition(column, filter, paramMap, indexHolder, false); + } + + private String buildHourDetailOrderBySql(List sortList) { + if (CollUtil.isEmpty(sortList)) { + return " ORDER BY baseStepSort ASC, rvcdStepSort ASC, rstcdStepSort ASC, siteStepSort ASC, stcd ASC"; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.SortDescriptor sort : sortList) { + if (sort == null || StrUtil.isBlank(sort.getField())) { + continue; + } + String column = mapHourColumn(sort.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(sort.getDir()) || "des".equalsIgnoreCase(sort.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + if (orders.isEmpty()) { + return " ORDER BY baseStepSort ASC, rvcdStepSort ASC, rstcdStepSort ASC, siteStepSort ASC, stcd ASC"; + } + return " ORDER BY " + String.join(", ", orders); + } + + private String buildHourGroupOrderBySql(List groups) { + if (CollUtil.isEmpty(groups)) { + return ""; + } + List orders = new ArrayList<>(); + for (DataSourceRequest.GroupDescriptor descriptor : groups) { + if (descriptor == null || StrUtil.isBlank(descriptor.getField())) { + continue; + } + String column = mapHourColumn(descriptor.getField()); + if (StrUtil.isBlank(column)) { + continue; + } + String dir = "desc".equalsIgnoreCase(descriptor.getDir()) || "des".equalsIgnoreCase(descriptor.getDir()) ? "DESC" : "ASC"; + orders.add(column + " " + dir); + } + return orders.isEmpty() ? "" : " ORDER BY " + String.join(", ", orders); + } + + private String mapHourColumn(String field) { + if (StrUtil.isBlank(field)) { + return null; + } + return switch (field) { + case "stcd" -> "t.stcd"; + case "stnm", "ennm", "titleName" -> "t.ennm"; + case "sttp", "sttpCode" -> "t.sttpCode"; + case "baseId" -> "t.baseId"; + case "baseName" -> "t.baseName"; + case "hbrvcd" -> "t.hbrvcd"; + case "hbrvcdName" -> "t.hbrvcdName"; + case "addvcdName" -> "t.addvcdName"; + case "lgtd" -> "t.lgtd"; + case "lttd" -> "t.lttd"; + case "dtmel" -> "t.dtmel"; + case "ttpwr" -> "t.ttpwr"; + case "normz" -> "t.normz"; + case "avq" -> "t.avq"; + case "dtin" -> "t.dtin"; + case "dtinEnv" -> "t.dtinEnv"; + case "prsc" -> "t.prsc"; + case "bldsttCcode", "bldstt" -> "t.bldsttCcode"; + case "qi" -> "t.qi"; + case "qo" -> "t.qo"; + case "qec" -> "t.qec"; + case "rz" -> "t.rz"; + case "qecRate" -> "t.qecRate"; + case "mwrRate" -> "t.mwrRate"; + case "avqRate" -> "t.avqRate"; + case "qecInterval" -> "t.qecInterval"; + case "mwrInterval" -> "t.mwrInterval"; + case "avqInterval" -> "t.avqInterval"; + case "anchoPointState" -> "t.anchoPointState"; + case "mwrPointState" -> "t.mwrPointState"; + case "avqPointState" -> "t.avqPointState"; + case "qiSum" -> "t.qiSum"; + case "qoSum" -> "t.qoSum"; + case "fillWater" -> "(t.qoSum - t.qiSum)"; + case "eqtp" -> "t.eqtp"; + case "baseStepSort" -> "NVL(t.baseStepSort, 999999)"; + case "rvcdStepSort" -> "NVL(t.rvcdStepSort, 999999)"; + case "rstcdStepSort" -> "NVL(t.rstcdStepSort, 999999)"; + case "siteStepSort" -> "NVL(t.siteStepSort, 999999)"; + default -> null; + }; + } + private DataSourceResult queryDetailList(DataSourceRequest dataSourceRequest, DataSourceLoadOptionsBase loadOptions) { StringBuilder sql = new StringBuilder(); @@ -1360,9 +1837,17 @@ public class EngEqDataServiceImpl implements EngEqDataService { DataSourceRequest.FilterDescriptor filter, Map paramMap, int[] indexHolder) { + return buildStaticAggregateSql(type, filter, paramMap, indexHolder, 0); + } + + private String buildStaticAggregateSql(String type, + DataSourceRequest.FilterDescriptor filter, + Map paramMap, + int[] indexHolder, + int yearOffset) { String tableName = "day".equalsIgnoreCase(type) ? "SD_QECDAY_S" : "SD_QEC_R"; String timeColumn = "day".equalsIgnoreCase(type) ? "data.DT" : "data.TM"; - String timeFilter = buildStaticTimeFilterCondition(filter, paramMap, indexHolder, timeColumn); + String timeFilter = buildIntervalTmFilterCondition(filter, timeColumn, paramMap, indexHolder, yearOffset); StringBuilder sql = new StringBuilder(); sql.append("SELECT data.STCD, ") .append("(CASE WHEN SUM(CASE WHEN data.SFDB IN (0, 1) THEN 1 ELSE 0 END) = 0 THEN NULL ")