Selaa lähdekoodia

优化分摊计算的逻辑

JammeyJiang 1 kuukausi sitten
vanhempi
commit
c00def9e81
1 muutettua tiedostoa jossa 272 lisäystä ja 55 poistoa
  1. 272 55
      src/main/java/com/kcim/service/impl/AllocationServiceImpl.java

+ 272 - 55
src/main/java/com/kcim/service/impl/AllocationServiceImpl.java

@@ -33,11 +33,13 @@ 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.ObjectUtils;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -120,6 +122,11 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
         if (respParamValueList.isEmpty()) {
             throw new CostException("本月成本分摊参数值未导入");
         }
+        Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup = respParamValueList.stream()
+                .collect(Collectors.groupingBy(
+                        ShareParamValue::getResponsibilityCode,
+                        Collectors.groupingBy(ShareParamValue::getShareParamCode)
+                ));
         // 得到这个医院所有的分摊层级列表排序
         List<CostShareLevelVO> shareLevelVOs = shareLevelService.getAll(hospId);
         if (CollUtil.isEmpty(shareLevelVOs)) {
@@ -177,8 +184,8 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
         List<Allocation> allocationCostList=new ArrayList<>();
         //逐级分摊
         for (CostShareLevelVO shareLevelVO : shareLevelVOs) {
-            List<Allocation> shareLevelAllocationList = allocationShareLevelCost(startDTO, shareLevelVO, responsibilityList, responsibilityShareIdMap, respDirectCostMap, respParamValueList,
-                    accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap, costAccountShareTargetMap,allocationCostList, timeMillis);
+            List<Allocation> shareLevelAllocationList = allocationShareLevelCost(startDTO, shareLevelVO, responsibilityList, responsibilityShareIdMap, respDirectCostMap, respParamValueGroup,
+                    accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap, costAccountShareTargetMap,allocationCostList, timeMillis,hospId);
             allocationCostList.addAll(shareLevelAllocationList);
         }
         //没有任何分摊数据
@@ -194,6 +201,19 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
         applyAllocationQuery(startDTO,respDirectCostMap,allocationCostList,responsibilityCodeMap);
     }
 
+    public void batchSaveAllocation(List<Allocation> allocationList) {
+        if (CollUtil.isEmpty(allocationList)) {
+            return;
+        }
+        // 调整批次大小,根据数据库性能测试确定最佳值
+        int batchSize = 5000;
+        // 分批次保存
+        for (int i = 0; i < allocationList.size(); i += batchSize) {
+            int end = Math.min(i + batchSize, allocationList.size());
+            this.saveBatch(allocationList.subList(i, end));
+        }
+    }
+
     /**
      * 一个分摊层级的分摊计算
      * @param startDTO 分摊年月所在对象
@@ -201,7 +221,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
      * @param responsibilityList 责任中心字典
      * @param responsibilityShareIdMap 各分摊层级的责任中心
      * @param respDirectCostMap 直接成本
-     * @param respParamValueList 分摊参数数值
+     * @param respParamValueGroup 分摊参数数值
      * @param accountShareResponsibilityMap 分摊参数对应
      * @param costAccountShareParamMap 分摊设置对应的分摊参数
      * @param costAccountShareDetailMap 分摊设置对应的会计科目
@@ -213,13 +233,13 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
                                                      List<Responsibility> responsibilityList,
                                                      Map<Long, List<Responsibility>> responsibilityShareIdMap,
                                                      Map<String, List<CostCostingGroup>> respDirectCostMap ,
-                                                     List<ShareParamValue> respParamValueList,
+                                                     Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup,
                                                      Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
                                                      Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
                                                      Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
                                                      Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
                                                      List<Allocation> allocationCostList,
-                                                     long timeMillis){
+                                                     long timeMillis, Long hospId){
         //分摊成本列表
         List<Allocation> allocationList=new ArrayList<>();
         // 分摊层级id
@@ -241,15 +261,22 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             return allocationList;
         }
 
-        //目标责任中心列表
-        List<Responsibility> targetResponsibilityList = responsibilityList.stream().filter(responsibility -> targetLevelList.contains(String.valueOf(responsibility.getShareLevel()))).collect(Collectors.toList());
-        if (CollectionUtils.isEmpty(targetResponsibilityList)) {
+        //目标责任中心列表 - 优化:预先创建Map以提高查找效率
+        Map<String, Responsibility> targetResponsibilityMap = responsibilityList.stream()
+                .filter(responsibility -> targetLevelList.contains(String.valueOf(responsibility.getShareLevel())))
+                .collect(Collectors.toMap(Responsibility::getResponsibilityCode, Function.identity(), (a, b) -> a));
+
+        if (targetResponsibilityMap.isEmpty()) {
             throw new CostException(String.format("[%s-%s]的分摊目标层级没有对应的责任中心",shareLevelVO.getLeverSort(),shareLevelVO.getShareName()));
         }
 
+        // 优化:预先创建间接成本的Map以提高查找效率
+        Map<String, List<Allocation>> indirectCostMap = allocationCostList.stream()
+                .collect(Collectors.groupingBy(Allocation::getTargetResponsibilityCode));
+
         // 按责任中心逐个开始分摊(并行)
-        allocationList = responsibilities.parallelStream().flatMap(responsibility ->  allocationResponsibilityCost(startDTO, shareLevelVO, responsibility, targetResponsibilityList, respDirectCostMap, respParamValueList,
-                    accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap,costAccountShareTargetMap, allocationCostList, timeMillis).stream()).collect(Collectors.toList());
+        allocationList = responsibilities.parallelStream().flatMap(responsibility ->  allocationResponsibilityCost(startDTO, shareLevelVO, responsibility, targetResponsibilityMap, respDirectCostMap, respParamValueGroup,
+                    accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap,costAccountShareTargetMap, indirectCostMap, timeMillis,hospId).stream()).collect(Collectors.toList());
         return allocationList;
     }
 
@@ -260,25 +287,25 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
      * @param shareLevelVO 分摊层级
      * @param responsibility 责任中心
      * @param respDirectCostMap 直接成本
-     * @param respParamValueList 分摊参数数值
+     * @param respParamValueGroup 分摊参数数值
      * @param accountShareResponsibilityMap 分摊参数对应
      * @param costAccountShareParamMap 分摊设置对应的分摊参数
      * @param costAccountShareDetailMap 分摊设置对应的会计科目
-     * @param allocationCostList 间接成本
+     * @param indirectCostMap 间接成本
      * @param timeMillis 时间戳
      */
     public List<Allocation> allocationResponsibilityCost(StartDTO startDTO,
                                              CostShareLevelVO shareLevelVO,
                                              Responsibility responsibility,
-                                             List<Responsibility> targetResponsibilityList,
+                                             Map<String, Responsibility> targetResponsibilityMap ,
                                              Map<String, List<CostCostingGroup>> respDirectCostMap ,
-                                             List<ShareParamValue> respParamValueList,
+                                             Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup,
                                              Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
                                              Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
                                              Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
                                              Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
-                                             List<Allocation> allocationCostList,
-                                             long timeMillis){
+                                             Map<String, List<Allocation>> indirectCostMap,
+                                             long timeMillis, Long hospId){
         //分摊结果列表
         List<Allocation> allocationList=new ArrayList<>();
         // 得到分摊参数对应记录,不存在,下一个
@@ -293,7 +320,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             throw new CostException(String.format("[%s-%s]的分摊设置有问题,合并计算的责任中心只允许设置一个分摊配置",responsibility.getResponsibilityCode(),responsibility.getResponsibilityName()));
         }
         //间接成本
-        List<Allocation> respIndirectCostList = allocationCostList.stream().filter(allocationCost -> allocationCost.getTargetResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
+        List<Allocation> respIndirectCostList =indirectCostMap.get(responsibility.getResponsibilityCode());
         //直接成本
         List<CostCostingGroup> respDirectCostList = respDirectCostMap.get(responsibility.getResponsibilityCode());
         //按分摊设置逐个计算
@@ -303,7 +330,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             //分摊设置对应的间接成本
             List<Allocation> paramIndirectCostList=new ArrayList<>();
             //获取分摊设置对应的目标责任中心
-            List<Responsibility> shareTargetRespCodeList = getShareTargetResponsibility(accountShare, targetResponsibilityList, costAccountShareTargetMap);
+            List<Responsibility> shareTargetRespCodeList = getShareTargetResponsibility(accountShare, targetResponsibilityMap, costAccountShareTargetMap);
             //所有目标责任中心的责任中心代码列表
             List<String> targetResponsibilityCodeList = shareTargetRespCodeList.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
             //合并计算
@@ -328,45 +355,78 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             //按分摊参数逐个计算所有目标责任中心的分摊金额
             for (CostAccountShareParam shareParam : costAccountShareParams) {
                 //获取所有目标责任中心的分摊参数数值信息
-                List<ShareParamValue> targetResponsibilityParamList = respParamValueList.stream().filter(respParamValue -> shareParam.getShareParamCode().equals(respParamValue.getShareParamCode())
-                        && targetResponsibilityCodeList.contains(respParamValue.getResponsibilityCode())).collect(Collectors.toList());
+                List<ShareParamValue> targetResponsibilityParamList =getTargetResponsibilityParamList( respParamValueGroup,targetResponsibilityCodeList,shareParam);
                 if(CollectionUtils.isEmpty(targetResponsibilityParamList)){
                     throw new CostException(String.format("[%s-%s]的目标责任中心找不到对应的参数数值,无法继续分摊",responsibility.getResponsibilityName(),shareParam.getShareParamName()));
                 }
                 //按分摊参数计算每个会计科目分摊到的金额
                 List<Allocation> allocationParamCosts = allocationParamCostCalc(startDTO, shareLevelVO, responsibility, shareTargetRespCodeList, paramDirectCostList,
-                        paramIndirectCostList, accountShares.get(NumberConstant.ZERO), shareParam, targetResponsibilityParamList, timeMillis);
+                        paramIndirectCostList, accountShares.get(NumberConstant.ZERO), shareParam, targetResponsibilityParamList, timeMillis, hospId);
                 allocationList.addAll(allocationParamCosts);
             }
         }
         return allocationList;
     }
 
+    /**
+     * 获取所有目标责任中心的分摊参数数值信息
+     * @param respParamValueGroup
+     * @param targetResponsibilityCodeList
+     * @param shareParam
+     * @return
+     */
+    public List<ShareParamValue> getTargetResponsibilityParamList(
+            Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup,
+            List<String> targetResponsibilityCodeList,
+            CostAccountShareParam shareParam) {
+
+        List<ShareParamValue> targetResponsibilityParamList = new ArrayList<>();
+        String shareParamCode = shareParam.getShareParamCode();
+
+        for (String targetResponsibilityCode : targetResponsibilityCodeList) {
+            Map<String, List<ShareParamValue>> shareParamValueMap = respParamValueGroup.get(targetResponsibilityCode);
+            if (shareParamValueMap != null) {
+                List<ShareParamValue> shareParamValues = shareParamValueMap.get(shareParamCode);
+                if (shareParamValues != null) {
+                    targetResponsibilityParamList.addAll(shareParamValues);
+                }
+            }
+        }
+        return targetResponsibilityParamList;
+    }
+
+
     /**
      * 获取分摊设置的目标责任中心
      * @param accountShare
-     * @param levelTargetResponsibility
+     * @param levelTargetResponsibilityMap
      * @param costAccountShareTargetMap
      * @return
      */
     public List<Responsibility> getShareTargetResponsibility(CostAccountShare accountShare,
-                                                             List<Responsibility> levelTargetResponsibility,
+                                                             Map<String, Responsibility> levelTargetResponsibilityMap,
                                                              Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap){
         //获取分摊设置对应的目标责任中心
         List<CostAccountShareTarget> shareTargetResponsibilityList=costAccountShareTargetMap.get(accountShare.getId());
         if(CollectionUtils.isEmpty(shareTargetResponsibilityList)){
-            return levelTargetResponsibility;
+            return new ArrayList<>(levelTargetResponsibilityMap.values());
         }
         //筛选出指定的目标责任中心
         List<String> shareTargetRespCodeList = shareTargetResponsibilityList.stream().map(CostAccountShareTarget::getTargetResponsibilityCode).collect(Collectors.toList());
-        List<Responsibility> shareTargetRespList = levelTargetResponsibility.stream().filter(responsibility -> shareTargetRespCodeList.contains(responsibility.getResponsibilityCode())).collect(Collectors.toList());
+        List<Responsibility> shareTargetRespList = new ArrayList<>();
+        for (String shareTargetRespCode : shareTargetRespCodeList) {
+            Responsibility levelTargetResponsibility = levelTargetResponsibilityMap.get(shareTargetRespCode);
+            if (levelTargetResponsibility == null) {
+                continue;
+            }
+            shareTargetRespList.add(levelTargetResponsibility);
+        }
         if(CollectionUtils.isEmpty(shareTargetRespList)){
             throw new CostException(String.format("[%s-%s]找不到对应的目标责任中心,无法继续分摊",accountShare.getResponsibilityName(),accountShare.getAlias()));
         }
         return shareTargetRespList;
     }
 
-
     /**
      * 按分摊参数计算每个会计科目分摊到的金额
      * @param startDTO 分摊年月所在对象
@@ -390,7 +450,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
                                                CostAccountShare costAccountShare,
                                                CostAccountShareParam shareParam,
                                                List<ShareParamValue> targetResponsibilityParamList,
-                                               long timeMillis){
+                                               long timeMillis, Long hospId){
         //重新定义一个列表用于合并直接成本和间接成本
         List<CostCostingGroup> respCostList=new ArrayList<>();
         //添加直接成本
@@ -410,46 +470,203 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
         }
         //按责任中心分组,方便取到对应责任中心的分摊参数数值
         Map<String, List<ShareParamValue>> targetRespParamGroup = targetResponsibilityParamList.stream().collect(Collectors.groupingBy(ShareParamValue::getResponsibilityCode));
+        //创建accountCode到accountName的映射
+        Map<String, String> accountCodeNameMap = respCostList.stream().collect(Collectors.toMap(CostCostingGroup::getAccountCode,
+                CostCostingGroup::getAccountName,
+                (existing, replacement) -> replacement // 处理重复键的情况,保留最后一个值
+                ));
         //按会计科目分组,相同会计科目一起分摊
-        Map<String, List<CostCostingGroup>> respDirectCostGroup = respCostList.stream().collect(Collectors.groupingBy(CostCostingGroup::getAccountCode));
+        Map<String, BigDecimal> respDirectCostGroup = respCostList.stream().collect(Collectors.groupingBy(CostCostingGroup::getAccountCode,
+                        Collectors.reducing(BigDecimal.ZERO,CostCostingGroup::getAmount,BigDecimal::add)));
+        //参数占比
+        BigDecimal paramRate = shareParam.getShareParamProportion().divide(new BigDecimal(NumberConstant.ONE_HUNDRED), NumberConstant.FOUR, RoundingMode.HALF_UP);
         //分摊结果列表
         List<Allocation> allocationList=new ArrayList<>();
-        // 按会计科目进行分摊计算
-        respDirectCostGroup.forEach((accountCode, costCostingGroups) -> {
-            //会计科目总金额
-            BigDecimal totalAmount = costCostingGroups.stream().map(CostCostingGroup::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
-            //没有金额的项目不需要做分摊处理
-            if (NumberConstant.ZERO.equals(totalAmount.compareTo(BigDecimal.ZERO))){
-                return;
+        for (Responsibility targetResponsibility : targetResponsibilityList){
+            List<ShareParamValue> targetRespParamValues = targetRespParamGroup.get(targetResponsibility.getResponsibilityCode());
+            //目标责任中心的分摊参数数值
+            BigDecimal targetRespParamValue = BigDecimal.ZERO;
+            if(!CollectionUtils.isEmpty(targetRespParamValues)) {
+                targetRespParamValue = targetRespParamValues.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+            //没有参数数值就不分摊计算了,不然数据会很多
+            if(NumberConstant.ZERO.equals(BigDecimal.ZERO.compareTo(targetRespParamValue))){
+                continue;
             }
-            for (Responsibility targetResponsibility : targetResponsibilityList) {
-                List<ShareParamValue> targetRespParamValues = targetRespParamGroup.get(targetResponsibility.getResponsibilityCode());
-                //目标责任中心的分摊参数数值
-                BigDecimal targetRespParamValue = BigDecimal.ZERO;
-                if(!CollectionUtils.isEmpty(targetRespParamValues)) {
-                    targetRespParamValue = targetRespParamValues.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add);
+            //计算分摊参数比例
+            BigDecimal shareParamRate =  targetRespParamValue.divide(totalParamValue, NumberConstant.FOUR, RoundingMode.HALF_UP);
+
+            for (Map.Entry<String, BigDecimal> entry : respDirectCostGroup.entrySet()) {
+                String accountCode = entry.getKey();
+                BigDecimal totalAmount = entry.getValue();
+                //没有金额的会计科目就不分摊计算了,不然数据会很多
+                if(NumberConstant.ZERO.equals(BigDecimal.ZERO.compareTo(totalAmount))){
+                    continue;
                 }
-                //计算分摊参数比例
-                BigDecimal shareParamRate =  targetRespParamValue.divide(totalParamValue, NumberConstant.FOUR, RoundingMode.HALF_UP);
-                //参数占比
-                BigDecimal paramRate = shareParam.getShareParamProportion().divide(new BigDecimal(NumberConstant.ONE_HUNDRED), NumberConstant.FOUR, RoundingMode.HALF_UP);
                 //计算分摊到的金额=目标责任中心的分摊参数数值*会计科目总金额/所有目标责任中心的分摊参数数值加总*参数比例
                 BigDecimal targetAmount = targetRespParamValue.multiply(totalAmount).multiply(paramRate).divide(totalParamValue, NumberConstant.FOUR, RoundingMode.HALF_UP);
                 //生成分摊结果的对象
-                Allocation targetAllocation = new Allocation();
-                targetAllocation.setDateMonth(startDTO.getMonth()).setDateYear(startDTO.getYear()).setLevelSort(shareLevelVO.getLeverSort())
-                        .setLevelName(shareLevelVO.getShareName()).setHospId(UserContext.getHospId()).setResponsibilityCode(responsibility.getResponsibilityCode())
-                        .setResponsibilityName(responsibility.getResponsibilityName()).setAccountShareId(costAccountShare.getId()).setAmount(targetAmount)
-                        .setCreateTime(timeMillis).setTargetResponsibilityCode(targetResponsibility.getResponsibilityCode()).setTargetResponsibilityName(targetResponsibility.getResponsibilityName())
-                        .setShareParamCode(shareParam.getShareParamCode()).setShareParamName(shareParam.getShareParamName()).setTotalAmount(totalAmount).setShareParamValueNum(targetRespParamValue)
-                        .setShareParamRate(shareParamRate).setShareLevelId(responsibility.getShareId()).setTargetShareLevelId(targetResponsibility.getShareId())
-                        .setAccountCode(accountCode).setAccountName(costCostingGroups.get(NumberConstant.ZERO).getAccountName());
+                Allocation targetAllocation =  createAllocation(startDTO, shareLevelVO, responsibility, targetResponsibility, costAccountShare,  shareParam,timeMillis,hospId);
+                targetAllocation.setAmount(targetAmount)
+                        .setTotalAmount(totalAmount)
+                        .setShareParamValueNum(targetRespParamValue)
+                        .setShareParamRate(shareParamRate)
+                        .setAccountCode(accountCode)
+                        .setAccountName(accountCodeNameMap.get(accountCode));
                 allocationList.add(targetAllocation);
             }
-        });
+        }
         return allocationList;
     }
 
+    /**
+     * 按分摊参数计算每个会计科目分摊到的金额(多线程)
+     * @param startDTO 分摊年月所在对象
+     * @param shareLevelVO 分摊层级
+     * @param responsibility 责任中心
+     * @param targetResponsibilityList 目标责任中心列表
+     * @param respDirectCostList 直接成本
+     * @param respIndirectCostList 间接成本
+     * @param costAccountShare 分摊参数对应
+     * @param shareParam 分摊参数
+     * @param targetResponsibilityParamList 目标责任中心的分摊参数数值列表
+     * @param timeMillis 时间戳
+     * @return
+     */
+    public List<Allocation> synAllocationParamCostCalc(StartDTO startDTO,
+                                                    CostShareLevelVO shareLevelVO,
+                                                    Responsibility responsibility,
+                                                    List<Responsibility> targetResponsibilityList,
+                                                    List<CostCostingGroup> respDirectCostList,
+                                                    List<Allocation> respIndirectCostList,
+                                                    CostAccountShare costAccountShare,
+                                                    CostAccountShareParam shareParam,
+                                                    List<ShareParamValue> targetResponsibilityParamList,
+                                                    long timeMillis, Long hospId){
+        //重新定义一个列表用于合并直接成本和间接成本
+        List<CostCostingGroup> respCostList=new ArrayList<>();
+        //添加直接成本
+        if(!CollectionUtils.isEmpty(respDirectCostList)){
+            respCostList.addAll(respDirectCostList);
+        }
+        //添加间接成本
+        if(!CollectionUtils.isEmpty(respIndirectCostList)){
+            //转成直接成本的对象
+            List<CostCostingGroup> respIndirectCosts = BeanUtil.convertList(respIndirectCostList, CostCostingGroup.class);
+            respCostList.addAll(respIndirectCosts);
+        }
+        //计算所有目标责任中心的分摊参数加总
+        BigDecimal totalParamValue= targetResponsibilityParamList.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add);
+        if (NumberConstant.ZERO.equals(totalParamValue.compareTo(BigDecimal.ZERO))){
+            throw new CostException(String.format("[%s-%s]的目标责任中心参数数值加总为0,无法继续分摊",responsibility.getResponsibilityName(),shareParam.getShareParamName()));
+        }
+
+        //按责任中心分组,方便取到对应责任中心的分摊参数数值
+        Map<String, BigDecimal> targetRespParamGroup=targetResponsibilityParamList.stream().collect(Collectors.groupingBy(ShareParamValue::getResponsibilityCode,Collectors.reducing(BigDecimal.ZERO, ShareParamValue::getValueNum, BigDecimal::add)));
+
+        //创建accountCode到accountName的映射
+        Map<String, String> accountCodeNameMap = respCostList.stream().collect(Collectors.toMap(
+                CostCostingGroup::getAccountCode,
+                CostCostingGroup::getAccountName,
+                (existing, replacement) -> replacement // 处理重复键的情况,保留最后一个值
+        ));
+
+        //按会计科目分组,相同会计科目一起分摊并计算总金额
+        Map<String, BigDecimal> respDirectCostGroup = respCostList.stream().collect(Collectors.groupingBy(
+                CostCostingGroup::getAccountCode,
+                Collectors.reducing(BigDecimal.ZERO, CostCostingGroup::getAmount, BigDecimal::add)
+        ));
+
+        //预计算参数比例,避免在循环中重复计算
+        BigDecimal paramRate = shareParam.getShareParamProportion()
+                .divide(new BigDecimal(NumberConstant.ONE_HUNDRED), NumberConstant.FOUR, RoundingMode.HALF_UP);
+
+        //分摊结果列表(使用线程安全的列表)
+        List<Allocation> allocationList = Collections.synchronizedList(new ArrayList<>());
+
+        //使用并行流处理目标责任中心
+        targetResponsibilityList.parallelStream().forEach(targetResponsibility -> {
+            //目标责任中心的分摊参数数值
+            BigDecimal targetRespParamValue = targetRespParamGroup.get(targetResponsibility.getResponsibilityCode());
+            if(ObjectUtils.isEmpty(targetRespParamValue)){
+                return;
+            }
+            //计算分摊参数比例
+            BigDecimal shareParamRate = targetRespParamValue.divide(totalParamValue, NumberConstant.FOUR, RoundingMode.HALF_UP);
+            //预计算基础金额,避免在内层循环中重复计算
+            BigDecimal baseAmount = targetRespParamValue.multiply(paramRate).divide(totalParamValue, NumberConstant.SIX, RoundingMode.HALF_UP);
+            //遍历每个会计科目
+            respDirectCostGroup.entrySet().parallelStream().forEach(entry -> {
+                String accountCode = entry.getKey();
+                BigDecimal totalAmount = entry.getValue();
+                //计算分摊到的金额=目标责任中心的分摊参数数值*会计科目总金额/所有目标责任中心的分摊参数数值加总*参数比例
+                //优化:使用预计算的baseAmount
+                BigDecimal targetAmount = totalAmount.multiply(baseAmount);
+                //生成分摊结果的对象
+                Allocation targetAllocation = createAllocation(startDTO, shareLevelVO, responsibility, targetResponsibility, costAccountShare,  shareParam,timeMillis,hospId);
+                targetAllocation.setAmount(targetAmount)
+                        .setTotalAmount(totalAmount)
+                        .setShareParamValueNum(targetRespParamValue)
+                        .setShareParamRate(shareParamRate)
+                        .setAccountCode(accountCode)
+                        .setAccountName(accountCodeNameMap.get(accountCode));
+                //同步添加到结果列表
+                synchronized(allocationList) {
+                    allocationList.add(targetAllocation);
+                }
+            });
+        });
+
+        return new ArrayList<>(allocationList); //返回普通ArrayList
+    }
+
+
+    /**
+     * 创建分摊结果对象
+     * @param startDTO
+     * @param shareLevelVO
+     * @param responsibility
+     * @param targetResponsibility
+     * @param costAccountShare
+     * @param shareParam
+     * @param timeMillis
+     * @param hospId
+     * @return
+     */
+    public Allocation createAllocation(StartDTO startDTO,
+                                       CostShareLevelVO shareLevelVO,
+                                       Responsibility responsibility,
+                                       Responsibility targetResponsibility,
+                                       CostAccountShare costAccountShare,
+                                       CostAccountShareParam shareParam,
+                                       long timeMillis,
+                                       Long hospId) {
+        Allocation targetAllocation = new Allocation();
+        targetAllocation.setDateMonth(startDTO.getMonth())
+                .setDateYear(startDTO.getYear())
+                .setLevelSort(shareLevelVO.getLeverSort())
+                .setLevelName(shareLevelVO.getShareName())
+                .setHospId(hospId)
+                .setResponsibilityCode(responsibility.getResponsibilityCode())
+                .setResponsibilityName(responsibility.getResponsibilityName())
+                .setAccountShareId(costAccountShare.getId())
+//                .setAmount(targetAmount)
+                .setCreateTime(timeMillis)
+                .setTargetResponsibilityCode(targetResponsibility.getResponsibilityCode())
+                .setTargetResponsibilityName(targetResponsibility.getResponsibilityName())
+                .setShareParamCode(shareParam.getShareParamCode())
+                .setShareParamName(shareParam.getShareParamName())
+//                .setTotalAmount(totalAmount)
+//                .setShareParamValueNum(targetRespParamValue)
+//                .setShareParamRate(shareParamRate)
+                .setShareLevelId(responsibility.getShareId())
+                .setTargetShareLevelId(targetResponsibility.getShareId());
+//                .setAccountCode(accountCode)
+//                .setAccountName(accountCodeNameMap.get(accountCode));
+        return targetAllocation;
+    }
+
+
     /**
      * 保存分摊结果查询表
      * @param startDTO 分摊年月所在对象
@@ -464,7 +681,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             List<AllocationQuery> directAllocationQueryList = createDirectAllocationQuery(startDTO, respCode, respCostList, responsibilityCodeMap);
             allocationQueryList.addAll(directAllocationQueryList);
         });
-        //处理接成本,间接成本肯定是按会计科目汇总的,可直接生成对象
+        //处理接成本,间接成本肯定是按会计科目汇总的,可直接生成对象
         for (Allocation indirectCost : allocationCostList) {
             AllocationQuery indirectAllocationQuery = createIndirectAllocationQuery(startDTO, indirectCost);
             allocationQueryList.add(indirectAllocationQuery);