|
@@ -0,0 +1,382 @@
|
|
|
|
|
+package com.usky.vpp.service.impl;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.usky.vpp.domain.VppDevice;
|
|
|
|
|
+import com.usky.vpp.domain.VppEnergyReadingMonthly;
|
|
|
|
|
+import com.usky.vpp.domain.VppSettlementBill;
|
|
|
|
|
+import com.usky.vpp.domain.VppSettlementBillDetail;
|
|
|
|
|
+import com.usky.vpp.domain.VppSite;
|
|
|
|
|
+import com.usky.vpp.enums.DeviceTypeMetricEnum;
|
|
|
|
|
+import com.usky.vpp.enums.TimeSegmentEnum;
|
|
|
|
|
+import com.usky.vpp.mapper.VppDeviceMapper;
|
|
|
|
|
+import com.usky.vpp.mapper.VppEnergyReadingMonthlyMapper;
|
|
|
|
|
+import com.usky.vpp.mapper.VppSettlementBillDetailMapper;
|
|
|
|
|
+import com.usky.vpp.mapper.VppSettlementBillMapper;
|
|
|
|
|
+import com.usky.vpp.mapper.VppSiteMapper;
|
|
|
|
|
+import com.usky.vpp.service.VppSettlementSyncService;
|
|
|
|
|
+import com.usky.vpp.service.VppTsdbQueryService;
|
|
|
|
|
+import com.usky.vpp.util.VppAuditHelper;
|
|
|
|
|
+import com.usky.vpp.util.VppEnergyUsageHelper;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
|
|
+import org.springframework.transaction.PlatformTransactionManager;
|
|
|
|
|
+import org.springframework.transaction.support.TransactionTemplate;
|
|
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
+
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.math.RoundingMode;
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.YearMonth;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.EnumMap;
|
|
|
|
|
+import java.util.HashMap;
|
|
|
|
|
+import java.util.LinkedHashSet;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
|
|
+import java.util.TreeMap;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 每月从时序库拉取站点分时电量,写入月度核算与电费账单(电费金额固定为 0)
|
|
|
|
|
+ */
|
|
|
|
|
+@Service
|
|
|
|
|
+public class VppSettlementSyncServiceImpl implements VppSettlementSyncService {
|
|
|
|
|
+
|
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(VppSettlementSyncServiceImpl.class);
|
|
|
|
|
+
|
|
|
|
|
+ private static final int CALC_STATUS_PENDING = 0;
|
|
|
|
|
+ private static final int PAYMENT_STATUS_UNPAID = 0;
|
|
|
|
|
+ private static final int SCALE = 4;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppSiteMapper siteMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppDeviceMapper deviceMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppEnergyReadingMonthlyMapper energyReadingMonthlyMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppSettlementBillMapper settlementBillMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppSettlementBillDetailMapper settlementBillDetailMapper;
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private VppTsdbQueryService vppTsdbQueryService;
|
|
|
|
|
+
|
|
|
|
|
+ private TransactionTemplate transactionTemplate;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
|
|
|
|
+ this.transactionTemplate = new TransactionTemplate(transactionManager);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int syncLastMonth() {
|
|
|
|
|
+ YearMonth lastMonth = YearMonth.now().minusMonths(1);
|
|
|
|
|
+ return syncMonth(lastMonth.getYear(), lastMonth.getMonthValue());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int syncMonth(int settleYear, int settleMonth) {
|
|
|
|
|
+ YearMonth yearMonth = YearMonth.of(settleYear, settleMonth);
|
|
|
|
|
+ LocalDateTime startInclusive = yearMonth.atDay(1).atStartOfDay();
|
|
|
|
|
+ LocalDateTime endExclusive = yearMonth.plusMonths(1).atDay(1).atStartOfDay();
|
|
|
|
|
+ LocalDateTime queryEnd = endExclusive.minusSeconds(1);
|
|
|
|
|
+ String settleYearStr = String.valueOf(settleYear);
|
|
|
|
|
+ LocalDate dueDate = yearMonth.plusMonths(1).atEndOfMonth();
|
|
|
|
|
+
|
|
|
|
|
+ List<VppSite> sites = siteMapper.selectList(new LambdaQueryWrapper<VppSite>()
|
|
|
|
|
+ .eq(VppSite::getDeleteFlag, VppAuditHelper.NOT_DELETED));
|
|
|
|
|
+ if (CollectionUtils.isEmpty(sites)) {
|
|
|
|
|
+ log.info("月度结算同步:无可用站点, settle={}-{}", settleYear, settleMonth);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int success = 0;
|
|
|
|
|
+ for (VppSite site : sites) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Boolean synced = transactionTemplate.execute(status ->
|
|
|
|
|
+ syncSite(site, settleYearStr, settleMonth, startInclusive, endExclusive, queryEnd, dueDate));
|
|
|
|
|
+ if (Boolean.TRUE.equals(synced)) {
|
|
|
|
|
+ success++;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ log.error("月度结算同步失败 siteId={}, settle={}-{}, err={}",
|
|
|
|
|
+ site.getId(), settleYear, settleMonth, ex.getMessage(), ex);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("月度结算同步完成 settle={}-{}, sites={}, success={}",
|
|
|
|
|
+ settleYear, settleMonth, sites.size(), success);
|
|
|
|
|
+ return success;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean syncSite(VppSite site,
|
|
|
|
|
+ String settleYear,
|
|
|
|
|
+ int settleMonth,
|
|
|
|
|
+ LocalDateTime startInclusive,
|
|
|
|
|
+ LocalDateTime endExclusive,
|
|
|
|
|
+ LocalDateTime queryEnd,
|
|
|
|
|
+ LocalDate dueDate) {
|
|
|
|
|
+ if (site == null || site.getId() == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (existsReading(site.getCustomerId(), site.getId(), settleYear, settleMonth)
|
|
|
|
|
+ || existsBill(site.getCustomerId(), site.getId(), settleYear, settleMonth)) {
|
|
|
|
|
+ log.info("月度结算已存在,跳过 siteId={}, settle={}-{}", site.getId(), settleYear, settleMonth);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SiteEnergyAggregate aggregate = querySiteEnergy(site.getId(), startInclusive, endExclusive, queryEnd);
|
|
|
|
|
+
|
|
|
|
|
+ VppEnergyReadingMonthly reading = buildReading(site, settleYear, settleMonth, aggregate);
|
|
|
|
|
+ energyReadingMonthlyMapper.insert(reading);
|
|
|
|
|
+
|
|
|
|
|
+ VppSettlementBill bill = buildBill(site, settleYear, settleMonth, reading.getTotalEnergyKwh(), dueDate);
|
|
|
|
|
+ settlementBillMapper.insert(bill);
|
|
|
|
|
+
|
|
|
|
|
+ for (VppSettlementBillDetail detail : buildBillDetails(bill.getId(), site.getTenantId(), aggregate)) {
|
|
|
|
|
+ settlementBillDetailMapper.insert(detail);
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private SiteEnergyAggregate querySiteEnergy(Long siteId,
|
|
|
|
|
+ LocalDateTime startInclusive,
|
|
|
|
|
+ LocalDateTime endExclusive,
|
|
|
|
|
+ LocalDateTime queryEnd) {
|
|
|
|
|
+ List<VppDevice> devices = deviceMapper.selectList(new LambdaQueryWrapper<VppDevice>()
|
|
|
|
|
+ .eq(VppDevice::getSiteId, siteId)
|
|
|
|
|
+ .eq(VppDevice::getDeleteFlag, VppAuditHelper.NOT_DELETED));
|
|
|
|
|
+ if (CollectionUtils.isEmpty(devices)) {
|
|
|
|
|
+ return SiteEnergyAggregate.empty();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<DeviceTypeMetricEnum, List<String>> typeDeviceUuids = new HashMap<>();
|
|
|
|
|
+ for (VppDevice device : devices) {
|
|
|
|
|
+ if (device == null || !StringUtils.hasText(device.getDeviceUuid())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ DeviceTypeMetricEnum.ofDeviceType(device.getDeviceType()).ifPresent(typeEnum ->
|
|
|
|
|
+ typeDeviceUuids.computeIfAbsent(typeEnum, key -> new ArrayList<>())
|
|
|
|
|
+ .add(device.getDeviceUuid().trim()));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (typeDeviceUuids.isEmpty()) {
|
|
|
|
|
+ log.warn("站点无匹配电量设备类型 siteId={}", siteId);
|
|
|
|
|
+ return SiteEnergyAggregate.empty();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ SiteEnergyAggregate aggregate = SiteEnergyAggregate.empty();
|
|
|
|
|
+ for (Map.Entry<DeviceTypeMetricEnum, List<String>> entry : typeDeviceUuids.entrySet()) {
|
|
|
|
|
+ DeviceTypeMetricEnum typeEnum = entry.getKey();
|
|
|
|
|
+ List<String> deviceUuids = new ArrayList<>(new LinkedHashSet<>(entry.getValue()));
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history =
|
|
|
|
|
+ vppTsdbQueryService.queryDeviceMetricHistory(
|
|
|
|
|
+ deviceUuids, startInclusive, queryEnd, typeEnum.getMetrics());
|
|
|
|
|
+ aggregate.merge(sumUsageBySegment(deviceUuids, history, startInclusive, endExclusive));
|
|
|
|
|
+ }
|
|
|
|
|
+ return aggregate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private SiteEnergyAggregate sumUsageBySegment(List<String> deviceUuids,
|
|
|
|
|
+ Map<String, Map<String, TreeMap<LocalDateTime, BigDecimal>>> history,
|
|
|
|
|
+ LocalDateTime startInclusive,
|
|
|
|
|
+ LocalDateTime endExclusive) {
|
|
|
|
|
+ SiteEnergyAggregate aggregate = SiteEnergyAggregate.empty();
|
|
|
|
|
+ if (CollectionUtils.isEmpty(deviceUuids) || history == null || history.isEmpty()) {
|
|
|
|
|
+ return aggregate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<TimeSegmentEnum, BigDecimal> forward = new EnumMap<>(TimeSegmentEnum.class);
|
|
|
|
|
+ Map<TimeSegmentEnum, BigDecimal> reverse = new EnumMap<>(TimeSegmentEnum.class);
|
|
|
|
|
+ for (TimeSegmentEnum segment : TimeSegmentEnum.values()) {
|
|
|
|
|
+ forward.put(segment, BigDecimal.ZERO);
|
|
|
|
|
+ reverse.put(segment, BigDecimal.ZERO);
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal totalForward = BigDecimal.ZERO;
|
|
|
|
|
+ BigDecimal totalReverse = BigDecimal.ZERO;
|
|
|
|
|
+ boolean hasData = false;
|
|
|
|
|
+
|
|
|
|
|
+ for (String deviceUuid : deviceUuids) {
|
|
|
|
|
+ Map<String, TreeMap<LocalDateTime, BigDecimal>> metricMap = history.get(deviceUuid);
|
|
|
|
|
+ if (metricMap == null || metricMap.isEmpty()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ for (TimeSegmentEnum segment : TimeSegmentEnum.values()) {
|
|
|
|
|
+ BigDecimal fwd = VppEnergyUsageHelper.calcUsage(
|
|
|
|
|
+ metricMap.get(segment.getForwardMetric()), startInclusive, endExclusive);
|
|
|
|
|
+ if (fwd != null) {
|
|
|
|
|
+ hasData = true;
|
|
|
|
|
+ forward.put(segment, forward.get(segment).add(fwd));
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal rev = VppEnergyUsageHelper.calcUsage(
|
|
|
|
|
+ metricMap.get(segment.getReverseMetric()), startInclusive, endExclusive);
|
|
|
|
|
+ if (rev != null) {
|
|
|
|
|
+ hasData = true;
|
|
|
|
|
+ reverse.put(segment, reverse.get(segment).add(rev));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal epp = VppEnergyUsageHelper.calcUsage(metricMap.get("epp"), startInclusive, endExclusive);
|
|
|
|
|
+ if (epp != null) {
|
|
|
|
|
+ hasData = true;
|
|
|
|
|
+ totalForward = totalForward.add(epp);
|
|
|
|
|
+ }
|
|
|
|
|
+ BigDecimal epn = VppEnergyUsageHelper.calcUsage(metricMap.get("epn"), startInclusive, endExclusive);
|
|
|
|
|
+ if (epn != null) {
|
|
|
|
|
+ hasData = true;
|
|
|
|
|
+ totalReverse = totalReverse.add(epn);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ BigDecimal sharp = scale(forward.get(TimeSegmentEnum.SPIKE));
|
|
|
|
|
+ BigDecimal peak = scale(forward.get(TimeSegmentEnum.PEAK));
|
|
|
|
|
+ BigDecimal flat = scale(forward.get(TimeSegmentEnum.FLAT));
|
|
|
|
|
+ BigDecimal valley = scale(forward.get(TimeSegmentEnum.VALLEY));
|
|
|
|
|
+ BigDecimal segmentSum = sharp.add(peak).add(flat).add(valley);
|
|
|
|
|
+
|
|
|
|
|
+ BigDecimal totalEnergy = totalForward.compareTo(BigDecimal.ZERO) > 0 ? scale(totalForward) : segmentSum;
|
|
|
|
|
+ BigDecimal reverseSum = reverse.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ BigDecimal genEnergy = totalReverse.compareTo(BigDecimal.ZERO) > 0 ? scale(totalReverse) : scale(reverseSum);
|
|
|
|
|
+
|
|
|
|
|
+ aggregate.hasData = hasData;
|
|
|
|
|
+ aggregate.sharpEnergyKwh = sharp;
|
|
|
|
|
+ aggregate.peakEnergyKwh = peak;
|
|
|
|
|
+ aggregate.flatEnergyKwh = flat;
|
|
|
|
|
+ aggregate.valleyEnergyKwh = valley;
|
|
|
|
|
+ aggregate.totalEnergyKwh = totalEnergy;
|
|
|
|
|
+ aggregate.genEnergyKwh = genEnergy;
|
|
|
|
|
+ return aggregate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private VppEnergyReadingMonthly buildReading(VppSite site,
|
|
|
|
|
+ String settleYear,
|
|
|
|
|
+ int settleMonth,
|
|
|
|
|
+ SiteEnergyAggregate aggregate) {
|
|
|
|
|
+ VppEnergyReadingMonthly reading = new VppEnergyReadingMonthly();
|
|
|
|
|
+ reading.setCustomerId(site.getCustomerId());
|
|
|
|
|
+ reading.setSiteId(site.getId());
|
|
|
|
|
+ reading.setSettleYear(settleYear);
|
|
|
|
|
+ reading.setSettleMonth(settleMonth);
|
|
|
|
|
+ reading.setSharpEnergyKwh(aggregate.sharpEnergyKwh);
|
|
|
|
|
+ reading.setPeakEnergyKwh(aggregate.peakEnergyKwh);
|
|
|
|
|
+ reading.setFlatEnergyKwh(aggregate.flatEnergyKwh);
|
|
|
|
|
+ reading.setValleyEnergyKwh(aggregate.valleyEnergyKwh);
|
|
|
|
|
+ reading.setTotalEnergyKwh(aggregate.totalEnergyKwh);
|
|
|
|
|
+ reading.setGenEnergyKwh(aggregate.genEnergyKwh);
|
|
|
|
|
+ reading.setCalcStatus(CALC_STATUS_PENDING);
|
|
|
|
|
+ reading.setCalcAt(null);
|
|
|
|
|
+ reading.setTenantId(site.getTenantId());
|
|
|
|
|
+ VppAuditHelper.fillCreate(reading);
|
|
|
|
|
+ if (reading.getTenantId() == null) {
|
|
|
|
|
+ reading.setTenantId(site.getTenantId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return reading;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private VppSettlementBill buildBill(VppSite site,
|
|
|
|
|
+ String settleYear,
|
|
|
|
|
+ int settleMonth,
|
|
|
|
|
+ BigDecimal totalEnergyKwh,
|
|
|
|
|
+ LocalDate dueDate) {
|
|
|
|
|
+ VppSettlementBill bill = new VppSettlementBill();
|
|
|
|
|
+ bill.setBillNo(VppAuditHelper.nextBillNo());
|
|
|
|
|
+ bill.setCustomerId(site.getCustomerId());
|
|
|
|
|
+ bill.setSiteId(site.getId());
|
|
|
|
|
+ bill.setSettleYear(settleYear);
|
|
|
|
|
+ bill.setSettleMonth(settleMonth);
|
|
|
|
|
+ bill.setTotalEnergyKwh(VppEnergyUsageHelper.zeroIfNull(totalEnergyKwh));
|
|
|
|
|
+ // 当前阶段电费统一为 0
|
|
|
|
|
+ bill.setTotalAmount(BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP));
|
|
|
|
|
+ bill.setPaidAmount(BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP));
|
|
|
|
|
+ bill.setPaymentStatus(PAYMENT_STATUS_UNPAID);
|
|
|
|
|
+ bill.setDueDate(dueDate);
|
|
|
|
|
+ bill.setGeneratedAt(LocalDateTime.now());
|
|
|
|
|
+ bill.setTenantId(site.getTenantId());
|
|
|
|
|
+ VppAuditHelper.fillCreate(bill);
|
|
|
|
|
+ if (bill.getTenantId() == null) {
|
|
|
|
|
+ bill.setTenantId(site.getTenantId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return bill;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private List<VppSettlementBillDetail> buildBillDetails(Long billId,
|
|
|
|
|
+ Integer tenantId,
|
|
|
|
|
+ SiteEnergyAggregate aggregate) {
|
|
|
|
|
+ List<VppSettlementBillDetail> details = new ArrayList<>(4);
|
|
|
|
|
+ details.add(buildDetail(billId, tenantId, TimeSegmentEnum.SPIKE, aggregate.sharpEnergyKwh));
|
|
|
|
|
+ details.add(buildDetail(billId, tenantId, TimeSegmentEnum.PEAK, aggregate.peakEnergyKwh));
|
|
|
|
|
+ details.add(buildDetail(billId, tenantId, TimeSegmentEnum.FLAT, aggregate.flatEnergyKwh));
|
|
|
|
|
+ details.add(buildDetail(billId, tenantId, TimeSegmentEnum.VALLEY, aggregate.valleyEnergyKwh));
|
|
|
|
|
+ return details;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private VppSettlementBillDetail buildDetail(Long billId,
|
|
|
|
|
+ Integer tenantId,
|
|
|
|
|
+ TimeSegmentEnum segment,
|
|
|
|
|
+ BigDecimal energyKwh) {
|
|
|
|
|
+ VppSettlementBillDetail detail = new VppSettlementBillDetail();
|
|
|
|
|
+ detail.setBillId(billId);
|
|
|
|
|
+ detail.setTimePeriod(segment.getPeriodCode());
|
|
|
|
|
+ detail.setEnergyKwh(VppEnergyUsageHelper.zeroIfNull(energyKwh));
|
|
|
|
|
+ detail.setPrice(BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP));
|
|
|
|
|
+ detail.setAmount(BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP));
|
|
|
|
|
+ detail.setTenantId(tenantId);
|
|
|
|
|
+ return detail;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean existsReading(Long customerId, Long siteId, String settleYear, int settleMonth) {
|
|
|
|
|
+ return energyReadingMonthlyMapper.selectCount(new LambdaQueryWrapper<VppEnergyReadingMonthly>()
|
|
|
|
|
+ .eq(VppEnergyReadingMonthly::getCustomerId, customerId)
|
|
|
|
|
+ .eq(VppEnergyReadingMonthly::getSiteId, siteId)
|
|
|
|
|
+ .eq(VppEnergyReadingMonthly::getSettleYear, settleYear)
|
|
|
|
|
+ .eq(VppEnergyReadingMonthly::getSettleMonth, settleMonth)
|
|
|
|
|
+ .eq(VppEnergyReadingMonthly::getDeleteFlag, VppAuditHelper.NOT_DELETED)) > 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private boolean existsBill(Long customerId, Long siteId, String settleYear, int settleMonth) {
|
|
|
|
|
+ return settlementBillMapper.selectCount(new LambdaQueryWrapper<VppSettlementBill>()
|
|
|
|
|
+ .eq(VppSettlementBill::getCustomerId, customerId)
|
|
|
|
|
+ .eq(VppSettlementBill::getSiteId, siteId)
|
|
|
|
|
+ .eq(VppSettlementBill::getSettleYear, settleYear)
|
|
|
|
|
+ .eq(VppSettlementBill::getSettleMonth, settleMonth)
|
|
|
|
|
+ .eq(VppSettlementBill::getDeleteFlag, VppAuditHelper.NOT_DELETED)) > 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static BigDecimal scale(BigDecimal value) {
|
|
|
|
|
+ return VppEnergyUsageHelper.zeroIfNull(value).setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static final class SiteEnergyAggregate {
|
|
|
|
|
+ private boolean hasData;
|
|
|
|
|
+ private BigDecimal sharpEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+ private BigDecimal peakEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+ private BigDecimal flatEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+ private BigDecimal valleyEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+ private BigDecimal totalEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+ private BigDecimal genEnergyKwh = BigDecimal.ZERO;
|
|
|
|
|
+
|
|
|
|
|
+ static SiteEnergyAggregate empty() {
|
|
|
|
|
+ SiteEnergyAggregate aggregate = new SiteEnergyAggregate();
|
|
|
|
|
+ aggregate.sharpEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ aggregate.peakEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ aggregate.flatEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ aggregate.valleyEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ aggregate.totalEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ aggregate.genEnergyKwh = BigDecimal.ZERO.setScale(SCALE, RoundingMode.HALF_UP);
|
|
|
|
|
+ return aggregate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void merge(SiteEnergyAggregate other) {
|
|
|
|
|
+ if (other == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.hasData = this.hasData || other.hasData;
|
|
|
|
|
+ this.sharpEnergyKwh = this.sharpEnergyKwh.add(other.sharpEnergyKwh);
|
|
|
|
|
+ this.peakEnergyKwh = this.peakEnergyKwh.add(other.peakEnergyKwh);
|
|
|
|
|
+ this.flatEnergyKwh = this.flatEnergyKwh.add(other.flatEnergyKwh);
|
|
|
|
|
+ this.valleyEnergyKwh = this.valleyEnergyKwh.add(other.valleyEnergyKwh);
|
|
|
|
|
+ this.totalEnergyKwh = this.totalEnergyKwh.add(other.totalEnergyKwh);
|
|
|
|
|
+ this.genEnergyKwh = this.genEnergyKwh.add(other.genEnergyKwh);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|