10 changed files with 507 additions and 1 deletions
-
29common/core/src/main/java/com/thing/common/core/utils/excel/ExcelUtils.java
-
43modules/report-analysis/src/main/java/com/thing/carbon/energyloss/controller/EnergyLossController.java
-
35modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossDTO.java
-
31modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossInfoDTO.java
-
37modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossReportParam.java
-
21modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/KeyAndCodeDTO.java
-
19modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/NameAndCodeDTO.java
-
33modules/report-analysis/src/main/java/com/thing/carbon/energyloss/excel/EnergyLossExcel.java
-
15modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/EnergyLossService.java
-
245modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/impl/EnergyLossServiceImpl.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); |
|||
} |
|||
} |
|||
@ -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; |
|||
|
|||
|
|||
} |
|||
@ -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; |
|||
|
|||
} |
|||
@ -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; |
|||
|
|||
} |
|||
@ -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; |
|||
|
|||
|
|||
|
|||
} |
|||
@ -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; |
|||
|
|||
} |
|||
@ -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; |
|||
|
|||
} |
|||
@ -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); |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue