package com.estate.expert.admin.service.impl;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.deepoove.poi.XWPFTemplate;
|
import com.estate.expert.admin.domain.business.device.usage.DeviceUsage;
|
import com.estate.expert.admin.domain.exam.eval.fuzzy.EvalFuzzyResult;
|
import com.estate.expert.admin.domain.exam.eval.score.EvalScoreResult;
|
import com.estate.expert.admin.domain.exam.record.error.ErrorRecordRepository;
|
import com.estate.expert.admin.domain.exam.task.check.CheckTask;
|
import com.estate.expert.admin.domain.exam.task.check.CheckTaskRepository;
|
import com.estate.expert.admin.domain.report.ReportTemplate;
|
import com.estate.expert.admin.domain.plan.PlanState;
|
import com.estate.expert.admin.enums.BizResultCode;
|
import com.estate.expert.admin.service.*;
|
import com.estate.expert.admin.service.eval.EvalFuzzyService;
|
import com.estate.expert.admin.service.eval.EvalScoreService;
|
import com.estate.expert.admin.stat.report.builder.DeviceReportBuilder;
|
import com.estate.expert.admin.stat.report.builder.ChengduHengtaiSystemReportBuilder;
|
import com.estate.expert.admin.stat.report.builder.ReportBuilderBase;
|
import com.estate.expert.admin.stat.report.builder.SystemReportBuilder;
|
import com.estate.expert.admin.stat.report.data.DeviceReportData;
|
import com.estate.expert.admin.stat.report.data.impl.DaiguanDeviceFuzzyReportData;
|
import com.estate.expert.admin.stat.report.data.impl.DaiguanDeviceScoreReportData;
|
import com.estate.expert.admin.stat.report.data.impl.DeviceFuzzyReportData;
|
import com.estate.expert.admin.stat.report.data.impl.DeviceScoreReportData;
|
import com.estate.expert.admin.stat.report.data.impl.SystemFuzzyReportData;
|
import com.estate.expert.admin.stat.report.data.impl.SystemScoreReportData;
|
import com.estate.expert.common.exception.BizException;
|
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
|
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayOutputStream;
|
import java.io.OutputStream;
|
import java.util.Collections;
|
import java.util.HashSet;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
/**
|
* 报告数据服务实现类
|
**/
|
@Slf4j
|
@Service
|
public class ReportServiceImpl implements ReportService {
|
|
private static final String DAIGUAN_TECH_REMARK = "岱观科技";
|
private static final String DAIGUAN_SYSTEM_TEMPLATE_FILE = "第三方评估报告new.docx";
|
private static final String DAIGUAN_REMARK = "岱观科技";
|
private static final String DAIGUAN_DEVICE_TEMPLATE_FILE = "设备风险评估报告new.docx";
|
private static final String CHENGDU_HENGTAI_REMARK = "成都衡泰";
|
|
@Resource
|
private ReportTemplateService reportTemplateService;
|
|
@Resource
|
private ProjectInfoService projectInfoService;
|
|
@Resource
|
private DeviceUsageService deviceUsageService;
|
|
@Resource
|
private EvalFuzzyService evalFuzzyService;
|
|
@Resource
|
private EvalScoreService evalScoreService;
|
|
@Resource
|
private ErrorRecordService errorRecordService;
|
|
@Resource
|
private ErrorRecordRepository errorRecordRepository;
|
|
@Resource
|
private CheckTaskRepository checkTaskRepository;
|
|
@Resource
|
private DeviceService deviceService;
|
|
@Resource
|
private UserFileService userFileService;
|
|
@Override
|
public JSONObject fuzzyReportData(Integer checkTaskId, Integer templateId) {
|
var evalFuzzyResult = evalFuzzyService.getByCheckTaskId(checkTaskId);
|
BizResultCode.EVAL_FUZZY_RESULT_NOT_EXIST.check(evalFuzzyResult == null);
|
|
var evalScoreResult = evalScoreService.getByCheckTaskId(checkTaskId);
|
BizResultCode.EVAL_SCORE_RESULT_NOT_EXIST.check(evalScoreResult == null);
|
|
var reportTemplate = reportTemplateService.get(templateId);
|
BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
|
|
switch (reportTemplate.getType()) {
|
case ThirdPartyReport:
|
return buildFuzzySystemReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
|
case DeviceReport:
|
return buildFuzzyDeviceReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
|
default:
|
throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
|
}
|
}
|
|
@Override
|
public JSONObject scoreReportData(Integer checkTaskId, Integer templateId) {
|
var evalFuzzyResult = evalFuzzyService.getByCheckTaskId(checkTaskId);
|
BizResultCode.EVAL_FUZZY_RESULT_NOT_EXIST.check(evalFuzzyResult == null);
|
|
var evalScoreResult = evalScoreService.getByCheckTaskId(checkTaskId);
|
BizResultCode.EVAL_SCORE_RESULT_NOT_EXIST.check(evalScoreResult == null);
|
|
var reportTemplate = reportTemplateService.get(templateId);
|
BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
|
|
switch (reportTemplate.getType()) {
|
case ThirdPartyReport:
|
return buildScoreSystemReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
|
case DeviceReport:
|
return buildScoreDeviceReportData(evalFuzzyResult, evalScoreResult, reportTemplate);
|
default:
|
throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
|
}
|
}
|
|
@Override
|
public XWPFTemplate fuzzyReport(Integer checkTaskId, Integer templateId) {
|
var reportData = fuzzyReportData(checkTaskId, templateId);
|
var builder = getReportBuilder(templateId);
|
var template = reportTemplateService.get(templateId);
|
|
// reportData to JSONObject
|
return builder.buildReport(reportData, template.getConfig());
|
}
|
|
@Override
|
public XWPFTemplate scoreReport(Integer checkTaskId, Integer templateId) {
|
var reportData = scoreReportData(checkTaskId, templateId);
|
var builder = getReportBuilder(templateId);
|
var template = reportTemplateService.get(templateId);
|
|
// reportData to JSONObject
|
return builder.buildReport(reportData, template.getConfig());
|
}
|
|
@Override
|
public void fuzzyReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream) {
|
try (var doc = fuzzyReport(checkTaskId, templateId)) {
|
convertToPdf(doc, outputStream);
|
} catch (Exception e) {
|
log.error("生成模糊评价PDF报告失败", e);
|
throw new BizException("生成模糊评价PDF报告失败");
|
}
|
}
|
|
@Override
|
public void scoreReportPdf(Integer checkTaskId, Integer templateId, OutputStream outputStream) {
|
try (var doc = scoreReport(checkTaskId, templateId)) {
|
convertToPdf(doc, outputStream);
|
} catch (Exception e) {
|
log.error("生成打分评价PDF报告失败", e);
|
throw new BizException("生成打分评价PDF报告失败");
|
}
|
}
|
|
/**
|
* 将Word文档转换为PDF
|
* @param template Word模板
|
* @param outputStream 输出流
|
*/
|
private void convertToPdf(XWPFTemplate template, OutputStream outputStream) throws Exception {
|
// 先将Word模板写入字节数组
|
ByteArrayOutputStream docOutputStream = new ByteArrayOutputStream();
|
template.write(docOutputStream);
|
|
// 从字节数组读取Word文档
|
ByteArrayInputStream docInputStream = new ByteArrayInputStream(docOutputStream.toByteArray());
|
org.apache.poi.xwpf.usermodel.XWPFDocument document = new org.apache.poi.xwpf.usermodel.XWPFDocument(docInputStream);
|
|
// 转换为PDF
|
PdfOptions options = PdfOptions.create();
|
PdfConverter.getInstance().convert(document, outputStream, options);
|
|
// 关闭资源
|
document.close();
|
docInputStream.close();
|
docOutputStream.close();
|
}
|
|
private ReportBuilderBase getReportBuilder(Integer templateId) {
|
var reportTemplate = reportTemplateService.get(templateId);
|
BizResultCode.BIZ_REPORT_TEMPLATE_NOT_EXIST.check(reportTemplate == null);
|
switch (reportTemplate.getType()) {
|
case ThirdPartyReport:
|
if (isChengduHengtaiTemplate(reportTemplate)) {
|
return new ChengduHengtaiSystemReportBuilder(userFileService);
|
}
|
if (isDaiguanTechTemplate(reportTemplate)) {
|
return new SystemReportBuilder(userFileService, DAIGUAN_SYSTEM_TEMPLATE_FILE);
|
}
|
return new SystemReportBuilder(userFileService);
|
case DeviceReport:
|
if (DAIGUAN_REMARK.equals(reportTemplate.getRemark())) {
|
return new DeviceReportBuilder(userFileService, DAIGUAN_DEVICE_TEMPLATE_FILE);
|
}
|
return new DeviceReportBuilder(userFileService);
|
default:
|
throw new BizException(BizResultCode.BIZ_REPORT_TEMPLATE_TYPE_NOT_EXIST);
|
}
|
}
|
|
private JSONObject buildFuzzySystemReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult, ReportTemplate reportTemplate) {
|
// 查询必须要的数据
|
var records = errorRecordService.listSystemErrors(evalFuzzyResult.getTask().getId());
|
var project = evalFuzzyResult.getProject();
|
var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
|
// var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
|
var deviceUsages = deviceUsageService.listUsages(project.getId(), null);
|
var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
|
var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
|
|
var problemFrequency = buildSystemProblemFrequency(project.getId(), records);
|
var projectCheckCount = countProjectChecks(project.getId());
|
|
// 生成报告数据
|
return SystemFuzzyReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.systemHierarchy(hierarchy)
|
.sysResult(evalFuzzyResult.getSystemRes())
|
.scoreResult(scoreResult.getSystemRes())
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.problemHazardCounts(problemFrequency.problemHazardCounts())
|
.projectCheckCount(projectCheckCount)
|
.build()
|
.generate();
|
}
|
|
private JSONObject buildScoreSystemReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult, ReportTemplate reportTemplate) {
|
// 查询必须要的数据
|
var records = errorRecordService.listSystemErrors(evalFuzzyResult.getTask().getId());
|
var project = evalFuzzyResult.getProject();
|
// var projectInfo = projectInfoService.latest(evalFuzzyResult.getProject().getId());
|
var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
|
var deviceUsages = deviceUsageService.listUsages(project.getId(), null);
|
var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
|
var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
|
|
var problemFrequency = buildSystemProblemFrequency(project.getId(), records);
|
var projectCheckCount = countProjectChecks(project.getId());
|
|
// 生成报告数据
|
return SystemScoreReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.systemHierarchy(hierarchy)
|
.sysResult(evalFuzzyResult.getSystemRes())
|
.scoreResult(scoreResult.getSystemRes())
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.problemHazardCounts(problemFrequency.problemHazardCounts())
|
.projectCheckCount(projectCheckCount)
|
.build()
|
.generate();
|
}
|
|
private record ProblemFrequency(Map<Integer, Long> problemHazardCounts) {
|
}
|
|
private record DeviceProblemFrequency(Map<String, Long> problemHazardCounts, Map<Integer, Long> deviceCheckCounts) {
|
}
|
|
private ProblemFrequency buildSystemProblemFrequency(Integer projectId, List<com.estate.expert.admin.domain.exam.record.error.ErrorRecord> currentTaskRecords) {
|
if (projectId == null || currentTaskRecords == null || currentTaskRecords.isEmpty()) {
|
return new ProblemFrequency(Collections.emptyMap());
|
}
|
|
var problemIds = currentTaskRecords.stream()
|
.map(r -> r.getProblem() != null ? r.getProblem().getId() : null)
|
.filter(java.util.Objects::nonNull)
|
.distinct()
|
.toList();
|
if (problemIds.isEmpty()) {
|
return new ProblemFrequency(Collections.emptyMap());
|
}
|
|
var taskIds = checkTaskRepository.listTaskIdsByProjectAndPlanState(projectId, PlanState.COMPLETE);
|
if (taskIds == null || taskIds.isEmpty()) {
|
return new ProblemFrequency(Collections.emptyMap());
|
}
|
|
Map<Integer, Long> hazardCounts = new HashMap<>();
|
for (var row : errorRecordRepository.countSystemHazardsByTaskIdsAndProblemIds(taskIds, problemIds)) {
|
if (row == null || row.length < 2 || row[0] == null || row[1] == null) {
|
continue;
|
}
|
hazardCounts.put(((Number) row[0]).intValue(), ((Number) row[1]).longValue());
|
}
|
|
return new ProblemFrequency(hazardCounts);
|
}
|
|
private DeviceProblemFrequency buildDeviceProblemFrequency(Integer projectId, Integer clientId) {
|
var taskIds = listTaskIdsByProjectAndClient(projectId, clientId);
|
if (taskIds.isEmpty()) {
|
return new DeviceProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
|
}
|
|
Map<String, Long> hazardCounts = new HashMap<>();
|
for (var row : errorRecordRepository.countDeviceHazardsByTaskIds(taskIds)) {
|
collectDeviceProblemFrequency(row, hazardCounts);
|
}
|
|
Map<Integer, Long> deviceCheckCounts = buildDeviceCheckFrequencyByCompletedTasks(projectId, clientId);
|
|
return new DeviceProblemFrequency(hazardCounts, deviceCheckCounts);
|
}
|
|
private void collectDeviceProblemFrequency(Object[] row, Map<String, Long> target) {
|
if (row == null || row.length < 3 || row[0] == null || row[2] == null) {
|
return;
|
}
|
Integer deviceId = ((Number) row[0]).intValue();
|
Integer problemId = row[1] == null ? null : ((Number) row[1]).intValue();
|
Long count = ((Number) row[2]).longValue();
|
target.put(DeviceReportData.buildDeviceProblemKey(deviceId, problemId), count);
|
}
|
|
private Map<Integer, Long> buildDeviceCheckFrequencyByCompletedTasks(Integer projectId, Integer clientId) {
|
if (projectId == null || clientId == null) {
|
return Collections.emptyMap();
|
}
|
var tasks = checkTaskRepository.listClosedByProjectAndClient(projectId, clientId);
|
if (tasks == null || tasks.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
Map<Integer, Long> deviceCheckCounts = new HashMap<>();
|
for (CheckTask task : tasks) {
|
for (Integer deviceId : collectTaskCheckedDeviceIds(task)) {
|
deviceCheckCounts.merge(deviceId, 1L, Long::sum);
|
}
|
}
|
return deviceCheckCounts;
|
}
|
|
private Set<Integer> collectTaskCheckedDeviceIds(CheckTask task) {
|
Set<Integer> deviceIds = new HashSet<>();
|
if (task == null) {
|
return deviceIds;
|
}
|
addDeviceIds(task.getDeviceFuzzyMap(), deviceIds);
|
addDeviceIds(task.getDeviceScoreMap(), deviceIds);
|
return deviceIds;
|
}
|
|
private void addDeviceIds(Map<Integer, Float> deviceMap, Set<Integer> target) {
|
if (deviceMap == null || deviceMap.isEmpty()) {
|
return;
|
}
|
for (Integer deviceId : deviceMap.keySet()) {
|
if (deviceId == null) {
|
continue;
|
}
|
target.add(deviceId);
|
}
|
}
|
|
private JSONObject buildFuzzyDeviceReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult, ReportTemplate reportTemplate) {
|
var records = errorRecordService.listDeviceErrors(evalFuzzyResult.getTask().getId());
|
var project = evalFuzzyResult.getProject();
|
var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
|
// var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
|
var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
|
var devices = deviceService.findAllById(deviceIds);
|
var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
|
var clientId = project.getClient() != null ? project.getClient().getId() : null;
|
var problemFrequency = buildDeviceProblemFrequency(project.getId(), clientId);
|
|
if (isDaiguanTemplate(reportTemplate)) {
|
return DaiguanDeviceFuzzyReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.deviceResMap(evalFuzzyResult.getDeviceResMap())
|
.deviceHierarchy(hierarchy)
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
|
.deviceCheckCounts(problemFrequency.deviceCheckCounts())
|
.build()
|
.generate();
|
}
|
|
// 生成报告数据
|
return DeviceFuzzyReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.deviceResMap(evalFuzzyResult.getDeviceResMap())
|
.deviceHierarchy(hierarchy)
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
|
.deviceCheckCounts(problemFrequency.deviceCheckCounts())
|
.build()
|
.generate();
|
}
|
|
private JSONObject buildScoreDeviceReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult evalScoreResult, ReportTemplate reportTemplate) {
|
var records = errorRecordService.listDeviceErrors(evalFuzzyResult.getTask().getId());
|
var project = evalFuzzyResult.getProject();
|
// var projectInfo = projectInfoService.getByCheckTaskId(evalFuzzyResult.getTask().getId());
|
var projectInfo = evalFuzzyResult.getTask().getProjectInfo();
|
var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
|
var devices = deviceService.findAllById(deviceIds);
|
var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
|
var clientId = project.getClient() != null ? project.getClient().getId() : null;
|
var problemFrequency = buildDeviceProblemFrequency(project.getId(), clientId);
|
|
if (isDaiguanTemplate(reportTemplate)) {
|
return DaiguanDeviceScoreReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.deviceResMap(evalFuzzyResult.getDeviceResMap())
|
.deviceScoreResMap(evalScoreResult.getDeviceResMap())
|
.deviceHierarchy(hierarchy)
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
|
.deviceCheckCounts(problemFrequency.deviceCheckCounts())
|
.build()
|
.generate();
|
}
|
|
// 生成报告数据
|
return DeviceScoreReportData.builder()
|
.reportId(evalFuzzyResult.getId())
|
.deviceResMap(evalFuzzyResult.getDeviceResMap())
|
.deviceScoreResMap(evalScoreResult.getDeviceResMap())
|
.deviceHierarchy(hierarchy)
|
.template(reportTemplate)
|
.project(project)
|
.projectInfo(projectInfo)
|
.devices(devices)
|
.records(records)
|
.deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
|
.deviceCheckCounts(problemFrequency.deviceCheckCounts())
|
.build()
|
.generate();
|
}
|
|
private List<Integer> listTaskIdsByProjectAndClient(Integer projectId, Integer clientId) {
|
if (projectId == null || clientId == null) {
|
return Collections.emptyList();
|
}
|
var taskIds = checkTaskRepository.listTaskIdsByProjectAndClient(projectId, clientId);
|
if (taskIds == null) {
|
return Collections.emptyList();
|
}
|
return taskIds;
|
}
|
|
private boolean isDaiguanTemplate(ReportTemplate reportTemplate) {
|
return reportTemplate != null && DAIGUAN_REMARK.equals(reportTemplate.getRemark());
|
}
|
|
private boolean isDaiguanTechTemplate(ReportTemplate reportTemplate) {
|
if (reportTemplate == null || reportTemplate.getRemark() == null) {
|
return false;
|
}
|
return DAIGUAN_TECH_REMARK.equals(reportTemplate.getRemark().trim());
|
}
|
|
private boolean isChengduHengtaiTemplate(ReportTemplate reportTemplate) {
|
return reportTemplate != null
|
&& reportTemplate.getRemark() != null
|
&& CHENGDU_HENGTAI_REMARK.equals(reportTemplate.getRemark().trim());
|
}
|
|
private long countProjectChecks(Integer projectId) {
|
if (projectId == null) {
|
return 0L;
|
}
|
var taskIds = checkTaskRepository.listTaskIdsByProjectAndPlanState(projectId, PlanState.COMPLETE);
|
if (taskIds == null) {
|
return 0L;
|
}
|
return taskIds.size();
|
}
|
|
}
|