ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/dto/EnergyReportQuery.java
@@ -11,4 +11,6 @@ private String stationId; private LocalDate startDate; private LocalDate endDate; /** 查看方式:station电站明细、summary按天汇总,默认station。 */ private String viewMode; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/mapper/EnergyReportMapper.java
@@ -13,6 +13,8 @@ public interface EnergyReportMapper { IPage<PhotovoltaicReportRow> selectPhotovoltaicPage(Page<PhotovoltaicReportRow> page, @Param("query") EnergyReportQuery query); IPage<PhotovoltaicReportRow> selectPhotovoltaicSummaryPage(Page<PhotovoltaicReportRow> page, @Param("query") EnergyReportQuery query); List<PhotovoltaicReportRow> selectPhotovoltaicList(@Param("query") EnergyReportQuery query); IPage<StorageDailyReportRow> selectStoragePage(Page<StorageDailyReportRow> page, @Param("query") EnergyReportQuery query); ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/service/EnergyReportService.java
@@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.other.energyreport.dto.EnergyReportQuery; import com.ruoyi.other.energyreport.mapper.EnergyReportMapper; import com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow; @@ -20,7 +21,19 @@ } public IPage<PhotovoltaicReportRow> photovoltaicPage(EnergyReportQuery query) { return mapper.selectPhotovoltaicPage(Page.of(pageNumber(query), pageSize(query)), query); if (query == null) { query = new EnergyReportQuery(); } String viewMode = query.getViewMode() == null || query.getViewMode().trim().isEmpty() ? "station" : query.getViewMode().trim(); Page<PhotovoltaicReportRow> page = Page.of(pageNumber(query), pageSize(query)); if ("summary".equalsIgnoreCase(viewMode)) { return mapper.selectPhotovoltaicSummaryPage(page, query); } if ("station".equalsIgnoreCase(viewMode)) { return mapper.selectPhotovoltaicPage(page, query); } throw new ServiceException("查看方式仅支持station、summary"); } public List<PhotovoltaicReportRow> photovoltaicList(EnergyReportQuery query) { ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationEarnMapper.java
@@ -2,9 +2,14 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.other.api.domain.TStationEarn; import com.ruoyi.other.api.domain.TStationInfo; import java.util.List; /** * 电站发电量统计 Mapper。 */ public interface TStationEarnMapper extends BaseMapper<TStationEarn> { List<TStationInfo> selectStationInfoAll(); } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnQuery.java
@@ -17,4 +17,5 @@ @ApiModelProperty("统计开始日期,yyyy-MM-dd") private LocalDate startSaveTime; @DateTimeFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("统计结束日期,yyyy-MM-dd") private LocalDate endSaveTime; @ApiModelProperty("查看方式:station电站明细、summary按天汇总,默认station") private String viewMode; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationEarnServiceImpl.java
@@ -3,21 +3,25 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.Lists; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.other.api.domain.TStationEarn; import com.ruoyi.other.api.domain.TStationInfo; import com.ruoyi.other.mapper.TStationEarnMapper; import com.ruoyi.other.query.StationEarnQuery; import com.ruoyi.other.query.StationEarnOverviewQuery; import com.ruoyi.other.query.StationEarnStatisticsQuery; import com.ruoyi.other.service.TStationEarnService; import com.ruoyi.other.util.KsolarUtils; import com.ruoyi.other.vo.StationEarnStatisticsItemVO; import com.ruoyi.other.vo.StationEarnStatisticsVO; import com.ruoyi.other.vo.StationEarnOverviewVO; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,10 +31,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.*; /** * 电站发电量统计服务实现。 @@ -39,6 +40,9 @@ public class TStationEarnServiceImpl extends ServiceImpl<TStationEarnMapper, TStationEarn> implements TStationEarnService { @Autowired public TStationEarnMapper mapper; private static final BigDecimal PHOTOVOLTAIC_CARBON_REDUCTION_FACTOR = new BigDecimal("0.0001564"); @@ -92,7 +96,14 @@ public PageInfo<TStationEarn> pageList(StationEarnQuery query) { if (query == null) query = new StationEarnQuery(); PageInfo<TStationEarn> page = new PageInfo<>(query.getPageCurr(), query.getPageSize()); page(page, buildQueryWrapper(query)); String viewMode = StringUtils.isBlank(query.getViewMode()) ? "station" : query.getViewMode().trim(); if ("summary".equalsIgnoreCase(viewMode)) { page(page, buildSummaryQueryWrapper(query)); } else if ("station".equalsIgnoreCase(viewMode)) { page(page, buildQueryWrapper(query)); } else { throw new ServiceException("查看方式仅支持station、summary"); } return page; } @@ -157,9 +168,23 @@ result.setDimension(dimension); result.setTotalGeneration(totalGeneration); result.setTotalEarn(totalEarn); result.setTotalCarbonReduction(calculateCarbonReduction(totalGeneration)); result.setTotalCarbonReduction(getAllCo2()); result.setItems(items); return result; } public BigDecimal getAllCo2() { BigDecimal co2List = BigDecimal.ZERO; List<TStationInfo> infos = mapper.selectStationInfoAll(); if(CollectionUtils.isNotEmpty(infos)) { for (TStationInfo info : infos) { JSONObject stationEarnObj = KsolarUtils.getStationEarnDetail(info.getStationId(), KsolarUtils.token()); if (Objects.nonNull(stationEarnObj)) { co2List = co2List.add(parseBigDecimal(stationEarnObj.getString("co2"))); } } } return co2List; } @Override @@ -232,6 +257,20 @@ .orderByDesc(TStationEarn::getCreateTime); } private QueryWrapper<TStationEarn> buildSummaryQueryWrapper(StationEarnQuery query) { return new QueryWrapper<TStationEarn>() .select("save_time", "COALESCE(SUM(elec_total), 0) AS elec_total", "COALESCE(SUM(earn_total), 0) AS earn_total") .eq(query.getPlatformId() != null, "platform_id", query.getPlatformId()) .eq(StringUtils.isNotBlank(query.getStationId()), "station_id", query.getStationId()) .ge(query.getStartSaveTime() != null, "save_time", query.getStartSaveTime()) .le(query.getEndSaveTime() != null, "save_time", query.getEndSaveTime()) .isNotNull("save_time") .groupBy("save_time") .orderByDesc("save_time"); } static List<TStationEarn> buildStationEarnSyncList(JSONArray stationEarnList, Map<String, TStationEarn> existingByKey) { ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationInfoServiceImpl.java
@@ -26,6 +26,7 @@ import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** @@ -49,7 +50,7 @@ @Transactional(rollbackFor = Exception.class) public void syncKsolarDataTask() { String token = KsolarUtils.token(); JSONObject statusJsonObj = KsolarUtils.getListStatus(token); //JSONObject statusJsonObj = KsolarUtils.getListStatus(token); log.info("-------1开始同步科士达-电站列表信息----"); // 电站列表 @@ -57,19 +58,41 @@ // 电站基本信息列表 JSONArray listBaseJsonArray = KsolarUtils.getStationListBase(1, 1000, token); List<TStationInfo> stationInfoList = build(listInfoJsonArray, listBaseJsonArray); if(CollectionUtils.isNotEmpty(stationInfoList)) { List<TStationInfo> existingStationList = lambdaQuery().select(TStationInfo::getStationId).list(); Set<String> existingStationIds = new HashSet<>(); for (TStationInfo stationInfo : existingStationList) { if (stationInfo.getStationId() != null) { existingStationIds.add(stationInfo.getStationId()); // 去除stationInfoList中的重复stationId Map<String, TStationInfo> stationMap = stationInfoList.stream().filter(item -> StringUtils.isNotEmpty(item.getStationId())) .collect(Collectors.toMap(TStationInfo::getStationId, Function.identity(), (o1, o2) -> o2)); stationInfoList = new ArrayList<>(stationMap.values()); // 查询数据库已有数据 List<TStationInfo> existingStationList = lambdaQuery().in(TStationInfo::getStationId, stationMap.keySet()).list(); // 转Map,方便查找 Map<String, TStationInfo> existingMap = existingStationList.stream().collect(Collectors.toMap(TStationInfo::getStationId, Function.identity())); List<TStationInfo> insertList = new ArrayList<>(); List<TStationInfo> updateList = new ArrayList<>(); for (TStationInfo station : stationInfoList) { TStationInfo dbStation = existingMap.get(station.getStationId()); if (dbStation == null) { // 数据库不存在 insertList.add(station); } else { // 数据库存在,需要更新;保留数据库主键,否则updateBatchById无法更新 station.setId(dbStation.getId()); updateList.add(station); } } Set<String> pendingStationIds = new HashSet<>(); stationInfoList.removeIf(stationInfo -> stationInfo.getStationId() == null || existingStationIds.contains(stationInfo.getStationId()) || !pendingStationIds.add(stationInfo.getStationId())); if (CollectionUtils.isNotEmpty(stationInfoList)) { saveBatch(stationInfoList); // 批量新增 if (CollectionUtils.isNotEmpty(insertList)) { saveBatch(insertList); } // 批量更新 if (CollectionUtils.isNotEmpty(updateList)) { updateBatchById(updateList); } } log.info("-------1结束同步科士达-电站列表信息----"); ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/util/KsolarUtils.java
@@ -380,5 +380,26 @@ } } /** * 查询单个电站的发电量和收益 */ public static JSONObject getStationEarnDetail(String stationId, String token) { try { HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/station/detail/earn")); get.header("Authorization", "Bearer "+token); if(StringUtils.isNotEmpty(stationId)) { get.form("stationId", stationId); } HttpResponse execute = get.execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); Object data = jsonObject.get("data"); return JSONObject.parseObject(data.toString()); } catch (Exception e) { log.error("电站的电量和收益统计查询-调用第三方接口报错:", e); return null; } } } ruoyi-service/ruoyi-other/src/main/resources/mapper/other/EnergyReportMapper.xml
@@ -29,6 +29,16 @@ ORDER BY earn.save_time DESC, earn.id DESC </select> <select id="selectPhotovoltaicSummaryPage" resultType="com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow"> SELECT earn.save_time stat_date, COALESCE(SUM(earn.elec_total), 0) generation, COALESCE(SUM(earn.earn_total), 0) income FROM t_station_earn earn <include refid="photovoltaicWhere"/> GROUP BY earn.save_time ORDER BY earn.save_time DESC </select> <select id="selectPhotovoltaicList" resultType="com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow"> SELECT <include refid="photovoltaicColumns"/> FROM t_station_earn earn ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationEarnMapper.xml
@@ -2,5 +2,7 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.other.mapper.TStationEarnMapper"> <select id="selectStationInfoAll" resultType="com.ruoyi.other.api.domain.TStationInfo"> select * from t_station_info where del_flag = 0 and data_source = 2 </select> </mapper> ruoyi-service/ruoyi-other/src/test/java/com/ruoyi/other/energyreport/service/EnergyReportServiceTest.java
@@ -50,4 +50,19 @@ verify(mapper).selectPhotovoltaicList(same(query)); } @Test void summaryViewUsesDailySummaryQuery() { EnergyReportService service = new EnergyReportService(mapper); EnergyReportQuery query = new EnergyReportQuery(); query.setViewMode("summary"); service.photovoltaicPage(query); @SuppressWarnings("unchecked") ArgumentCaptor<Page<PhotovoltaicReportRow>> page = ArgumentCaptor.forClass(Page.class); verify(mapper).selectPhotovoltaicSummaryPage(page.capture(), same(query)); assertEquals(1, page.getValue().getCurrent()); assertEquals(10, page.getValue().getSize()); } }