package com.estate.expert.admin.stat.report.data; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.estate.expert.admin.domain.business.device.Device; import com.estate.expert.admin.domain.exam.eval.fuzzy.FuzzyValue; import com.estate.expert.admin.domain.exam.record.error.ErrorLevel; import com.estate.expert.admin.domain.exam.record.error.ErrorRecord; import com.estate.expert.admin.domain.misc.UserFile; import com.estate.expert.admin.domain.project.Project; import com.estate.expert.admin.domain.project.info.ProjectInfo; import com.estate.expert.admin.domain.report.ReportTemplate; import com.estate.expert.admin.utils.tree.TreeNode; import lombok.experimental.SuperBuilder; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** * 报告数据基类 * 这里将原始的数据,通过JSON的形式进行组织 * 便于后续的模板渲染 */ @SuperBuilder public abstract class ReportDataBase { private static final String DAIGUAN_REMARK = "岱观科技"; private static final String DEFAULT_COMPANY_NAME = "四川信立隆第三方评估咨询有限公司"; private static final String DAIGUAN_COMPANY_NAME = "四川岱观科技有限公司"; ReportTemplate template; List devices; Project project; ProjectInfo projectInfo; private int reportId; /** * 生成报告数据 * @return 报告数据 */ public JSONObject generate() { var result = buildReportInfo(); result.put("工程概况", buildProjectInfo()); result.put("设备信息", buildDeviceInfo()); result.put("设备分组信息", buildDeviceGroupInfo()); result.put("评估结果", buildEvalInfo()); return result; } /** * 构建评估信息 * @return 评估信息 */ protected abstract JSONObject buildEvalInfo(); /** * 构建报告信息 * @return 报告信息 */ protected JSONObject buildReportInfo() { JSONObject result = new JSONObject(); var reportDate = LocalDate.now(); result.put("项目名称", project.getName()); result.put("报告编号", template.getNumber() + "-" + String.format("%08d", reportId)); result.put("报告日期", reportDate); result.put("报告日期中文", reportDate.format(DateTimeFormatter.ofPattern("yyyy年M月d日"))); result.put("报告年份", reportDate.getYear()); result.put("报告月份", reportDate.getMonthValue()); result.put("报告日期日", reportDate.getDayOfMonth()); result.put("公司名称", buildCompanyName()); return result; } private String buildCompanyName() { if (template != null && DAIGUAN_REMARK.equals(template.getRemark())) { return DAIGUAN_COMPANY_NAME; } return DEFAULT_COMPANY_NAME; } /** * 构建设备信息 * @return 设备信息 */ protected List buildDeviceInfo() { List deviceInfos = new ArrayList<>(); // 按照设备类型排序 var sortedDevices = devices.stream() .sorted(Comparator.comparing(device -> device.getType() != null ? device.getType().ordinal() : Integer.MAX_VALUE)) .collect(Collectors.toList()); for (var device : sortedDevices) { JSONObject deviceInfo = new JSONObject(); deviceInfo.put("设备类型", device.getType().getDesc()); deviceInfo.put("设备编号", device.getManufacturerNumber()); deviceInfo.put("设备租赁单位", device.getProperties().get("工程起重机械租赁单位")); deviceInfo.put("设备使用单位", device.getProperties().get("使用单位")); deviceInfo.put("安拆单位", device.getProperties().get("工程起重机械安拆单位")); deviceInfo.put("检测单位", device.getProperties().get("工程起重机械维保单位")); deviceInfos.add(deviceInfo); } return deviceInfos; } /** * 按设备类型汇总设备信息,供新版报告模板使用 * @return 设备分组信息 */ protected List buildDeviceGroupInfo() { Map> groupedDevices = devices.stream() .sorted(Comparator.comparing(device -> device.getType() != null ? device.getType().ordinal() : Integer.MAX_VALUE)) .collect(Collectors.groupingBy( device -> device.getType() != null ? device.getType().getDesc() : "", LinkedHashMap::new, Collectors.toList() )); List groupInfos = new ArrayList<>(); groupedDevices.forEach((deviceType, groupDevices) -> { var deviceNumbers = groupDevices.stream() .map(Device::getManufacturerNumber) .filter(StringUtils::hasText) .collect(Collectors.toList()); if (deviceNumbers.isEmpty()) { deviceNumbers.add(""); } for (int i = 0; i < deviceNumbers.size(); i++) { JSONObject groupInfo = new JSONObject(); groupInfo.put("设备类型", i == 0 ? deviceType : ""); groupInfo.put("设备数量", i == 0 ? groupDevices.size() : ""); groupInfo.put("设备编号", deviceNumbers.get(i)); groupInfos.add(groupInfo); } }); return groupInfos; } /** * 构建错误级别 * @param node 节点 * @return 错误级别 */ protected JSONObject buildErrorLevel(TreeNode node) { JSONObject result = new JSONObject(); if(node == null) return result; int totalErrors = Arrays.stream(node.getData().getTotalErrorCounts()).sum(); result.put("隐患数量", totalErrors); List errorInfos = new ArrayList<>(); for (int i = 0; i<4 ; i++) { var level = ErrorLevel.values()[i]; var count = node.getData().getTotalErrorCounts()[i]; var info = new JSONObject(); info.put("隐患等级", level.getDesc()); info.put("隐患程度", level.getDesc2()); info.put("数量", count); info.put("比例", formatPercent(count * 1.0 / totalErrors)); errorInfos.add(info); } result.put("一级隐患数量", node.getData().getTotalErrorCounts()[0]); result.put("二级隐患数量", node.getData().getTotalErrorCounts()[1]); result.put("三级隐患数量", node.getData().getTotalErrorCounts()[2]); result.put("四级隐患数量", node.getData().getTotalErrorCounts()[3]); result.put("分项", errorInfos); return result; } /** * 构建项目信息 * @return 项目信息 */ protected JSONObject buildProjectInfo() { JSONObject info = new JSONObject(); info.put("工程名称", project.getName()); if(project.getAddressInfo() != null) info.put("工程地址", project.getAddressInfo().getFullAddress()); if(project.getDevelopmentCompanyInfo() != null) { info.put("建设单位", project.getDevelopmentCompanyInfo().getName()); info.put("项目负责人", project.getDevelopmentCompanyInfo().getLeader()); } if(project.getSupervisorCompanyInfo() != null){ info.put("监理单位", project.getSupervisorCompanyInfo().getName()); info.put("项目总监", project.getSupervisorCompanyInfo().getLeader()); } if(project.getConstructionCompanyInfo() != null){ info.put("施工单位", project.getConstructionCompanyInfo().getName()); info.put("项目经理", project.getConstructionCompanyInfo().getLeader()); } info.put("工程类型", project.getType().getDesc()); info.put("工程规模", project.getScale()); if (projectInfo != null) { info.put("项目简介", projectInfo.getDetail()); if(projectInfo.getDangerousOptions() != null) { var dangerStr = ""; var d0 = Arrays.stream(projectInfo.getDangerousOptions()).map(s -> s.getDesc() + ",").collect(Collectors.joining()); if(StringUtils.hasText(d0)) dangerStr += "危险性较大工程:[" + d0 + "]"; var d1 = Arrays.stream(projectInfo.getSuperDangerousOptions()).map(s -> s.getDesc() + ",").collect(Collectors.joining()); if(StringUtils.hasText(d1)) dangerStr += "\n超过一定规模的危险性较大工程:[" + d1 + "]"; dangerStr = dangerStr.replace(",]", "]"); info.put("危险性", dangerStr); } info.put("近一季度施工进展情况", projectInfo.getProgress()); } return info; } /** * 去除字符串首尾空白字符 */ private String trimText(String text) { return StringUtils.hasText(text) ? text.trim() : text; } /** * 构建记录详情 * @param record 记录 * @return 记录详情 */ protected JSONObject buildRecordDetail(ErrorRecord record) { var problem = record.getProblem(); JSONObject subItem = new JSONObject(); if(record.getDevice() != null) subItem.put("设备编号", record.getDevice().getManufacturerNumber()); subItem.put("隐患等级", record.getLevel().getDesc()); subItem.put("问题部位", record.getProblemPart()); subItem.put("问题备注", trimText(StringUtils.hasText(record.getRemark()) ? record.getRemark() : problem.getDescription())); subItem.put("建议措施", trimText(record.getSuggestion())); subItem.put("问题图片", buildImage(record.getImages())); subItem.put("问题描述", trimText(StringUtils.hasText(problem.getDescription()) ? problem.getDescription() : record.getRemark())); if(!CollectionUtils.isEmpty(problem.getSpecificTerms())){ StringBuilder sb = new StringBuilder(); var terms = CollectionUtils.isEmpty(record.getSpecificTermIndexes()) ? problem.getSpecificTerms() : record.getSpecificTermIndexes().stream() .filter(idx -> idx < problem.getSpecificTerms().size()) .map(problem.getSpecificTerms()::get) .collect(Collectors.toList()); for(int i = 0; i < terms.size(); i++) { sb.append(terms.get(i)); if(i < terms.size() - 1) { sb.append("\n"); } } subItem.put("违反条款", sb.toString()); } if(!problem.getNumberFactors().isEmpty()){ var numberFactorIndex = Math.min(record.getNumberFactorIndex(), problem.getNumberFactors().size() - 1); subItem.put("问题数量", problem.getNumberFactors().get(numberFactorIndex).getName()); } if(!problem.getScaleFactors().isEmpty()){ var scaleFactorIndex = Math.min(record.getScaleFactorIndex(), problem.getScaleFactors().size() - 1); subItem.put("问题规模", problem.getScaleFactors().get(scaleFactorIndex).getName()); } return subItem; } /** * 构建图片 * @param images 图片 * @return 图片 */ private JSONArray buildImage(List images) { if(CollectionUtils.isEmpty(images)) return new JSONArray(); return images.stream().map(s -> { Map map = new HashMap<>(); map.put("ID", s.getId()); return map; }).collect(Collectors.toCollection(JSONArray::new)); } /** * 格式化百分比 * @param value 值 * @return 百分比 */ protected String formatPercent(double value) { return String.format("%.2f%%", value * 100); } /** * 格式化浮点数 * @param value 值 * @return 浮点数 */ protected String formatFloat(double value) { return String.format("%.2f", value); } /** * 格式化浮点数 * @param value 值 * @return 浮点数 */ protected String formatFloatF4(double value) { return String.format("%.4f", value); } }