package com.imed.costaccount.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; 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.service.impl.ServiceImpl; import com.imed.costaccount.common.constants.NumberConstant; import com.imed.costaccount.common.exception.CostException; import com.imed.costaccount.common.util.BeanUtil; import com.imed.costaccount.common.util.JacksonUtil; import com.imed.costaccount.common.util.PageUtils; import com.imed.costaccount.common.util.UserContext; import com.imed.costaccount.mapper.AllocationMapper; import com.imed.costaccount.model.*; import com.imed.costaccount.model.dto.StartDTO; import com.imed.costaccount.model.vo.*; import com.imed.costaccount.service.*; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Sheet; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @Slf4j @Service("allocationService") public class AllocationServiceImpl extends ServiceImpl implements AllocationService { @Value("${file.serverPath}") private String fileTempPath; @Value("${file.serverUrl}") private String FILE_PATH; private final CostCostingGroupService costCostingGroupService; private final CostShareLevelService shareLevelService; private final ResponsibilityService responsibilityService; private final CostAccountShareService accountShareService; private final ShareParamValueService shareParamValueService; private final CostShareParamService shareParamService; private final AllocationQueryService allocationQueryService; public AllocationServiceImpl(CostCostingGroupService costCostingGroupService, CostShareLevelService shareLevelService, ResponsibilityService responsibilityService, CostAccountShareService accountShareService, ShareParamValueService shareParamValueService, CostShareParamService shareParamService, AllocationQueryService allocationQueryService, AllocationQueryService allocationQueryService1) { this.costCostingGroupService = costCostingGroupService; this.shareLevelService = shareLevelService; this.responsibilityService = responsibilityService; this.accountShareService = accountShareService; this.shareParamValueService = shareParamValueService; this.shareParamService = shareParamService; this.allocationQueryService = allocationQueryService1; } /** * 分摊成本数据 * * @param startDTO {@link StartDTO} * @param hospId 医院id */ @Override @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED) public void startAllocation(StartDTO startDTO, Long hospId) { long timeMillis = System.currentTimeMillis(); // 得到这个月的所有导入的成本数据 List costingGroups = costCostingGroupService.getByYearAndDate(startDTO.getYear(), startDTO.getMonth(), hospId); // 没有重新导入 if (costingGroups.isEmpty()) { throw new CostException("本月分摊数据未导入"); } // 导入数据按责任中心归类 Map> responsibilityCodeMap = costingGroups.stream().collect(Collectors.groupingBy(CostCostingGroup::getResponsibilityCode)); // 得到这个月导入的成本分摊参数值列表 List shareParamValues = shareParamValueService.getListByYearAndMonth(startDTO.getYear(), startDTO.getMonth(), hospId); if (shareParamValues.isEmpty()) { throw new CostException("本月成本分摊参数值未导入"); } Map> paramValueRespCodeMap = shareParamValues.stream().collect(Collectors.groupingBy(ShareParamValue::getResponsibilityCode)); // 删除该年月已经分摊过的数据 removeData(startDTO, hospId); // 得到这个医院所有的分摊层级列表排序 List shareLevelVOs = shareLevelService.getAll(hospId); if (CollUtil.isEmpty(shareLevelVOs)) { throw new CostException("请先设置医院分摊层级"); } List allocations = new LinkedList<>(); // key 责任中心代码, value 分摊过来的钱 // Map costMap = new ConcurrentReaderHashMap(); List costList = new ArrayList<>(); for (CostShareLevelVO shareLevelVO : shareLevelVOs) { // 分摊层级id Long levelId = shareLevelVO.getId(); // 目标分摊层级,可能不存在 String targetLevel = shareLevelVO.getTargetLevel(); if (StrUtil.isBlank(targetLevel)) { throw new CostException("未设置目标层级"); } // 计算方式 0是合并计算 1是分开计算 Integer calcType = shareLevelVO.getCalcType(); // 得到该分摊层级下责任中心列表,如果不存在,下一个 List responsibilities = responsibilityService.getLevelIdByCode(levelId, hospId); if (responsibilities.isEmpty()) { continue; } // 遍历责任中心得到对应的分摊参数对应 for (Responsibility responsibility : responsibilities) { String responsibilityCode = responsibility.getResponsibilityCode(); // 得到分摊参数对应记录,不存在,下一个 List accountShares = accountShareService.getByResponsibility(responsibilityCode, hospId); if (accountShares.isEmpty()) { continue; } // 遍历分摊参数对应记录 for (CostAccountShare accountShare : accountShares) { Long accountShareId = accountShare.getId(); String paramList = accountShare.getParamList(); List accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class); // 如果分摊比例未设置直接报错 if (StrUtil.isBlank(paramList)) { throw new CostException("责任中心:" + accountShare.getResponsibilityName() + ";会计中心为:" + accountShare.getAccountingNames() + ";未设置分摊参数比例"); } List groups = responsibilityCodeMap.get(responsibilityCode); if (CollUtil.isEmpty(groups)) { continue; } // 计算本次分摊的钱 BigDecimal totalAmount = this.getCostAmount(accountShare, calcType, responsibilityCodeMap, costList); if (totalAmount.equals(BigDecimal.ZERO)) { continue; } // 相关的分摊参数比例 for (AccountShareVO accountShareVO : accountShareVOs) { String paramCode = accountShareVO.getShareParamCode(); String shareParamPopout = accountShareVO.getShareParamPopout(); BigDecimal rate = new BigDecimal("1"); if (!"100".equals(shareParamPopout)) { rate = new BigDecimal("0." + shareParamPopout); } // 本次的分摊比例计算 BigDecimal thisAmount = rate.multiply(totalAmount); // 得到目标层级责任中心列表 List targetResponsibilities = this.getTargetResponsibility(targetLevel, hospId, shareLevelVO.getLeverSort()); if (targetResponsibilities.isEmpty()) { throw new CostException("找不到目标责任中心"); } // 目标责任中心得到对应 List targetShareParmValue = getTarget(targetResponsibilities, accountShareVO, paramValueRespCodeMap); if (CollUtil.isEmpty(targetResponsibilities)) { throw new CostException("找不到目标责任中心对应的分摊参数值"); } // 分母 BigDecimal reduce = targetShareParmValue.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add); for (ShareParamValue paramValue : targetShareParmValue) { // 分子 BigDecimal numerator = paramValue.getValueNum(); BigDecimal targetAmount = thisAmount.multiply(numerator).divide(reduce, 4); Allocation targetAllocation = new Allocation(); String valueResponsibilityCode = paramValue.getResponsibilityCode(); String targetRespName = responsibilityService.getByCode(valueResponsibilityCode, hospId); Long targetShareLevelId = responsibilityService.getLevelIdByCode(valueResponsibilityCode, hospId); if (Objects.isNull(targetShareLevelId)) { throw new CostException("目标责任中心分摊层级异常"); } String shareParamName = shareParamService.getByCode(paramValue.getShareParamCode(), hospId); targetAllocation.setDateMonth(startDTO.getMonth()).setDateYear(startDTO.getYear()).setLevelSort(shareLevelVO.getLeverSort()) .setLevelName(shareLevelVO.getShareName()).setHospId(hospId).setResponsibilityCode(responsibility.getResponsibilityCode()) .setResponsibilityName(responsibility.getResponsibilityName()).setAccountShareId(accountShareId).setAmount(targetAmount) .setCreateTime(timeMillis).setTargetResponsibilityCode(valueResponsibilityCode).setTargetResponsibilityName(targetRespName) .setShareParamCode(paramValue.getShareParamCode()).setShareParamName(shareParamName).setTotalAmount(totalAmount).setShareParamValueNum(paramValue.getValueNum()) .setShareParamRate(numerator.divide(reduce, 4)).setShareLevelId(levelId).setTargetShareLevelId(targetShareLevelId) ; // todo 目标分摊层级责任中心 就是当前列个表中的责任中心 allocations.add(targetAllocation); costList.add(targetAllocation); } } } } } this.saveBatch(allocations); List list = this.list( new LambdaQueryWrapper() .eq(Allocation::getHospId, hospId).eq(Allocation::getDateYear, startDTO.getYear()).eq(Allocation::getDateMonth, startDTO.getMonth()) ); if (list.isEmpty()) { log.error("未分摊到数据......"); return; } // 入cost_allocation_query 表 便于后续操作 this.saveAllocationQuery(list, costingGroups, hospId, startDTO.getYear(), startDTO.getMonth()); } private void removeData(StartDTO startDTO, Long hospId) { this.remove( new LambdaQueryWrapper() .eq(Allocation::getDateYear, startDTO.getYear()) .eq(Allocation::getDateMonth, startDTO.getMonth()) .eq(Allocation::getHospId, hospId) ); allocationQueryService.remove( new LambdaQueryWrapper() .eq(AllocationQuery::getDateYear, startDTO.getYear()) .eq(AllocationQuery::getDateMonth, startDTO.getMonth()) .eq(AllocationQuery::getHospId, hospId) ); } @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void saveAllocationQuery(List list, List costingGroups, Long hospId, Integer year, Integer month) { List saveList = new ArrayList<>(); List maxId = shareLevelService.getMaxId(hospId); list = list.stream().filter(i -> maxId.contains(i.getTargetShareLevelId())).collect(Collectors.toList()); list.forEach(i -> { Long accountShareId = i.getAccountShareId(); CostAccountShare byId = accountShareService.getById(accountShareId); if (Objects.isNull(byId)) { return; } String accountingCodes = byId.getAccountingCodes(); if (StrUtil.isBlank(accountingCodes)) { return; } String accountingNames = byId.getAccountingNames(); String alias = byId.getAlias(); if (StrUtil.isNotBlank(alias)) { accountingNames = alias; } AllocationQuery allocationQuery = new AllocationQuery(); allocationQuery.setDateYear(i.getDateYear()).setDateMonth(i.getDateMonth()) .setHospId(hospId).setResponsibilityCode(i.getResponsibilityCode()) .setResponsibilityName(i.getResponsibilityName()) .setOriginId(i.getId()).setOriginType(1L).setAmount(i.getAmount()) .setAccountingCode(accountingCodes).setAccountingName(accountingNames) .setCreateTime(System.currentTimeMillis()) .setLevelSort(i.getLevelSort()).setLevelName(i.getLevelName()) ; saveList.add(allocationQuery); }); costingGroups = costCostingGroupService.getRealData(maxId, hospId, year, month); costingGroups.forEach(i -> { AllocationQuery allocationQuery = new AllocationQuery(); String responsibilityCode = i.getResponsibilityCode(); Long levelId = responsibilityService.getLevelIdByCode(responsibilityCode, hospId); if (Objects.isNull(levelId)) { throw new CostException("责任中心" + i.getResponsibilityName() + "数据异常"); } CostShareLevel byId = shareLevelService.getById(levelId); if (Objects.isNull(byId)) { throw new CostException("责任中心" + i.getResponsibilityName() + "分摊层级数据异常"); } allocationQuery.setDateYear(i.getDateYear()).setDateMonth(i.getDateMonth()) .setHospId(hospId).setResponsibilityCode(responsibilityCode).setResponsibilityName(i.getResponsibilityName()) .setOriginId(i.getId()).setOriginType(2L).setAmount(i.getAmount()) .setAccountingCode(i.getAccountCode()).setAccountingName(i.getAccountName()) .setCreateTime(System.currentTimeMillis()) .setLevelSort(byId.getLeverSort()).setLevelName(byId.getShareName()) ; saveList.add(allocationQuery); }); allocationQueryService.saveBatch(saveList); } /** * 得到目标月成本分摊参数值数据 * * @param targetResponsibilities * @param map * @return */ private List getTarget(List targetResponsibilities, AccountShareVO accountShareVO, Map> map) { // 目标的责任中心 List shareParamValues = map.entrySet().stream().map(Map.Entry::getValue).flatMap(Collection::stream).collect(Collectors.toList()); List originRespCodes = targetResponsibilities.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList()); return shareParamValues.stream().filter(j -> originRespCodes.contains(j.getResponsibilityCode())) .filter(i -> i.getShareParamCode().equals(accountShareVO.getShareParamCode())).collect(Collectors.toList()); } /** * 计算本次的成本金额 * * @return */ private BigDecimal getCostAmount(CostAccountShare accountShare, Integer calcType, Map> map, List costList) { // 是否包含分摊成本 0不包含 1 包含 Integer isShareCost = accountShare.getIsShareCost(); String accountingCodes = accountShare.getAccountingCodes(); String responsibilityCode = accountShare.getResponsibilityCode(); List costingGroups = map.get(responsibilityCode); if (CollUtil.isEmpty(costingGroups)) { return BigDecimal.ZERO; } BigDecimal costAmount = BigDecimal.ZERO; List all = new ArrayList<>(); if (!costList.isEmpty()) { all = costList.stream().filter(i -> i.getTargetResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList()); } // 计算方式 0是合并计算 1是分开计算 if (calcType == 0) { costAmount = costingGroups.stream().map(CostCostingGroup::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if (!all.isEmpty()) { BigDecimal bigDecimal = all.stream() .map(Allocation::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::subtract); if (Objects.nonNull(bigDecimal)) { costAmount = costAmount.add(bigDecimal); } } } else { if (StrUtil.isBlank(accountingCodes)) { return BigDecimal.ZERO; } ArrayList accountCodes = CollUtil.newArrayList(accountingCodes.split(StrUtil.COMMA)); List costGroups = costingGroups.stream().filter(i -> accountCodes.contains(i.getAccountCode())).collect(Collectors.toList()); costAmount = costGroups.stream().map(CostCostingGroup::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if (isShareCost == 1) { if (!all.isEmpty()) { BigDecimal bigDecimal = all.stream() .map(Allocation::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::subtract); if (Objects.nonNull(bigDecimal)) { costAmount = costAmount.add(bigDecimal); } } } } return costAmount; } /** * 通过目标层级获取目标责任中心 * * @param targetLevel 目标层级 2,3,4 * @param leverSort * @return List */ private List getTargetResponsibility(String targetLevel, Long hospId, Integer leverSort) { ArrayList targetLevelList = CollUtil.newArrayList(StrUtil.split(targetLevel, StrUtil.COMMA)); if (targetLevelList.size() == 1) { if (leverSort.equals(Integer.parseInt(targetLevelList.get(0)))) { return new ArrayList<>(); } } List shareLevels = shareLevelService.getListByLevelSort(targetLevelList, hospId); if (shareLevels.isEmpty()) { throw new CostException("请重新设置分摊层级"); } List shareLevelIds = shareLevels.stream().map(CostShareLevel::getId).collect(Collectors.toList()); return responsibilityService.getByLevelIds(shareLevelIds, hospId); } /** * 分摊后查询列表 * * @param year 年月 (yyyy-MM-dd) * @param responsibilityCode 责任中心代码 * @param current 当前页 * @param pageSize 当前页展示的数据大小 * @param hospId 医院id * @return PageUtils */ @Override public PageUtils queryAfterAllocation(String year, String responsibilityCode, Integer current, Integer pageSize, Long hospId) { Integer dateYear = null; Integer dateMonth = null; if (StrUtil.isNotBlank(year)) { DateTime dateTime = DateUtil.parseDate(year); dateYear = DateUtil.year(dateTime); dateMonth = DateUtil.month(dateTime) + 1; } Integer startIndex = (current - 1) * pageSize; List list = baseMapper.queryAfterAllocationList(dateYear, dateMonth, responsibilityCode, startIndex, pageSize, hospId); int totalCount = baseMapper.queryAfterAllocationListCount(dateYear, dateMonth, responsibilityCode, hospId); BigDecimal sum = baseMapper.queryAfterAllocationListSum(dateYear, dateMonth, responsibilityCode, hospId); return new PageUtils(list, totalCount, pageSize, current, sum); } /** * 分摊报表导出 * * @param writer {@link ExcelWriter} * @param levelSort 分摊层级 就是第几次分摊 * @param sheet 报表 * @param year 年 * @param month 月 * @param shareLevelId * @return */ @Override public ExcelWriter getShareReportTemplate(ExcelWriter writer, Integer levelSort, Sheet sheet, Integer year, Integer month, Long shareLevelId) { // 获取数据 List allocationReportVOList = getAllocationReportVOS(levelSort, year, month, shareLevelId); // 设置导出 Map> responsibilityMap = allocationReportVOList.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode)); Map> targetResponsibilityMap = allocationReportVOList.stream().collect(Collectors.groupingBy(AllocationReportVO::getTargetResponsibilityCode)); // 以会计科目查 Map allAccMap = allocationReportVOList.stream().collect(Collectors.toMap(k -> k.getResponsibilityName() + k.getAccountName() + k.getTargetResponsibilityName() + k.getShareParamName(), synOne -> synOne)); // 用别名查 过滤别名不为空的 Map allAliMap = allocationReportVOList.stream().filter(i -> StrUtil.isNotBlank(i.getAlias())).collect(Collectors.toMap(k -> k.getResponsibilityName() + k.getAlias() + k.getTargetResponsibilityName() + k.getShareParamName(), synOne -> synOne)); // Map allAliMap = allocationReportVOList.stream().collect(Collectors.toMap(k -> k.getResponsibilityName() + k.getAlias() + k.getTargetResponsibilityName() + k.getShareParamName(), synOne -> synOne)); // 当前责任中心下面有几个会计科目 后面进行合并使用 int numResponsibility; // // 从第几列开始编写数据 int column = levelSort + 3; Set keySet = responsibilityMap.keySet(); for (String key : keySet) { List allocationReportVOS = responsibilityMap.get(key); Map linkedHashMap = new LinkedHashMap<>(); allocationReportVOS.forEach(i -> { String s = i.getResponsibilityCode() + i.getAccountCode(); if (!linkedHashMap.containsKey(s)) { linkedHashMap.put(s, i); } }); numResponsibility = linkedHashMap.size(); if (numResponsibility >= NumberConstant.TWO) { Set strings = linkedHashMap.keySet(); for (String s : strings) { AllocationReportVO allocationReportVO = linkedHashMap.get(s); if (StrUtil.isBlank(allocationReportVO.getAlias())) { writer.writeCellValue(column, 0, allocationReportVO.getResponsibilityName()); // 别名不存在 writer.writeCellValue(column, 1, allocationReportVO.getAccountName()); } else { // 不为空 设置别名 writer.writeCellValue(column, 0, allocationReportVO.getResponsibilityName()); writer.writeCellValue(column, 1, allocationReportVO.getAlias()); } writer.writeCellValue(column, 2, allocationReportVO.getTotalAmounts()); column++; } } else { // 不需要合并单元格 writer.writeCellValue(column, 0, allocationReportVOS.get(0).getResponsibilityName()); if (StrUtil.isNotBlank(allocationReportVOS.get(0).getAlias())) { writer.writeCellValue(column, 1, allocationReportVOS.get(0).getAlias()); } else { writer.writeCellValue(column, 1, allocationReportVOS.get(0).getAccountName()); } writer.writeCellValue(column, 2, allocationReportVOS.get(0).getTotalAmounts()); column++; } } // 设置单元格合并 for (int j = 1; j < levelSort; j++) { writer.merge(0, 1, j, j, "第" + j + "次分摊", false); } // 目标责任集合 writer.passCurrentRow(); // 从第三行开始 int num = 3; Set targetSet = targetResponsibilityMap.keySet(); for (String target : targetSet) { List allocationReportVOS = targetResponsibilityMap.get(target); Map linkedHashMap = new LinkedHashMap<>(); allocationReportVOS.forEach(i -> { String s = i.getTargetResponsibilityCode() + i.getShareParamName(); if (!linkedHashMap.containsKey(s)) { linkedHashMap.put(s, i); } }); int shareParamSize = linkedHashMap.size(); if (shareParamSize >= NumberConstant.TWO) { // 责任中心 AllocationReportVO costCostingVO = allocationReportVOS.get(0); // 设置第几次分摊的值 for (int k = 0; k < levelSort - 1; k++) { writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, costCostingVO.getTargetShareMoneys().get(k), false); } // 设置对应的分摊参数值 Set strings = linkedHashMap.keySet(); for (String s : strings) { AllocationReportVO allocationReportVO = linkedHashMap.get(s); writer.writeCellValue(0, num, allocationReportVO.getTargetResponsibilityName()); writer.writeCellValue(levelSort, num, allocationReportVO.getShareParamName()); writer.writeCellValue(levelSort + 1, num, allocationReportVO.getShareParamValueNums()); writer.writeCellValue(levelSort + 2, num, allocationReportVO.getShareParamRates()); for (int m = levelSort + 3; m < column; m++) { // x是m y是num // 获取当前这一列对应的责任中心 以及会计科目 // 第一行责任中心 String responsibilityName = sheet.getRow(0).getCell(m).getStringCellValue(); // 第二行的会计科目或者 String accountNameOrAlias = sheet.getRow(1).getCell(m).getStringCellValue(); // 这一行的目标责任中心 String otherResponsibilityName = sheet.getRow(num).getCell(0).getStringCellValue(); // 分摊参数 String shareName = sheet.getRow(num).getCell(levelSort).getStringCellValue(); String sss = responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName; AllocationReportVO vo = allAliMap.get(sss); AllocationReportVO allocationReportVO2 = allAccMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName); AllocationReportVO allocationReportVO3 = allAliMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName); if (Objects.nonNull(allocationReportVO2)) { writer.writeCellValue(m, num, allocationReportVO2.getAmounts()); } else if (Objects.nonNull(allocationReportVO3)) { writer.writeCellValue(m, num, allocationReportVO3.getAmounts()); } else { writer.writeCellValue(m, num, 0); } } num++; } } if (shareParamSize < NumberConstant.TWO) { writer.writeCellValue(0, num, allocationReportVOS.get(0).getTargetResponsibilityName()); for (int k = 0; k < levelSort - 1; k++) { writer.writeCellValue(k + 1, num, allocationReportVOS.get(0).getTargetShareMoneys().get(k)); } writer.writeCellValue(levelSort, num, allocationReportVOS.get(0).getShareParamName()); writer.writeCellValue(levelSort + 1, num, allocationReportVOS.get(0).getShareParamValueNums()); writer.writeCellValue(levelSort + 2, num, allocationReportVOS.get(0).getShareParamRates()); for (int m = levelSort + 4; m < column; m++) { // x是m y是num // 获取当前这一列对应的责任中心 以及会计科目 // 第一行责任中心 String responsibilityName = sheet.getRow(0).getCell(m).getStringCellValue(); // 第二行的会计科目或者 String accountNameOrAlias = sheet.getRow(1).getCell(m).getStringCellValue(); // 这一行的目标责任中心 String otherResponsibilityName = sheet.getRow(num).getCell(0).getStringCellValue(); // 分摊参数 String shareName = sheet.getRow(num).getCell(levelSort).getStringCellValue(); AllocationReportVO allocationReportVO2 = allAccMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName); AllocationReportVO allocationReportVO3 = allAliMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName); if (Objects.nonNull(allocationReportVO2)) { writer.writeCellValue(m, num, allocationReportVO2.getAmounts()); } else if (Objects.nonNull(allocationReportVO3)) { writer.writeCellValue(m, num, allocationReportVO3.getAmounts()); } else { writer.writeCellValue(m, num, 0); } } num++; } } Map rowMap = new HashMap<>(); int cc = levelSort + 3; // 合并行 boolean otherData = false; for (int m = levelSort + 3; m < column - 1; m++) { // String cellValue = sheet.getRow(0).getCell(m).getStringCellValue(); // if (!rowMap.containsKey(cellValue)){ // rowMap.put(cellValue,m); // Integer integer = rowMap.get(sheet.getRow(0).getCell(m).getStringCellValue()); // String value = sheet.getRow(0).getCell(m ).getStringCellValue(); // writer.merge(0, 0, rowMap.get(sheet.getRow(0).getCell(m-1).getStringCellValue()), m-1, sheet.getRow(0).getCell(m-1).getStringCellValue(), false); // } String cellValue1 = sheet.getRow(0).getCell(m).getStringCellValue(); String cellValue2 = sheet.getRow(0).getCell(m + 1).getStringCellValue(); if (!cellValue1.equals(cellValue2)) { otherData = true; writer.merge(0, 0, cc, m, cellValue1, false); cc = m + 1; } if (m == column - 2) { writer.merge(0, 0, cc, m + 1, sheet.getRow(0).getCell(m + 1).getStringCellValue(), false); } } // 合并列 int jj = 3; for (int i = 3; i < num - 1; i++) { String cellValue1 = sheet.getRow(i).getCell(0).getStringCellValue(); String cellValue2 = sheet.getRow(i + 1).getCell(0).getStringCellValue(); if (!cellValue1.equals(cellValue2)) { otherData = true; writer.merge(jj, i, 0, 0, cellValue1, false); jj = i + 1; } else if (i == num - 2) { writer.merge(jj, i + 1, 0, 0, cellValue1, false); } } for (int i = 0; i < 30; i++) { // 调整每一列宽度 sheet.autoSizeColumn((short) i); // 解决自动设置列宽中文失效的问题 sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 14 / 10); } return writer; } /** * 查询数据 * * @param levelSort * @param year * @param month * @return */ private List getAllocationReportVOS(Integer levelSort, Integer year, Integer month, Long shareLevelId) { Long hospId = UserContext.getHospId(); if (Objects.isNull(levelSort) || Objects.isNull(year) || Objects.isNull(month)) { throw new CostException(500, "参数异常"); } // 处理第几次分摊计算值 List allocationList = baseMapper.selectList(new QueryWrapper().lambda() .eq(Allocation::getHospId, hospId).eq(Allocation::getLevelSort, levelSort).eq(Allocation::getShareLevelId, shareLevelId).eq(Allocation::getDateYear, year) .eq(Allocation::getDateMonth, month)); // 找会计科室的时候使用的 List allocations = baseMapper.selectList(new QueryWrapper().lambda() .eq(Allocation::getHospId, hospId).eq(Allocation::getDateYear, year) .eq(Allocation::getDateMonth, month)); Map> accrepMap = allocations.stream().collect(Collectors.groupingBy(k -> k.getLevelSort() + "cost" + k.getResponsibilityCode())); LinkedList shareMoney = new LinkedList<>(); List costAccountShareList = accountShareService.list(new QueryWrapper().lambda() .eq(CostAccountShare::getHospId, hospId)); Map accountShareMap = costAccountShareList.stream().collect(Collectors.toMap(CostAccountShare::getId, synOne -> synOne)); List allocationReportVOList = BeanUtil.convertList(allocationList, AllocationReportVO.class); // 设置会计科目的 allocationReportVOList.forEach(i -> { Long accountShareId = i.getAccountShareId(); CostAccountShare costAccountShare = accountShareMap.get(accountShareId); if (Objects.isNull(costAccountShare)) { throw new CostException(500, "成本参数参数设置对应不存在"); } i.setAccountCode(costAccountShare.getAccountingCodes()); i.setAccountName(costAccountShare.getAccountingNames()); i.setAlias(costAccountShare.getAlias()); if (levelSort > 1) { for (int j = 1; j < levelSort; j++) { AtomicReference money = new AtomicReference<>(new BigDecimal("0.0000")); List allocations1 = accrepMap.get(j + "cost" + i.getResponsibilityCode()); if (CollUtil.isNotEmpty(allocations1)) { allocations1.forEach(m -> { money.updateAndGet(v -> v.add(m.getAmount())); shareMoney.add(month.toString()); }); } else { // TODO 封装测试数据 shareMoney.add("0"); } } } i.setTargetShareMoneys(shareMoney); // 设置字符串类型数据 i.setTotalAmounts(i.getTotalAmount().toString()); i.setShareParamValueNums(i.getShareParamValueNum().toString()); i.setShareParamRates(i.getShareParamRate().toString()); i.setAmounts(i.getAmount().toString()); }); return allocationReportVOList; } /** * 分摊后报表 * * @param year 年月(yyyy-MM-dd) * @param responsibilityCode 责任中心代码 * @param hospId 医院id * @return List */ @Override public CollectDataFormVO queryAfterAllocationForm(String year, String responsibilityCode, Long hospId) { DateTime dateTime = DateUtil.parseDate(year); int dateYear = DateUtil.year(dateTime); int month = DateUtil.month(dateTime) + 1; List responsibilityCodeAndNames = allocationQueryService.getRespCodeAndName(hospId, dateYear, month); List accountCodeAndNames = allocationQueryService.getAccountCodeAndName(hospId, dateYear, month); // todo 校验两个List是否为空 // 填充 responsibilityCodeAndNames.add(0, new CodeAndNameVO("#", "#")); responsibilityCodeAndNames.add(responsibilityCodeAndNames.size(), new CodeAndNameVO("合计", "合计")); List titleData = responsibilityCodeAndNames.stream().map(CodeAndNameVO::getName).collect(Collectors.toList()); List respCodes = responsibilityCodeAndNames.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList()); Map titleMap = new HashMap<>(); for (int i = 0; i < titleData.size(); i++) { titleMap.put(i + 1, titleData.get(i)); } List> realDatas = new ArrayList<>(); List accountCodes = accountCodeAndNames.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList()); for (CodeAndNameVO account : accountCodeAndNames) { Map map = new HashMap<>(); for (int i = 0; i < responsibilityCodeAndNames.size(); i++) { if (i == 0) { map.put(i + 1, account.getName()); continue; } else if (i == responsibilityCodeAndNames.size() - 1) { // todo 计算最右侧合计的钱 BigDecimal amount = allocationQueryService.getTotalByAccountAndResps(hospId, dateYear, month, account.getCode(), respCodes); map.put(i + 1, amount); continue; } // TODO: 2021/8/26 计算 中间的钱 BigDecimal amount = allocationQueryService.getTotalByAccountAndRespCode(hospId, dateYear, month, account.getCode(), respCodes.get(i)); map.put(i + 1, amount); } realDatas.add(map); } // 尾栏计算 Map map = new HashMap<>(); for (int i = 0; i < titleData.size(); i++) { if (i == 0) { map.put(i + 1, "合计"); continue; } else if (i == titleData.size() - 1) { // TODO: 2021/8/26 计算 BigDecimal bigDecimal = allocationQueryService.getTotalMoney(dateYear, month, hospId); map.put(i + 1, bigDecimal); continue; } BigDecimal bigDecimal = allocationQueryService.getCountByRespAndAccounts(hospId, dateYear, month, responsibilityCodeAndNames.get(i).getCode(), accountCodes); map.put(i + 1, bigDecimal); } return new CollectDataFormVO(titleMap, realDatas, map); } /** * 分摊后报表输出 * * @param date yyyy-MM-dd * @param hospId 医院id * @return List */ @Override public List afterAllocationFormList(String date, Long hospId) { DateTime parse = DateUtil.parse(date); int year = DateUtil.year(parse); int month = DateUtil.month(parse) + 1; // 得到这个月的分摊过的分摊层级 List list = baseMapper.getAllSortLevel(hospId, year, month); // list. List vos = list.stream().map(i -> { AfterAllocationFormVO vo = new AfterAllocationFormVO(); vo.setId(i.getId()); vo.setYear(i.getDateYear()); vo.setMonth(i.getDateMonth()); vo.setShareLevel(i.getLevelSort()); vo.setShareReportName(i.getShareParamName() + "分摊"); vo.setShareTime(DateUtil.date(i.getCreateTime())); vo.setShareLevelId(i.getShareLevelId()); return vo; }).collect(Collectors.toList()); return vos; } /** * 按时间计算分摊数据 * * @param year 年月 * @param month 月 * @param hospId * @param levelSorts * @return */ @Override public List getByDate(int year, int month, Long hospId, List levelSorts) { return this.list( new LambdaQueryWrapper() .eq(Allocation::getDateYear, year) .eq(Allocation::getDateMonth, month) .eq(Allocation::getHospId, hospId) .in(Allocation::getLevelSort, levelSorts) ); } }