|
|
@@ -11,7 +11,9 @@ import com.usky.demo.domain.EnergyItemTrendPointVO;
|
|
|
import com.usky.demo.domain.EnergyItemTrendQueryVO;
|
|
|
import com.usky.demo.domain.EnergyItemTrendResultVO;
|
|
|
import com.usky.ems.domain.*;
|
|
|
+import com.usky.ems.mapper.BaseSpaceGatewayMapper;
|
|
|
import com.usky.ems.mapper.DmpProductMapper;
|
|
|
+import com.usky.ems.mapper.EmsDeviceItemCodeMapper;
|
|
|
import com.usky.ems.mapper.EmsDeviceMapper;
|
|
|
import com.usky.ems.mapper.EmsEnergyItemCodeMapper;
|
|
|
import com.usky.ems.mapper.EmsProjectConversionFactorMapper;
|
|
|
@@ -20,6 +22,7 @@ import com.usky.ems.mapper.EmsProjectMapper;
|
|
|
import com.usky.ems.service.EmsModelService;
|
|
|
import com.usky.ems.service.EmsOverviewService;
|
|
|
import com.usky.ems.service.BaseSpaceService;
|
|
|
+import com.usky.ems.service.DmpDeviceService;
|
|
|
import com.usky.ems.service.vo.EmsEnergyTypeVO;
|
|
|
import com.usky.ems.service.vo.EmsOverviewDeviceSystemStatVO;
|
|
|
import com.usky.ems.service.vo.EmsOverviewEnergyItemVO;
|
|
|
@@ -43,7 +46,9 @@ import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.LinkedHashMap;
|
|
|
import java.util.Objects;
|
|
|
+import java.util.Set;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -78,6 +83,9 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
@Autowired
|
|
|
private EmsEnergyItemCodeMapper emsEnergyItemCodeMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private EmsDeviceItemCodeMapper emsDeviceItemCodeMapper;
|
|
|
+
|
|
|
@Autowired
|
|
|
private EmsProjectMapper emsProjectMapper;
|
|
|
|
|
|
@@ -90,6 +98,12 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
@Autowired
|
|
|
private DmpProductMapper dmpProductMapper;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private BaseSpaceGatewayMapper baseSpaceGatewayMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DmpDeviceService dmpDeviceService;
|
|
|
+
|
|
|
@Autowired
|
|
|
private RemoteTsdbProxyService remoteTsdbProxyService;
|
|
|
|
|
|
@@ -232,8 +246,8 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
* 分类能耗统计:按能源类型关联产品汇总 TSDB 用量,并计算环比/同比及折标煤、碳排放。
|
|
|
*/
|
|
|
@Override
|
|
|
- public Map<String, Object> queryClassificationEnergy(Integer dateType, String identifier, Integer energyType, Long projectId) {
|
|
|
- if (dateType == null || StringUtils.isBlank(identifier) || energyType == null) {
|
|
|
+ public Map<String, Object> queryClassificationEnergy(Integer dateType, Integer energyType, Long projectId) {
|
|
|
+ if (dateType == null || energyType == null) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@@ -249,17 +263,23 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
coalFactor, co2Factor);
|
|
|
}
|
|
|
|
|
|
+ String identifier = resolveRootIdentifierByEnergyType(energyType);
|
|
|
+ if (identifier == null) {
|
|
|
+ return buildClassificationResult(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO,
|
|
|
+ coalFactor, co2Factor);
|
|
|
+ }
|
|
|
+
|
|
|
LocalDateTime endTime = LocalDateTime.now();
|
|
|
LocalDateTime startTime = getStartTime(dateType, endTime);
|
|
|
if (startTime == null) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- BigDecimal data = sumEnergyByProductCodes(productCodeList, identifier.toLowerCase(), startTime, endTime);
|
|
|
+ BigDecimal data = sumEnergyByProductCodes(productCodeList, identifier, startTime, endTime);
|
|
|
|
|
|
LocalDateTime pariPassuEndTime = endTime.minusYears(1);
|
|
|
LocalDateTime pariPassuStartTime = getStartTime(dateType, pariPassuEndTime);
|
|
|
- BigDecimal pariPassuData = sumEnergyByProductCodes(productCodeList, identifier.toLowerCase(), pariPassuStartTime, pariPassuEndTime);
|
|
|
+ BigDecimal pariPassuData = sumEnergyByProductCodes(productCodeList, identifier, pariPassuStartTime, pariPassuEndTime);
|
|
|
|
|
|
LocalDateTime sequentialEndTime;
|
|
|
if (dateType == 1) {
|
|
|
@@ -270,7 +290,7 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
sequentialEndTime = endTime.minusYears(1);
|
|
|
}
|
|
|
LocalDateTime sequentialStartTime = getStartTime(dateType, sequentialEndTime);
|
|
|
- BigDecimal sequentialData = sumEnergyByProductCodes(productCodeList, identifier.toLowerCase(), sequentialStartTime, sequentialEndTime);
|
|
|
+ BigDecimal sequentialData = sumEnergyByProductCodes(productCodeList, identifier, sequentialStartTime, sequentialEndTime);
|
|
|
|
|
|
return buildClassificationResult(data, sequentialData, pariPassuData, coalFactor, co2Factor);
|
|
|
}
|
|
|
@@ -322,9 +342,20 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
|
|
|
private BigDecimal sumEnergyByProductCodes(List<String> productCodeList, String fieldIdentifier,
|
|
|
LocalDateTime startTime, LocalDateTime endTime) {
|
|
|
+ return sumEnergyByProductCodes(productCodeList, fieldIdentifier, startTime, endTime, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal sumEnergyByProductCodes(List<String> productCodeList, String fieldIdentifier,
|
|
|
+ LocalDateTime startTime, LocalDateTime endTime,
|
|
|
+ List<String> deviceUuidList) {
|
|
|
BigDecimal total = BigDecimal.ZERO;
|
|
|
String start = formatTsdbTime(startTime);
|
|
|
String end = formatTsdbTime(endTime);
|
|
|
+ List<String> effectiveDeviceUuids = deviceUuidList == null ? null : deviceUuidList.stream()
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
+ .map(String::trim)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
for (String productCode : productCodeList) {
|
|
|
if (StringUtils.isBlank(productCode)) {
|
|
|
continue;
|
|
|
@@ -334,6 +365,9 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
queryVO.setSuperTable("super_" + productCode.trim());
|
|
|
queryVO.setStartTime(start);
|
|
|
queryVO.setEndTime(end);
|
|
|
+ if (effectiveDeviceUuids != null && !effectiveDeviceUuids.isEmpty()) {
|
|
|
+ queryVO.setDeviceUuid(effectiveDeviceUuids);
|
|
|
+ }
|
|
|
EnergyItemSumResultVO apiResult = remoteTsdbProxyService.sumEnergyItem(queryVO);
|
|
|
if (apiResult == null || apiResult.getSumDiff() == null) {
|
|
|
continue;
|
|
|
@@ -420,8 +454,8 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
* 能耗用能趋势:按产品+时间范围查询 TSDB 得 time/value,再按原系统 getListResult 逻辑封装。
|
|
|
*/
|
|
|
@Override
|
|
|
- public List<Map<String, Object>> queryEnergyTrend(Integer dateType, String identifier, Integer energyType) {
|
|
|
- if (dateType == null || StringUtils.isBlank(identifier) || energyType == null) {
|
|
|
+ public List<Map<String, Object>> queryEnergyTrend(Integer dateType, Integer energyType) {
|
|
|
+ if (dateType == null|| energyType == null) {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
@@ -431,6 +465,11 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
+ String identifier = resolveRootIdentifierByEnergyType(energyType);
|
|
|
+ if (identifier == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
if (dateType == 1 || dateType == 2 || dateType == 3) {
|
|
|
return buildEnergyTrendResult(productCodeList, identifier, dateType);
|
|
|
}
|
|
|
@@ -590,6 +629,24 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 按能源类型取根分项 identifier(parent_code=0)。
|
|
|
+ */
|
|
|
+ private String resolveRootIdentifierByEnergyType(Integer energyType) {
|
|
|
+ if (energyType == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ EmsEnergyItemCode rootItem = emsEnergyItemCodeMapper.selectOne(
|
|
|
+ Wrappers.lambdaQuery(EmsEnergyItemCode.class)
|
|
|
+ .eq(EmsEnergyItemCode::getParentCode, "0")
|
|
|
+ .eq(EmsEnergyItemCode::getEnergyType, energyType)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (rootItem == null || StringUtils.isBlank(rootItem.getIdentifier())) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return rootItem.getIdentifier().trim().toLowerCase();
|
|
|
+ }
|
|
|
+
|
|
|
private EmsEnergyItemCode resolveEnergyItemCode(String identifier) {
|
|
|
EmsEnergyItemCode itemCode = emsEnergyItemCodeMapper.selectOne(
|
|
|
Wrappers.lambdaQuery(EmsEnergyItemCode.class).eq(EmsEnergyItemCode::getCode, identifier));
|
|
|
@@ -701,84 +758,136 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 建筑能耗分析(模拟数据版本)
|
|
|
- * 参考原系统 queryBuildingRanking:按指定时间维度与能耗条目,对建筑/楼层进行能耗排名。
|
|
|
- * 当前实现:空间信息从 base_space 真实查询(建筑 type=3;指定 spaceId 时取子节点),仅能耗值使用规则模拟。
|
|
|
+ * 建筑能耗分析:从 base_space 取 type=3 建筑,经 base_space_gateway → dmp_device 定位设备,
|
|
|
+ * 再按能源类型关联产品调用 TSDB 分项汇总。
|
|
|
*/
|
|
|
@Override
|
|
|
- public List<Map<String, Object>> queryBuildingRanking(Integer dateType, String itemCode, Long spaceId) {
|
|
|
- List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
-
|
|
|
- if (dateType == null || itemCode == null || itemCode.trim().isEmpty()) {
|
|
|
- return resultList;
|
|
|
+ public List<Map<String, Object>> queryBuildingRanking(Integer dateType, Integer energyType) {
|
|
|
+ if (dateType == null || energyType == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
BaseSpace project = baseSpaceService.getOne(
|
|
|
- new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BaseSpace>()
|
|
|
- .eq(BaseSpace::getRootId, 0)
|
|
|
+ new LambdaQueryWrapper<BaseSpace>()
|
|
|
+ .eq(BaseSpace::getParentId, 0)
|
|
|
.eq(BaseSpace::getTenantId, SecurityUtils.getTenantId()));
|
|
|
if (project == null || project.getId() == null) {
|
|
|
- return resultList;
|
|
|
- }
|
|
|
- Long rootSpaceId = project.getId();
|
|
|
-
|
|
|
- // 2. 查询空间列表:
|
|
|
- // - 未指定 spaceId:取根空间下 type=3 的建筑(base_space)
|
|
|
- // - 指定 spaceId:取该空间下直接子节点(新表无独立楼层类型时,用子空间展示排名)
|
|
|
- List<BaseSpace> spaceList;
|
|
|
- if (spaceId == null) {
|
|
|
- spaceList = baseSpaceService.list(
|
|
|
- new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BaseSpace>()
|
|
|
- .eq(BaseSpace::getRootId, rootSpaceId)
|
|
|
- .eq(BaseSpace::getType, 3)
|
|
|
- );
|
|
|
- } else {
|
|
|
- spaceList = baseSpaceService.list(
|
|
|
- new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<BaseSpace>()
|
|
|
- .eq(BaseSpace::getParentId, spaceId)
|
|
|
- );
|
|
|
+ return new ArrayList<>();
|
|
|
}
|
|
|
+
|
|
|
+ List<BaseSpace> spaceList = baseSpaceService.list(
|
|
|
+ new LambdaQueryWrapper<BaseSpace>()
|
|
|
+ .eq(BaseSpace::getParentId, project.getId())
|
|
|
+ .eq(BaseSpace::getType, 3));
|
|
|
if (spaceList == null || spaceList.isEmpty()) {
|
|
|
- return resultList;
|
|
|
+ return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
- // 3. 为每个空间模拟能耗值(真实系统中此处应从 TSDB 或能耗统计表获取)
|
|
|
- BigDecimal base = new BigDecimal("1000");
|
|
|
- BigDecimal step = new BigDecimal("150");
|
|
|
- BigDecimal factor;
|
|
|
- if (dateType == 1) {
|
|
|
- factor = BigDecimal.ONE;
|
|
|
- } else if (dateType == 2) {
|
|
|
- factor = new BigDecimal("1.5");
|
|
|
- } else if (dateType == 3) {
|
|
|
- factor = new BigDecimal("2.0");
|
|
|
- } else {
|
|
|
- factor = BigDecimal.ONE;
|
|
|
+ List<String> productCodeList = dmpProductMapper.selectProductCodesByEnergyType(
|
|
|
+ SecurityUtils.getTenantId(), energyType);
|
|
|
+ if (productCodeList == null || productCodeList.isEmpty()) {
|
|
|
+ return new ArrayList<>();
|
|
|
}
|
|
|
+ Set<String> productCodeSet = productCodeList.stream()
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
+ .map(String::trim)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
|
|
|
- for (int i = 0; i < spaceList.size(); i++) {
|
|
|
- BaseSpace space = spaceList.get(i);
|
|
|
- if (space == null) {
|
|
|
+ Map<Long, List<String>> spaceDeviceUuidMap = loadSpaceDeviceUuidMap(spaceList, productCodeSet);
|
|
|
+
|
|
|
+ LocalDateTime endTime = LocalDateTime.now();
|
|
|
+ LocalDateTime startTime = getStartTime(dateType, endTime);
|
|
|
+ if (startTime == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ String identifier = resolveRootIdentifierByEnergyType(energyType);
|
|
|
+ if (identifier == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, BigDecimal> dataMap = new LinkedHashMap<>();
|
|
|
+ for (BaseSpace space : spaceList) {
|
|
|
+ if (space == null || space.getId() == null) {
|
|
|
continue;
|
|
|
}
|
|
|
- Map<String, Object> map = new HashMap<>();
|
|
|
- map.put("name", space.getName());
|
|
|
- BigDecimal value = base.subtract(step.multiply(BigDecimal.valueOf(i))).multiply(factor);
|
|
|
- map.put("value", value);
|
|
|
- resultList.add(map);
|
|
|
+ List<String> deviceUuids = spaceDeviceUuidMap.get(space.getId());
|
|
|
+ if (deviceUuids == null || deviceUuids.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ BigDecimal value = sumEnergyByProductCodes(productCodeList, identifier,
|
|
|
+ startTime, endTime, deviceUuids);
|
|
|
+ if (value != null) {
|
|
|
+ dataMap.put(space.getId(), value);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 4. 按 value 从大到小排序,形成能耗排名
|
|
|
- resultList.sort((m1, m2) -> {
|
|
|
- BigDecimal v1 = (BigDecimal) m1.get("value");
|
|
|
- BigDecimal v2 = (BigDecimal) m2.get("value");
|
|
|
- if (v1 == null && v2 == null) return 0;
|
|
|
- if (v1 == null) return 1;
|
|
|
- if (v2 == null) return -1;
|
|
|
- return v2.compareTo(v1);
|
|
|
- });
|
|
|
+ Map<Long, BaseSpace> spaceMap = spaceList.stream()
|
|
|
+ .filter(space -> space.getId() != null)
|
|
|
+ .collect(Collectors.toMap(BaseSpace::getId, space -> space, (oldVal, newVal) -> oldVal));
|
|
|
|
|
|
- return resultList;
|
|
|
+ return dataMap.entrySet().stream()
|
|
|
+ .sorted(Map.Entry.comparingByValue())
|
|
|
+ .map(entry -> {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ BaseSpace space = spaceMap.get(entry.getKey());
|
|
|
+ map.put("name", space != null ? space.getName() : null);
|
|
|
+ map.put("value", entry.getValue());
|
|
|
+ return map;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按空间批量解析网关及子设备 UUID(base_space_gateway → dmp_device)。
|
|
|
+ */
|
|
|
+ private Map<Long, List<String>> loadSpaceDeviceUuidMap(List<BaseSpace> spaceList, Set<String> productCodeSet) {
|
|
|
+ List<Long> spaceIds = spaceList.stream()
|
|
|
+ .map(BaseSpace::getId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (spaceIds.isEmpty()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ List<BaseSpaceGateway> links = baseSpaceGatewayMapper.selectList(
|
|
|
+ Wrappers.lambdaQuery(BaseSpaceGateway.class).in(BaseSpaceGateway::getSpaceId, spaceIds));
|
|
|
+ if (links == null || links.isEmpty()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Long> gatewayToSpace = new HashMap<>();
|
|
|
+ for (BaseSpaceGateway link : links) {
|
|
|
+ if (link.getSpaceId() == null || StringUtils.isBlank(link.getGatewayUuid())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ gatewayToSpace.putIfAbsent(link.getGatewayUuid().trim(), link.getSpaceId());
|
|
|
+ }
|
|
|
+ if (gatewayToSpace.isEmpty()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, List<String>> spaceDeviceUuidMap = new HashMap<>();
|
|
|
+ for (String gatewayUuid : gatewayToSpace.keySet()) {
|
|
|
+ Long spaceId = gatewayToSpace.get(gatewayUuid);
|
|
|
+ List<DmpDevice> devices = dmpDeviceService.getDevicesByGatewayUuid(gatewayUuid);
|
|
|
+ if (devices == null || devices.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ for (DmpDevice device : devices) {
|
|
|
+ if (device == null || StringUtils.isBlank(device.getDeviceUuid())
|
|
|
+ || StringUtils.isBlank(device.getProductCode())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (!productCodeSet.contains(device.getProductCode().trim())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ spaceDeviceUuidMap.computeIfAbsent(spaceId, key -> new ArrayList<>())
|
|
|
+ .add(device.getDeviceUuid().trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ spaceDeviceUuidMap.replaceAll((spaceId, uuids) -> uuids.stream().distinct().collect(Collectors.toList()));
|
|
|
+ return spaceDeviceUuidMap;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -906,44 +1015,58 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
|
|
|
/**
|
|
|
* 分项能耗占比
|
|
|
- * - 分项定义来自 leo.ems_energy_item_code:给定 itemCode 作为父项,按 parent_code 查询下级分项;
|
|
|
- * - 若无下级分项,则仅返回父项自身;
|
|
|
- * - 各分项及汇总能耗数值暂按规则模拟。
|
|
|
+ * - 根分项按 energyType 从 ems_energy_item_code 解析;
|
|
|
+ * - 冷/热(3/4)不展开下级,仅返回根分项;
|
|
|
+ * - 其余类型按 parent_code 展开子分项;
|
|
|
+ * - 各分项设备范围来自 ems_device_item_code,再调用 TSDB 汇总。
|
|
|
*/
|
|
|
@Override
|
|
|
- public List<Map<String, Object>> queryItemRatio(Integer dateType, String itemCode, Long projectId) {
|
|
|
+ public List<Map<String, Object>> queryItemRatio(Integer dateType, Integer energyType) {
|
|
|
List<Map<String, Object>> resultList = new ArrayList<>();
|
|
|
- if (dateType == null || itemCode == null || itemCode.trim().isEmpty()) {
|
|
|
+ if (dateType == null || energyType == null) {
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ EmsEnergyItemCode parent = emsEnergyItemCodeMapper.selectOne(
|
|
|
+ Wrappers.lambdaQuery(EmsEnergyItemCode.class)
|
|
|
+ .eq(EmsEnergyItemCode::getParentCode, "0")
|
|
|
+ .eq(EmsEnergyItemCode::getEnergyType, energyType)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (parent == null || StringUtils.isBlank(parent.getIdentifier())) {
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> productCodeList = dmpProductMapper.selectProductCodesByEnergyType(
|
|
|
+ SecurityUtils.getTenantId(), energyType);
|
|
|
+ if (productCodeList == null || productCodeList.isEmpty()) {
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
- // 当前实现中 startTime/spaceId 仅为预留,不参与模拟计算
|
|
|
LocalDateTime endTime = LocalDateTime.now();
|
|
|
LocalDateTime startTime = getStartTime(dateType, endTime);
|
|
|
if (startTime == null) {
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
- // 查询父分项编码
|
|
|
- EmsEnergyItemCode parent = emsEnergyItemCodeMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<EmsEnergyItemCode>()
|
|
|
- .eq(EmsEnergyItemCode::getCode, itemCode)
|
|
|
- );
|
|
|
- if (parent == null) {
|
|
|
+ String parentIdentifier = parent.getIdentifier().trim().toLowerCase();
|
|
|
+
|
|
|
+ if (energyType == 3 || energyType == 4) {
|
|
|
+
|
|
|
+ BigDecimal total = sumEnergyForItemCode(productCodeList, parentIdentifier, parent.getCode(), startTime, endTime);
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ map.put("name", parent.getName());
|
|
|
+ map.put("consume", total);
|
|
|
+ map.put("total", total);
|
|
|
+ resultList.add(map);
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
- // 模拟父分项总能耗
|
|
|
- BigDecimal total = simulateItemConsume(itemCode, dateType, 0);
|
|
|
|
|
|
- // 查询子分项列表(按 parent_code)
|
|
|
+ BigDecimal total = sumEnergyForItemCode(productCodeList, parentIdentifier, null, startTime, endTime);
|
|
|
List<EmsEnergyItemCode> children = emsEnergyItemCodeMapper.selectList(
|
|
|
- new LambdaQueryWrapper<EmsEnergyItemCode>()
|
|
|
- .eq(EmsEnergyItemCode::getParentCode, parent.getCode())
|
|
|
- );
|
|
|
-
|
|
|
+ Wrappers.lambdaQuery(EmsEnergyItemCode.class)
|
|
|
+ .eq(EmsEnergyItemCode::getParentCode, parent.getCode()));
|
|
|
if (children == null || children.isEmpty()) {
|
|
|
- // 无下级分项:仅返回父项自身
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
|
map.put("name", parent.getName());
|
|
|
map.put("consume", total);
|
|
|
@@ -952,43 +1075,47 @@ public class EmsOverviewServiceImpl implements EmsOverviewService {
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
- int index = 0;
|
|
|
for (EmsEnergyItemCode child : children) {
|
|
|
- if (child == null) continue;
|
|
|
- BigDecimal consume = simulateItemConsume(child.getCode(), dateType, index);
|
|
|
+ if (child == null || StringUtils.isBlank(child.getIdentifier())) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String childIdentifier = child.getIdentifier().trim().toLowerCase();
|
|
|
+ BigDecimal consume = sumEnergyForItemCode(productCodeList, childIdentifier, child.getCode(), startTime, endTime);
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
|
map.put("name", child.getName());
|
|
|
map.put("consume", consume);
|
|
|
map.put("total", total);
|
|
|
resultList.add(map);
|
|
|
- index++;
|
|
|
}
|
|
|
|
|
|
return resultList;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 分项能耗模拟函数
|
|
|
- * 根据 dateType 与 index 返回不同量级的示例值。
|
|
|
- */
|
|
|
- private BigDecimal simulateItemConsume(String code, Integer dateType, int index) {
|
|
|
- BigDecimal base = new BigDecimal("500");
|
|
|
- BigDecimal step = new BigDecimal("80");
|
|
|
- BigDecimal factor;
|
|
|
- if (dateType != null && dateType == 1) {
|
|
|
- factor = BigDecimal.ONE;
|
|
|
- } else if (dateType != null && dateType == 2) {
|
|
|
- factor = new BigDecimal("1.5");
|
|
|
- } else if (dateType != null && dateType == 3) {
|
|
|
- factor = new BigDecimal("2.0");
|
|
|
- } else {
|
|
|
- factor = BigDecimal.ONE;
|
|
|
+ private BigDecimal sumEnergyForItemCode(List<String> productCodeList, String fieldIdentifier, String itemCode, LocalDateTime startTime, LocalDateTime endTime) {
|
|
|
+ if(itemCode == null || itemCode.isEmpty()) {
|
|
|
+ return sumEnergyByProductCodes(productCodeList, fieldIdentifier, startTime, endTime, null);
|
|
|
}
|
|
|
- BigDecimal value = base.subtract(step.multiply(BigDecimal.valueOf(index))).multiply(factor);
|
|
|
- if (value.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
- value = BigDecimal.ZERO;
|
|
|
+ List<String> deviceUuids = resolveDeviceUuidsByItemCode(itemCode);
|
|
|
+ if (deviceUuids.isEmpty()) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
}
|
|
|
- return value.setScale(2, RoundingMode.UP);
|
|
|
+ return sumEnergyByProductCodes(productCodeList, fieldIdentifier, startTime, endTime, deviceUuids);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<String> resolveDeviceUuidsByItemCode(String itemCode) {
|
|
|
+ if (StringUtils.isBlank(itemCode)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<String> deviceUuids = emsDeviceItemCodeMapper.selectDeviceUuidsByItemCode(
|
|
|
+ SecurityUtils.getTenantId(), itemCode.trim());
|
|
|
+ if (deviceUuids == null || deviceUuids.isEmpty()) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ return deviceUuids.stream()
|
|
|
+ .filter(StringUtils::isNotBlank)
|
|
|
+ .map(String::trim)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
/** 根据设备系统编码返回名称(与 dmp_product.deviceType 含义保持一致) */
|