Browse Source

损耗分析报表-20240914

thing_master
xiezw 1 year ago
parent
commit
ea01cf9278
  1. 29
      common/core/src/main/java/com/thing/common/core/utils/excel/ExcelUtils.java
  2. 43
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/controller/EnergyLossController.java
  3. 35
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossDTO.java
  4. 31
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossInfoDTO.java
  5. 37
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossReportParam.java
  6. 21
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/KeyAndCodeDTO.java
  7. 19
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/NameAndCodeDTO.java
  8. 33
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/excel/EnergyLossExcel.java
  9. 15
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/EnergyLossService.java
  10. 245
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/impl/EnergyLossServiceImpl.java

29
common/core/src/main/java/com/thing/common/core/utils/excel/ExcelUtils.java

@ -16,7 +16,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
@ -48,6 +48,33 @@ public class ExcelUtils {
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response){
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
public static void exportExcel1(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response){
defaultExport1(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
private static void defaultExport1(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
// 设置第一列左对齐
Sheet sheet = workbook.getSheetAt(0);
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.LEFT);
style.setVerticalAlignment(VerticalAlignment.CENTER);
// 获取第一列列索引
int firstColumnIndex = 0;
// 遍历所有行
for (Row row : sheet) {
Cell cell = row.getCell(firstColumnIndex);
if (cell != null) {
cell.setCellStyle(style);
}
}
// 下载文件
downLoadExcel(fileName, response, workbook);
}
}
public static void exportExcel(List<?> list, Class<?> pojoClass, String title, String sheetName, String fileName, ExcelType excelType, HttpServletResponse response){

43
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/controller/EnergyLossController.java

@ -0,0 +1,43 @@
package com.thing.carbon.energyloss.controller;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import com.thing.carbon.energyloss.service.EnergyLossService;
import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("energy/loss")
@Tag(name="能源损耗")
@RequiredArgsConstructor
public class EnergyLossController {
@Autowired
private EnergyLossService energyLossService;
@PostMapping("report")
@Operation(summary="能源损耗报表")
public Result<List<EnergyLossDTO>> energyLossReport(@RequestBody EnergyLossReportParam param) {
List<EnergyLossDTO> list = energyLossService.energyLossReport(param);
return new Result<List<EnergyLossDTO>>().ok(list);
}
@PostMapping("export")
@Operation(summary="能源损耗报表导出")
public void energyLossReport(@RequestBody EnergyLossReportParam param, HttpServletResponse response){
List<EnergyLossExcel> list = energyLossService.getEnergyLossList(param);
ExcelUtils.exportExcel1(list, null, "能源损耗报表", EnergyLossExcel.class, "能源损耗报表.xls", response);
}
}

35
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossDTO.java

@ -0,0 +1,35 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "损耗报表数据")
public class EnergyLossDTO {
@Schema(description = "能源节点")
private String thingName;
@Schema(description = "能源code")
private String thingCode;
@Schema(description = "当前支路能耗")
private BigDecimal currentValue;
@Schema(description = "下级支路能耗合计")
private BigDecimal lastValue;
@Schema(description = "差值")
private BigDecimal differenceValue;
@Schema(description = "相差百分比")
private BigDecimal percentValue;
@Schema(description = "子项")
private List<EnergyLossDTO> childs;
}

31
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossInfoDTO.java

@ -0,0 +1,31 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "损耗报表数据1")
public class EnergyLossInfoDTO {
@Schema(description = "能源节点")
private String thingName;
@Schema(description = "能源code")
private String thingCode;
@Schema(description = "当前支路能耗")
private BigDecimal currentValue;
@Schema(description = "下级支路能耗合计")
private BigDecimal lastValue;
@Schema(description = "差值")
private BigDecimal differenceValue;
@Schema(description = "相差百分比")
private BigDecimal percentValue;
}

37
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossReportParam.java

@ -0,0 +1,37 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@Schema( name= "能源损耗入参")
public class EnergyLossReportParam implements Serializable {
@Serial
private static final long serialVersionUID = -8868412528182030308L;
@Schema(description = "开始时间")
private String beginTime;
@Schema(description = "结束时间")
private String endTime;
@Schema(description = "标签组名称")
private String labelGroupName;
@NotNull(message = "根主键不能为空", groups = Default.class)
@Schema(description = "根主键")
private Long rootId;
@Schema(description = "物属性code类型(hh mm yy),分别对应日月年")
private String thingAttrCodeType;
@Schema(description = "配置类型 例如:监控分析配置,用量分析配置")
private String configType;
}

21
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/KeyAndCodeDTO.java

@ -0,0 +1,21 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "属性和物code")
public class KeyAndCodeDTO {
@Schema(description = "属性key")
private String key;
@Schema(description = "物code")
private String code;
}

19
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/NameAndCodeDTO.java

@ -0,0 +1,19 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema( name= "物名称和物code")
public class NameAndCodeDTO {
@Schema(description = "物名称")
private String name;
@Schema(description = "物code")
private String code;
@Schema(description = "物id")
private Long thingId;
}

33
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/excel/EnergyLossExcel.java

@ -0,0 +1,33 @@
package com.thing.carbon.energyloss.excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class EnergyLossExcel {
@Excel(name = "能源节点", orderNum = "1", width = 30)
private String thingName;
// @Excel(name = "能源code", orderNum = "1")
// private String thingCode;
@Excel(name = "当前支路能耗", orderNum = "2", width = 30)
private BigDecimal currentValue;
@Excel(name = "下级支路能耗合计", orderNum = "3", width = 30)
private BigDecimal lastValue;
@Excel(name = "差值", orderNum = "4", width = 30)
private BigDecimal differenceValue;
@Excel(name = "相差百分比(%)", orderNum = "5", width = 30)
private BigDecimal percentValue;
}

15
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/EnergyLossService.java

@ -0,0 +1,15 @@
package com.thing.carbon.energyloss.service;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossInfoDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import java.util.List;
public interface EnergyLossService {
List<EnergyLossDTO> energyLossReport(EnergyLossReportParam param);
List<EnergyLossExcel> getEnergyLossList(EnergyLossReportParam param);
}

245
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/impl/EnergyLossServiceImpl.java

@ -0,0 +1,245 @@
package com.thing.carbon.energyloss.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import com.thing.carbon.energyloss.service.EnergyLossService;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.device.source.entity.IotThingSourceEntity;
import com.thing.device.source.mapper.IotThingSourceMapper;
import com.thing.thing.context.service.ThingManageContextService;
import com.thing.thing.relation.detail.dto.IotThingRelationDetailDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class EnergyLossServiceImpl implements EnergyLossService {
@Autowired
private ThingManageContextService thingManageContextService;
@Autowired
private TsKvService tsKvService;
@Resource
private IotThingSourceMapper iotThingSourceDao;
@Override
public List<EnergyLossDTO> energyLossReport(EnergyLossReportParam param) {
List<EnergyLossDTO> result = new ArrayList<>();
String beginTime = param.getBeginTime();
String endTime = param.getEndTime();
Long beginTs = DateTimeUtils.dateToStamp(beginTime);
Long endTs = DateTimeUtils.dateToStamp(endTime);
Long rootId = param.getRootId();
String labelGroupName = param.getLabelGroupName();
if (rootId==null){
return result;
}
//根据rootId获取该结构下所有的物
Optional<List<IotThingRelationDetailDTO>> relationDetailDTOS = thingManageContextService.findRootDetailAllByRootId(rootId);
List<IotThingRelationDetailDTO> relations = relationDetailDTOS.orElseGet(Collections::emptyList).stream().toList();
if (CollectionUtil.isEmpty(relations)){
return result;
}
List<String> codes = relationDetailDTOS.orElseGet(Collections::emptyList).stream().map(IotThingRelationDetailDTO::getToCode).toList();
Map<String, Collection<String>> multiMap = new HashMap<>();
//根据物code和标签组名称遍历查询对应配置的属性key
if (CollectionUtil.isNotEmpty(codes)){
for (String code:codes){
List<IotThingSourceEntity> iotThingSourceEntities = iotThingSourceDao.selectListExt(QueryWrapper.create()
.eq(IotThingSourceEntity::getThingCode, code)
.eq(IotThingSourceEntity::getRootId, rootId)
.eq(IotThingSourceEntity::getConfigType, param.getConfigType())
.eq(IotThingSourceEntity::getThingAttrGroup,labelGroupName)
.eq(IotThingSourceEntity::getStartStatus,"0"));
String key=null;
if (CollectionUtil.isNotEmpty(iotThingSourceEntities)){
key = iotThingSourceEntities.get(0).getThingAttrCode();
}
List<String> keys = new ArrayList<>();
keys.add(key);
if (StringUtils.isNotBlank(key)){
multiMap.put(code,keys);
}
}
}
//获取物 对应时间的能耗值
Map<String, BigDecimal> codeAndValueMap = new HashMap<>();
List<TsKvDTO> dataList = tsKvService.findTsKvByMultiMap(multiMap, beginTs, endTs, Boolean.FALSE);
if (CollectionUtil.isNotEmpty(dataList)){
codeAndValueMap = dataList.stream()
.filter(dto -> dto.getVal() != null && !dto.getVal().isEmpty())
.collect(Collectors.groupingBy(
TsKvDTO::getThingCode,
Collectors.mapping(
dto -> new BigDecimal(dto.getVal()),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
//处理结构,根据fromId分组并排序
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap = relations.stream()
.collect(Collectors.groupingBy(IotThingRelationDetailDTO::getFromId));
fromIdMap.forEach((fromId, list) ->
list.sort(Comparator.comparing(IotThingRelationDetailDTO::getSort))
);
//组装数据并赋值
result = buildEnergyLossDTOListRecursive(fromIdMap, rootId,codeAndValueMap);
return result;
}
@Override
public List<EnergyLossExcel> getEnergyLossList(EnergyLossReportParam param) {
List<EnergyLossExcel> result = new ArrayList<>();
List<EnergyLossDTO> result1;
String beginTime = param.getBeginTime();
String endTime = param.getEndTime();
Long beginTs = DateTimeUtils.dateToStamp(beginTime);
Long endTs = DateTimeUtils.dateToStamp(endTime);
Long rootId = param.getRootId();
String labelGroupName = param.getLabelGroupName();
if (rootId==null){
return result;
}
//根据rootId获取该结构下所有的物
Optional<List<IotThingRelationDetailDTO>> relationDetailDTOS = thingManageContextService.findRootDetailAllByRootId(rootId);
List<IotThingRelationDetailDTO> relations = relationDetailDTOS.orElseGet(Collections::emptyList).stream().toList();
if (CollectionUtil.isEmpty(relations)){
return result;
}
List<String> codes = relationDetailDTOS.orElseGet(Collections::emptyList).stream().map(IotThingRelationDetailDTO::getToCode).toList();
Map<String, Collection<String>> multiMap = new HashMap<>();
//根据物code和标签组名称遍历查询对应配置的属性key
if (CollectionUtil.isNotEmpty(codes)){
for (String code:codes){
List<IotThingSourceEntity> iotThingSourceEntities = iotThingSourceDao.selectListExt(QueryWrapper.create()
.eq(IotThingSourceEntity::getThingCode, code)
.eq(IotThingSourceEntity::getRootId, rootId)
.eq(IotThingSourceEntity::getConfigType, param.getConfigType())
.eq(IotThingSourceEntity::getThingAttrGroup,labelGroupName)
.eq(IotThingSourceEntity::getStartStatus,"0"));
String key=null;
if (CollectionUtil.isNotEmpty(iotThingSourceEntities)){
key = iotThingSourceEntities.get(0).getThingAttrCode();
}
List<String> keys = new ArrayList<>();
keys.add(key);
if (StringUtils.isNotBlank(key)){
multiMap.put(code,keys);
}
}
}
//获取物 对应时间的能耗值
Map<String, BigDecimal> codeAndValueMap = new HashMap<>();
List<TsKvDTO> dataList = tsKvService.findTsKvByMultiMap(multiMap, beginTs, endTs, Boolean.FALSE);
if (CollectionUtil.isNotEmpty(dataList)){
codeAndValueMap = dataList.stream()
.filter(dto -> dto.getVal() != null && !dto.getVal().isEmpty())
.collect(Collectors.groupingBy(
TsKvDTO::getThingCode,
Collectors.mapping(
dto -> new BigDecimal(dto.getVal()),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
//处理结构,根据fromId分组并排序
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap = relations.stream()
.collect(Collectors.groupingBy(IotThingRelationDetailDTO::getFromId));
fromIdMap.forEach((fromId, list) ->
list.sort(Comparator.comparing(IotThingRelationDetailDTO::getSort))
);
//组装数据并赋值
result1 = buildEnergyLossDTOListRecursive(fromIdMap, rootId,codeAndValueMap);
int depth=0;
processWithHierarchy(result,result1,depth);
return result;
}
private String getIndentedName(String name, int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" "); // Four spaces for each level of indentation
}
sb.append(name);
return sb.toString();
}
private EnergyLossExcel convertToEnergyLossInfoDTO(EnergyLossDTO energyLossDTO,int depth) {
if (energyLossDTO == null) {
return null;
}
EnergyLossExcel energyLossInfoDTO = new EnergyLossExcel();
energyLossInfoDTO.setThingName(getIndentedName(energyLossDTO.getThingName(),depth));
// energyLossInfoDTO.setThingCode(energyLossDTO.getThingCode());
energyLossInfoDTO.setCurrentValue(energyLossDTO.getCurrentValue());
energyLossInfoDTO.setLastValue(energyLossDTO.getLastValue());
energyLossInfoDTO.setDifferenceValue(energyLossDTO.getDifferenceValue());
energyLossInfoDTO.setPercentValue(energyLossDTO.getPercentValue());
return energyLossInfoDTO;
}
public List<EnergyLossExcel> processWithHierarchy(List<EnergyLossExcel> result,List<EnergyLossDTO> energyLossDTOList,int depth) {
for (EnergyLossDTO dto : energyLossDTOList) {
EnergyLossExcel infoDTO = convertToEnergyLossInfoDTO(dto,depth);
result.add(infoDTO);
// Recursively process child items
if (dto.getChilds() != null) {
processWithHierarchy(result,dto.getChilds(),depth + 1);
}
}
return result;
}
private List<EnergyLossDTO> buildEnergyLossDTOListRecursive(
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap,
Long rootId,Map<String, BigDecimal> codeAndValueMap) {
List<IotThingRelationDetailDTO> childDataList = fromIdMap.getOrDefault(rootId, Collections.emptyList());
List<EnergyLossDTO> dtos = new ArrayList<>();
for (IotThingRelationDetailDTO data : childDataList) {
EnergyLossDTO dto = new EnergyLossDTO();
dto.setThingName(data.getToName());
dto.setThingCode(data.getToCode());
BigDecimal currentValue = codeAndValueMap.getOrDefault(data.getToCode(), BigDecimal.ZERO);
dto.setCurrentValue(currentValue);
List<EnergyLossDTO> children = buildEnergyLossDTOListRecursive(fromIdMap,data.getToId(),codeAndValueMap);
dto.setChilds(children);
BigDecimal lastValue = children.stream()
.map(EnergyLossDTO::getCurrentValue)
.reduce(BigDecimal.ZERO, BigDecimal::add);
dto.setLastValue(lastValue);
BigDecimal differenceValue = currentValue.subtract(lastValue);
BigDecimal percentValue = currentValue.compareTo(BigDecimal.ZERO) == 0
? BigDecimal.ZERO
: differenceValue.divide(currentValue, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
dto.setDifferenceValue(differenceValue);
dto.setPercentValue(percentValue);
dtos.add(dto);
}
return dtos;
}
}
Loading…
Cancel
Save