Quellcode durchsuchen

service-vpp模块代码更新

hanzhengyi vor 4 Tagen
Ursprung
Commit
fb49c1cf2b

+ 2 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/domain/VppReportTask.java

@@ -38,6 +38,8 @@ public class VppReportTask implements Serializable {
     private Long assigneeId;
     @TableField("remind_days")
     private Integer remindDays;
+    @TableField("site_ids")
+    private String siteIds;
     @TableField("tenant_id")
     private Integer tenantId;
     @TableField("create_time")

+ 147 - 13
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/impl/VppReportInfoServiceImpl.java

@@ -3,6 +3,7 @@ package com.usky.vpp.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.usky.common.core.bean.CommonPage;
+import com.usky.common.security.utils.SecurityUtils;
 import com.usky.common.core.exception.BusinessException;
 import com.usky.vpp.config.VppReportProperties;
 import com.usky.vpp.domain.VppCustomer;
@@ -51,9 +52,11 @@ import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @Service
@@ -104,6 +107,8 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
     @Transactional(rollbackFor = Exception.class)
     public ReportTaskCreateResultVO createTask(ReportTaskCreateRequest request) {
         validateCreateTaskRequest(request);
+        Integer tenantId = resolveCurrentTenantId();
+        List<Long> siteIds = validateAndNormalizeSiteIds(request.getSiteIds(), tenantId);
 
         String taskNo = VppReportHelper.nextTaskNo();
         ensureTaskNoUnique(taskNo);
@@ -118,6 +123,7 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         task.setTaskStatus(VppReportHelper.TASK_STATUS_PENDING_FILL);
         task.setAssigneeId(request.getAssigneeId());
         task.setRemindDays(request.getRemindDays() != null ? request.getRemindDays() : 3);
+        task.setSiteIds(VppReportHelper.toJson(siteIds));
         VppAuditHelper.fillCreate(task);
         taskMapper.insert(task);
 
@@ -144,6 +150,7 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         result.setReportPeriod(record.getReportPeriod());
         result.setTaskStatus(task.getTaskStatus());
         result.setRecordStatus(record.getRecordStatus());
+        result.setSiteIds(siteIds);
         return result;
     }
 
@@ -209,9 +216,12 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
     @Override
     public ReportValidateResultVO validateData(Long id) {
         VppReportRecord record = requireRecord(id);
+        VppReportTask task = requireTask(record.getTaskId());
         VppReportData data = requireReportData(record.getId());
         Map<String, Object> formData = VppReportHelper.parseFormData(data.getFormData());
-        int systemPvCount = countResourceType("PV");
+        Integer tenantId = resolveTenantId(record, task);
+        List<Long> siteIds = resolveScopedSiteIds(task);
+        int systemPvCount = countResourceType("PV", tenantId, siteIds);
         ReportValidateResultVO result = VppReportHelper.validateFormData(formData, systemPvCount, true);
         data.setValidationErrors(VppReportHelper.toJson(result.getErrors()));
         VppAuditHelper.fillUpdate(data);
@@ -346,12 +356,20 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
     }
 
     private ReportPrefillVO buildPrefillData(VppReportRecord record, VppReportTask task) {
+        Integer tenantId = resolveTenantId(record, task);
+        List<Long> scopedSiteIds = resolveScopedSiteIds(task);
         VppReportHelper.PeriodRange period = VppReportHelper.parseReportPeriod(record.getReportPeriod());
-        List<VppCustomer> customers = listActiveCustomers();
-        List<VppResourcePoint> resources = listActiveResources();
-        List<VppSite> sites = listActiveSites();
-        List<VppEnergySummaryDaily> energyRows = listEnergyRows(period);
-        List<VppDrEvent> drEvents = listDrEvents(period);
+
+        List<VppSite> sites = listActiveSites(tenantId, scopedSiteIds);
+        List<VppCustomer> customers = listScopedCustomers(tenantId, sites);
+        List<VppResourcePoint> resources = listScopedResources(tenantId, sites);
+        List<Long> resourceIds = resources.stream()
+                .map(VppResourcePoint::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+
+        List<VppEnergySummaryDaily> energyRows = listEnergyRows(period, resourceIds);
+        List<VppDrEvent> drEvents = listDrEvents(period, tenantId);
         List<VppDrEvaluation> evaluations = listDrEvaluations(drEvents);
         return VppReportHelper.buildPrefill(record, task, customers, resources, sites,
                 energyRows, drEvents, evaluations);
@@ -425,6 +443,7 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         vo.setAssigneeId(task.getAssigneeId());
         vo.setAssigneeName(task.getCreatedBy());
         vo.setRemindDays(task.getRemindDays());
+        vo.setSiteIds(resolveScopedSiteIds(task));
         return vo;
     }
 
@@ -441,6 +460,7 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         vo.setReportOrg(task.getReportOrg());
         vo.setReportOrgName(VppReportHelper.resolveReportOrgName(task.getReportOrg()));
         vo.setSubmitMode(record.getSubmitMode());
+        vo.setSiteIds(resolveScopedSiteIds(task));
         vo.setRecordStatus(record.getRecordStatus());
         vo.setReportFileUrl(record.getReportFileUrl());
         vo.setReceiptFileUrl(record.getReceiptFileUrl());
@@ -620,32 +640,87 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
                 .collect(Collectors.toList());
     }
 
-    private List<VppCustomer> listActiveCustomers() {
+    private Integer resolveTenantId(VppReportRecord record, VppReportTask task) {
+        if (record != null && record.getTenantId() != null) {
+            return record.getTenantId();
+        }
+        if (task != null && task.getTenantId() != null) {
+            return task.getTenantId();
+        }
+        try {
+            return SecurityUtils.getTenantId();
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+
+    private List<VppCustomer> listScopedCustomers(Integer tenantId, List<VppSite> sites) {
+        Set<Long> customerIds = sites.stream()
+                .map(VppSite::getCustomerId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toCollection(HashSet::new));
+        if (!customerIds.isEmpty()) {
+            LambdaQueryWrapper<VppCustomer> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(VppCustomer::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                    .in(VppCustomer::getId, customerIds);
+            applyTenantFilter(wrapper, tenantId, VppCustomer::getTenantId);
+            return customerMapper.selectList(wrapper);
+        }
+        return listActiveCustomers(tenantId);
+    }
+
+    private List<VppCustomer> listActiveCustomers(Integer tenantId) {
         LambdaQueryWrapper<VppCustomer> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(VppCustomer::getDeleteFlag, VppAuditHelper.NOT_DELETED);
+        applyTenantFilter(wrapper, tenantId, VppCustomer::getTenantId);
         return customerMapper.selectList(wrapper);
     }
 
-    private List<VppResourcePoint> listActiveResources() {
+    private List<VppResourcePoint> listScopedResources(Integer tenantId, List<VppSite> sites) {
+        List<Long> siteIds = sites.stream()
+                .map(VppSite::getId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        if (siteIds.isEmpty()) {
+            return listActiveResources(tenantId);
+        }
+        LambdaQueryWrapper<VppResourcePoint> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(VppResourcePoint::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .in(VppResourcePoint::getSiteId, siteIds);
+        applyTenantFilter(wrapper, tenantId, VppResourcePoint::getTenantId);
+        return resourcePointMapper.selectList(wrapper);
+    }
+
+    private List<VppResourcePoint> listActiveResources(Integer tenantId) {
         LambdaQueryWrapper<VppResourcePoint> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(VppResourcePoint::getDeleteFlag, VppAuditHelper.NOT_DELETED);
+        applyTenantFilter(wrapper, tenantId, VppResourcePoint::getTenantId);
         return resourcePointMapper.selectList(wrapper);
     }
 
-    private List<VppSite> listActiveSites() {
+    private List<VppSite> listActiveSites(Integer tenantId, List<Long> scopedSiteIds) {
         LambdaQueryWrapper<VppSite> wrapper = new LambdaQueryWrapper<>();
-        wrapper.eq(VppSite::getDeleteFlag, VppAuditHelper.NOT_DELETED);
+        wrapper.eq(VppSite::getDeleteFlag, VppAuditHelper.NOT_DELETED)
+                .orderByAsc(VppSite::getSiteName);
+        applyTenantFilter(wrapper, tenantId, VppSite::getTenantId);
+        if (scopedSiteIds != null && !scopedSiteIds.isEmpty()) {
+            wrapper.in(VppSite::getId, scopedSiteIds);
+        }
         return siteMapper.selectList(wrapper);
     }
 
-    private int countResourceType(String resourceType) {
+    private int countResourceType(String resourceType, Integer tenantId, List<Long> siteIds) {
         LambdaQueryWrapper<VppResourcePoint> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(VppResourcePoint::getDeleteFlag, VppAuditHelper.NOT_DELETED)
                 .eq(VppResourcePoint::getResourceType, resourceType);
+        applyTenantFilter(wrapper, tenantId, VppResourcePoint::getTenantId);
+        if (siteIds != null && !siteIds.isEmpty()) {
+            wrapper.in(VppResourcePoint::getSiteId, siteIds);
+        }
         return resourcePointMapper.selectCount(wrapper).intValue();
     }
 
-    private List<VppEnergySummaryDaily> listEnergyRows(VppReportHelper.PeriodRange period) {
+    private List<VppEnergySummaryDaily> listEnergyRows(VppReportHelper.PeriodRange period, List<Long> resourceIds) {
         if (period == null) {
             return Collections.emptyList();
         }
@@ -653,10 +728,15 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         wrapper.eq(VppEnergySummaryDaily::getDeleteFlag, VppAuditHelper.NOT_DELETED)
                 .ge(VppEnergySummaryDaily::getSummaryDate, period.getStart())
                 .le(VppEnergySummaryDaily::getSummaryDate, period.getEnd());
+        if (resourceIds != null && !resourceIds.isEmpty()) {
+            wrapper.in(VppEnergySummaryDaily::getResourceId, resourceIds);
+        } else {
+            return Collections.emptyList();
+        }
         return energySummaryDailyMapper.selectList(wrapper);
     }
 
-    private List<VppDrEvent> listDrEvents(VppReportHelper.PeriodRange period) {
+    private List<VppDrEvent> listDrEvents(VppReportHelper.PeriodRange period, Integer tenantId) {
         if (period == null) {
             return Collections.emptyList();
         }
@@ -666,9 +746,17 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         wrapper.eq(VppDrEvent::getDeleteFlag, VppAuditHelper.NOT_DELETED)
                 .ge(VppDrEvent::getStartTime, start)
                 .le(VppDrEvent::getStartTime, end);
+        applyTenantFilter(wrapper, tenantId, VppDrEvent::getTenantId);
         return drEventMapper.selectList(wrapper);
     }
 
+    private <T> void applyTenantFilter(LambdaQueryWrapper<T> wrapper, Integer tenantId,
+                                       com.baomidou.mybatisplus.core.toolkit.support.SFunction<T, ?> column) {
+        if (tenantId != null) {
+            wrapper.eq(column, tenantId);
+        }
+    }
+
     private List<VppDrEvaluation> listDrEvaluations(List<VppDrEvent> events) {
         if (events == null || events.isEmpty()) {
             return Collections.emptyList();
@@ -738,6 +826,52 @@ public class VppReportInfoServiceImpl implements VppReportInfoService {
         if (request.getReportCycle() == 2 && !reportPeriod.matches("\\d{4}")) {
             throw new BusinessException("年报报送周期须为 YYYY 格式");
         }
+        if (request.getSiteIds() == null || request.getSiteIds().isEmpty()) {
+            throw new BusinessException("请至少选择一个关联站点");
+        }
+    }
+
+    private Integer resolveCurrentTenantId() {
+        try {
+            return SecurityUtils.getTenantId();
+        } catch (Exception ex) {
+            return null;
+        }
+    }
+
+    private List<Long> resolveScopedSiteIds(VppReportTask task) {
+        if (task == null) {
+            return Collections.emptyList();
+        }
+        return VppReportHelper.parseSiteIds(task.getSiteIds());
+    }
+
+    private List<Long> validateAndNormalizeSiteIds(List<Long> siteIds, Integer tenantId) {
+        if (siteIds == null || siteIds.isEmpty()) {
+            throw new BusinessException("请至少选择一个关联站点");
+        }
+        List<Long> distinct = siteIds.stream()
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (distinct.isEmpty()) {
+            throw new BusinessException("请至少选择一个关联站点");
+        }
+        List<VppSite> sites = siteMapper.selectBatchIds(distinct);
+        Map<Long, VppSite> siteMap = sites.stream()
+                .filter(site -> site.getDeleteFlag() == null
+                        || Objects.equals(site.getDeleteFlag(), VppAuditHelper.NOT_DELETED))
+                .collect(Collectors.toMap(VppSite::getId, site -> site, (left, right) -> left));
+        for (Long siteId : distinct) {
+            VppSite site = siteMap.get(siteId);
+            if (site == null) {
+                throw new BusinessException("站点不存在或已删除: " + siteId);
+            }
+            if (tenantId != null && site.getTenantId() != null && !tenantId.equals(site.getTenantId())) {
+                throw new BusinessException("站点不属于当前租户: " + siteId);
+            }
+        }
+        return distinct;
     }
 
     private String resolveReportPeriod(ReportTaskCreateRequest request) {

+ 2 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/ReportRecordVO.java

@@ -25,4 +25,6 @@ public class ReportRecordVO {
     private List<ReportAuditLogVO> auditLogs;
     private Map<String, Object> formData;
     private Boolean isDraft;
+    /** 任务关联站点,预填报与校验均按此范围汇总 */
+    private List<Long> siteIds;
 }

+ 3 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/ReportTaskCreateRequest.java

@@ -3,6 +3,7 @@ package com.usky.vpp.service.vo;
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * 新增报送任务请求
@@ -21,4 +22,6 @@ public class ReportTaskCreateRequest {
     private String reportPeriod;
     /** 报送方式:1接口推送 2手动上传,默认 1 */
     private Integer submitMode;
+    /** 关联站点 ID 列表,至少选择一个 */
+    private List<Long> siteIds;
 }

+ 3 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/ReportTaskCreateResultVO.java

@@ -2,6 +2,8 @@ package com.usky.vpp.service.vo;
 
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * 新增报送任务响应
  */
@@ -15,4 +17,5 @@ public class ReportTaskCreateResultVO {
     private String reportPeriod;
     private Integer taskStatus;
     private Integer recordStatus;
+    private List<Long> siteIds;
 }

+ 2 - 0
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/service/vo/ReportTaskVO.java

@@ -3,6 +3,7 @@ package com.usky.vpp.service.vo;
 import lombok.Data;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 @Data
 public class ReportTaskVO {
@@ -19,4 +20,5 @@ public class ReportTaskVO {
     private Long assigneeId;
     private String assigneeName;
     private Integer remindDays;
+    private List<Long> siteIds;
 }

+ 27 - 4
service-vpp/service-vpp-biz/src/main/java/com/usky/vpp/util/VppReportHelper.java

@@ -22,6 +22,7 @@ import java.time.YearMonth;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -107,6 +108,18 @@ public final class VppReportHelper {
         }
     }
 
+    public static List<Long> parseSiteIds(String json) {
+        if (!StringUtils.hasText(json)) {
+            return Collections.emptyList();
+        }
+        try {
+            return OBJECT_MAPPER.readValue(json, new TypeReference<List<Long>>() {
+            });
+        } catch (Exception ex) {
+            return Collections.emptyList();
+        }
+    }
+
     public static ReportPrefillVO buildPrefill(VppReportRecord record,
                                              VppReportTask task,
                                              List<VppCustomer> customers,
@@ -164,7 +177,7 @@ public final class VppReportHelper {
         }
         prefill.setDrTotalSubsidy(drSubsidy);
 
-        String vppName = resolveVppName(sites, task);
+        String vppName = resolveVppName(sites, customers, task);
         Map<String, Object> formData = new LinkedHashMap<>();
         Map<String, Object> basicInfo = new LinkedHashMap<>();
         basicInfo.put("vppName", vppName);
@@ -249,9 +262,19 @@ public final class VppReportHelper {
         }
     }
 
-    private static String resolveVppName(List<VppSite> sites, VppReportTask task) {
-        if (sites != null && !sites.isEmpty() && StringUtils.hasText(sites.get(0).getSiteName())) {
-            return sites.get(0).getSiteName();
+    private static String resolveVppName(List<VppSite> sites, List<VppCustomer> customers, VppReportTask task) {
+        if (sites != null) {
+            for (VppSite site : sites) {
+                if (StringUtils.hasText(site.getOwnerName())) {
+                    return site.getOwnerName();
+                }
+            }
+        }
+        if (customers != null && customers.size() == 1) {
+            String name = customers.get(0).getCustomerName();
+            if (StringUtils.hasText(name)) {
+                return name;
+            }
         }
         if (task != null && StringUtils.hasText(task.getTaskName())) {
             return task.getTaskName();

+ 13 - 0
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_report_task_site_ids_migration.sql

@@ -0,0 +1,13 @@
+-- 报送任务关联站点(已有库执行,可重复执行)
+
+SET @sql = IF(
+    (SELECT COUNT(*) FROM information_schema.columns
+     WHERE table_schema = DATABASE()
+       AND table_name = 'vpp_report_task'
+       AND column_name = 'site_ids') = 0,
+    'ALTER TABLE `vpp_report_task` ADD COLUMN `site_ids` JSON NULL COMMENT ''关联站点ID列表'' AFTER `remind_days`',
+    'SELECT 1'
+);
+PREPARE stmt FROM @sql;
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;

+ 1 - 0
service-vpp/service-vpp-biz/src/main/resources/sql/vpp_schema.sql

@@ -348,6 +348,7 @@ CREATE TABLE `vpp_report_task` (
     `task_status` TINYINT NOT NULL COMMENT '0待填报 1待审核 2报送中 3已完成 4已逾期',
     `assignee_id` BIGINT NULL COMMENT '填报人',
     `remind_days` INT NULL COMMENT '提前提醒天数',
+    `site_ids` JSON NULL COMMENT '关联站点ID列表',
     `tenant_id` INT NULL COMMENT '租户ID',
     `create_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
     `update_time` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',