package com.kcim.service.impl; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.afterturn.easypoi.util.PoiCellUtil; import cn.afterturn.easypoi.util.PoiMergeCellUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.ExcelWriter; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.ImmutableMap; import com.kcim.common.constants.NumberConstant; import com.kcim.common.constants.ParameterConstant; import com.kcim.common.constants.SQLParameter; import com.kcim.common.constants.SplitConstant; import com.kcim.common.enums.CustomSqlTypeEnum; import com.kcim.common.enums.DateStyleEnum; import com.kcim.common.enums.ErrorCodeEnum; import com.kcim.common.exception.CostException; import com.kcim.common.file.MinioConfig; import com.kcim.common.file.MinioFileUtil; import com.kcim.common.util.*; import com.kcim.common.util.excel.ExcelPoiUtil; import com.kcim.common.util.excel.entity.ColEntity; import com.kcim.common.util.excel.entity.TitleEntity; import com.kcim.dao.mapper.CostDepartmentProfitMapper; import com.kcim.dao.model.*; import com.kcim.dao.repository.ComputeLastProfitDateRepository; import com.kcim.dao.repository.CostDepartmentProfitAccountRepository; import com.kcim.dao.repository.CostDepartmentProfitRepository; import com.kcim.dao.repository.ResponsibilityRepository; import com.kcim.service.*; import com.kcim.vo.*; import com.kcim.web.reponse.BatchCostProfitResponse; import com.kcim.web.reponse.ComputeProfitCollectResponse; import com.kcim.web.reponse.CostProfitRedirectResponse; import com.kcim.web.reponse.ProfitReportResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.IntStream; import static com.kcim.common.constants.Constant.PROFIT_REPORT_TYPE; import static com.kcim.common.constants.ParameterConstant.MEDICAL_TECHNIQUES_SHARE_LEVEL_ID; @Service("costDepartmentProfitService") @Slf4j @AllArgsConstructor public class CostDepartmentProfitServiceImpl extends ServiceImpl implements CostDepartmentProfitService { // @Value("${file.filelocal}") // private String hospProfitReportUrl; // // @Value("${file.serverUrl}") // private String serverUrl; private final ReportFormService reportFormService; private final IncomeCollectionService incomeCollectionService; private final CostShareLevelService costShareLevelService; private final ResponsibilityService responsibilityService; private final ReportRelationService reportRelationService; private final AllocationService allocationService; private final AllocationQueryService allocationQueryService; private final FileRecordService fileRecordService; private final MinioConfig minioConfig; private final MinioFileUtil minioFileUtil; private final CenterService centerService; private final CostDepartmentProfitRepository costDepartmentProfitRepository; private final ComputeLastProfitDateRepository computeLastProfitDateRepository; private final AccountingService accountingService; private final CostAccountShareService costAccountShareService; private final UserResponsibilityRightService userResponsibilityRightService; ResponsibilityRepository responsibilityRepository; CostDepartmentProfitAccountRepository costDepartmentProfitAccountRepository; private final SqlService sqlService; private final String AMOUNT = "金额"; private final String PERCENT = "占比"; private final String AMOUNT_FIELD = "amount"; private final String PERCENT_FIELD = "percent"; // // public CostDepartmentProfitServiceImpl(ReportFormService reportFormService, IncomeCollectionService incomeCollectionService, CostShareLevelService costShareLevelService, ResponsibilityService responsibilityService, ReportRelationService reportRelationService, AllocationService allocationService, AllocationQueryService allocationQueryService, FileRecordService fileRecordService, MinioConfig minioConfig, MinioFileUtil minioFileUtil, CenterService centerService, CostDepartmentProfitRepository costDepartmentProfitRepository, ComputeLastProfitDateRepository computeLastProfitDateRepository, AccountingService accountingService, CostAccountShareService costAccountShareService, SqlService sqlService, UserResponsibilityRightService userResponsibilityRightService) { // this.reportFormService = reportFormService; // this.incomeCollectionService = incomeCollectionService; // this.costShareLevelService = costShareLevelService; // this.responsibilityService = responsibilityService; // this.reportRelationService = reportRelationService; // this.allocationService = allocationService; // this.allocationQueryService = allocationQueryService; // this.fileRecordService = fileRecordService; // this.minioConfig = minioConfig; // this.minioFileUtil = minioFileUtil; // this.centerService = centerService; // this.costDepartmentProfitRepository = costDepartmentProfitRepository; // this.computeLastProfitDateRepository = computeLastProfitDateRepository; // this.accountingService = accountingService; // this.costAccountShareService = costAccountShareService; // this.sqlService = sqlService; // this.userResponsibilityRightService = userResponsibilityRightService; // } /** * 查询科室损益数据 * * @param current * @param pageSize * @param responsibilityCode * @param date * @param hospId * @return */ @Override public PageUtils queryList(Integer current, Integer pageSize, String responsibilityCode, String date, Long hospId) { int year = 0; int month = 0; if (StrUtil.isNotBlank(date)) { Date dateTime = DateUtils.StringToDate(date, DateStyleEnum.YYYY_MM_DD); year = DateUtil.year(dateTime); month = DateUtil.month(dateTime) + 1; } Page departmentProfitPage = new Page<>(current, pageSize); // 查询的时候过过滤那些计算方式是不设置的数据 Page pages = this.page(departmentProfitPage, new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(StrUtil.isNotBlank(responsibilityCode), CostDepartmentProfit::getResponsibilityCode, responsibilityCode) .eq(StrUtil.isNotBlank(date), CostDepartmentProfit::getYear, year) .eq(StrUtil.isNotBlank(date), CostDepartmentProfit::getMonth, month) .ne(CostDepartmentProfit::getCalcType, NumberConstant.ZERO).orderByDesc(CostDepartmentProfit::getAmount)); List records = pages.getRecords(); List costDepartmentProfitVOList = BeanUtil.convertList(records, CostDepartmentProfitVO.class); DecimalFormat df = new DecimalFormat("0.00%"); for (CostDepartmentProfitVO costDepartmentProfitVO : costDepartmentProfitVOList) { if (costDepartmentProfitVO.getPercent() != null) { costDepartmentProfitVO.setPercentName(df.format(costDepartmentProfitVO.getPercent())); } } PageUtils pageUtils = new PageUtils(pages); pageUtils.setList(costDepartmentProfitVOList); return pageUtils; } /** * 科室损益计算 * * @param date * @param hospId */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void setDepartmentProfit(String date, Long hospId) { DateTime parse = DateUtil.parse(date); int year = DateUtil.year(parse); int month = DateUtil.month(parse) + 1; // 先查询指定条件的报表数据 查询损益表的数据 List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, NumberConstant.ZERO)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } // 遍历报表数据根据报表数据计算方式进行计算 //这里拆分成两个 原有的最后一层 以及 参数医技 // 查询最后一个层级的责任中心 List costShareLevelList = costShareLevelService.list(new QueryWrapper().lambda() .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort)); if (CollUtil.isEmpty(costShareLevelList)) { throw new CostException(500, "分摊层级未设置"); } // TODO 可能多个 Long id = costShareLevelList.get(0).getId(); // 查询责任中心里面是这个层级的所有的收益中心 List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId).eq(Responsibility::getResponsibilityType, NumberConstant.ONE).eq(Responsibility::getShareId, id)); //通过参数获取医技成分摊层级id CommonParameterVo parameter = centerService.getParameter(MEDICAL_TECHNIQUES_SHARE_LEVEL_ID); // 归集后 List incomeList = incomeCollectionService.list(new QueryWrapper().lambda() .eq(IncomeCollection::getHospId, hospId) .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month)); if (CollUtil.isEmpty(incomeList)) { throw new CostException(500, "归集后数据不存在"); } Map> reportRelationMap = reportRelationService.list(new QueryWrapper().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId)); // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据 List allocationQueryList = allocationQueryService.list(new QueryWrapper().lambda() .eq(AllocationQuery::getHospId, hospId) .eq(year > 0, AllocationQuery::getDateYear, year) .eq(month > 0, AllocationQuery::getDateMonth, month) .eq(AllocationQuery::getShareType, NumberConstant.ONE) ); if (CollUtil.isEmpty(allocationQueryList)) { throw new CostException(500, "分摊后数据不存在"); } //获取医技分摊后数据 List medicalTechniquesAllocationQueryList = allocationQueryService.list(new QueryWrapper().lambda() .eq(AllocationQuery::getHospId, hospId) .eq(year > 0, AllocationQuery::getDateYear, year) .eq(month > 0, AllocationQuery::getDateMonth, month) .eq(AllocationQuery::getShareType, NumberConstant.TWO) ); // 封装数据 List allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class); allocationQueryReportVOList.forEach(i -> { i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA))); i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA))); }); List medicalTechniquesAllocationQueryReportVOList = BeanUtil.convertList(medicalTechniquesAllocationQueryList, AllocationQueryReportVO.class); medicalTechniquesAllocationQueryReportVOList.forEach(i -> { i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA))); i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA))); }); // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用 List allocationList = allocationService.list(new QueryWrapper().lambda().eq(Allocation::getHospId, hospId) .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month)); if (CollUtil.isEmpty(allocationList)) { throw new CostException(500, "分摊报表数据不存在"); } // 查询所有指定类型的损益表 // 每个责任中心对应报表都要生成记录 // 封装需要设置的数据 List list = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, responsibilityList, incomeList, reportRelationMap, allocationQueryReportVOList, allocationList, NumberConstant.ONE); // 删除这个年月的数据 this.remove(new QueryWrapper().lambda().eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month)); // 添加数据 List costDepartmentProfits = BeanUtil.convertList(list, CostDepartmentProfit.class); if (Objects.nonNull(parameter)) { String value = parameter.getValue(); if (StringUtils.isEmpty(value)) { throw new CostException("医技成分摊层级id参数未设置"); } // 查询责任中心里面是医技分摊层级的 List medicalTechniquesResponsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, value)); List medicalTechniquesList = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, medicalTechniquesResponsibilityList, incomeList, reportRelationMap, medicalTechniquesAllocationQueryReportVOList, allocationList, NumberConstant.TWO); List medicalTechniquesCostDepartmentProfits = BeanUtil.convertList(medicalTechniquesList, CostDepartmentProfit.class); if (!CollectionUtils.isEmpty(medicalTechniquesCostDepartmentProfits)) { costDepartmentProfits.addAll(medicalTechniquesCostDepartmentProfits); } } long l = System.currentTimeMillis(); costDepartmentProfits.forEach(i -> { i.setCreateTime(l); }); this.saveBatch(costDepartmentProfits); } private List getCostDepartmentProfitVOS(Long hospId, int year, int month, List reportFormList, List costShareLevelList, List responsibilityList, List incomeList, Map> reportRelationMap, List allocationQueryReportVOList, List allocationList, Integer shareType) { List list = new ArrayList<>(); int finalYear = year; int finalMonth = month; responsibilityList.forEach(i -> { reportFormList.forEach(j -> { CostDepartmentProfitVO costDepartmentProfitVO = new CostDepartmentProfitVO(); costDepartmentProfitVO.setYear(finalYear); costDepartmentProfitVO.setMonth(finalMonth); costDepartmentProfitVO.setReportId(j.getId()); costDepartmentProfitVO.setReportNum(j.getNum()); costDepartmentProfitVO.setCalcType(j.getCalcType()); costDepartmentProfitVO.setReportName(j.getReportName()); costDepartmentProfitVO.setCalcFormula(j.getCalcFormula()); costDepartmentProfitVO.setReportParentId(j.getParentId()); costDepartmentProfitVO.setResponsibilityCode(i.getResponsibilityCode()); costDepartmentProfitVO.setResponsibilityName(i.getResponsibilityName()); costDepartmentProfitVO.setCostType(NumberConstant.ONE); costDepartmentProfitVO.setIncomeType(NumberConstant.ONE); costDepartmentProfitVO.setHospId(hospId); costDepartmentProfitVO.setShareType(shareType); costDepartmentProfitVO.setType(j.getCostType()); costDepartmentProfitVO.setFraction(j.getFraction()); list.add(costDepartmentProfitVO); }); }); Map> listMap = list.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getReportId)); List allList = BeanUtil.convertList(list, CostDepartmentProfitVO.class); // 记录每一次计算的钱 list.forEach(i -> { Integer calcType = i.getCalcType(); if (NumberConstant.ONE.equals(calcType)) { // TODO 按照会计科目进行计算 i.setAmount(setAccountReportData(i, incomeList, allocationQueryReportVOList, reportRelationMap, allList)); } else if (NumberConstant.TWO.equals(calcType)) { // TODO 按照分摊层级进行计算 i.setAmount(setShareLevelReportData(i, costShareLevelList, reportRelationMap, allocationList, allList)); } else if (NumberConstant.THREE.equals(calcType)) { // TODO 按照小计进行计算 i.setAmount(setSubtotal(i, costShareLevelList, listMap, list, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList)); } else if (NumberConstant.FOUR.equals(calcType)) { // TODO 按照计算公式进行计算 i.setAmount(setCalculation(i, list, costShareLevelList, listMap, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList)); } else if (NumberConstant.FIVE.equals(calcType)) { // TODO 按照责任中心进行计算 i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList)); } else { i.setAmount(new BigDecimal("0.000000")); } }); //计算占比 if (CollectionUtils.isEmpty(list)) { return list; } //单独计算计算公式数据 setCalculationAmount(list); //收入 List profitIncomeList = list.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList()); List profitIncome = costPercent(profitIncomeList, "收入"); //成本 List profitCostList = list.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList()); List profitCost = costPercent(profitCostList, "成本"); //不计算项目 List noCompute = list.stream().filter(f -> f.getFraction().equals(NumberConstant.THREE)).collect(Collectors.toList()); noCompute.forEach(profitVO -> profitVO.setPercent(null)); if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) { profitIncome.addAll(profitCost); profitIncome.addAll(noCompute); return profitIncome; } else if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(noCompute)) { profitIncome.addAll(noCompute); return profitIncome; } else if (!CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) { profitCost.addAll(noCompute); return profitCost; } else if (!CollectionUtils.isEmpty(noCompute)) { return noCompute; } else { return list; } } private static void setCalculationAmount(List list) { Map> collect = list.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getResponsibilityCode)); collect.forEach((responsibilityCode, v) -> { // Map dataMap = new HashMap<>(); // for (CostDepartmentProfitVO costDepartmentProfitVO : v) { // if (costDepartmentProfitVO.getAmount() != null) { // dataMap.put(costDepartmentProfitVO.getReportNum(), costDepartmentProfitVO.getAmount()); // } else { // dataMap.put(costDepartmentProfitVO.getReportNum(), new BigDecimal("0.000000")); // } // } Map> collect1 = v.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getCalcType)); //取出所有计算公式数据 List costDepartmentProfitVOS = collect1.get(NumberConstant.FOUR); costDepartmentProfitVOS.sort(Comparator.comparing(CostDepartmentProfitVO::getReportNum, Comparator.nullsLast(Integer::compareTo))); for (CostDepartmentProfitVO profitVO : costDepartmentProfitVOS) { // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2] String formula = profitVO.getCalcFormula(); //找出公式当中所有代码 String replace = formula.replace("[", "") .replace("]", "") .replace("-", ",") .replace("+", ",") .replace("*", ",") .replace("/", ","); ArrayList codeList = CollUtil.newArrayList(replace.split(",")); Map codeMap = new ConcurrentHashMap<>(); for (int j = 0; j < codeList.size(); j++) { codeMap.put(j, codeList.get(j)); } List expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "") .replace("]", "").trim(), 0) .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList()); // 得到预算表达式 得到所有表达式的Map + - 相关的 Map expressionMap = new ConcurrentHashMap<>(); for (int k = 0; k < expressions.size(); k++) { expressionMap.put(k, expressions.get(k)); } // 数字的索引和表达式的索引累加计算 Set codeSet = codeMap.keySet(); List codes = new ArrayList<>(codeSet); AtomicReference totalAmount = new AtomicReference<>(new BigDecimal("0.000000")); for (int i = 0; i < codes.size(); i++) { // 编号 String code = codeMap.get(i); BigDecimal amount = null; for (CostDepartmentProfitVO costDepartmentProfitVO : v) { if (costDepartmentProfitVO.getReportNum().equals(Integer.valueOf(code))) { amount = costDepartmentProfitVO.getAmount(); } } // BigDecimal amount = dataMap.get(Integer.valueOf(code)); if (amount == null) { continue; } // BigDecimal amount = new BigDecimal(o.toString()); String str = expressionMap.get(i); if (str.equals("+")) { totalAmount.set(totalAmount.get().add(amount)); } else if (str.contains("-")) { totalAmount.set(totalAmount.get().subtract(amount)); } else if (str.contains("*")) { totalAmount.set(totalAmount.get().multiply(amount)); } else if (str.contains("/")) { if (amount.compareTo(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP)) == 0) { totalAmount.set(BigDecimal.ZERO); break; } else { totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP)); } } } profitVO.setAmount(totalAmount.get()); } }); } private List costPercent(List profitIncomeList, String type) { List list = new ArrayList<>(); Map> responsibilityGroup = profitIncomeList.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getResponsibilityCode)); responsibilityGroup.forEach((k, v) -> { Map> collect = v.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getFraction)); //分母只有一个 List denominatorList = collect.get(NumberConstant.TWO); if (CollectionUtils.isEmpty(denominatorList)) { throw new CostException(type + "项目未配置分母,请查证后再计算科室损益"); } if (denominatorList.size() > 1) { throw new CostException(type + "收入项目分母大于一个,请查证后再计算科室损益"); } BigDecimal denominator = denominatorList.get(0).getAmount(); //收入分子 List numeratorList = collect.get(NumberConstant.ONE); if (denominator.compareTo(BigDecimal.ZERO) == 0) { for (CostDepartmentProfitVO profitVO : numeratorList) { profitVO.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP)); } denominatorList.get(0).setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP)); } else { for (CostDepartmentProfitVO profitVO : numeratorList) { profitVO.setPercent(profitVO.getAmount().divide(denominator, 4, RoundingMode.HALF_UP)); } denominatorList.get(0).setPercent(BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP)); } list.add(denominatorList.get(0)); list.addAll(numeratorList); }); return list; } /** * 科室损益计算导出 * * @param writer * @param sheet * @param date */ @Override public void getDepartmentProfit(ExcelWriter writer, Sheet sheet, String date) { Long hospId = UserContext.getHospId(); //先展示所有责任中心 非汇总中心 收益中心的责任中心 // 查询所有的节点 List responsibilityList = responsibilityService.list(new QueryWrapper().lambda().eq(Responsibility::getHospId, hospId)); if (CollUtil.isEmpty(responsibilityList)) { throw new CostException(500, "责任中心不存在"); } // 设置表头 Map> responsibilityMap = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getId)); List responsibilities = responsibilityList.stream().filter(i -> NumberConstant.TWO.equals(i.getIsGatherCenter()) && NumberConstant.ONE.equals(i.getResponsibilityType())).collect(Collectors.toList()); Map> responsibilityParentMap = responsibilities.stream().collect(Collectors.groupingBy(Responsibility::getParentId)); Set keySet = responsibilityParentMap.keySet(); int column = 2; for (Long parentId : keySet) { // 同一父节点的叶子节点数据 List list = responsibilityParentMap.get(parentId); for (int i = 0; i < list.size(); i++) { String responsibilityName1 = list.get(i).getResponsibilityName(); // 父层级责任中心名称 List responsibilityList1 = responsibilityMap.get(list.get(i).getParentId()); if (CollUtil.isEmpty(responsibilityList1)) { writer.writeCellValue(column, 0, null); } else { // 父层级责任中心名称 String responsibilityName = responsibilityList1.get(0).getResponsibilityName(); // 子层级责任中心名称 writer.writeCellValue(column, 0, responsibilityName); } writer.writeCellValue(column, 1, responsibilityName1); column++; } } writer.merge(1, 1, 0, 1, "项目", false); DateTime dateTime = DateUtil.parse(date); int year = DateUtil.year(dateTime); int month = DateUtil.month(dateTime) + 1; // 设置列 List departmentProfits = this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, 0)); // 用来筛选金额 Map profitMap = departmentProfits.stream().filter(i -> i.getReportParentId() != 0L).collect(Collectors.toMap(k -> k.getReportName() + "cost" + k.getResponsibilityName(), synOne -> synOne)); // 报表的父层级报表 Map> departmentParentReportMap = departmentProfits.stream().filter(i -> i.getReportParentId() == 0L) .collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)).entrySet().stream() .sorted(Map.Entry.comparingByKey()).collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> oldVal, LinkedHashMap::new ) ); // 不是父节点的所有叶子节点 Map> listParentMap = departmentProfits.stream().filter(i -> i.getReportParentId() != 0L).collect(Collectors.groupingBy(CostDepartmentProfit::getReportParentId)); Set ids = departmentParentReportMap.keySet(); // 默认是在第二行开始的 int row = 2; int columnNum = 0; for (Long id : ids) { String reportParentName = departmentParentReportMap.get(id).get(0).getReportName(); List profitList = listParentMap.get(id); Map> linkedHashMap = profitList.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportNum)).entrySet().stream() .sorted(Map.Entry.comparingByKey()).collect( Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> oldVal, LinkedHashMap::new )); Set reportNums = linkedHashMap.keySet(); for (Integer reportNum : reportNums) { // 这一行要显示的记录 List costDepartmentProfits = linkedHashMap.get(reportNum); // 子层级扥报表名称 String reportName = costDepartmentProfits.get(0).getReportName(); for (int i = 0; i < costDepartmentProfits.size(); i++) { // 添加项目名称 columnNum++; writer.writeCellValue(0, row, reportParentName); writer.writeCellValue(1, row, reportName); for (int j = 0; j < column - 2; j++) { // TODO 设置添加具体金额 // 获取表格对应的字段的值 String responsibilityTopName = sheet.getRow(1).getCell(j + 2).getStringCellValue(); String reportTopName = sheet.getRow(row).getCell(1).getStringCellValue(); BigDecimal amount = profitMap.get(reportTopName + "cost" + responsibilityTopName).getAmount(); writer.writeCellValue(j + 2, row, amount); } } row++; } } // TODO 合并留在最后 int cc = 2; // 合并行 for (int m = 2; m < column - 1; m++) { String cellValue1 = sheet.getRow(0).getCell(m).getStringCellValue(); String cellValue2 = sheet.getRow(0).getCell(m + 1).getStringCellValue(); if (!cellValue1.equals(cellValue2)) { if (cc != m) { writer.merge(0, 0, cc, m, cellValue1, false); } else { writer.writeCellValue(cc, 0, cellValue1); } cc = m + 1; } else if (m == column - 2) { writer.merge(0, 0, cc, m + 1, sheet.getRow(0).getCell(m + 1).getStringCellValue(), false); } } // 合并列 int jj = 2; for (int i = 2; i < row - 1; i++) { String cellValue1 = sheet.getRow(i).getCell(0).getStringCellValue(); String cellValue2 = sheet.getRow(i + 1).getCell(0).getStringCellValue(); if (!cellValue1.equals(cellValue2)) { if (jj != i) { writer.merge(jj, i, 0, 0, cellValue1, false); } else { writer.writeCellValue(0, jj, cellValue1); } jj = i + 1; } else if (i == row - 2) { writer.merge(jj, i + 1, 0, 0, cellValue1, false); } } // 设置列宽 for (int i = 0; i < 50; i++) { // 调整每一列宽度 sheet.autoSizeColumn((short) i); // 解决自动设置列宽中文失效的问题 sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 14 / 10); } } private void getDepartmentProfit(String date, OutputStream outputStream, Integer reportType, String name) throws Exception { Long hospId = UserContext.getHospId(); DateTime dateTime = DateUtil.parse(date); int year = DateUtil.year(dateTime); int month = DateUtil.month(dateTime) + 1; // 查询所有的节点 List responsibilityList = responsibilityService.list(new QueryWrapper().lambda().eq(Responsibility::getHospId, hospId)); if (CollUtil.isEmpty(responsibilityList)) { throw new CostException(500, "责任中心不存在"); } Map responseCodeParentIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b)); // Map responseCodeIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getId, (a, b) -> b)); Map responsibilityIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b)); // Map> responsibilityMap = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getId)); // List responsibilities = responsibilityList.stream().filter(i -> NumberConstant.TWO.equals(i.getIsGatherCenter()) && NumberConstant.ONE.equals(i.getResponsibilityType())).collect(Collectors.toList()); // Map> responsibilityParentMap = responsibilities.stream().collect(Collectors.groupingBy(Responsibility::getParentId)); // // 表头 List departmentProfits = this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month) .eq(CostDepartmentProfit::getShareType, reportType)); if (CollectionUtils.isEmpty(departmentProfits)) { throw new CostException(500, name + "未进行科室损益计算"); } for (CostDepartmentProfit departmentProfit : departmentProfits) { Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode()); if (aLong != null) { if (aLong.equals(NumberConstant.ZERO_L)) { // Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode()); departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName()); } else { Responsibility responsibility = responsibilityIdMap.get(aLong); if (Objects.nonNull(responsibility)) { departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName()); } } } } //损益表设置 List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, reportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } Map> collect = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getParentId)); Map> heads = new HashMap<>();// 最终导出的多个sheet的表头 Map>> datas = new HashMap<>();// 最终导出的多个sheet的内容 Map types = new HashMap<>(); Map> mergeindexs = new HashMap<>();// 最终导出的每个sheet的需要纵向合并的单元格列号 //第一层 List firstTitle = collect.get(NumberConstant.ZERO_L); List titleList = new ArrayList<>(); titleList.add(new TitleEntity("0", null, name, false, NumberConstant.ZERO)); //添加默认三列责任中心 setDefaultColumn(titleList); for (ReportForm reportForm : firstTitle) { TitleEntity entity = new TitleEntity(); entity.setId(String.valueOf(reportForm.getId())); entity.setPid(String.valueOf(reportForm.getParentId())); entity.setContent(reportForm.getReportName()); entity.setFieldName(String.valueOf(reportForm.getNum())); entity.setWidth(20); entity.setSort(reportForm.getSort()); boolean child = getChild(titleList, reportForm, collect); entity.setLast(child); titleList.add(entity); } titleList.sort(Comparator.comparing(TitleEntity::getSort)); // List costDepartmentProfitsDoctor = departmentProfits.stream().filter(f -> f.getShareType().equals(NumberConstant.ONE)).collect(Collectors.toList()); // List costDepartmentProfits = departmentProfits.stream().filter(f -> f.getShareType().equals(NumberConstant.TWO)).collect(Collectors.toList()); //行 Map> doctorParentMap = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode)); // Map> yiParentMap = costDepartmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode)); //列 List titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList()); List> rowList = new ArrayList<>(); // List> rowList1 = new ArrayList<>(); setRowList(doctorParentMap, titleEntities, rowList); // setRowList(yiParentMap, titleEntities, rowList1); ExcelPoiUtil excelTool = new ExcelPoiUtil(name); Map param = ImmutableMap.builder().put("id", "id").put("pid", "pid") .put("content", "content").put("fieldName", "fieldName").put("width", "width").build(); List titleData = excelTool.colEntityTransformer(titleList, param, "0"); Map> autoRowHeights = new HashMap<>(); heads.put(name, titleData);// 每个sheet的表头,sheet名称为key datas.put(name, rowList);// 每个sheet的内容,sheet名称为key types.put(name, 0);// 每个sheet的样式类型,sheet名称为key mergeindexs.put(name, Arrays.asList(0, 1));// 每个sheet的默认行高,sheet名称为key autoRowHeights.put(name, Arrays.asList(1, 2, 3, 4, 5)); // heads.put("科室损益-医技", titleData);// 每个sheet的表头,sheet名称为key // datas.put("科室损益-医技", rowList1);// 每个sheet的内容,sheet名称为key // types.put("科室损益-医技", 0);// 每个sheet的样式类型,sheet名称为key // mergeindexs.put("科室损益-医技", Arrays.asList(0, 1));// 每个sheet的默认行高,sheet名称为key // autoRowHeights.put("科室损益-医技", Arrays.asList(1, 2, 3, 4, 5)); // 多个sheet导出 HSSFWorkbook workbook = excelTool.exportWorkbook(heads, datas, types, autoRowHeights, mergeindexs); // excelTool.save(workbook, "D:\\科室损益.xls"); workbook.write(outputStream); workbook.close(); } private static void setRowList(Map> doctorParentMap, List titleEntities, List> rowList) { DecimalFormat df = new DecimalFormat("0.00%"); doctorParentMap.forEach((k, v) -> { Map> listMap = v.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getResponsibilityCode)); listMap.forEach((k1, v1) -> { Map map = v1.stream().collect(Collectors.toMap(costDepartmentProfit -> String.valueOf(costDepartmentProfit.getReportNum()), costDepartmentProfit -> costDepartmentProfit, (a, b) -> b)); for (int i = 0; i < 2; i++) { Map m = new HashMap(); for (TitleEntity titleEntity : titleEntities) { if (titleEntity.getId().equals("parentResponsibility")) { m.put("parent", v1.get(0).getParentResponsibilityName()); } else if (titleEntity.getId().equals("childResponsibility")) { m.put("child", v1.get(0).getResponsibilityName()); } else if (titleEntity.getId().equals("item")) { if (i == 0) { m.put("itemType", "金额"); } else { m.put("itemType", "占比"); } } else { CostDepartmentProfit profit = map.get(titleEntity.getFieldName()); if (Objects.isNull(profit)) { m.put(titleEntity.getFieldName(), ""); } else { if (i == 0) { m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString()); } else { if (profit.getPercent() != null) { m.put(titleEntity.getFieldName(), df.format(profit.getPercent())); } else { m.put(titleEntity.getFieldName(), ""); } } } } } rowList.add(m); } }); }); } private void setDefaultColumn(List titleList) { TitleEntity parentResponsibility = new TitleEntity(); parentResponsibility.setId("parentResponsibility"); parentResponsibility.setPid("0"); parentResponsibility.setContent(""); parentResponsibility.setFieldName("parent"); parentResponsibility.setWidth(15); parentResponsibility.setSort(NumberConstant.ZERO); parentResponsibility.setLast(true); titleList.add(parentResponsibility); TitleEntity childResponsibility = new TitleEntity(); childResponsibility.setId("childResponsibility"); childResponsibility.setPid("0"); childResponsibility.setContent(""); childResponsibility.setFieldName("child"); childResponsibility.setWidth(15); childResponsibility.setSort(NumberConstant.ZERO); childResponsibility.setLast(true); titleList.add(childResponsibility); TitleEntity item = new TitleEntity(); item.setId("item"); item.setPid("0"); item.setContent(""); item.setFieldName("itemType"); item.setWidth(10); item.setSort(NumberConstant.ZERO); item.setLast(true); titleList.add(item); } private boolean getChild(List titleList, ReportForm reportForm, Map> collect) { List forms = collect.get(reportForm.getId()); if (!CollectionUtils.isEmpty(forms)) { for (ReportForm form : forms) { TitleEntity entity = new TitleEntity(); entity.setId(String.valueOf(form.getId())); entity.setPid(String.valueOf(form.getParentId())); entity.setContent(form.getReportName()); entity.setFieldName(String.valueOf(form.getNum())); entity.setWidth(15); entity.setSort(form.getSort()); boolean last = getChild(titleList, form, collect); entity.setLast(last); titleList.add(entity); } return false; } else { return true; } } private boolean getChild(List titleList, String parentResponsibilityCode, Map> collect, Map responseCodeIdMap, String pid) { List forms = collect.get(parentResponsibilityCode); if (!CollectionUtils.isEmpty(forms)) { for (ResponsibilityVo form : forms) { TitleEntity entity = new TitleEntity(); entity.setPid(pid); entity.setContent(form.getResponsibilityName()); entity.setFieldName(form.getResponsibilityName()); entity.setWidth(10); entity.setSort(form.getSort()); if (form.getResponsibilityCode().equals(parentResponsibilityCode)) { entity.setId(responseCodeIdMap.get(form.getResponsibilityCode()) + "child"); entity.setLast(false); titleList.add(entity); //添加固定两列金额 占比 TitleEntity amountEntity = new TitleEntity(); amountEntity.setId(parentResponsibilityCode + "|" + AMOUNT_FIELD); amountEntity.setPid(responseCodeIdMap.get(form.getResponsibilityCode()) + "child"); amountEntity.setContent("金额"); amountEntity.setFieldName(parentResponsibilityCode + "|" + AMOUNT_FIELD); amountEntity.setWidth(15); amountEntity.setSort(2); amountEntity.setLast(true); titleList.add(amountEntity); TitleEntity percentEntity = new TitleEntity(); percentEntity.setId(parentResponsibilityCode + "|" + PERCENT_FIELD); percentEntity.setPid(responseCodeIdMap.get(form.getResponsibilityCode()) + "child"); percentEntity.setContent("占比"); percentEntity.setFieldName(parentResponsibilityCode + "|" + PERCENT_FIELD); percentEntity.setWidth(10); percentEntity.setSort(2); percentEntity.setLast(true); titleList.add(percentEntity); } else { entity.setId(String.valueOf(responseCodeIdMap.get(form.getResponsibilityCode()))); boolean last = getChild(titleList, form.getResponsibilityCode(), collect, responseCodeIdMap, String.valueOf(responseCodeIdMap.get(form.getResponsibilityCode()))); entity.setLast(last); titleList.add(entity); } } } else { //添加固定两列金额 占比 TitleEntity amountEntity = new TitleEntity(); amountEntity.setId(parentResponsibilityCode + "|" + AMOUNT_FIELD); amountEntity.setPid(pid); amountEntity.setContent("金额"); amountEntity.setFieldName(parentResponsibilityCode + "|" + AMOUNT_FIELD); amountEntity.setWidth(15); amountEntity.setSort(2); amountEntity.setLast(true); titleList.add(amountEntity); TitleEntity percentEntity = new TitleEntity(); percentEntity.setId(parentResponsibilityCode + "|" + PERCENT_FIELD); percentEntity.setPid(pid); percentEntity.setContent("占比"); percentEntity.setFieldName(parentResponsibilityCode + "|" + PERCENT_FIELD); percentEntity.setWidth(10); percentEntity.setSort(2); percentEntity.setLast(true); titleList.add(percentEntity); } return false; } private List getEntityList(ReportForm reportForm, Map> collect) { List list = new ArrayList<>(); List forms = collect.get(reportForm.getId()); if (!CollectionUtils.isEmpty(forms)) { for (ReportForm form : forms) { ExcelExportEntity entity = new ExcelExportEntity(); entity.setName(form.getReportName()); entity.setKey(form.getNum()); entity.setOrderNum(form.getSort()); entity.setList(getEntityList(form, collect)); list.add(entity); } } return list; } /** * 科室损益计算导出 * * @param date * @param hospId * @param reportType */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void getDepartProfitReport(String date, Long hospId, Integer reportType) throws Exception { DateTime dateTime = DateUtil.parse(date); int year = DateUtil.year(dateTime); int month = DateUtil.month(dateTime) + 1; int day = DateUtil.dayOfMonth(dateTime); DictDataVo dict = centerService.getDict(PROFIT_REPORT_TYPE); if (Objects.isNull(dict)) { throw new CostException("未找到损益报表类型字典"); } List dataVoList = dict.getDataVoList(); if (CollectionUtils.isEmpty(dataVoList)) { throw new CostException("未找到损益报表类型字典"); } // Map dictMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, vo -> vo, (a, b) -> b)); //去除全院损益字典 List collect = dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.ONE_S)).collect(Collectors.toList()); if (CollectionUtils.isEmpty(collect)) { throw new CostException("未找到科室损益报表类型字典"); } for (DictDataVo vo : collect) { Integer reportDictType = Integer.valueOf(vo.getCode()); // String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒"); // FileItemFactory factory = new DiskFileItemFactory(5242880, null); // FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, vo.getName() + time + ".xlsx"); //// try { OutputStream outputStream = fileItem.getOutputStream(); // getDepartmentProfit(date, outputStream, reportDictType,vo.getName()); exportDepartmentProfit(date, outputStream, reportDictType, vo.getName()); // } catch (Exception e) { // throw new RuntimeException(e); // } MultipartFile multipartFile = new CommonsMultipartFile(fileItem); String file = uploadFile(multipartFile); FileRecord fileRecord = new FileRecord(); fileRecord.setFileName(vo.getName() + time + ".xlsx") .setFileSource(reportType) .setFileType(vo.getName()) .setFileUrl(file) .setHospId(hospId) .setDateYear(year).setDateMonth(month) .setCreateTime(System.currentTimeMillis()); fileRecordService.save(fileRecord); fileItem.delete(); } } // public void getDepartProfitReport(String date, Long hospId, Integer reportType) throws Exception { // DateTime dateTime = DateUtil.parse(date); // int year = DateUtil.year(dateTime); // int month = DateUtil.month(dateTime) + 1; // int day = DateUtil.dayOfMonth(dateTime); // // // String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒"); // FileItemFactory factory = new DiskFileItemFactory(5242880, null); // FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, "测试临床" + time + ".xls"); // OutputStream outputStream = fileItem.getOutputStream(); // // handleDepartmentProfit(date, outputStream,8,"测试临床"); // // } private void getLastDefaultHeader(List titleList, String responsibilityId) { TitleEntity amountEntity = new TitleEntity(); amountEntity.setId(NumberConstant.ONE_S); amountEntity.setPid(responsibilityId); amountEntity.setContent(AMOUNT); amountEntity.setFieldName(AMOUNT); amountEntity.setWidth(20); amountEntity.setLast(true); titleList.add(amountEntity); TitleEntity percentEntity = new TitleEntity(); percentEntity.setId(NumberConstant.TWO_S); percentEntity.setPid(responsibilityId); percentEntity.setContent(PERCENT); percentEntity.setFieldName(PERCENT); percentEntity.setWidth(20); percentEntity.setLast(true); titleList.add(percentEntity); } public String uploadFile(MultipartFile file) { Long hospId = UserContext.getCurrentLoginHospId(); String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + ".xls"; DateTime date = DateUtil.date(); int month = DateUtil.month(date) + 1; int year = DateUtil.year(date); int day = DateUtil.dayOfMonth(date); String fileUrl = ""; try { // file.transferTo(new File(localFilePath)); // String format = DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN); String dataDirectory = minioConfig.getBucketName(); String uploadFileName = "departReport" + "/" + hospId + "/" + year + "/" + month + "/" + day + "/" + fileName; InputStream inputStream = file.getInputStream(); minioFileUtil.putObject(dataDirectory, uploadFileName, inputStream); fileUrl = minioFileUtil.getObjectUrl(dataDirectory, uploadFileName); } catch (IOException e) { log.error("【文件上传至服务器】失败,绝对路径:{}", e.getMessage()); throw new CostException(ErrorCodeEnum.FILE_UPLOAD_ERROR); } return fileUrl; } /** * 删除科室损益数据 * * @param idList 科室损益的Id的集合 */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void deleteByIds(List idList) { this.removeByIds(idList); } @Override public void computeProfit(String computeDate, Long hospId, String reportType) { //需要用代码计算时 if(IsNeedCalc(reportType)){ String parameterValue = centerService.getParameterValue(ParameterConstant.ALLOCATION_TYPE); if (NumberConstant.ONE_S.equals(parameterValue)) { //按责任中心分摊的科室损益计算 computeProfitAction(computeDate, hospId, reportType); }else if (NumberConstant.TWO_S.equals(parameterValue)) { //按会计科目分摊的科室损益计算 calcDeptProfit(computeDate, hospId, reportType); } //计算同环比 handleSpecificMonthsCalculation(hospId, computeDate, reportType); } execDeptProfitSql(computeDate, reportType); } @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void computeProfitAction(String computeDate, Long hospId, String reportType) { // DateTime parse = DateUtil.parse(computeDate); // int year = DateUtil.year(parse); // int month = DateUtil.month(parse) + 1; Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); // 先查询指定条件的报表数据 查询损益表的数据 List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, reportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } // 遍历报表数据根据报表数据计算方式进行计算 //这里拆分成两个 原有的最后一层 以及 参数医技 DictDataVo dataVo = getDictDataVo(reportType); Long id = Long.valueOf(dataVo.getExpandOne()); // 查询最后一个层级的责任中心 List costShareLevelList = costShareLevelService.list(new QueryWrapper().lambda() .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort)); if (CollUtil.isEmpty(costShareLevelList)) { throw new CostException(500, "分摊层级未设置"); } // // TODO 可能多个 // Long id = costShareLevelList.get(0).getId(); // 查询责任中心里面是这个层级的所有的收益中心 // List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() // .eq(Responsibility::getHospId, hospId).eq(Responsibility::getResponsibilityType, NumberConstant.ONE).eq(Responsibility::getShareId, id)); List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, id)); // 查询责任中心里面是医技分摊层级的 // List medicalTechniquesResponsibilityList = responsibilityService.list(new QueryWrapper().lambda() // .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, value)); // 归集后 List incomeList = incomeCollectionService.list(new QueryWrapper().lambda() .eq(IncomeCollection::getHospId, hospId) .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month)); if (CollUtil.isEmpty(incomeList)) { throw new CostException(500, "归集后数据不存在"); } Map> reportRelationMap = reportRelationService.list(new QueryWrapper().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId)); // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据 List allocationQueryList = allocationQueryService.list(new QueryWrapper().lambda().eq(AllocationQuery::getHospId, hospId) .eq(year > 0, AllocationQuery::getDateYear, year) .eq(month > 0, AllocationQuery::getDateMonth, month)); if (CollUtil.isEmpty(allocationQueryList)) { throw new CostException(500, "分摊后数据不存在"); } // 封装数据 List allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class); allocationQueryReportVOList.forEach(i -> { i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA))); i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA))); }); // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用 List allocationList = allocationService.list(new QueryWrapper().lambda().eq(Allocation::getHospId, hospId) .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month)); if (CollUtil.isEmpty(allocationList)) { throw new CostException(500, "分摊报表数据不存在"); } // 查询所有指定类型的损益表 // 每个责任中心对应报表都要生成记录 // 封装需要设置的数据 List list = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, responsibilityList, incomeList, reportRelationMap, allocationQueryReportVOList, allocationList, Integer.valueOf(reportType)); // 删除这个年月的数据 this.remove(new QueryWrapper().lambda().eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, Integer.valueOf(reportType))); // 添加数据 List costDepartmentProfits = BeanUtil.convertList(list, CostDepartmentProfit.class); long l = System.currentTimeMillis(); costDepartmentProfits.forEach(i -> { i.setCreateTime(l); }); this.saveBatch(costDepartmentProfits); //记录最后一次 损益计算日期 computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate); } /** * 处理指定月份及关联月份的计算(当前月、下个月、明年同月) * * @param hospId 院区ID * @param computeDate 日期字符串,格式:YYYY-MM * @param shareType 报表类型 */ public void handleSpecificMonthsCalculation(Long hospId, String computeDate, String shareType) { // 解析输入的年月 Integer currentYear = ComputeDateUtils.getComputeYear(computeDate); Integer currentMonth = ComputeDateUtils.getComputeMonth(computeDate); // 计算需要处理的期间信息 List periods = calculateAllRelatedPeriods(currentYear, currentMonth); // 获取所有相关的期间数据 Map> allDataMap = loadAllPeriodData(hospId, shareType, periods); // 对每个期间执行计算 for (PeriodInfoVO period : periods) { String currentKey = buildPeriodKey(period.getYear(), period.getMonth()); if (allDataMap.containsKey(currentKey) && !CollectionUtils.isEmpty(allDataMap.get(currentKey))) { List currentRecords = allDataMap.get(currentKey); List prevRecords = getPeriodData(allDataMap, period.getPrevYear(), period.getPrevMonth()); List lastYearRecords = getPeriodData(allDataMap, period.getLastYear(), period.getLastMonth()); // 执行批量计算 calculatePeriodComparisonWithPreloadedData(currentRecords, prevRecords, lastYearRecords); } } } /** * 构建所有需要处理的期间信息 */ private List calculateAllRelatedPeriods(int baseYear, int baseMonth) { List result = new ArrayList<>(); // 添加当前期间 result.add(calculatePeriodInfo(baseYear, baseMonth)); // 下个月 int nextMonth = baseMonth + 1; int nextMonthYear = baseYear; if (baseMonth == 12) { nextMonth = 1; nextMonthYear += 1; } result.add(calculatePeriodInfo(nextMonthYear, nextMonth)); // 明年同月 result.add(calculatePeriodInfo(baseYear + 1, baseMonth)); return result; } /** * 构建单个期间的信息(当前月、上月、去年同期) */ private PeriodInfoVO calculatePeriodInfo(int year, int month) { PeriodInfoVO info = new PeriodInfoVO(); info.setYear( year); info.setMonth( month); // 上期 if (month == 1) { info.setPrevYear(year - 1); info.setPrevMonth(12); } else { info.setPrevYear( year); info.setPrevMonth(month - 1); } // 同期 info.setLastYear(year - 1); info.setLastMonth( month); return info; } /** * 加载所有相关期间的数据(去重处理) */ private Map> loadAllPeriodData(Long hospId, String shareType, List periods) { Set allPeriodKeys = new HashSet<>(); // 收集所有需要查询的年月组合 for (PeriodInfoVO period : periods) { allPeriodKeys.add(buildPeriodKey(period.getYear(), period.getMonth())); allPeriodKeys.add(buildPeriodKey(period.getPrevYear(), period.getPrevMonth())); allPeriodKeys.add(buildPeriodKey(period.getLastYear(), period.getLastMonth())); } // 去重后查询 Map> result = new HashMap<>(); Set processedKeys = new HashSet<>(); // 已处理的键集合 for (String key : allPeriodKeys) { if (!processedKeys.contains(key)) { int[] ym = parsePeriodKey(key); List records = getPeriodRecords(hospId, shareType, ym[0], ym[1]); result.put(key, records); processedKeys.add(key); // 标记为已处理 } } return result; } /** * 获取指定期间的数据 * * @param hospId 院区ID * @param shareType 报表类型 * @param year 年份 * @param month 月份 * @return 符合条件的数据列表 */ private List getPeriodRecords(Long hospId, String shareType, int year, int month) { return this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getShareType, shareType) .eq(CostDepartmentProfit::getYear, year) .eq(CostDepartmentProfit::getMonth, month) .eq(CostDepartmentProfit::getDeleteTime, 0)); } /** * 根据年月获取对应的数据(从内存中查找) */ private List getPeriodData(Map> dataMap, int year, int month) { String key = buildPeriodKey(year, month); return dataMap.getOrDefault(key, Collections.emptyList()); } /** * 批量计算同环比及同期金额(使用预加载数据) */ public void calculatePeriodComparisonWithPreloadedData( List currentRecords, List prevRecords, List lastYearRecords) { if (CollectionUtils.isEmpty(currentRecords)) { return; } // 创建责任码+报表编号到记录的映射 Map prevMap = new HashMap<>(); for (CostDepartmentProfit record : prevRecords) { String key = buildRecordKey(record); prevMap.put(key, record); } Map lastYearMap = new HashMap<>(); for (CostDepartmentProfit record : lastYearRecords) { String key = buildRecordKey(record); lastYearMap.put(key, record); } // 批量更新数据 for (CostDepartmentProfit record : currentRecords) { String key = buildRecordKey(record); CostDepartmentProfit prevRecord = prevMap.get(key); CostDepartmentProfit lastYearRecord = lastYearMap.get(key); // 设置上期和同期金额 record.setPrevPeriodAmount(prevRecord != null ? prevRecord.getAmount() : BigDecimal.ZERO); record.setSamePeriodAmount(lastYearRecord != null ? lastYearRecord.getAmount() : BigDecimal.ZERO); // 计算环比和同比 record.setMomRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getPrevPeriodAmount())); record.setYoyRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getSamePeriodAmount())); } // 批量更新数据库 this.updateBatchById(currentRecords); } /** * 构建期间键(用于存储和检索数据) */ private String buildPeriodKey(int year, int month) { return year + "_" + month; } /** * 解析期间键为年月数组 */ private int[] parsePeriodKey(String key) { String[] parts = key.split("_"); return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])}; } /** * 构建记录的唯一标识键(责任码 + 报表编号) */ private String buildRecordKey(CostDepartmentProfit record) { return record.getResponsibilityCode() + "_" + record.getReportNum(); } /** * 安全地计算百分比:避免除零错误 */ private BigDecimal calculateProfitRate(BigDecimal current, BigDecimal base) { if (base == null || base.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } BigDecimal bigDecimal = current.divide(base, 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP); return bigDecimal; } /** * 执行科室损益后续脚本 * * @param computeDate * @param reportType */ public void execDeptProfitSql(String computeDate, String reportType) { Map sqlParameter = new HashMap<>(); sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, computeDate); sqlParameter.put(SQLParameter.REPORT_TYPE_CODE, reportType); sqlService.autoExecuteSql(CustomSqlTypeEnum.DEPT_PROFIT_CALC.getCode(), sqlParameter); } private DictDataVo getDictDataVo(String reportType) { DictDataVo dict = centerService.getDict(PROFIT_REPORT_TYPE); if (Objects.isNull(dict)) { throw new CostException("未找到损益报表类型字典"); } List dataVoList = dict.getDataVoList(); if (CollectionUtils.isEmpty(dataVoList)) { throw new CostException("未找到损益报表类型字典"); } Map dictMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, vo -> vo, (a, b) -> b)); DictDataVo dataVo = dictMap.get(reportType); if (Objects.isNull(dataVo)) { throw new CostException("未找到损益报表类型为【" + reportType + "】的字典"); } return dataVo; } /** * 计算界面报表样式展示 * * @param computeDate 核算年月 * @param hospId 医院id * @param reportType 报表类型 * @return */ @Override public Object computeProfitReport(String computeDate, Long hospId, String reportType) { Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); Integer integerReportType = Integer.valueOf(reportType); List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } List commonTitleReportVos = reportFormList.stream().map(reportForm -> { CommonTitleReportVo commonTitleReportVo = new CommonTitleReportVo(reportForm.getId(), reportForm.getParentId(), reportForm.getReportName(), reportForm.getSort()); commonTitleReportVo.setDataType(reportForm.getDataType()); commonTitleReportVo.setDecimalPlace(reportForm.getDecimalPlace()); commonTitleReportVo.setPermil(reportForm.getPermil()); return commonTitleReportVo; }).collect(Collectors.toList()); // List commonTitleReportVos = BeanUtil.convertList(reportFormList,CommonTitleReportVo.class); Map> collect = commonTitleReportVos.stream().collect(Collectors.groupingBy(CommonTitleReportVo::getParentReportId)); List titleReportVoList = collect.get(NumberConstant.ZERO_L); for (CommonTitleReportVo reportVo : titleReportVoList) { List childList = collect.get(reportVo.getReportId()); if (!CollectionUtils.isEmpty(childList)) { childList.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo))); reportVo.setChildTitle(setReportChildren(childList, collect)); } } ProfitReportResponse response = new ProfitReportResponse(); if (!CollectionUtils.isEmpty(titleReportVoList)) { titleReportVoList.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo))); } response.setTitle(titleReportVoList); List departmentProfits = this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year) .eq(CostDepartmentProfit::getMonth, month) .eq(CostDepartmentProfit::getShareType, integerReportType)); if (CollectionUtils.isEmpty(departmentProfits)) { response.setData(new ArrayList<>()); return response; } List filterProfit = new ArrayList<>(); Map> collectGroup = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)); for (ReportForm reportForm : reportFormList) { Integer hide = reportForm.getHide(); if (hide.equals(NumberConstant.ONE)) { List costDepartmentProfits = collectGroup.get(reportForm.getId()); if (!CollectionUtils.isEmpty(costDepartmentProfits)) { filterProfit.addAll(costDepartmentProfits); } } } List costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class); Map> responseGroup = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode)); //取一行数据 作为父类模版 Set>> entrySet = responseGroup.entrySet(); Map.Entry> firstEntry = entrySet.iterator().next(); List parentModel = firstEntry.getValue(); //备注:所有记算过的数据都是最后一层责任中心,所以按最后一层责任 中心 找出所有上级责任中心后 给模版添加到上层责任中心 //按报表类型 取字典 DictDataVo dataVo = getDictDataVo(reportType); Long id = Long.valueOf(dataVo.getExpandOne()); //按字典给护 的 分摊层级id 查找对应报表 的责任中心 找出的是没有父类的 List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId) .eq(Responsibility::getShareId, id)); if (CollectionUtils.isEmpty(responsibilityList)) { throw new CostException("未找到对应分摊层级责任中心"); } //获取授权的责任中心 responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList); //获取当前院区所有的责任中心 List responsibilityAllList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId)); Map map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b)); Map responseCodeParentIdMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b)); Map responseNameMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName, (a, b) -> b)); //通过查询的最下层责任中心 找到其所有父类责任中心 List parentResponseList = new ArrayList<>(); for (Responsibility responsibility : responsibilityList) { if (responsibility.getParentId().equals(NumberConstant.ZERO_L)) { parentResponseList.add(responsibility); } else { Responsibility responsibility1 = map.get(responsibility.getParentId()); if (Objects.nonNull(responsibility1)) { parentResponseList.add(responsibility1); if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) { getResponsibilityParent(responsibility1, map, parentResponseList); } } } } //去除重复组装数据 List parentResponsibility = parentResponseList.stream().distinct().collect(Collectors.toList()); //找出最外层用于出参循环 List responseParent = parentResponsibility.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList()); //只留下中间责任中心 parentResponsibility.removeAll(responseParent); //最上级添加模版 List parentReportVos = new ArrayList<>(); for (Responsibility responsibility : responseParent) { List profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class); for (CostProfitVo costProfitVo : profitVos) { costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode()); costProfitVo.setResponsibilityName(responsibility.getResponsibilityName()); costProfitVo.setSort(responsibility.getSort()); costProfitVo.setAmount(BigDecimal.ZERO); costProfitVo.setPercent(BigDecimal.ZERO); parentReportVos.add(costProfitVo); } } //中间责任中心 添加模版 添加父类责任中心 List middleReportVos = new ArrayList<>(); for (Responsibility responsibility : parentResponsibility) { List profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class); Long aLong = responseCodeParentIdMap.get(responsibility.getResponsibilityCode()); for (CostProfitVo costProfitVo : profitVos) { costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode()); costProfitVo.setResponsibilityName(responsibility.getResponsibilityName()); costProfitVo.setSort(responsibility.getSort()); costProfitVo.setAmount(BigDecimal.ZERO); costProfitVo.setPercent(BigDecimal.ZERO); if (aLong.equals(NumberConstant.ZERO_L)) { costProfitVo.setParentResponsibilityCode(responsibility.getResponsibilityCode()); costProfitVo.setParentResponsibilityName(responsibility.getResponsibilityName()); } else { Responsibility responsibility1 = map.get(aLong); if (Objects.nonNull(responsibility1)) { costProfitVo.setParentResponsibilityCode(responsibility1.getResponsibilityCode()); costProfitVo.setParentResponsibilityName(responsibility1.getResponsibilityName()); } } middleReportVos.add(costProfitVo); } } // 添加父类责任中心 //已计算过的数据添加上级责任中心 for (CostProfitVo departmentProfit : costProfitVos) { Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode()); if (aLong != null) { if (aLong.equals(NumberConstant.ZERO_L)) { // Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode()); departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName()); } else { Responsibility responsibility = map.get(aLong); if (Objects.nonNull(responsibility)) { departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName()); } } } } //已计算过的 按责任中心-报表id 分组 Map>> sumGroup = new HashMap<>(); //已计算过的 按父类责任中心分组 Map> collect1 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode)); if (!CollectionUtils.isEmpty(collect1)) { collect1.forEach((k, v) -> { Map> collect2 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); sumGroup.put(k, collect2); }); } //计算所有中间层 List middleFilterReportVos = new ArrayList<>(); for (CostProfitVo middleReportVo : middleReportVos) { String responsibilityCode = middleReportVo.getResponsibilityCode(); Map> longListMap = sumGroup.get(responsibilityCode); if (!CollectionUtils.isEmpty(longListMap)) { List profitVos = longListMap.get(middleReportVo.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); if (!CollectionUtils.isEmpty(profitVos)) { profitVos.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); middleReportVo.setAmount(sum.get()); } } else { //未在最下层找到数据的可能还是一个分类 提取出来 middleFilterReportVos.add(middleReportVo); } } //用于处理多层级中 有两层中间层的数据 if (!CollectionUtils.isEmpty(middleFilterReportVos)) { handleMiddleFilterReport(middleReportVos, middleFilterReportVos); } Map>> sumMiddleGroup = new HashMap<>(); Map> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode)); if (!CollectionUtils.isEmpty(collect2)) { collect2.forEach((k, v) -> { Map> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); sumMiddleGroup.put(k, collect3); }); } // 最上层的需要执行两次分组 两层时取最后一层计算 多层时取 中间层计算合计 for (CostProfitVo parentReportVo : parentReportVos) { String responsibilityCode = parentReportVo.getResponsibilityCode(); Map> longListMap = sumGroup.get(responsibilityCode); //在最下层找到的 说明是两层 if (!CollectionUtils.isEmpty(longListMap)) { List profitVos = longListMap.get(parentReportVo.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); if (!CollectionUtils.isEmpty(profitVos)) { profitVos.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } //再找中间层是否存在子类 Map> longListMap1 = sumMiddleGroup.get(responsibilityCode); if (!CollectionUtils.isEmpty(longListMap1)) { List profitVos1 = longListMap1.get(parentReportVo.getReportId()); if (!CollectionUtils.isEmpty(profitVos1)) { profitVos1.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } } parentReportVo.setAmount(sum.get()); } else { //未在最下层找到从中间层找进行计算 Map> longListMap1 = sumMiddleGroup.get(responsibilityCode); if (!CollectionUtils.isEmpty(longListMap1)) { List profitVos = longListMap1.get(parentReportVo.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); if (!CollectionUtils.isEmpty(profitVos)) { profitVos.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } parentReportVo.setAmount(sum.get()); } } } //把最上层 中间层 最下层组装成一个list 进行分组 //组装数据 Map> collect3 = parentReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode)); List list = new ArrayList<>(); collect3.forEach((k, v) -> { CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo(); // List costProfitVos1 = collect3.get(s); vo.setResponsibilityCode(k); vo.setResponsibilityName(responseNameMap.get(k)); if (!CollectionUtils.isEmpty(v)) { vo.setSort(v.get(0).getSort()); List dataReportVos = new ArrayList<>(); for (CostProfitVo costProfitVo : v) { CommonDataReportVo vo1 = new CommonDataReportVo(); vo1.setReportId(costProfitVo.getReportId()); vo1.setValue(costProfitVo.getAmount()); dataReportVos.add(vo1); } vo.setProfitList(dataReportVos); } else { vo.setSort(NumberConstant.ZERO); vo.setProfitList(new ArrayList<>()); } list.add(vo); }); middleReportVos.addAll(costProfitVos); Map> collect5 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode)); List list1 = new ArrayList<>(); collect5.forEach((k, v) -> { CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo(); vo.setResponsibilityCode(k); vo.setResponsibilityName(responseNameMap.get(k)); if (!CollectionUtils.isEmpty(v)) { vo.setParentResponsibilityCode(v.get(0).getParentResponsibilityCode()); vo.setSort(v.get(0).getSort()); List dataReportVos = new ArrayList<>(); for (CostProfitVo costProfitVo : v) { CommonDataReportVo vo1 = new CommonDataReportVo(); vo1.setReportId(costProfitVo.getReportId()); vo1.setValue(costProfitVo.getAmount()); dataReportVos.add(vo1); } vo.setProfitList(dataReportVos); } else { vo.setSort(NumberConstant.ZERO); vo.setProfitList(new ArrayList<>()); } list1.add(vo); }); Map> collect4 = list1.stream().collect(Collectors.groupingBy(CostResponsibilityProfitVo::getParentResponsibilityCode)); for (CostResponsibilityProfitVo vo : list) { List list2 = collect4.get(vo.getResponsibilityCode()); if (!CollectionUtils.isEmpty(list2)) { if (!list2.get(0).getResponsibilityCode().equals(vo.getResponsibilityCode())) { vo.setChild(setProfitChildren(list2, collect4)); } } } //按责任中心序号排序 costResponsibilityProfitVoSort(list); response.setData(list); //提取出最上层 return response; } private static void handleMiddleFilterReport(List middleReportVos, List middleFilterReportVos) { //去除没计算完的 middleReportVos.removeAll(middleFilterReportVos); //说明有没计算完的 Map>> sumFilterGroup = new HashMap<>(); //已计算过的 按父类责任中心分组 Map> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode)); if (!CollectionUtils.isEmpty(collect2)) { collect2.forEach((k, v) -> { Map> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); sumFilterGroup.put(k, collect3); }); } for (CostProfitVo middleReportVo : middleFilterReportVos) { String responsibilityCode = middleReportVo.getResponsibilityCode(); Map> longListMap = sumFilterGroup.get(responsibilityCode); if (!CollectionUtils.isEmpty(longListMap)) { List profitVos = longListMap.get(middleReportVo.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); if (!CollectionUtils.isEmpty(profitVos)) { profitVos.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); middleReportVo.setAmount(sum.get()); } } //todo:先处理到四层 } //添加回去 middleReportVos.addAll(middleFilterReportVos); } private List setProfitChildren(List child, Map> collect) { for (CostResponsibilityProfitVo reportVo : child) { if (!CollectionUtils.isEmpty(collect.get(reportVo.getResponsibilityCode()))) { reportVo.setChild(setProfitChildren(collect.get(reportVo.getResponsibilityCode()), collect)); } } return child; } private List setReportChildren(List child, Map> collect) { for (CommonTitleReportVo reportVo : child) { if (!CollectionUtils.isEmpty(collect.get(reportVo.getReportId()))) { reportVo.setChildTitle(setReportChildren(collect.get(reportVo.getReportId()), collect)); } } if (!CollectionUtils.isEmpty(child)) { child.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo))); } return child; } /** * 损益计算获取责任中心列表 * * @param reportType 报表类型 * @param responsibilityName 责任中心名称 * @return 责任中心列表 */ @Override public Object getProfitResponsibility(String reportType, String responsibilityName) { Long hospId = UserContext.getHospId(); DictDataVo dataVo = getDictDataVo(reportType); Long id = Long.valueOf(dataVo.getExpandOne()); List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId) .eq(Responsibility::getShareId, id) .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null)) .like(StrUtil.isNotBlank(responsibilityName), Responsibility::getResponsibilityName, responsibilityName)); if (CollectionUtils.isEmpty(responsibilityList)) { throw new CostException("未找到对应分摊层级责任中心"); } //获取授权的责任中心 responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList); List responsibilityAllList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId)); Map map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b)); List addList = new ArrayList<>(); for (Responsibility responsibility : responsibilityList) { Responsibility responsibility1 = map.get(responsibility.getParentId()); if (Objects.nonNull(responsibility1)) { addList.add(responsibility1); if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) { getResponsibilityParent(responsibility1, map, addList); } } } if (!CollectionUtils.isEmpty(addList)) { //去重 List collect = addList.stream().distinct().collect(Collectors.toList()); responsibilityList.addAll(collect); } Map> collect = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId)); List responsibilities = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); for (Responsibility responsibility : responsibilities) { List responsibilities1 = collect.get(responsibility.getId()); if (!CollectionUtils.isEmpty(responsibilities1)) { responsibility.setChildren(setResponsibilityChildren(responsibilities1, collect)); } } responsibilitySort(responsibilities); return responsibilities; } private void getResponsibilityParent(Responsibility responsibility, Map collect, List addList) { Responsibility responsibility1 = collect.get(responsibility.getParentId()); if (Objects.nonNull(responsibility1)) { addList.add(responsibility1); if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) { getResponsibilityParent(responsibility1, collect, addList); } } } private List setResponsibilityChildren(List child, Map> collect) { for (Responsibility responsibility : child) { if (!CollectionUtils.isEmpty(collect.get(responsibility.getId()))) { responsibility.setChildren(setResponsibilityChildren(collect.get(responsibility.getId()), collect)); } } return child; } /** * @param computeDate * @param hospId * @param reportType * @param responsibilityCode * @return */ @Override public Object getComputeProfitList(String computeDate, Long hospId, String reportType, String responsibilityCode) { Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); //取出计算当前月计算过的科室损益 List departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode); if (CollectionUtils.isEmpty(departmentProfits)) { throw new CostException(500, "未进行科室损益计算"); } Integer integerReportType = Integer.valueOf(reportType); List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, integerReportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } List filterProfit = new ArrayList<>(); Map> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)); for (ReportForm reportForm : reportFormList) { Integer hide = reportForm.getHide(); if (hide.equals(NumberConstant.ONE)) { // filterProfit.addAll(collect1.get(reportForm.getId())); List costDepartmentProfits = collect1.get(reportForm.getId()); if (!CollectionUtils.isEmpty(costDepartmentProfits)) { filterProfit.addAll(costDepartmentProfits); } } } Map sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b)); Map descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b)); Map> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId)); List costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class); costProfitVos.forEach(profitVo -> { profitVo.setDescription(descriptionMap.get(profitVo.getReportId())); profitVo.setSort(sortMap.get(profitVo.getReportId())); List profitReportFormList = reportIdMap.get(profitVo.getReportId()); if (!CollectionUtils.isEmpty(profitReportFormList)) { profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType()); profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace()); profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil()); } else { profitVo.setDataType(NumberConstant.ONE); profitVo.setDecimalPlace(NumberConstant.TWO); profitVo.setPermil(NumberConstant.ONE); } }); Map> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId)); List costProfitParentVos = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); for (CostProfitVo costProfitVo : costProfitParentVos) { List costProfitVo1 = collect.get(costProfitVo.getReportId()); if (!CollectionUtils.isEmpty(costProfitVo1)) { costProfitVo.setChildren(setChildren(costProfitVo1, collect)); } } if (!CollectionUtils.isEmpty(costProfitParentVos)) { costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } return costProfitParentVos; } @Override public Object getLastComputeDate() { Long hospId = UserContext.getHospId(); ComputeLastProfitDate lastComputeDate = computeLastProfitDateRepository.getLastComputeDate(hospId); if (Objects.nonNull(lastComputeDate)) { return lastComputeDate.getComputeDate(); } int year = DateUtils.getYear(new Date()); int month = DateUtils.getMonth(new Date()) + 1; if (month < 10) { return year + "-0" + month; } else { return year + "-" + month; } } @Override public Object getBatchComputeProfitList(String beginComputeDate, String endComputeDate, Long hospId, String reportType, String responsibilityCode) { Map> map = new HashMap<>(); List responses = new ArrayList<>(); if (beginComputeDate.equals(endComputeDate)) { Integer year = ComputeDateUtils.getComputeYear(beginComputeDate); Integer month = ComputeDateUtils.getComputeMonth(beginComputeDate); //取出计算当前月计算过的科室损益 List departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode); if (CollectionUtils.isEmpty(departmentProfits)) { throw new CostException(500, "未进行科室损益计算"); } Integer integerReportType = Integer.valueOf(reportType); List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, integerReportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } Map> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId)); List filterProfit = new ArrayList<>(); Map> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)); for (ReportForm reportForm : reportFormList) { Integer hide = reportForm.getHide(); if (hide.equals(NumberConstant.ONE)) { // filterProfit.addAll(collect1.get(reportForm.getId())); List costDepartmentProfits = collect1.get(reportForm.getId()); if (!CollectionUtils.isEmpty(costDepartmentProfits)) { filterProfit.addAll(costDepartmentProfits); } } } Map sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b)); Map descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b)); List costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class); costProfitVos.forEach(profitVo -> { profitVo.setDescription(descriptionMap.get(profitVo.getReportId())); profitVo.setSort(sortMap.get(profitVo.getReportId())); List profitReportFormList = reportIdMap.get(profitVo.getReportId()); if (!CollectionUtils.isEmpty(profitReportFormList)) { profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType()); profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace()); profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil()); } else { profitVo.setDataType(NumberConstant.ONE); profitVo.setDecimalPlace(NumberConstant.TWO); profitVo.setPermil(NumberConstant.ONE); } }); Map> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId)); List costProfitParentVos = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); for (CostProfitVo costProfitVo : costProfitParentVos) { List costProfitVo1 = collect.get(costProfitVo.getReportId()); if (!CollectionUtils.isEmpty(costProfitVo1)) { costProfitVo.setChildren(setChildren(costProfitVo1, collect)); } } if (!CollectionUtils.isEmpty(costProfitParentVos)) { costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } BatchCostProfitResponse response = new BatchCostProfitResponse(); response.setComputeDate(beginComputeDate); response.setProfitVoList(costProfitParentVos); response.setAllowDrillDown(true); responses.add(response); return responses; } else { Date date = DateUtils.StringToDate(beginComputeDate, DateStyleEnum.YYYY_MM); Date endDate = DateUtils.StringToDate(endComputeDate, DateStyleEnum.YYYY_MM); if (DateUtils.compareDate(date, endDate)) { throw new CostException("开始日期不能大于结束日期"); } List intervalMonthList = DateUtils.getIntervalMonthList(date, endDate); List allCostProfitVo=new ArrayList<>(); if (!CollectionUtils.isEmpty(intervalMonthList)) { for (String computeDates : intervalMonthList) { Integer year = ComputeDateUtils.getComputeYear(computeDates); Integer month = ComputeDateUtils.getComputeMonth(computeDates); //取出计算当前月计算过的科室损益 List departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode); if (CollectionUtils.isEmpty(departmentProfits)) { throw new CostException(500, "未进行科室损益计算"); } Integer integerReportType = Integer.valueOf(reportType); List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, integerReportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } Map> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId)); List filterProfit = new ArrayList<>(); Map> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)); for (ReportForm reportForm : reportFormList) { Integer hide = reportForm.getHide(); if (hide.equals(NumberConstant.ONE)) { // filterProfit.addAll(collect1.get(reportForm.getId())); List costDepartmentProfits = collect1.get(reportForm.getId()); if (!CollectionUtils.isEmpty(costDepartmentProfits)) { filterProfit.addAll(costDepartmentProfits); } } } Map sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b)); Map descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b)); List costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class); costProfitVos.forEach(profitVo -> { profitVo.setDescription(descriptionMap.get(profitVo.getReportId())); profitVo.setSort(sortMap.get(profitVo.getReportId())); List profitReportFormList = reportIdMap.get(profitVo.getReportId()); if (!CollectionUtils.isEmpty(profitReportFormList)) { profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType()); profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace()); profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil()); } else { profitVo.setDataType(NumberConstant.ONE); profitVo.setDecimalPlace(NumberConstant.TWO); profitVo.setPermil(NumberConstant.ONE); } }); //记录所有月份的科室损益数据 allCostProfitVo.addAll(costProfitVos); Map> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId)); List costProfitParentVos = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); for (CostProfitVo costProfitVo : costProfitParentVos) { List costProfitVo1 = collect.get(costProfitVo.getReportId()); if (!CollectionUtils.isEmpty(costProfitVo1)) { costProfitVo.setChildren(setChildren(costProfitVo1, collect)); } } if (!CollectionUtils.isEmpty(costProfitParentVos)) { costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } BatchCostProfitResponse response = new BatchCostProfitResponse(); response.setComputeDate(computeDates); response.setProfitVoList(costProfitParentVos); response.setAllowDrillDown(true); responses.add(response); } //获取月度汇总数据 List costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo); if(!CollectionUtils.isEmpty(costProfitVos)){ BatchCostProfitResponse response = new BatchCostProfitResponse(); response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate)); response.setProfitVoList(costProfitVos); response.setAllowDrillDown(false); response.setMonthlyAccumulation(true); responses.add(NumberConstant.ZERO,response); } return responses; } else { return responses; } } } /** * 获取树状结构的科室损益数据 * @param costProfitVos * @return */ public List getCostProfitVoTree(List costProfitVos){ // 参数校验 if (CollectionUtils.isEmpty(costProfitVos)) { return Collections.emptyList(); } Map> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId)); List costProfitParentVos = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); for (CostProfitVo costProfitVo : costProfitParentVos) { List costProfitVo1 = collect.get(costProfitVo.getReportId()); if (!CollectionUtils.isEmpty(costProfitVo1)) { costProfitVo.setChildren(setChildren(costProfitVo1, collect)); } } if (!CollectionUtils.isEmpty(costProfitParentVos)) { costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } return costProfitParentVos; } /** * 生成多月份汇总的科室损益数据 * * @param allCostProfitVo 原始数据列表 * @return 汇总后的科室损益数据 */ private List generateSummaryForMultipleMonths(List allCostProfitVo){ // 参数校验 if (CollectionUtils.isEmpty(allCostProfitVo)) { return Collections.emptyList(); } List profitVoList=new ArrayList<>() ; Map> reportGroup = allCostProfitVo.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); reportGroup.forEach((reportId, profitVos) -> { CostProfitVo costProfitVo = BeanUtil.convertObj(profitVos.get(NumberConstant.ZERO), CostProfitVo.class); BigDecimal totalAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getAmount()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal totalBudgetAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getBudgetAmount()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal totalPrevPeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getPrevPeriodAmount()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO)) .reduce(BigDecimal.ZERO, BigDecimal::add); costProfitVo.setAmount(totalAmount); costProfitVo.setBudgetAmount(totalBudgetAmount); costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount); costProfitVo.setSamePeriodAmount(totalSamePeriodAmount); costProfitVo.setCompletionRate(calculateRate(costProfitVo.getAmount(), costProfitVo.getBudgetAmount())); costProfitVo.setMomRate(calculateRate(costProfitVo.getAmount().subtract(costProfitVo.getPrevPeriodAmount()), costProfitVo.getPrevPeriodAmount())); costProfitVo.setYoyRate(calculateRate(costProfitVo.getAmount().subtract(costProfitVo.getSamePeriodAmount()), costProfitVo.getSamePeriodAmount())); profitVoList.add(costProfitVo); }); //转成树状结构 List costProfitVoTree = getCostProfitVoTree(profitVoList); return costProfitVoTree; } @Override public Object getRedirectData(String computeDate, Long reportId, Long hospId, String reportType, String responsibilityCode) { //查询报表项目 Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); LambdaQueryWrapper reportFormQueryWrapper = new LambdaQueryWrapper<>(); reportFormQueryWrapper.eq(ReportForm::getHospId, hospId); reportFormQueryWrapper.eq(ReportForm::getReportType, reportType); reportFormQueryWrapper.eq(ReportForm::getId, reportId); //这里所有配置都需要做特殊处理,为防程序报错及项目调整,已计算过的数据可能需要查询已作废的报表项目设置 ReportForm one = reportFormService.getByReportId(hospId, reportType, reportId); if (Objects.isNull(one)) { throw new CostException("未找到报表id为【" + reportId + "】报表配置,请确认数据是否有调整"); } Integer calcType = one.getCalcType(); //查询关联关系 Map> reportRelationMap = reportRelationService.list(new QueryWrapper().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId)); List reportRelations = reportRelationMap.get(reportId); if (CollectionUtils.isEmpty(reportRelations)) { throw new CostException("未找到报表id为【" + reportId + "】报表关系对应配置,请确认数据是否有调整"); } //会计科目代码 List relations = reportRelations.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); DecimalFormat df = new DecimalFormat("0.00%"); if (calcType.equals(NumberConstant.ONE)) { // 归集后 List incomeList = incomeCollectionService.list(new QueryWrapper().lambda() .eq(IncomeCollection::getHospId, hospId) .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month) .eq(IncomeCollection::getResponsibilityCode, responsibilityCode)); // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据 List allocationQueryList = allocationQueryService.list(new QueryWrapper().lambda().eq(AllocationQuery::getHospId, hospId) .eq(year > 0, AllocationQuery::getDateYear, year) .eq(month > 0, AllocationQuery::getDateMonth, month) .eq(AllocationQuery::getTargetResponsibilityCode, responsibilityCode)); // 封装数据 List allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class); allocationQueryReportVOList.forEach(i -> { i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA))); i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA))); }); //取会计科目字典 List accountList1 = accountingService.getAccountList(hospId, relations); if (CollectionUtils.isEmpty(accountList1)) { throw new CostException("未找到会计科目字典"); } // 查找在归集数据里面当前责任中心对应的这些会计科目的金额 Map> incomeCollect = new HashMap<>(); if (!CollectionUtils.isEmpty(incomeList)) { List incomeCollectionList = incomeList.stream().filter(income -> relations.contains(income.getAccountingCode())).collect(Collectors.toList()); incomeCollect = incomeCollectionList.stream().collect(Collectors.groupingBy(IncomeCollection::getAccountingCode)); } // 需要查询分摊后的表 Map> costCollect = new HashMap<>(); if (!CollectionUtils.isEmpty(allocationQueryReportVOList)) { List reportVOList = allocationQueryReportVOList.stream().filter(m -> relations.contains(m.getAccountingCode())).collect(Collectors.toList()); costCollect = reportVOList.stream().collect(Collectors.groupingBy(AllocationQueryReportVO::getAccountingCode)); } List list = new ArrayList<>(); for (Accounting accounting : accountList1) { AccountAmountVo vo = new AccountAmountVo(); vo.setAccountCode(accounting.getAccountingCode()); vo.setAccountName(accounting.getAccountingName()); List incomeCollections = incomeCollect.get(accounting.getAccountingCode()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.000000")); if (!CollectionUtils.isEmpty(incomeCollections)) { incomeCollections.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } List costCollections = costCollect.get(accounting.getAccountingCode()); if (!CollectionUtils.isEmpty(costCollections)) { costCollections.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } vo.setAmount(sum.get().setScale(2, RoundingMode.HALF_UP)); list.add(vo); } return list; } else if (calcType.equals(NumberConstant.TWO)) { //分摊层级 // List list = responsibilityService.list(new QueryWrapper() // .lambda() // .select(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName) // .eq(Responsibility::getHospId, hospId).in(Responsibility::getShareId, relations)); // if(CollectionUtils.isEmpty(list)){ // throw new CostException(reportId+"下报表下,关联的分摊层级【"+relations+"】未找到责任中心数据"); // } List accountShares = costAccountShareService.getAll(); if (CollectionUtils.isEmpty(accountShares)) { throw new CostException("成本分摊参数对应不存在"); } Map accountShareMap = accountShares.stream().collect(Collectors.toMap(CostAccountShare::getId, accountShare -> accountShare, (a, b) -> b)); // List collect = list.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList()); List allocationList = allocationService.list(new QueryWrapper() .lambda() .eq(Allocation::getHospId, hospId) .eq(year > 0, Allocation::getDateYear, year) .eq(month > 0, Allocation::getDateMonth, month) .eq(Allocation::getTargetResponsibilityCode, responsibilityCode) .in(Allocation::getShareLevelId, relations)); List allocationReportVOS = BeanUtil.convertList(allocationList, AllocationReportVO.class); for (AllocationReportVO allocationReportVO : allocationReportVOS) { CostAccountShare costAccountShare = accountShareMap.get(allocationReportVO.getAccountShareId()); if (Objects.nonNull(costAccountShare)) { String paramList = costAccountShare.getParamList(); if (!StringUtils.isEmpty(paramList)) { List accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class); if (!CollectionUtils.isEmpty(accountShareVOs)) { Map shareParamPercentMap = accountShareVOs.stream().collect(Collectors.toMap(AccountShareVO::getShareParamCode, AccountShareVO::getShareParamPopout, (a, b) -> b)); String s = shareParamPercentMap.get(allocationReportVO.getShareParamCode()); if (!StringUtils.isEmpty(s)) { allocationReportVO.setShareParamPercent(new BigDecimal(s).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)); } } } String alias = costAccountShare.getAlias(); if (StringUtils.isEmpty(alias)) { allocationReportVO.setAlias(costAccountShare.getAccountingNames()); } else { allocationReportVO.setAlias(alias); } } } Map> collect1 = allocationReportVOS.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode)); List responses = new ArrayList<>(); collect1.forEach((k, v) -> { CostProfitRedirectResponse response = new CostProfitRedirectResponse(); Map> aliasCollect = v.stream().collect(Collectors.groupingBy(AllocationReportVO::getAlias)); List aliasVos = new ArrayList<>(); aliasCollect.forEach((k1, v1) -> { CostProfitRedirectAliasVo redirectAliasVo = new CostProfitRedirectAliasVo(); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); List dataVoList = new ArrayList<>(); v1.forEach(f -> { CostProfitRedirectDataVo dataVo = new CostProfitRedirectDataVo(); BigDecimal shareParamPercent = f.getShareParamPercent(); if (shareParamPercent != null) { dataVo.setShareParamAmount(f.getTotalAmount().multiply(shareParamPercent).setScale(2, RoundingMode.HALF_UP)); dataVo.setShareParamName(f.getShareParamName() + "(" + df.format(shareParamPercent) + ")"); } dataVo.setShareParamCode(f.getShareParamCode()); dataVo.setShareParamNum(f.getShareParamValueNum()); dataVo.setShareParamRate(df.format(f.getShareParamRate())); dataVo.setShareParamValue(f.getAmount()); sum.updateAndGet(i -> i.add(f.getTotalAmount())); redirectAliasVo.setAlias(k1 + "(" + f.getTotalAmount().setScale(2, RoundingMode.HALF_UP) + ")"); dataVoList.add(dataVo); }); // if(!CollectionUtils.isEmpty(dataVoList)){ // for (CostProfitRedirectDataVo dataVo : dataVoList) { // if(sum.get().compareTo(BigDecimal.ZERO.setScale(4,RoundingMode.HALF_UP))==0){ // dataVo.setShareParamName(dataVo.getShareParamName()+"0.0000"); // }else { // BigDecimal divide = dataVo.getShareParamAmount().divide(sum.get(), 2, RoundingMode.HALF_UP); // dataVo.setShareParamName(dataVo.getShareParamName()); // } // } // } // redirectAliasVo.setAlias(k1+"("+sum.get()+")"); redirectAliasVo.setShareParamData(dataVoList); aliasVos.add(redirectAliasVo); }); response.setResponseCode(k); response.setResponseName(v.get(0).getResponsibilityName()); response.setDataList(aliasVos); responses.add(response); }); return responses; } else if (calcType.equals(NumberConstant.FIVE)) { //责任中心 List accountShares = costAccountShareService.getAll(); if (CollectionUtils.isEmpty(accountShares)) { throw new CostException("成本分摊参数对应不存在"); } Map accountShareMap = accountShares.stream().collect(Collectors.toMap(CostAccountShare::getId, accountShare -> accountShare, (a, b) -> b)); List allocationList = allocationService.list(new QueryWrapper() .lambda() .eq(Allocation::getHospId, hospId) .eq(year > 0, Allocation::getDateYear, year) .eq(month > 0, Allocation::getDateMonth, month) .eq(Allocation::getTargetResponsibilityCode, responsibilityCode) .in(Allocation::getResponsibilityCode, relations)); List allocationReportVOS = BeanUtil.convertList(allocationList, AllocationReportVO.class); for (AllocationReportVO allocationReportVO : allocationReportVOS) { CostAccountShare costAccountShare = accountShareMap.get(allocationReportVO.getAccountShareId()); if (Objects.nonNull(costAccountShare)) { String paramList = costAccountShare.getParamList(); if (!StringUtils.isEmpty(paramList)) { List accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class); if (!CollectionUtils.isEmpty(accountShareVOs)) { Map shareParamPercentMap = accountShareVOs.stream().collect(Collectors.toMap(AccountShareVO::getShareParamCode, AccountShareVO::getShareParamPopout, (a, b) -> b)); String s = shareParamPercentMap.get(allocationReportVO.getShareParamCode()); if (!StringUtils.isEmpty(s)) { allocationReportVO.setShareParamPercent(new BigDecimal(s).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)); } } } String alias = costAccountShare.getAlias(); if (StringUtils.isEmpty(alias)) { allocationReportVO.setAlias(costAccountShare.getAccountingNames()); } else { allocationReportVO.setAlias(alias); } } } Map> collect1 = allocationReportVOS.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode)); List responses = new ArrayList<>(); collect1.forEach((k, v) -> { CostProfitRedirectResponse response = new CostProfitRedirectResponse(); Map> aliasCollect = v.stream().collect(Collectors.groupingBy(AllocationReportVO::getAlias)); List aliasVos = new ArrayList<>(); aliasCollect.forEach((k1, v1) -> { CostProfitRedirectAliasVo redirectAliasVo = new CostProfitRedirectAliasVo(); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); List dataVoList = new ArrayList<>(); v1.forEach(f -> { CostProfitRedirectDataVo dataVo = new CostProfitRedirectDataVo(); BigDecimal shareParamPercent = f.getShareParamPercent(); if (shareParamPercent != null) { dataVo.setShareParamAmount(f.getTotalAmount().multiply(shareParamPercent)); dataVo.setShareParamName(f.getShareParamName() + "(" + df.format(shareParamPercent) + ")"); } dataVo.setShareParamCode(f.getShareParamCode()); // dataVo.setShareParamName(f.getShareParamName()); dataVo.setShareParamNum(f.getShareParamValueNum()); dataVo.setShareParamRate(df.format(f.getShareParamRate())); dataVo.setShareParamValue(f.getAmount()); sum.updateAndGet(i -> i.add(f.getTotalAmount())); redirectAliasVo.setAlias(k1 + "(" + f.getTotalAmount().setScale(2, RoundingMode.HALF_UP) + ")"); dataVoList.add(dataVo); }); // if (!CollectionUtils.isEmpty(dataVoList)) { // for (CostProfitRedirectDataVo dataVo : dataVoList) { // if (sum.get().compareTo(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP)) == 0) { // dataVo.setShareParamName(dataVo.getShareParamName() + "0.0000"); // } else { // BigDecimal divide = dataVo.getShareParamAmount().divide(sum.get(), 2, RoundingMode.HALF_UP); //// dataVo.setShareParamName(dataVo.getShareParamName()+"("+divide+")"); // dataVo.setShareParamName(dataVo.getShareParamName()); // // } // } // } redirectAliasVo.setShareParamData(dataVoList); aliasVos.add(redirectAliasVo); }); response.setResponseCode(k); response.setResponseName(v.get(0).getResponsibilityName()); response.setDataList(aliasVos); responses.add(response); }); return responses; } return new ArrayList<>(); } @Override public Object getComputeProfitCollect(String computeDate, Long hospId, String reportType) { Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); Integer integerReportType = Integer.valueOf(reportType); DictDataVo dataVo = getDictDataVo(reportType); Long id = Long.valueOf(dataVo.getExpandOne()); List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId) .eq(Responsibility::getShareId, id) .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null))); if (CollectionUtils.isEmpty(responsibilityList)) { throw new CostException("未找到对应分摊层级责任中心"); } //获取授权的责任中心 responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList); List responsibilityAllList = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, hospId)); Map map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b)); List addList = new ArrayList<>(); for (Responsibility responsibility : responsibilityList) { Responsibility responsibility1 = map.get(responsibility.getParentId()); if (Objects.nonNull(responsibility1)) { addList.add(responsibility1); if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) { getResponsibilityParent(responsibility1, map, addList); } } } if (!CollectionUtils.isEmpty(addList)) { //去重 List collect = addList.stream().distinct().collect(Collectors.toList()); responsibilityList.addAll(collect); } //找出最外层用于出参循环 Map> responsibilityGroup = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId)); List responseParent = responsibilityList.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList()); //只留下中间责任中心 responsibilityList.removeAll(responseParent); List list = new ArrayList<>(); for (Responsibility responsibility : responseParent) { CommonResponsibilityReportVo commonResponsibilityReportVo = new CommonResponsibilityReportVo(); commonResponsibilityReportVo.setResponsibilityCode(responsibility.getResponsibilityCode()); commonResponsibilityReportVo.setResponsibilityName(responsibility.getResponsibilityName()); commonResponsibilityReportVo.setSort(responsibility.getSort()); List responsibilities = responsibilityGroup.get(responsibility.getId()); if (!CollectionUtils.isEmpty(responsibilities)) { commonResponsibilityReportVo.setChild(getChildTitle(responsibilities, responsibilityGroup)); } else { //要显示占比时自动生成默认金额占比层 if (IsShowPercent()) { commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility)); } else { //不显示占比时,直接责任中心作为金额层 commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD); } } list.add(commonResponsibilityReportVo); } ComputeProfitCollectResponse response = new ComputeProfitCollectResponse(); commonResponsibilityReportVoSort(list); response.setTitle(list); List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "【" + integerReportType + "】损益表配置未找到"); } List reportFormCustomVos = BeanUtil.convertList(reportFormList, ReportFormCustomVo.class); List departmentProfits = this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year) .eq(CostDepartmentProfit::getMonth, month) .eq(CostDepartmentProfit::getShareType, integerReportType)); List costProfitVos = BeanUtil.convertList(departmentProfits, CostProfitVo.class); //按责任中心-reportId进行分组 Map> collect2 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); DecimalFormat df = new DecimalFormat("0.00%"); Map> reportDataMap = new HashMap<>(); collect2.forEach((k, v) -> { List reportVos = new ArrayList<>(); v.forEach(f -> { ReportVo amount = new ReportVo(); amount.setCode(f.getResponsibilityCode() + AMOUNT_FIELD); amount.setValue(f.getAmount()); reportVos.add(amount); ReportVo percent = new ReportVo(); percent.setCode(f.getResponsibilityCode() + PERCENT_FIELD); if (f.getPercent() != null) { percent.setValue(df.format(f.getPercent())); } else { percent.setValue(""); } reportVos.add(percent); }); reportDataMap.put(k, reportVos); }); for (ReportFormCustomVo reportFormCustomVo : reportFormCustomVos) { List reportVos = reportDataMap.get(reportFormCustomVo.getId()); if (!CollectionUtils.isEmpty(responsibilityGroup)) { reportFormCustomVo.setData(reportVos); } } Map> collect = reportFormCustomVos.stream().collect(Collectors.groupingBy(ReportFormCustomVo::getParentId)); List costProfitVos1 = collect.get(0L); collect.remove(NumberConstant.ZERO_L); //最外层排序 if (!CollectionUtils.isEmpty(costProfitVos1)) { costProfitVos1.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo))); } for (ReportFormCustomVo costProfitVo : costProfitVos1) { List costProfitVo1 = collect.get(costProfitVo.getId()); if (!CollectionUtils.isEmpty(costProfitVo1)) { //子项排序 costProfitVo1.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo))); costProfitVo.setChildren(setCustomChildren(costProfitVo1, collect)); } } response.setData(costProfitVos1); return response; // // // // //取一行数据 作为父类模版 // Set>> entrySet = responseGroup.entrySet(); // Map.Entry> firstEntry = entrySet.iterator().next(); // List parentModel = firstEntry.getValue(); // //备注:所有记算过的数据都是最后一层责任中心,所以按最后一层责任 中心 找出所有上级责任中心后 给模版添加到上层责任中心 // //按报表类型 取字典 // DictDataVo dataVo = getDictDataVo(reportType); // Long id = Long.valueOf(dataVo.getExpandOne()); // // //按字典给护 的 分摊层级id 查找对应报表 的责任中心 找出的是没有父类的 // List responsibilityList = responsibilityService.list(new QueryWrapper().lambda() // .eq(Responsibility::getHospId, hospId) // .eq(Responsibility::getShareId, id)); // if (CollectionUtils.isEmpty(responsibilityList)) { // throw new CostException("未找到对应分摊层级责任中心"); // } // //获取当前院区所有的责任中心 // List responsibilityAllList = responsibilityService.list(new QueryWrapper().lambda() // .eq(Responsibility::getHospId, hospId)); // Map map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b)); // Map responseCodeParentIdMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b)); // Map responseNameMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName, (a, b) -> b)); // // // //通过查询的最下层责任中心 找到其所有父类责任中心 // List parentResponseList = new ArrayList<>(); // for (Responsibility responsibility : responsibilityList) { // if (responsibility.getParentId().equals(NumberConstant.ZERO_L)) { // parentResponseList.add(responsibility); // } else { // Responsibility responsibility1 = map.get(responsibility.getParentId()); // if (Objects.nonNull(responsibility1)) { // parentResponseList.add(responsibility1); // if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) { // getResponsibilityParent(responsibility1, map, parentResponseList); // } // } // } // // } // //去除重复组装数据 // List parentResponsibility = parentResponseList.stream().distinct().collect(Collectors.toList()); // //找出最外层用于出参循环 // List responseParent = parentResponsibility.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList()); // //只留下中间责任中心 // parentResponsibility.removeAll(responseParent); // // //最上级添加模版 // List parentReportVos = new ArrayList<>(); // for (Responsibility responsibility : responseParent) { // List profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class); // for (CostProfitVo costProfitVo : profitVos) { // costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode()); // costProfitVo.setResponsibilityName(responsibility.getResponsibilityName()); // costProfitVo.setAmount(BigDecimal.ZERO); // costProfitVo.setPercent(BigDecimal.ZERO); // parentReportVos.add(costProfitVo); // } // } // // //中间责任中心 添加模版 添加父类责任中心 // List middleReportVos = new ArrayList<>(); // for (Responsibility responsibility : parentResponsibility) { // List profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class); // Long aLong = responseCodeParentIdMap.get(responsibility.getResponsibilityCode()); // for (CostProfitVo costProfitVo : profitVos) { // costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode()); // costProfitVo.setResponsibilityName(responsibility.getResponsibilityName()); // costProfitVo.setAmount(BigDecimal.ZERO); // costProfitVo.setPercent(BigDecimal.ZERO); // if (aLong.equals(NumberConstant.ZERO_L)) { // costProfitVo.setParentResponsibilityCode(responsibility.getResponsibilityCode()); // costProfitVo.setParentResponsibilityName(responsibility.getResponsibilityName()); // } else { // Responsibility responsibility1 = map.get(aLong); // if (Objects.nonNull(responsibility1)) { // costProfitVo.setParentResponsibilityCode(responsibility1.getResponsibilityCode()); // costProfitVo.setParentResponsibilityName(responsibility1.getResponsibilityName()); // } // } // middleReportVos.add(costProfitVo); // } // } // //添加父类责任中心 // //已计算过的数据添加上级责任中心 // for (CostProfitVo departmentProfit : costProfitVos) { // Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode()); // if (aLong != null) { // if (aLong.equals(NumberConstant.ZERO_L)) { //// Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode()); // departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode()); // departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName()); // } else { // Responsibility responsibility = map.get(aLong); // if (Objects.nonNull(responsibility)) { // departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode()); // departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName()); // } // } // } // } // //已计算过的 按责任中心-报表id 分组 // Map>> sumGroup = new HashMap<>(); // //已计算过的 按父类责任中心分组 // Map> collect1 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode)); // if (!CollectionUtils.isEmpty(collect1)) { // collect1.forEach((k, v) -> { // Map> collect2 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); // sumGroup.put(k, collect2); // }); // } // // //计算所有中间层 // List middleFilterReportVos = new ArrayList<>(); // for (CostProfitVo middleReportVo : middleReportVos) { // String responsibilityCode = middleReportVo.getResponsibilityCode(); // Map> longListMap = sumGroup.get(responsibilityCode); // if (!CollectionUtils.isEmpty(longListMap)) { // List profitVos = longListMap.get(middleReportVo.getReportId()); // AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); // if (!CollectionUtils.isEmpty(profitVos)) { // profitVos.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); // // middleReportVo.setAmount(sum.get()); // } // } else { // //未在最下层找到数据的可能还是一个分类 提取出来 // middleFilterReportVos.add(middleReportVo); // } // } // //用于处理多层级中 有两层中间层的数据 // if (!CollectionUtils.isEmpty(middleFilterReportVos)) { // handleMiddleFilterReport(middleReportVos, middleFilterReportVos); // } // Map>> sumMiddleGroup = new HashMap<>(); // Map> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode)); // if (!CollectionUtils.isEmpty(collect2)) { // collect2.forEach((k, v) -> { // Map> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId)); // sumMiddleGroup.put(k, collect3); // }); // } // // // 最上层的需要执行两次分组 两层时取最后一层计算 多层时取 中间层计算合计 // for (CostProfitVo parentReportVo : parentReportVos) { // String responsibilityCode = parentReportVo.getResponsibilityCode(); // Map> longListMap = sumGroup.get(responsibilityCode); // //在最下层找到的 说明是两层 // if (!CollectionUtils.isEmpty(longListMap)) { // List profitVos = longListMap.get(parentReportVo.getReportId()); // AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); // if (!CollectionUtils.isEmpty(profitVos)) { // profitVos.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); // } // //再找中间层是否存在子类 // Map> longListMap1 = sumMiddleGroup.get(responsibilityCode); // if (!CollectionUtils.isEmpty(longListMap1)) { // List profitVos1 = longListMap1.get(parentReportVo.getReportId()); // if (!CollectionUtils.isEmpty(profitVos1)) { // profitVos1.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); // } // } // parentReportVo.setAmount(sum.get()); // } else { // //未在最下层找到从中间层找进行计算 // Map> longListMap1 = sumMiddleGroup.get(responsibilityCode); // if (!CollectionUtils.isEmpty(longListMap1)) { // List profitVos = longListMap1.get(parentReportVo.getReportId()); // AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); // if (!CollectionUtils.isEmpty(profitVos)) { // profitVos.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); // } // parentReportVo.setAmount(sum.get()); // } // } // } // //把最上层 中间层 最下层组装成一个list 进行分组 // // //组装数据 // Map> collect3 = parentReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode)); // List list = new ArrayList<>(); // collect3.forEach((k, v) -> { // CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo(); //// List costProfitVos1 = collect3.get(s); // vo.setResponsibilityCode(k); // vo.setResponsibilityName(responseNameMap.get(k)); // if (!CollectionUtils.isEmpty(v)) { // List dataReportVos = new ArrayList<>(); // for (CostProfitVo costProfitVo : v) { // CommonDataReportVo vo1 = new CommonDataReportVo(); // vo1.setReportId(costProfitVo.getReportId()); // vo1.setValue(costProfitVo.getAmount()); // dataReportVos.add(vo1); // } // vo.setProfitList(dataReportVos); // } else { // vo.setProfitList(new ArrayList<>()); // } // list.add(vo); // }); // middleReportVos.addAll(costProfitVos); // Map> collect5 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode)); // List list1 = new ArrayList<>(); // collect5.forEach((k, v) -> { // CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo(); // vo.setResponsibilityCode(k); // vo.setResponsibilityName(responseNameMap.get(k)); // if (!CollectionUtils.isEmpty(v)) { // vo.setParentResponsibilityCode(v.get(0).getParentResponsibilityCode()); // List dataReportVos = new ArrayList<>(); // for (CostProfitVo costProfitVo : v) { // CommonDataReportVo vo1 = new CommonDataReportVo(); // vo1.setReportId(costProfitVo.getReportId()); // vo1.setValue(costProfitVo.getAmount()); // dataReportVos.add(vo1); // } // vo.setProfitList(dataReportVos); // } else { // vo.setProfitList(new ArrayList<>()); // } // list1.add(vo); // }); // Map> collect4 = list1.stream().collect(Collectors.groupingBy(CostResponsibilityProfitVo::getParentResponsibilityCode)); // for (CostResponsibilityProfitVo vo : list) { // List list2 = collect4.get(vo.getResponsibilityCode()); // if (!CollectionUtils.isEmpty(list2)) { // if (!list2.get(0).getResponsibilityCode().equals(vo.getResponsibilityCode())) { // vo.setChild(setProfitChildren(list2, collect4)); // } // } // } // response.setData(list); // // //提取出最上层 // // // return response; } /** * 是否显示占比 * * @return */ public boolean IsShowPercent() { String parameterValue = centerService.getParameterValue(ParameterConstant.SHOW_PERCENT); return NumberConstant.ONE_S.equals(parameterValue); } /** * 是否需要代码计算 * @return */ public boolean IsNeedCalc(String reportType) { String parameterValue = centerService.getParameterValue(ParameterConstant.SQL_CALC_REPORT_TYPE); if(StringUtils.isEmpty(parameterValue)){ return true; } //不需计算的报表类型列表 List nonCalcReportTypeList = Arrays.stream(parameterValue.split(SplitConstant.SEPARATOR_VERTICALLINE)).collect(Collectors.toList()); return !nonCalcReportTypeList.contains(reportType); } private List getChildTitle(List responsibilities, Map> responsibilityGroup) { List list = new ArrayList<>(); for (Responsibility responsibility : responsibilities) { CommonResponsibilityReportVo commonResponsibilityReportVo = new CommonResponsibilityReportVo(); commonResponsibilityReportVo.setResponsibilityCode(responsibility.getResponsibilityCode()); commonResponsibilityReportVo.setResponsibilityName(responsibility.getResponsibilityName()); commonResponsibilityReportVo.setSort(responsibility.getSort()); List responsibilityChild = responsibilityGroup.get(responsibility.getId()); if (!CollectionUtils.isEmpty(responsibilityChild)) { commonResponsibilityReportVo.setChild(getChildTitle(responsibilityChild, responsibilityGroup)); } else { // //添加金额占比 // commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility)); //要显示占比时自动生成默认金额占比层 if (IsShowPercent()) { commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility)); } else { //不显示占比时,直接责任中心作为金额层 commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD); } } list.add(commonResponsibilityReportVo); } return list; } private @NotNull List setDefalutChildList(Responsibility responsibility) { List childList = new ArrayList<>(); CommonResponsibilityReportVo amount = new CommonResponsibilityReportVo(); amount.setResponsibilityCode(responsibility.getResponsibilityCode() + AMOUNT_FIELD); amount.setResponsibilityName(AMOUNT); amount.setSort(1); childList.add(amount); CommonResponsibilityReportVo percent = new CommonResponsibilityReportVo(); percent.setResponsibilityCode(responsibility.getResponsibilityCode() + PERCENT_FIELD); percent.setResponsibilityName(PERCENT); percent.setSort(2); childList.add(percent); return childList; } private List setChildren(List child, Map> collect) { for (CostProfitVo costProfitVo : child) { if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getReportId()))) { costProfitVo.setChildren(setChildren(collect.get(costProfitVo.getReportId()), collect)); } } if (!CollectionUtils.isEmpty(child)) { child.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } return child; } private List setCustomChildren(List child, Map> collect) { for (ReportFormCustomVo costProfitVo : child) { if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getId()))) { costProfitVo.setChildren(setCustomChildren(collect.get(costProfitVo.getId()), collect)); } } if (!CollectionUtils.isEmpty(child)) { child.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo))); } return child; } /** * 按照会计科目进行计算 * * @param i */ private BigDecimal setAccountReportData(CostDepartmentProfitVO i, List list, List allocationQueryReportVOList, Map> reportRelationMap, List allList) { // 在报表关联里面查询当前报表关联的 Long reportId = i.getReportId(); List reportRelationList = reportRelationMap.get(reportId); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.000")); if (CollUtil.isNotEmpty(reportRelationList)) { // 获取对应的会计科目信息 筛选会计科目的Code List accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); // 查找在归集数据里面当前责任中心对应的这些会计科目的金额 List incomeCollectionList = list.stream().filter(income -> income.getResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList()); // 需要查询分摊后的表 List reportVOList = allocationQueryReportVOList.stream().filter(m -> m.getTargetResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(m.getAccountingCode())).collect(Collectors.toList()); if (CollUtil.isNotEmpty(incomeCollectionList)) { incomeCollectionList.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } // 成本减 if (CollUtil.isNotEmpty(reportVOList)) { reportVOList.forEach(m -> { sum.updateAndGet(v -> v.add(m.getAmount())); }); } } // i.setAmount(new BigDecimal(sum.toString())); // numMap.put(i.getReportNum()+i.getResponsibilityCode(),new BigDecimal(sum.toString())); return sum.get(); } /** * 按照分摊层级进行计算 * 按照分摊层级计算 报表分摊层级是当前的层级 并且目标责任中心失败当前责任中心 */ private BigDecimal setShareLevelReportData(CostDepartmentProfitVO i, List costShareLevelList, Map> reportRelationMap, List allocationList, List allList) { List reportRelationList = reportRelationMap.get(i.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.000")); if (CollUtil.isNotEmpty(reportRelationList)) { // 找到对应的分摊层级的Id 但是分摊报表里面存的是分摊层级的序号 List shareLevelIds = reportRelationList.stream().map(ReportRelation::getRelationCode).map(Long::valueOf).collect(Collectors.toList()); // List levelShortList = costShareLevelList.stream() // .filter(m -> shareLevelIds.contains(m.getId())) // .map(CostShareLevel::getLeverSort).collect(Collectors.toList()); if (CollUtil.isNotEmpty(shareLevelIds)) { // 查询报表里面是当前分摊层级的数据 List allocations = allocationList.stream().filter(m -> shareLevelIds.contains(m.getShareLevelId()) && m.getTargetResponsibilityCode().equals(i.getResponsibilityCode())).collect(Collectors.toList()); if (CollUtil.isNotEmpty(allocations)) { // allocations.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); sum.set(reduce); } } } // i.setAmount(new BigDecimal(sum.toString())); return sum.get(); } /** * 按照责任中心进行计算 * 原始责任中心是设置的责任中心 目标责任中心是报表的责任中心 * 查询分摊报表里面目标责任中心是当前责任中心 报表责任中心是当前设置的责任中心 */ public BigDecimal setResponsibilityCode(CostDepartmentProfitVO costDepartmentProfitVO, Map> reportRelationMap, List allocationList, List allList) { // 获取当前报表对应的责任中心 List reportRelationList = reportRelationMap.get(costDepartmentProfitVO.getReportId()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.000")); if (CollUtil.isNotEmpty(reportRelationList)) { // 获取对应的责任中心的Code集合 这个是设置的责任中心 List responsibilityCodes = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); if (CollUtil.isNotEmpty(responsibilityCodes)) { // 查询报表里面是当前分摊层级的数据 List allocations = allocationList.stream().filter(i -> i.getTargetResponsibilityCode().equals(costDepartmentProfitVO.getResponsibilityCode()) && responsibilityCodes.contains(i.getResponsibilityCode())).collect(Collectors.toList()); if (CollUtil.isNotEmpty(allocations)) { BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); sum.set(reduce); // allocations.forEach(m -> { // sum.updateAndGet(v -> v.add(m.getAmount())); // }); } } } // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString())); return sum.get(); } /** * 按照小计的计算方式 * 同一个目录下相同的其他金额的和 */ public BigDecimal setSubtotal(CostDepartmentProfitVO costDepartmentProfitVO, List costShareLevelList, Map> listMap, List profitVOS, List list, List allocationQueryReportVOList, Map> reportRelationMap, List allocationList, List allList) { // 因为报表是按照报表项目的升序进行排序的 前面的报表是已经进行计算了的 // 查询当前报表的父层级id Long reportParentId = costDepartmentProfitVO.getReportParentId(); String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode(); // 查询报表里面在当前父层级下的并且不是自己的报表项目 List costDepartmentProfitVOS = allList.stream().filter(i -> i.getReportParentId().equals(reportParentId) && i.getResponsibilityCode().equals(responsibilityCode) && !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList()); AtomicReference sum = new AtomicReference<>(new BigDecimal("0.0000")); // 遍历数据 之前的已经经过了计算 costDepartmentProfitVOS.forEach(i -> { Long reportId = i.getReportId(); List costDepartmentProfitVOS1 = listMap.get(reportId); if (CollUtil.isEmpty(costDepartmentProfitVOS1)) { throw new CostException(500, "报表未找到"); } BigDecimal amount = getAmount(costDepartmentProfitVOS1, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList); sum.set(amount.add(sum.get())); }); // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString())); return sum.get(); } /*** * 按照计算方式进行计算 */ public BigDecimal setCalculation(CostDepartmentProfitVO costDepartmentProfitVO, List costDepartmentProfitVOList, List costShareLevelList, Map> listMap, List list, List allocationQueryReportVOList, Map> reportRelationMap, List allocationList, List allList) { // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2] String calcFormula = costDepartmentProfitVO.getCalcFormula(); String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode(); String replace = calcFormula.replace("[", "").replace("]", "").replace("+", ",").replace("-", ",-"); List calcFormulaList = Arrays.stream(replace.split(StrUtil.COMMA)).map(Integer::valueOf).collect(Collectors.toList()); // 查询这个编号集合的报表 AtomicReference bigDecimal = new AtomicReference<>(new BigDecimal("0.0000")); calcFormulaList.forEach(calc -> { Integer calcNum = Math.abs(calc); List reportIdList = allList.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode) && calcNum.equals(i.getReportNum())).map(CostDepartmentProfitVO::getReportId).collect(Collectors.toList()); if (CollUtil.isNotEmpty(reportIdList)) { reportIdList.forEach(i -> { List profitVOS = listMap.get(i); if (CollUtil.isEmpty(profitVOS)) { throw new CostException(500, "报表未找到"); } BigDecimal amount = getAmount(profitVOS, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList); if (calc > 0) { bigDecimal.updateAndGet(v -> v.add(amount)); } else { bigDecimal.updateAndGet(v -> v.subtract(amount)); } }); } }); return bigDecimal.get(); } /** * 判断是那种计算方式 调用方法进行计算 */ public BigDecimal getAmount(List profitVOS, List costShareLevelList, String responsibilityCode, List list, List allocationQueryReportVOList, Map> reportRelationMap, List allocationList, Map> listMap, List allList) { BigDecimal bigDecimal = new BigDecimal("0.0000"); // 在对这个报表进行过滤 List costDepartmentProfitVOS = profitVOS.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList()); // 都一个就是 CostDepartmentProfitVO costDepartmentProfitVO = costDepartmentProfitVOS.get(0); Integer calcType = costDepartmentProfitVO.getCalcType(); if (NumberConstant.ONE.equals(calcType)) { // 调用计算的方法 按照会计科目 bigDecimal = setAccountReportData(costDepartmentProfitVO, list, allocationQueryReportVOList, reportRelationMap, allList); } else if (NumberConstant.TWO.equals(calcType)) { // 按照分摊层级 bigDecimal = setShareLevelReportData(costDepartmentProfitVO, costShareLevelList, reportRelationMap, allocationList, allList); } else if (NumberConstant.THREE.equals(calcType)) { // 小计 bigDecimal = setSubtotal(costDepartmentProfitVO, costShareLevelList, listMap, profitVOS, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList); } else if (NumberConstant.FIVE.equals(calcType)) { // 按照责任中心 bigDecimal = setResponsibilityCode(costDepartmentProfitVO, reportRelationMap, allocationList, allList); } else if (NumberConstant.FOUR.equals(calcType)) { // bigDecimal = setCalculation(costDepartmentProfitVO, costDepartmentProfitVOS, costShareLevelList, listMap, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList); } return bigDecimal; } private void exportDepartmentProfit(String date, OutputStream outputStream, Integer reportType, String name) throws Exception { Long hospId = UserContext.getHospId(); DateTime dateTime = DateUtil.parse(date); int year = DateUtil.year(dateTime); int month = DateUtil.month(dateTime) + 1; // 查询所有的节点 List responsibilityList = responsibilityService.list(new QueryWrapper().lambda().eq(Responsibility::getHospId, hospId)); if (CollUtil.isEmpty(responsibilityList)) { throw new CostException(500, "责任中心不存在"); } Map responseCodeParentIdMap = new HashMap<>(); Map responsibilityIdMap = new HashMap<>(); Map responseCodeNameMap = new HashMap<>(); Map responseCodeIdMap = new HashMap<>(); Map responsibilityCodeMap = new HashMap<>(); Map responsibilityStatusMap = new HashMap<>(); Map responsibilitySortMap = new HashMap<>(); responsibilityList.forEach(responsibility1 -> { responsibilityCodeMap.put(responsibility1.getResponsibilityCode(), responsibility1); responseCodeIdMap.put(responsibility1.getResponsibilityCode(), responsibility1.getId()); responseCodeNameMap.put(responsibility1.getResponsibilityCode(), responsibility1.getResponsibilityName()); responsibilityIdMap.put(responsibility1.getId(), responsibility1); responseCodeParentIdMap.put(responsibility1.getResponsibilityCode(), responsibility1.getParentId()); responsibilityStatusMap.put(responsibility1.getResponsibilityCode(), responsibility1.getStatus()); Integer sort = responsibility1.getSort(); responsibilitySortMap.put(responsibility1.getResponsibilityCode(), sort != null ? sort : Integer.valueOf(1)); }); // 损益表数据 List departmentProfits = this.list(new QueryWrapper().lambda() .eq(CostDepartmentProfit::getHospId, hospId) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month) .eq(CostDepartmentProfit::getShareType, reportType)); if (CollectionUtils.isEmpty(departmentProfits)) { throw new CostException(500, name + "未进行科室损益计算"); } //判断一下责任中心是否停用 List removeList = new ArrayList<>(); for (CostDepartmentProfit departmentProfit : departmentProfits) { Integer i = responsibilityStatusMap.get(departmentProfit.getResponsibilityCode()); if (i != null && i == 0) { removeList.add(departmentProfit); } Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode()); if (aLong != null) { if (aLong.equals(NumberConstant.ZERO_L)) { departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName()); } else { Responsibility responsibility = responsibilityIdMap.get(aLong); if (Objects.nonNull(responsibility)) { departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode()); departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName()); } } } } //删除停用责任中心数据 if (!CollectionUtils.isEmpty(removeList)) { departmentProfits.removeAll(removeList); } List profitList = departmentProfits.stream().filter(f -> StringUtils.isEmpty(f.getParentResponsibilityCode())).collect(Collectors.toList()); if (!CollectionUtils.isEmpty(profitList)) { log.info("{}报表类型存在无上级责任中心的数据,请核实配置数据", reportType); } Map> profitReportIdGroup = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)); Map> profitReportResponsibilityGroup = new HashMap<>(); profitReportIdGroup.forEach((k, v) -> { profitReportResponsibilityGroup.put(k, v.stream().collect(Collectors.toMap(CostDepartmentProfit::getResponsibilityCode, costDepartmentProfit -> costDepartmentProfit, (a, b) -> b))); }); // Map> doctorParentMap = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode)); //损益表设置 List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getReportType, reportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } //第一层 List titleList = new ArrayList<>(); titleList.add(new TitleEntity("0", null, name, false, NumberConstant.ZERO)); //从损益数据中提取出所有责任中心组装成树 List responsibilityVos = new ArrayList<>(); for (CostDepartmentProfit departmentProfit : departmentProfits) { Responsibility responsibility = responsibilityCodeMap.get(departmentProfit.getResponsibilityCode()); ResponsibilityVo responsibilityVo = new ResponsibilityVo(); responsibilityVo.setParentResponsibilityCode(departmentProfit.getParentResponsibilityCode()); responsibilityVo.setParentResponsibilityName(departmentProfit.getParentResponsibilityName()); responsibilityVo.setResponsibilityCode(departmentProfit.getResponsibilityCode()); responsibilityVo.setResponsibilityName(departmentProfit.getResponsibilityName()); responsibilityVo.setSort(responsibility.getSort()); responsibilityVos.add(responsibilityVo); } ListUtils.sort(responsibilityVos, ResponsibilityVo::getParentResponsibilityName); Map> responsibilityMap = responsibilityVos.stream().distinct().collect(Collectors.groupingBy(ResponsibilityVo::getParentResponsibilityCode)); responsibilityMap.forEach((k, v) -> { TitleEntity entity = new TitleEntity(); entity.setId(String.valueOf(responseCodeIdMap.get(k))); entity.setPid("0"); entity.setContent(responseCodeNameMap.get(k)); entity.setFieldName(responseCodeNameMap.get(k)); entity.setWidth(15); entity.setSort(responsibilitySortMap.get(k)); boolean child = getChild(titleList, k, responsibilityMap, responseCodeIdMap, String.valueOf(responseCodeIdMap.get(k))); entity.setLast(child); titleList.add(entity); }); final List finalReportFormList = reportFormList; List reportForms = reportFormList.stream().filter(i -> i.getParentId() == 0) .peek(i -> i.setChild(this.getReportFormChild(i, finalReportFormList))) .collect(Collectors.toList()); //列 List titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList()); List> rowList = new ArrayList<>(); List depthList = new ArrayList<>(); for (ReportForm reportForm : reportForms) { int child = TreeDepthUtil.getTreeDepthByDfsWithRecursion(reportForm, "child"); depthList.add(child); } OptionalInt max = depthList.stream().mapToInt(Integer::intValue).max(); //根据报表设置最深深度添加 默认列 int asInt = max.getAsInt(); for (int i = 1; i <= asInt; i++) { TitleEntity parentResponsibility = new TitleEntity(); parentResponsibility.setId(String.valueOf(i)); parentResponsibility.setPid("0"); parentResponsibility.setContent(""); parentResponsibility.setFieldName(String.valueOf(i)); parentResponsibility.setWidth(15); parentResponsibility.setSort(NumberConstant.ZERO); parentResponsibility.setLast(true); titleList.add(parentResponsibility); } titleList.sort(Comparator.comparing(TitleEntity::getSort)); DecimalFormat df = new DecimalFormat("0.00%"); //递归排序 formSort(reportForms); //配置单元格数据 for (ReportForm reportForm : reportForms) { int fieldId = 1; Map m = new HashMap(); if (!CollectionUtils.isEmpty(reportForm.getChild())) { m.put(Integer.toString(fieldId), reportForm.getReportName()); setRowList(fieldId, reportForm.getChild(), profitReportResponsibilityGroup, rowList, df, titleEntities, m, asInt); } else { for (int i = 1; i <= asInt; i++) { m.put(Integer.toString(i), reportForm.getReportName()); } Map map = profitReportResponsibilityGroup.get(reportForm.getId()); for (TitleEntity titleEntity : titleEntities) { String fieldName = titleEntity.getFieldName(); if (fieldName.contains(AMOUNT_FIELD)) { String[] split1 = StringUtils.split(fieldName, "|"); if (split1 != null) { CostDepartmentProfit costDepartmentProfit = map.get(split1[0]); m.put(fieldName, costDepartmentProfit.getAmount().setScale(2, RoundingMode.HALF_UP).toString()); } else { m.put(fieldName, ""); } } else if (fieldName.contains(PERCENT_FIELD)) { String[] split1 = StringUtils.split(fieldName, "|"); if (split1 != null) { CostDepartmentProfit costDepartmentProfit = map.get(split1[0]); if (costDepartmentProfit.getPercent() != null) { m.put(fieldName, df.format(costDepartmentProfit.getPercent())); } else { m.put(fieldName, ""); } } else { m.put(fieldName, ""); } } } rowList.add(m); } } //表头树进行excel 元素转换 ExcelPoiUtil excelTool = new ExcelPoiUtil(name); Map param = ImmutableMap.builder().put("id", "id").put("pid", "pid") .put("content", "content").put("fieldName", "fieldName").put("width", "width").build(); List titleData = excelTool.colEntityTransformer(titleList, param, "0"); List mergeList = IntStream.range(0, asInt).boxed().collect(Collectors.toList()); // 多个sheet导出 XSSFWorkbook workbook = excelTool.exportXssfWorkbook(titleData, rowList, null); // CellRangeAddress cellAddresses = new CellRangeAddress(4,7,0,4); // workbook.getSheetAt(0).addMergedRegion(cellAddresses); //表头占的行数 int totalRow = titleData.get(0).getTotalRow(); int[] relationColl = new int[mergeList.size()]; Map mergeMap = IntStream.range(0, mergeList.size()).boxed().collect(Collectors.toMap(i -> i, i -> relationColl, (a, b) -> b)); //手动横向合并 addMergeCells(workbook, mergeMap, asInt); //纵向合并 PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0), mergeMap, totalRow); // int[] relationTitleColl = new int[totalRow]; // // Map mergeTitleMap = IntStream.range(asInt-1, titleData.get(0).getTotalCol()).boxed().collect(Collectors.toMap(i -> i, i -> relationTitleColl, (a, b) -> b)); // PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0),mergeTitleMap,1,totalRow-1); // excelTool.save(workbook, "D:\\测试用.xlsx"); workbook.write(outputStream); workbook.close(); } private static void addMergeCells(XSSFWorkbook workbook, Map mergeMap, int asInt) { XSSFSheet sheet = workbook.getSheetAt(0); //最后一行 Set colKeyList = mergeMap.keySet(); int endRow = sheet.getLastRowNum(); for (int i = 4; i <= endRow; i++) { //mergeMap List cellText = new ArrayList<>(); for (Integer integer : colKeyList) { XSSFRow row = sheet.getRow(i); String text = PoiCellUtil.getCellValue(row.getCell(integer)); cellText.add(text); } // 过滤出元素出现次数大于 1 (重复元素)的 entry List collect = cellText.stream().filter(j -> !Objects.equals(j, "")) // list 对应的 Stream 并过滤"" .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)) // 获得元素出现频率的 Map,键为元素,值为元素出现的次数 .values() .stream() // 所有 entry 对应的 Stream .filter(integer -> integer > 1) // 获得 entry 的键(重复元素)对应的 Stream .collect(Collectors.toList()); if (!CollectionUtils.isEmpty(collect)) { sheet.addMergedRegion(new CellRangeAddress(i, i, mergeMap.size() - collect.get(0), asInt - 1)); } } } private void setRowList(int fieldId, List child, Map> profitReportResponsibilityGroup, List> rowList, DecimalFormat df, List titleEntities, Map parentFieldMap, int maxDepth) { fieldId++; for (ReportForm reportForm : child) { Map m = new HashMap(parentFieldMap); m.put(Integer.toString(fieldId), reportForm.getReportName()); if (!CollectionUtils.isEmpty(reportForm.getChild())) { setRowList(fieldId, reportForm.getChild(), profitReportResponsibilityGroup, rowList, df, titleEntities, m, maxDepth); } else { if (fieldId < maxDepth) { for (int i = 1; i <= maxDepth - fieldId; i++) { m.put(Integer.toString(fieldId + i), reportForm.getReportName()); } } Map map = profitReportResponsibilityGroup.get(reportForm.getId()); for (TitleEntity titleEntity : titleEntities) { String fieldName = titleEntity.getFieldName(); if (fieldName.contains(AMOUNT_FIELD)) { String[] split1 = StringUtils.split(fieldName, "|"); if (split1 != null) { if (map != null) { CostDepartmentProfit costDepartmentProfit = map.get(split1[0]); if (Objects.nonNull(costDepartmentProfit)) { m.put(fieldName, costDepartmentProfit.getAmount().setScale(2, RoundingMode.HALF_UP).toString()); } else { m.put(fieldName, ""); } } else { m.put(fieldName, ""); } } else { m.put(fieldName, ""); } } else if (fieldName.contains(PERCENT_FIELD)) { String[] split1 = StringUtils.split(fieldName, "|"); if (split1 != null) { if (map != null) { CostDepartmentProfit costDepartmentProfit = map.get(split1[0]); if (costDepartmentProfit.getPercent() != null) { m.put(fieldName, df.format(costDepartmentProfit.getPercent())); } else { m.put(fieldName, ""); } } else { m.put(fieldName, ""); } } else { m.put(fieldName, ""); } } } rowList.add(m); } } } private List getReportFormChild(ReportForm parent, List reportFormList) { return reportFormList.stream().filter(o -> o.getParentId().equals(parent.getId())) .peek(o -> o.setChild(this.getReportFormChild(o, reportFormList))) .collect(Collectors.toList()); // } private void formSort(List reportFormList) { for (ReportForm reportForm : reportFormList) { if (!CollectionUtils.isEmpty(reportForm.getChild())) { formSort(reportForm.getChild()); } } reportFormList.sort(Comparator.comparing(ReportForm::getSort)); } private void responsibilitySort(List responsibilityList) { for (Responsibility responsibility : responsibilityList) { if (!CollectionUtils.isEmpty(responsibility.getChildren())) { responsibilitySort(responsibility.getChildren()); } } responsibilityList.sort(Comparator.comparing(Responsibility::getSort, Comparator.nullsLast(Integer::compareTo))); } private void commonResponsibilityReportVoSort(List T) { for (CommonResponsibilityReportVo responsibility : T) { if (!CollectionUtils.isEmpty(responsibility.getChild())) { commonResponsibilityReportVoSort(responsibility.getChild()); } } T.sort(Comparator.comparing(CommonResponsibilityReportVo::getSort, Comparator.nullsLast(Integer::compareTo))); } private void costResponsibilityProfitVoSort(List T) { for (CostResponsibilityProfitVo responsibility : T) { if (!CollectionUtils.isEmpty(responsibility.getChild())) { costResponsibilityProfitVoSort(responsibility.getChild()); } } T.sort(Comparator.comparing(CostResponsibilityProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } @Override public Object getBatchComputeProfitListByYear(String startYear, String endYear, String reportType, String responsibilityCode) { Integer integerReportType = Integer.valueOf(reportType); Long hospId = UserContext.getHospId(); List responses = new ArrayList<>(); // 解析起止年份 int startY = Integer.parseInt(startYear); int endY = Integer.parseInt(endYear); if (startY > endY) { throw new CostException(500, "起始年份不能大于结束年份"); } // 获取报表配置 List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, hospId) .eq(ReportForm::getDeleteTime, NumberConstant.ZERO) .eq(ReportForm::getReportType, integerReportType)); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } Map reportMap = reportFormList.stream() .collect(Collectors.toMap(ReportForm::getId, report -> report)); // 取非隐藏的报表项目ID List activeReportIdList = reportFormList.stream() .filter(report -> NumberConstant.ONE.equals(report.getHide())) .map(ReportForm::getId) .collect(Collectors.toList()); // 获取当前年份和上一年度的汇总数据(一次性查询) List summaryList = this.baseMapper.getAnnualSummaryByYearRange(startY, endY, hospId, integerReportType, responsibilityCode); List preYearSummaryList = this.baseMapper.getAnnualSummaryByYearRange(startY - 1, endY - 1, hospId, integerReportType, responsibilityCode); // 按年份分组处理数据 Map> currentYearMap = new HashMap<>(); Map> preYearMap = new HashMap<>(); // 将结果按年份分组 if (!CollectionUtils.isEmpty(summaryList)) { currentYearMap = summaryList.stream() .collect(Collectors.groupingBy(CostProfitVo::getYear)); } if (!CollectionUtils.isEmpty(preYearSummaryList)) { preYearMap = preYearSummaryList.stream() .collect(Collectors.groupingBy(CostProfitVo::getYear)); } // 遍历每个年份进行数据处理 for (int year = startY; year <= endY; year++) { int previousYear = year - 1; List currentYearList = currentYearMap.get(year); List previousYearList = preYearMap.get(previousYear); if (CollectionUtils.isEmpty(currentYearList)) { continue; } // 只处理非隐藏的项目 List activeCostProfitVo = currentYearList.stream() .filter(vo -> activeReportIdList.contains(vo.getReportId())) .collect(Collectors.toList()); if (CollectionUtils.isEmpty(activeCostProfitVo)) { continue; } // 创建映射以便快速查找上一年的数据 Map preYearCostProfitMap = new HashMap<>(); if (!CollectionUtils.isEmpty(previousYearList)) { preYearCostProfitMap = previousYearList.stream() .collect(Collectors.toMap(CostProfitVo::getReportId, costProfitVo -> costProfitVo)); } // 计算完成率、环比、同比 for (CostProfitVo vo : activeCostProfitVo) { // 设置同期数据 if (preYearCostProfitMap.containsKey(vo.getReportId())) { vo.setSamePeriodAmount(preYearCostProfitMap.get(vo.getReportId()).getAmount()); } else { vo.setSamePeriodAmount(BigDecimal.ZERO); } vo.setCompletionRate(calculateRate(vo.getAmount(), vo.getBudgetAmount())); vo.setMomRate(calculateRate(vo.getAmount().subtract(vo.getPrevPeriodAmount()), vo.getPrevPeriodAmount())); vo.setYoyRate(calculateRate(vo.getAmount().subtract(vo.getSamePeriodAmount()), vo.getSamePeriodAmount())); // 设置报表相关属性 ReportForm reportForm = reportMap.get(vo.getReportId()); if (reportForm != null) { vo.setDescription(reportForm.getDescription()); vo.setSort(reportForm.getSort()); vo.setPermil(reportForm.getPermil()); vo.setDataType(reportForm.getDataType()); vo.setDecimalPlace(reportForm.getDecimalPlace()); } } // 构建树状结构 Map> collect = activeCostProfitVo.stream() .collect(Collectors.groupingBy(CostProfitVo::getReportParentId)); List costProfitParentVos = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); if (!CollectionUtils.isEmpty(costProfitParentVos)) { costProfitParentVos.forEach(parentVo -> { parentVo.setChildren(collect.get(parentVo.getReportId())); }); costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo))); } BatchCostProfitResponse response = new BatchCostProfitResponse(); response.setComputeDate(String.valueOf(year)); response.setProfitVoList(costProfitParentVos); response.setAllowDrillDown(false); responses.add(response); } return responses; } /** * 安全地计算百分比:避免除零错误 */ private BigDecimal calculateRate(BigDecimal current, BigDecimal base) { if (base == null || base.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } BigDecimal rate = current.divide(base, 4, RoundingMode.HALF_UP); return rate.setScale(4, RoundingMode.HALF_UP); } /** * 计算科室损益 * @param computeDate * @param hospId * @param reportType */ private void calcDeptProfit(String computeDate, Long hospId, String reportType) { //获取科室损益计算所需的数据 ProfitCalculationDataVo profitCalculationData = getProfitCalculationData(computeDate, hospId, reportType); //计算科室损益 List costDepartmentProfitVOS = calcDeptProfit(profitCalculationData); // 删除这个年月的数据 deleteDeptProfit(profitCalculationData.getYear(),profitCalculationData.getMonth(),reportType ); // 添加数据 List costDepartmentProfits = BeanUtil.convertList(costDepartmentProfitVOS, CostDepartmentProfit.class); //统一创建时间 long l = System.currentTimeMillis(); costDepartmentProfits.forEach(i -> { i.setCreateTime(l); }); //保存科室损益数据 this.saveBatch(costDepartmentProfits); //处理科室损益的会计科目金额数据 List costDepartmentProfitAccounts=new ArrayList<>(); for (CostDepartmentProfit deptProfit : costDepartmentProfits) { deptProfit.getCostDepartmentProfitAccounts().forEach(account -> { account.setDeptProfitId(deptProfit.getId()); account.setComputeDate(computeDate); account.setHospId(hospId); }); costDepartmentProfitAccounts.addAll(deptProfit.getCostDepartmentProfitAccounts()); } //保存科室损益的会计科目金额数据 costDepartmentProfitAccountRepository.saveBatch(costDepartmentProfitAccounts); //记录最后一次 损益计算日期 computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate); } /** * 获取科室损益计算所需的数据 * @param computeDate * @param hospId * @param reportType * @return */ public ProfitCalculationDataVo getProfitCalculationData(String computeDate, Long hospId, String reportType) { ProfitCalculationDataVo profitCalculationData = new ProfitCalculationDataVo(); Integer year = ComputeDateUtils.getComputeYear(computeDate); Integer month = ComputeDateUtils.getComputeMonth(computeDate); // 获取指定类型的报表配置 List reportFormList = getReportForm(reportType); if (CollUtil.isEmpty(reportFormList)) { throw new CostException(500, "损益表未找到"); } //获取报表设置明细 List reportRelation = getReportRelation(); Map> reportRelationMap = reportRelation.stream().collect(Collectors.groupingBy(ReportRelation::getReportId)); // 查询最后一个层级的责任中心 List costShareLevelList = getCostShareLevelList(); if (CollUtil.isEmpty(costShareLevelList)) { throw new CostException(500, "分摊层级未设置"); } //获取指定报表对应的责任中心 List responsibilityList = getReportResponsibilityList(reportType); // 获取归集后的收入数据 List incomeList = getIncomeCollectionList(year,month); if (CollUtil.isEmpty(incomeList)) { throw new CostException(500, "归集后数据不存在"); } // 获取分摊后数据 List allocationQueryList = allocationQueryService.getAllByDate(hospId,year,month); if (CollUtil.isEmpty(allocationQueryList)) { throw new CostException(500, "分摊后数据不存在"); } // 封装数据 List allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class); allocationQueryReportVOList.forEach(i -> { i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA))); i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA))); }); // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用 List allocationList = allocationService.getByDate( year, month, hospId); if (CollUtil.isEmpty(allocationList)) { throw new CostException(500, "分摊报表数据不存在"); } profitCalculationData.setComputeDate(computeDate); profitCalculationData.setYear(year); profitCalculationData.setMonth(month); profitCalculationData.setHospId(hospId); profitCalculationData.setReportType(reportType); profitCalculationData.setReportFormList(reportFormList); profitCalculationData.setReportRelationList(reportRelation); profitCalculationData.setReportRelationMap(reportRelationMap); profitCalculationData.setCostShareLevelList(costShareLevelList); profitCalculationData.setResponsibilityList(responsibilityList); return profitCalculationData; } /** * 计算科室损益 * @param profitCalculationData * @return */ private List calcDeptProfit(ProfitCalculationDataVo profitCalculationData) { List firstLevelReports = profitCalculationData.getReportFormList().stream().filter(i -> i.getParentId().equals(NumberConstant.ZERO)).collect(Collectors.toList()); if(CollectionUtils.isEmpty(firstLevelReports)){ throw new CostException(500, "未找到第一层报表项目,请检查报表配置"); } //按顺序号排序 firstLevelReports.sort(Comparator.comparing(ReportForm::getSort, Comparator.nullsLast(Integer::compareTo))); Map> reportParentGroup = profitCalculationData.getReportFormList().stream().collect(Collectors.groupingBy(ReportForm::getParentId)); List costDepartmentProfitVOList = new ArrayList<>(); //循环设置子级报表项目 for (ReportForm reportForm : firstLevelReports) { setChildReport(reportForm,reportParentGroup); } //按责任中心计算科室损益 for (Responsibility responsibility : profitCalculationData.getResponsibilityList()) { Map costDepartmentProfitMap=new HashMap<>(); //计算责任中心的所有报表项目 for (ReportForm reportForm : firstLevelReports) { calcRespReportAmount(responsibility, reportForm,profitCalculationData, costDepartmentProfitMap); } //添加到结果集合 costDepartmentProfitVOList.addAll(costDepartmentProfitMap.values()); } return null; } /** * 循环设置子级报表项目 * @param reportForm * @param reportParentGroup */ public void setChildReport(ReportForm reportForm ,Map> reportParentGroup){ List childReportForms = reportParentGroup.get(reportForm.getId()); if(CollUtil.isEmpty(childReportForms)){ return; } reportForm.setChild(childReportForms); for (ReportForm cildReportForm : childReportForms) { setChildReport(cildReportForm,reportParentGroup); } } /** * 计算指定责任中心指定报表项目的金额(优先计算子级,再按顺序号计算非公式项,最后计算公式项) * @param profitCalculationData * @param costDepartmentProfitMap * @param parentReport * @param responsibility */ public void calcRespReportAmount(Responsibility responsibility, ReportForm parentReport , ProfitCalculationDataVo profitCalculationData, Map costDepartmentProfitMap){ //有子级的优先计算子级 if(!CollUtil.isEmpty(parentReport.getChild())){ //计算报表项目的金额 for (ReportForm reportForm : parentReport.getChild()) { //计算子级的金额 calcRespReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap); } //找出所有类型不是计算公式且不是不设置的报表项 List calcReportList = parentReport.getChild().stream().filter(i ->!NumberConstant.ZERO.equals(i.getCalcType())&& !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList()); //优先计算类型为非计算公式的报表项 if (!CollUtil.isEmpty(calcReportList)){ for (ReportForm reportForm : calcReportList) { calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap); } } //找出所有类型为计算公式的报表项 List formulaReportList = parentReport.getChild().stream().filter(i -> NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList()); //再计算类型为计算公式的报表项 if (!CollUtil.isEmpty(formulaReportList)){ for (ReportForm reportForm : formulaReportList) { calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap); } } }else{ //没有子级项目的只要计算自己 calcReportAmount(responsibility,parentReport,profitCalculationData,costDepartmentProfitMap); } } /** * 计算一个报表项目的金额 * @param profitCalculationData * @param costDepartmentProfitMap * @param reportForm */ public void calcReportAmount(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData,Map costDepartmentProfitMap){ Integer calcType = reportForm.getCalcType(); CostDepartmentProfitVO costDepartmentProfitVO = createCostDepartmentProfitVO(responsibility,reportForm,profitCalculationData); switch (calcType){ case 1: if(NumberConstant.ONE.equals(reportForm.getCostType())){ //按收入会计科目计算 setIncomeAccountReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm); }else{ //按成本会计科目计算 setCostAccountReportValue(costDepartmentProfitVO,profitCalculationData, responsibility, reportForm); } break; case 2: //按分摊层级计算 setShareLevelReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm); break; case 4: //按公式计算 setFormulaReportValue(costDepartmentProfitVO,costDepartmentProfitMap,responsibility,reportForm); break; case 5: //按责任中心计算 setResponsibilityReportValue(costDepartmentProfitVO,profitCalculationData,costDepartmentProfitMap,responsibility,reportForm); break; } //记录下已计算好的报表项目 if(!costDepartmentProfitMap.containsKey(reportForm.getNum())){ costDepartmentProfitMap.put(reportForm.getNum(),costDepartmentProfitVO); } } /** * 创建一个科室损益计算结果对象 * @param responsibility * @param reportForm * @param profitCalculationData * @return */ public CostDepartmentProfitVO createCostDepartmentProfitVO(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData){ CostDepartmentProfitVO costDepartmentProfitVO = new CostDepartmentProfitVO(); costDepartmentProfitVO.setYear(profitCalculationData.getYear()); costDepartmentProfitVO.setMonth(profitCalculationData.getMonth()); costDepartmentProfitVO.setReportId(reportForm.getId()); costDepartmentProfitVO.setReportNum(reportForm.getNum()); costDepartmentProfitVO.setCalcType(reportForm.getCalcType()); costDepartmentProfitVO.setReportName(reportForm.getReportName()); costDepartmentProfitVO.setCalcFormula(reportForm.getCalcFormula()); costDepartmentProfitVO.setReportParentId(reportForm.getParentId()); costDepartmentProfitVO.setResponsibilityCode(responsibility.getResponsibilityCode()); costDepartmentProfitVO.setResponsibilityName(responsibility.getResponsibilityName()); costDepartmentProfitVO.setCostType(NumberConstant.ONE); costDepartmentProfitVO.setIncomeType(NumberConstant.ONE); costDepartmentProfitVO.setHospId(UserContext.getHospId()); costDepartmentProfitVO.setShareType(Integer.valueOf(profitCalculationData.getReportType())); costDepartmentProfitVO.setType(reportForm.getCostType()); costDepartmentProfitVO.setFraction(reportForm.getFraction()); costDepartmentProfitVO.setAmount(BigDecimal.ZERO); costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>()); return costDepartmentProfitVO; } /** * 获取按责任中心计算结果 * @param profitCalculationData * @param costDepartmentProfitMap * @param reportForm * @return */ private void setResponsibilityReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Map costDepartmentProfitMap, Responsibility responsibility, ReportForm reportForm) { List reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId()); if(CollectionUtils.isEmpty(reportRelationList)){ return ; } // 获取对应的会计科目信息 筛选会计科目的Code List responsibilityCodeList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); //类型是收入时取分摊结果表单的数据计算 // 需要查询分摊后的表 List reportVOList = profitCalculationData.getAllocationQueryReportVOList().stream().filter(m -> m.getTargetResponsibilityCode().equals(responsibility.getResponsibilityCode()) &&NumberConstant.TWO.equals(m.getOriginType().intValue()) && responsibilityCodeList.contains(m.getResponsibilityCode())).collect(Collectors.toList()); if (CollUtil.isEmpty(reportVOList)) { return ; } List costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList); BigDecimal totalAmount = costDepartmentProfitAccounts.stream() .map(CostDepartmentProfitAccount::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); costDepartmentProfitVO.setAmount(totalAmount); costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts); } /** * 获取按公式计算结果 * @param responsibility * @param costDepartmentProfitMap * @param reportForm * @return */ private void setFormulaReportValue(CostDepartmentProfitVO costDepartmentProfitVO,Map costDepartmentProfitMap,Responsibility responsibility, ReportForm reportForm) { // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2] String formula = reportForm.getCalcFormula(); if (StrUtil.isBlank(formula)) { costDepartmentProfitVO.setAmount(BigDecimal.ZERO); costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>()); return ; } String responsibilityCode = responsibility.getResponsibilityCode(); // 找出公式当中所有代码 String replace = formula.replace("[", "") .replace("]", "") .replace("-", ",") .replace("+", ",") .replace("*", ",") .replace("/", ","); ArrayList codeList = CollUtil.newArrayList(replace.split(",")); Map codeMap = new ConcurrentHashMap<>(); for (int j = 0; j < codeList.size(); j++) { codeMap.put(j, codeList.get(j)); } List expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "") .replace("]", "").trim(), 0) .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList()); // 得到预算表达式 得到所有表达式的Map + - * / 相关的 Map expressionMap = new ConcurrentHashMap<>(); for (int k = 0; k < expressions.size(); k++) { expressionMap.put(k, expressions.get(k)); } // 数字的索引和表达式的索引累加计算 Set codeSet = codeMap.keySet(); List codes = new ArrayList<>(codeSet); AtomicReference totalAmount = new AtomicReference<>(BigDecimal.ZERO); List baseDeptProfitAccounts=new ArrayList<>(); for (int i = 0; i < codes.size(); i++) { // 编号 String code = codeMap.get(i); CostDepartmentProfitVO reportData = costDepartmentProfitMap.get(Integer.valueOf(code)); // 检查报表数据是否存在且属于当前责任中心 if (reportData == null || !responsibilityCode.equals(reportData.getResponsibilityCode())) { continue; } BigDecimal amount = reportData.getAmount(); if (amount == null) { amount = BigDecimal.ZERO; } String str = expressionMap.get(i); if (str.equals("+")) { baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.ONE); totalAmount.set(totalAmount.get().add(amount)); } else if (str.contains("-")) { baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.NEGATIVE); totalAmount.set(totalAmount.get().subtract(amount)); } else if (str.contains("*")) { totalAmount.set(totalAmount.get().multiply(amount)); } else if (str.contains("/")) { if (amount.compareTo(BigDecimal.ZERO) == 0) { log.error("报表项【" + reportForm.getReportName() + "】公式除数为0,报表编号为【" + code + "】"); totalAmount.set(BigDecimal.ZERO); break; } else { totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP)); } } } //有乘除算法的只要赋值,不用设置会计科目金额 if(formula.contains("*")||formula.contains("/")){ costDepartmentProfitVO.setAmount(totalAmount.get()); costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>()); }else{ costDepartmentProfitVO.setAmount(totalAmount.get()); costDepartmentProfitVO.setCostDepartmentProfitAccounts(baseDeptProfitAccounts); } } /** * 对两个CostDepartmentProfitVO对象的costDepartmentProfitAccounts列表进行加减运算 * 按照相同的costType和accountType进行合并计算,只处理amount字段 * * @param firstList 第一个CostDepartmentProfitVO对象 * @param secondList 第二个CostDepartmentProfitVO对象 * @param operation 运算符,1表示加法,-1表示减法 * @return 运算结果列表 */ public List calculateAccountAmounts( List firstList, List secondList, int operation) { // 处理空列表情况 firstList = firstList != null ?firstList : new ArrayList<>(); secondList = secondList != null ?secondList: new ArrayList<>(); // 创建结果列表,先复制第一个列表的所有元素 List result = firstList.stream() .map(account -> { CostDepartmentProfitAccount copy = new CostDepartmentProfitAccount(); copy.setCostType(account.getCostType()); copy.setAccountType(account.getAccountType()); copy.setAmount(account.getAmount() != null ? account.getAmount() : BigDecimal.ZERO); return copy; }) .collect(Collectors.toList()); // 处理第二个列表中的每个元素 for (CostDepartmentProfitAccount secondAccount : secondList) { if (secondAccount.getAmount() == null) { continue; // 跳过金额为空的记录 } // 查找是否在结果列表中已有相同costType和accountType的记录 boolean found = false; for (CostDepartmentProfitAccount resultAccount : result) { if (Objects.equals(resultAccount.getCostType(), secondAccount.getCostType()) && Objects.equals(resultAccount.getAccountType(), secondAccount.getAccountType())) { // 找到匹配项,进行加减运算 BigDecimal firstAmount = resultAccount.getAmount() != null ? resultAccount.getAmount() : BigDecimal.ZERO; BigDecimal secondAmount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO; if (operation == 1) { resultAccount.setAmount(firstAmount.add(secondAmount)); } else if (operation == -1) { resultAccount.setAmount(firstAmount.subtract(secondAmount)); } found = true; break; } } // 如果未找到匹配项,则添加新记录 if (!found) { CostDepartmentProfitAccount newAccount = new CostDepartmentProfitAccount(); newAccount.setCostType(secondAccount.getCostType()); newAccount.setAccountType(secondAccount.getAccountType()); // 加法直接添加金额,减法添加负金额 if (operation == 1) { newAccount.setAmount(secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO); } else if (operation == -1) { BigDecimal amount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO; newAccount.setAmount(amount.negate()); // 设置为负值 } result.add(newAccount); } } return result; } /** * 获取按分摊层级计算结果 * @param profitCalculationData * @param reportForm * @return */ private void setShareLevelReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) { List reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId()); if(CollectionUtils.isEmpty(reportRelationList)){ return ; } // 获取对应的会计科目信息 筛选会计科目的Code List shareLevelIdList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); //类型是收入时取分摊结果表单的数据计算 // 需要查询分摊后的表 List reportVOList = profitCalculationData.getAllocationQueryReportVOList().stream().filter(m -> m.getTargetResponsibilityCode().equals(responsibility.getResponsibilityCode()) &&NumberConstant.TWO.equals(m.getOriginType().intValue()) && shareLevelIdList.contains(m.getShareLevelId())).collect(Collectors.toList()); if (CollUtil.isEmpty(reportVOList)) { return ; } List costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList); BigDecimal totalAmount = costDepartmentProfitAccounts.stream() .map(CostDepartmentProfitAccount::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); costDepartmentProfitVO.setAmount(totalAmount); costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts); } /** * 按收入会计科目计算 * @param costDepartmentProfitVO * @param profitCalculationData * @param responsibility * @param reportForm */ private void setIncomeAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO,ProfitCalculationDataVo profitCalculationData, Responsibility responsibility,ReportForm reportForm) { List reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId()); if(CollectionUtils.isEmpty(reportRelationList)){ return ; } // 获取对应的会计科目信息 筛选会计科目的Code List accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); // 查找在归集数据里面当前责任中心对应的这些会计科目的金额 List incomeCollectionList = profitCalculationData.getIncomeList().stream().filter(income -> income.getResponsibilityCode().equals(responsibility.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList()); if(CollectionUtils.isEmpty(incomeCollectionList)){ return ; } BigDecimal totalAmount = incomeCollectionList.stream() .map(IncomeCollection::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); costDepartmentProfitVO.setAmount(totalAmount); } /** *获取按成本会计科目计算的结果 * @param profitCalculationData * @param responsibility * @param reportForm * @return */ private void setCostAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) { List reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId()); if(CollectionUtils.isEmpty(reportRelationList)){ return ; } // 获取对应的会计科目信息 筛选会计科目的Code List accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList()); //类型是收入时取分摊结果表单的数据计算 // 需要查询分摊后的表 List reportVOList = profitCalculationData.getAllocationQueryReportVOList().stream().filter(m -> m.getTargetResponsibilityCode().equals(responsibility.getResponsibilityCode()) &&(NumberConstant.ZERO.equals(reportForm.getCostType())||reportForm.getCostType().equals(m.getOriginType().intValue())) &&accountList.contains(m.getAccountingCode())).collect(Collectors.toList()); if (CollUtil.isEmpty(reportVOList)) { return ; } List costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList); BigDecimal totalAmount = costDepartmentProfitAccounts.stream() .map(CostDepartmentProfitAccount::getAmount) .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add); costDepartmentProfitVO.setAmount(totalAmount); costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts); } /** * 将分摊结果按会计科目类别+成本类别分组汇总 * @param reportVOList * @return */ public List calculateCostByTypeAndAccount(List reportVOList) { // 按costType+accountType分组计算各组的金额amount Map groupedAmounts = reportVOList.stream() .collect(Collectors.groupingBy( vo -> vo.getCostType() + "_" + vo.getAccountType(), Collectors.reducing( BigDecimal.ZERO, AllocationQueryReportVO::getAmount, BigDecimal::add ) )); // 按组生成CostDepartmentProfitAccount对象 return groupedAmounts.entrySet().stream() .map(entry -> { String[] keys = entry.getKey().split("_", 2); CostDepartmentProfitAccount account = new CostDepartmentProfitAccount(); account.setCostType(keys[0]); account.setAccountType(keys[1]); account.setAmount(entry.getValue()); return account; }) .collect(Collectors.toList()); } /** * 获取指定类型的报表配置 * @param reportType * @return */ public List getReportForm(String reportType){ List reportFormList = reportFormService.list(new QueryWrapper().lambda() .eq(ReportForm::getHospId, UserContext.getHospId()) .eq(ReportForm::getReportType, reportType)); return reportFormList; } /** * 获取报表关系 * @return */ public List getReportRelation(){ List list = reportRelationService.list(new QueryWrapper().lambda().eq(ReportRelation::getHospId, UserContext.getHospId())); return list; } /** * 获取指定报表对应的责任中心 * @param reportType * @return */ public List getReportResponsibilityList(String reportType){ DictDataVo dataVo = getDictDataVo(reportType); Long id = Long.valueOf(dataVo.getExpandOne()); List list = responsibilityService.list(new QueryWrapper().lambda() .eq(Responsibility::getHospId, UserContext.getHospId()) .eq(Responsibility::getIsGatherCenter, 2) .eq(Responsibility::getDeleteTime, 0) .eq(Responsibility::getShareId, id)); return list; } /** * 获取分摊层级字典 * @return */ public List getCostShareLevelList(){ List costShareLevelList = costShareLevelService.list(new QueryWrapper().lambda() .eq(CostShareLevel::getHospId, UserContext.getHospId()).orderByDesc(CostShareLevel::getLeverSort)); return costShareLevelList; } /** * 获取归集后的收入数据 * @param year * @param month * @return */ public List getIncomeCollectionList(Integer year, Integer month) { List list = incomeCollectionService.list(new QueryWrapper().lambda() .eq(IncomeCollection::getHospId, UserContext.getHospId()) .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month)); return list; } /** * 删除指定月份的科室损益数据 * @param year * @param month * @param reportType */ public void deleteDeptProfit(Integer year, Integer month,String reportType) { // 删除这个年月的数据 this.remove(new QueryWrapper().lambda().eq(CostDepartmentProfit::getHospId, UserContext.getHospId()) .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, Integer.valueOf(reportType))); } }