package com.kcim.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.kcim.common.constants.NumberConstant; import com.kcim.common.constants.SQLParameter; import com.kcim.common.enums.CustomSqlTypeEnum; import com.kcim.common.exception.CostException; import com.kcim.common.util.BeanUtil; import com.kcim.common.util.JacksonUtil; import com.kcim.common.util.PageUtils; import com.kcim.common.util.UserContext; import com.kcim.dao.mapper.AllocationMapper; import com.kcim.dao.model.*; import com.kcim.dao.model.dto.StartDTO; import com.kcim.dao.repository.ResponsibilityRepository; import com.kcim.service.*; import com.kcim.vo.*; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Sheet; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; 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; private final ResponsibilityRepository responsibilityRepository; private final CenterService centerService; private final SqlService sqlService; public AllocationServiceImpl(CostCostingGroupService costCostingGroupService, CostShareLevelService shareLevelService, ResponsibilityService responsibilityService, CostAccountShareService accountShareService, ShareParamValueService shareParamValueService, CostShareParamService shareParamService, AllocationQueryService allocationQueryService, ResponsibilityRepository responsibilityRepository, CenterService centerService, SqlService sqlService) { this.costCostingGroupService = costCostingGroupService; this.shareLevelService = shareLevelService; this.responsibilityService = responsibilityService; this.accountShareService = accountShareService; this.shareParamValueService = shareParamValueService; this.shareParamService = shareParamService; this.allocationQueryService = allocationQueryService; this.responsibilityRepository = responsibilityRepository; this.centerService = centerService; this.sqlService = sqlService; } /** * 分摊成本数据 * * @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 costShareParamList = shareParamService.getAll(hospId); if (CollUtil.isEmpty(costShareParamList)) { throw new CostException("请先设置分摊参数字典"); } Map ShareParamNameMap = costShareParamList.stream().collect(Collectors.toMap(CostShareParamVO::getShareParamCode, CostShareParamVO::getShareParamName, (a, b) -> b)); //责任中心 List responsibilityList = responsibilityRepository.getList(hospId); if (CollUtil.isEmpty(responsibilityList)) { throw new CostException("请先设置责任中心"); } //按shareId分组 Map> responsibilityShareIdMap = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getShareId)); Map responsibilityNameMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName, (a, b) -> b)); Map responsibilityShareIdDictMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getShareId, (a, b) -> b)); //分摊参数对应 List accountShareList = accountShareService.getAll(); if (CollUtil.isEmpty(accountShareList)) { throw new CostException("请先设置责任中心分摊参数对应"); } Map> accountShareResponsibilityMap = accountShareList.stream().collect(Collectors.groupingBy(CostAccountShare::getResponsibilityCode)); 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 = responsibilityShareIdMap.get(levelId); // List responsibilities = responsibilityService.getLevelIdByCode(levelId, hospId); // if (responsibilities.isEmpty()) { // continue; // } if(CollectionUtils.isEmpty(responsibilities)){ continue; } // 优化 // 遍历责任中心得到对应的分摊参数对应 for (Responsibility responsibility : responsibilities) { // String responsibilityCode = responsibility.getResponsibilityCode(); // 得到分摊参数对应记录,不存在,下一个 List accountShares = accountShareResponsibilityMap.get(responsibility.getResponsibilityCode()); // List accountShares = accountShareService.getByResponsibility(responsibilityCode, hospId); if (CollectionUtils.isEmpty(accountShares)) { continue; } // 遍历分摊参数对应记录 for (CostAccountShare accountShare : accountShares) { Long accountShareId = accountShare.getId(); String paramList = accountShare.getParamList(); // 如果分摊比例未设置直接报错 if (StrUtil.isBlank(paramList)) { throw new CostException("责任中心:" + accountShare.getResponsibilityName() + ";会计科目为:" + accountShare.getAccountingNames() + ";未设置分摊参数比例"); } List accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class); // List groups = responsibilityCodeMap.get(responsibilityCode); // if (CollUtil.isEmpty(groups)) { // continue; // } // 计算本次分摊的钱 BigDecimal totalAmount = this.getCostAmount(accountShare, calcType, responsibilityCodeMap, costList); if (totalAmount.equals(BigDecimal.ZERO)) { continue; } // 相关的分摊参数比例 if (!CollectionUtils.isEmpty(accountShareVOs)) { for (AccountShareVO accountShareVO : accountShareVOs) { // String paramCode = accountShareVO.getShareParamCode(); String shareParamPopout = accountShareVO.getShareParamPopout(); BigDecimal bigDecimal = new BigDecimal(shareParamPopout); BigDecimal rate = bigDecimal.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP); // 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 targetShareParamValue = getTarget(targetResponsibilities, accountShareVO, paramValueRespCodeMap); if (CollUtil.isEmpty(targetShareParamValue)) { throw new CostException("找不到目标责任中心对应的分摊参数【"+accountShareVO.getShareParamCode()+"】值"); } // 分母 BigDecimal reduce = targetShareParamValue.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add); for (ShareParamValue paramValue : targetShareParamValue) { // 分子 BigDecimal numerator = paramValue.getValueNum(); BigDecimal targetAmount = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : thisAmount.multiply(numerator).divide(reduce, RoundingMode.HALF_UP); BigDecimal percent = reduce.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : numerator.divide(reduce, RoundingMode.HALF_UP); Allocation targetAllocation = new Allocation(); String valueResponsibilityCode = paramValue.getResponsibilityCode(); //优化循环调用 String targetRespName = responsibilityNameMap.get(valueResponsibilityCode); // String targetRespName = responsibilityService.getByCode(valueResponsibilityCode, hospId); Long targetShareLevelId = responsibilityShareIdDictMap.get(valueResponsibilityCode); // Long targetShareLevelId = responsibilityService.getLevelIdByCode(valueResponsibilityCode, hospId); if (Objects.isNull(targetShareLevelId)) { throw new CostException("目标责任中心分摊层级异常"); } String shareParamName = ShareParamNameMap.get(paramValue.getShareParamCode()); // 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(percent).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, hospId, startDTO.getYear(), startDTO.getMonth(),shareLevelVOs,accountShareList); Map sqlParameter = new HashMap<>(); if(startDTO.getMonth()<10){ sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE,startDTO.getYear()+"-0"+startDTO.getMonth()); }else{ sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE,startDTO.getYear()+"-"+startDTO.getMonth()); } sqlService.autoExecuteSql(CustomSqlTypeEnum.COST_ALLOCATION_CALC.getCode(),sqlParameter); } 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, Long hospId, Integer year, Integer month, List shareLevelVOs, List accountShareList) { List saveList = new ArrayList<>(); List maxId = shareLevelService.getMaxId(hospId); // List maxList = list.stream().filter(i -> maxId.contains(i.getTargetShareLevelId())).collect(Collectors.toList()); Map> collect = list.stream().collect(Collectors.groupingBy(Allocation::getTargetShareLevelId)); //优化 去除循环调用 // List all = accountShareService.getAll(); Map accountShareMap = accountShareList.stream().collect(Collectors.toMap(CostAccountShare::getId, costAccountShare -> costAccountShare, (a, b) -> b)); // 得到这个月的所有导入的成本数据用责任中心关联取得shareId 优化 去除循环调用 List costingGroups = costCostingGroupService.getRealData(CollUtil.newArrayList(), hospId, year, month); Map> costShareIdGroup = costingGroups.stream().collect(Collectors.groupingBy(CostCostingGroup::getShareId)); for (CostShareLevelVO shareLevelVO : shareLevelVOs) { List allocations = collect.get(shareLevelVO.getId()); if(!CollectionUtils.isEmpty(allocations)){ setAfterAllocation(allocations, hospId, saveList,accountShareMap); } if(!CollectionUtils.isEmpty(costShareIdGroup.get(shareLevelVO.getId()))){ setPreAllocation(hospId,saveList,shareLevelVO,costShareIdGroup.get(shareLevelVO.getId())); } } allocationQueryService.saveBatch(saveList); } private void setPreAllocation(Long hospId, List saveList, CostShareLevelVO shareLevelVO, List costingGroups) { // List costingGroups = costCostingGroupService.getRealData(CollUtil.newArrayList(maxId), hospId, year, month); costingGroups.forEach(i -> { 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(i.getAccountCode()).setAccountingName(i.getAccountName()) .setCreateTime(System.currentTimeMillis()) .setLevelSort(shareLevelVO.getLeverSort()).setLevelName(shareLevelVO.getShareName()) .setTargetResponsibilityCode(i.getResponsibilityCode()) .setTargetResponsibilityName(i.getResponsibilityName()) .setShareLevelId(0L); saveList.add(allocationQuery); }); } private void setAfterAllocation(List list, Long hospId, List saveList, Map accountShareMap) { list.forEach(i -> { Long accountShareId = i.getAccountShareId(); CostAccountShare byId = accountShareMap.get(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(2L).setAmount(i.getAmount()) .setAccountingCode(accountingCodes).setAccountingName(accountingNames) .setCreateTime(System.currentTimeMillis()) .setLevelSort(i.getLevelSort()).setLevelName(i.getLevelName()) .setTargetResponsibilityCode(i.getTargetResponsibilityCode()) .setTargetResponsibilityName(i.getTargetResponsibilityName()) .setShareLevelId(i.getShareLevelId()); saveList.add(allocationQuery); }); } /** * 得到目标月成本分摊参数值数据 * * @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)) { List all = costList.stream().filter(i -> i.getTargetResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList()); if (CollUtil.isEmpty(all) || isShareCost == 0) { return BigDecimal.ZERO; } BigDecimal reduce = all.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); return reduce; } else { 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::add); 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::add); 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) { // 获取数据 Map> targetTotalMoneys = new HashMap<>(); List allocationReportVOList = getAllocationReportVOS(levelSort, year, month, shareLevelId,targetTotalMoneys); // 设置导出 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)); // 当前责任中心下面有几个会计科目 后面进行合并使用 final int[] numResponsibility = new int[1]; levelSort=levelSort+1; // // 从第几列开始编写数据 final int[] column = {levelSort + 3}; responsibilityMap.forEach((key,value)->{ Map linkedHashMap = new LinkedHashMap<>(); value.forEach(i -> { String s = i.getResponsibilityCode() + i.getAccountCode(); if (!linkedHashMap.containsKey(s)) { linkedHashMap.put(s, i); } }); numResponsibility[0] = linkedHashMap.size(); if (numResponsibility[0] >= NumberConstant.TWO) { Set strings = linkedHashMap.keySet(); for (String s : strings) { AllocationReportVO allocationReportVO = linkedHashMap.get(s); if (StrUtil.isBlank(allocationReportVO.getAlias())) { writer.writeCellValue(column[0], 0, allocationReportVO.getResponsibilityName()); // 别名不存在 writer.writeCellValue(column[0], 1, allocationReportVO.getAccountName()); } else { // 不为空 设置别名 writer.writeCellValue(column[0], 0, allocationReportVO.getResponsibilityName()); writer.writeCellValue(column[0], 1, allocationReportVO.getAlias()); } writer.writeCellValue(column[0], 2, allocationReportVO.getTotalAmounts()); column[0]++; } } else { // 不需要合并单元格 writer.writeCellValue(column[0], 0, value.get(0).getResponsibilityName()); if (StrUtil.isNotBlank(value.get(0).getAlias())) { writer.writeCellValue(column[0], 1, value.get(0).getAlias()); } else { writer.writeCellValue(column[0], 1, value.get(0).getAccountName()); } writer.writeCellValue(column[0], 2, value.get(0).getTotalAmounts()); column[0]++; } }); // 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[0] = linkedHashMap.size(); // if (numResponsibility[0] >= NumberConstant.TWO) { // Set strings = linkedHashMap.keySet(); // for (String s : strings) { // AllocationReportVO allocationReportVO = linkedHashMap.get(s); // if (StrUtil.isBlank(allocationReportVO.getAlias())) { // writer.writeCellValue(column[0], 0, allocationReportVO.getResponsibilityName()); // // 别名不存在 // writer.writeCellValue(column[0], 1, allocationReportVO.getAccountName()); // } else { // // 不为空 设置别名 // writer.writeCellValue(column[0], 0, allocationReportVO.getResponsibilityName()); // writer.writeCellValue(column[0], 1, allocationReportVO.getAlias()); // } // writer.writeCellValue(column[0], 2, allocationReportVO.getTotalAmounts()); // column[0]++; // } // } else { // // 不需要合并单元格 // writer.writeCellValue(column[0], 0, allocationReportVOS.get(0).getResponsibilityName()); // if (StrUtil.isNotBlank(allocationReportVOS.get(0).getAlias())) { // writer.writeCellValue(column[0], 1, allocationReportVOS.get(0).getAlias()); // } else { // writer.writeCellValue(column[0], 1, allocationReportVOS.get(0).getAccountName()); // } // writer.writeCellValue(column[0], 2, allocationReportVOS.get(0).getTotalAmounts()); // column[0]++; // } // } // 设置单元格合并 for (int j = 1; j < levelSort; j++) { writer.merge(0, 1, j, j, "第" + j + "次分摊", false); } // 目标责任集合 writer.passCurrentRow(); // 从第三行开始 int num = 3; Set targetSet = targetResponsibilityMap.keySet(); int t = 0; 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); // 设置第几次分摊的值 List targetShareMoneyList = targetTotalMoneys.get(target); // for (int k = 0; k < levelSort - 1; k++) { // writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, costCostingVO.getTargetShareMoneys().get(t++), false); // // } for (int k = 0; k < levelSort - 1; k++) { Object allocationAmount = getAllocationAmount(levelSort, k, allocationReportVOS, targetShareMoneyList); writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, allocationAmount, false); } // if(!CollectionUtils.isEmpty(targetShareMoneyList)){ // for (int k = 0; k < levelSort - 1; k++) { // if(k==levelSort-2){ // BigDecimal totalAmount = allocationReportVOS.stream().map(AllocationReportVO::getAmount) // .reduce(BigDecimal.ZERO, BigDecimal::add); // writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, totalAmount, false); // }else { // writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, targetShareMoneyList.get(k), false); // } // } // }else { // for (int k = 0; k < levelSort - 1; k++) { // if(k==levelSort-2){ // BigDecimal totalAmount = allocationReportVOS.stream().map(AllocationReportVO::getAmount) // .reduce(BigDecimal.ZERO, BigDecimal::add); // writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, totalAmount, false); // }else { // writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, "0.0000", 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[0]; 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)); // } List targetShareMoneyList = targetTotalMoneys.get(target); for (int k = 0; k < levelSort - 1; k++) { Object allocationAmount = getAllocationAmount(levelSort, k, allocationReportVOS, targetShareMoneyList); writer.writeCellValue(k + 1, num, allocationAmount); } // if(!CollectionUtils.isEmpty(targetShareMoneyList)){ // for (int k = 0; k < levelSort - 1; k++) { // if(k==levelSort-2){ // BigDecimal totalAmount = allocationReportVOS.stream().map(AllocationReportVO::getAmount) // .reduce(BigDecimal.ZERO, BigDecimal::add); // writer.writeCellValue(k + 1, num, totalAmount); // }else { // writer.writeCellValue(k + 1, num, targetShareMoneyList.get(k)); // } // } // }else { // for (int k = 0; k < levelSort - 1; k++) { // if(k==levelSort-2){ // BigDecimal totalAmount = allocationReportVOS.stream().map(AllocationReportVO::getAmount) // .reduce(BigDecimal.ZERO, BigDecimal::add); // writer.writeCellValue(k + 1, num, totalAmount); // }else { // writer.writeCellValue(k + 1, num, "0.0000"); // } // } // } 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 + 3; m < column[0]; 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[0] - 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)) { if (cc != m) { writer.merge(0, 0, cc, m, cellValue1, false); } else { writer.writeCellValue(cc, 0, cellValue1); } cc = m + 1; } else if (m == column[0] - 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)) { if (jj != i) { writer.merge(jj, i, 0, 0, cellValue1, false); } else { writer.writeCellValue(0, jj, cellValue1); } 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 index * @param allocationReportVOS * @param targetShareMoneyList * @return */ public Object getAllocationAmount(int levelSort,int index,List allocationReportVOS,List targetShareMoneyList){ //当前层级取分摊金额加总 if(index==levelSort-2){ BigDecimal totalAmount = allocationReportVOS.stream().map(AllocationReportVO::getAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); return totalAmount; } //取不到对应层级的分摊总金额 if(CollectionUtils.isEmpty(targetShareMoneyList)||targetShareMoneyList.size()<=index){ return BigDecimal.valueOf(NumberConstant.ZERO,NumberConstant.FOUR); } //取对应层级的分摊总金额 return targetShareMoneyList.get(index); } /** * 查询数据 * * @param levelSort * @param year * @param month * @param targetTotalMoneys * @return */ private List getAllocationReportVOS(Integer levelSort, Integer year, Integer month, Long shareLevelId, Map> targetTotalMoneys) { Long hospId = UserContext.getCurrentLoginHospId(); 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.getTargetResponsibilityCode())); 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); List shareParamVOList = shareParamService.getAll(hospId); Map shareParamStatusMap = shareParamVOList.stream().collect(Collectors.toMap(CostShareParamVO::getShareParamCode, paramVO -> paramVO.getStatus() == null ? NumberConstant.ONE : paramVO.getStatus(), (a, b) -> b)); List removeList = new ArrayList<>(); // 设置会计科目的 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) { List targetMoney = new ArrayList<>(); for (int j = 1; j < levelSort; j++) { // 每一次计算要设置为0 AtomicReference money = new AtomicReference<>(new BigDecimal("0.0000")); List allocations1 = accrepMap.get(j + "cost" + i.getTargetResponsibilityCode()); if (CollUtil.isNotEmpty(allocations1)) { allocations1.forEach(m -> { money.updateAndGet(v -> v.add(m.getAmount())); // System.out.println(m.getAmount()); }); } else { // TODO 封装测试数据 shareMoney.add("0"); } // System.out.println("第"+j+"次"+money); shareMoney.add(money.toString()); targetMoney.add(money.toString()); } if(!CollectionUtils.isEmpty(targetTotalMoneys)){ List strings = targetTotalMoneys.get(i.getTargetResponsibilityCode()); if(CollectionUtils.isEmpty(strings)){ targetTotalMoneys.put(i.getTargetResponsibilityCode(),targetMoney); } }else { targetTotalMoneys.put(i.getTargetResponsibilityCode(),targetMoney); } } i.setTargetShareMoneys(shareMoney); // 设置字符串类型数据 i.setTotalAmounts(i.getTotalAmount().toString()); i.setShareParamValueNums(i.getShareParamValueNum().toString()); i.setShareParamRates(i.getShareParamRate().toString()); i.setAmounts(i.getAmount().toString()); //校验是否有分摊参数未启用 Integer status = shareParamStatusMap.get(i.getShareParamCode()); if(status != null&&status.equals(NumberConstant.ZERO)){ removeList.add(i); } }); //校验是否有分摊参数未启用 未启用分摊参数 移除 if(!CollectionUtils.isEmpty(removeList)){ allocationReportVOList.removeAll(removeList); } 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); Map map = shareLevelService.list(new QueryWrapper().lambda().eq(CostShareLevel::getHospId, hospId)).stream().collect(Collectors.toMap(CostShareLevel::getId, synOne -> synOne)); // 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(map.get(i.getShareLevelId()).getShareName() + "分摊"); vo.setShareTime(DateUtil.date(i.getCreateTime())); vo.setShareLevelId(i.getShareLevelId()); return vo; }).collect(Collectors.toList()); return vos; } /** * 按时间计算分摊数据 * * @param year 年月 * @param month 月 * @param hospId * @return */ @Override public List getByDate(int year, int month, Long hospId) { return this.list( new LambdaQueryWrapper() .eq(Allocation::getDateYear, year) .eq(Allocation::getDateMonth, month) .eq(Allocation::getHospId, hospId) ); } }