|
@@ -33,11 +33,13 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Propagation;
|
|
import org.springframework.transaction.annotation.Propagation;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
+import org.springframework.util.ObjectUtils;
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
import java.math.RoundingMode;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
+import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
@@ -120,6 +122,11 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
if (respParamValueList.isEmpty()) {
|
|
if (respParamValueList.isEmpty()) {
|
|
|
throw new CostException("本月成本分摊参数值未导入");
|
|
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);
|
|
List<CostShareLevelVO> shareLevelVOs = shareLevelService.getAll(hospId);
|
|
|
if (CollUtil.isEmpty(shareLevelVOs)) {
|
|
if (CollUtil.isEmpty(shareLevelVOs)) {
|
|
@@ -177,8 +184,8 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
List<Allocation> allocationCostList=new ArrayList<>();
|
|
List<Allocation> allocationCostList=new ArrayList<>();
|
|
|
//逐级分摊
|
|
//逐级分摊
|
|
|
for (CostShareLevelVO shareLevelVO : shareLevelVOs) {
|
|
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);
|
|
allocationCostList.addAll(shareLevelAllocationList);
|
|
|
}
|
|
}
|
|
|
//没有任何分摊数据
|
|
//没有任何分摊数据
|
|
@@ -194,6 +201,19 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
applyAllocationQuery(startDTO,respDirectCostMap,allocationCostList,responsibilityCodeMap);
|
|
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 分摊年月所在对象
|
|
* @param startDTO 分摊年月所在对象
|
|
@@ -201,7 +221,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
* @param responsibilityList 责任中心字典
|
|
* @param responsibilityList 责任中心字典
|
|
|
* @param responsibilityShareIdMap 各分摊层级的责任中心
|
|
* @param responsibilityShareIdMap 各分摊层级的责任中心
|
|
|
* @param respDirectCostMap 直接成本
|
|
* @param respDirectCostMap 直接成本
|
|
|
- * @param respParamValueList 分摊参数数值
|
|
|
|
|
|
|
+ * @param respParamValueGroup 分摊参数数值
|
|
|
* @param accountShareResponsibilityMap 分摊参数对应
|
|
* @param accountShareResponsibilityMap 分摊参数对应
|
|
|
* @param costAccountShareParamMap 分摊设置对应的分摊参数
|
|
* @param costAccountShareParamMap 分摊设置对应的分摊参数
|
|
|
* @param costAccountShareDetailMap 分摊设置对应的会计科目
|
|
* @param costAccountShareDetailMap 分摊设置对应的会计科目
|
|
@@ -213,13 +233,13 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
List<Responsibility> responsibilityList,
|
|
List<Responsibility> responsibilityList,
|
|
|
Map<Long, List<Responsibility>> responsibilityShareIdMap,
|
|
Map<Long, List<Responsibility>> responsibilityShareIdMap,
|
|
|
Map<String, List<CostCostingGroup>> respDirectCostMap ,
|
|
Map<String, List<CostCostingGroup>> respDirectCostMap ,
|
|
|
- List<ShareParamValue> respParamValueList,
|
|
|
|
|
|
|
+ Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup,
|
|
|
Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
|
|
Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
|
|
|
Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
|
|
Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
|
|
|
Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
|
|
Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
|
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
|
|
|
List<Allocation> allocationCostList,
|
|
List<Allocation> allocationCostList,
|
|
|
- long timeMillis){
|
|
|
|
|
|
|
+ long timeMillis, Long hospId){
|
|
|
//分摊成本列表
|
|
//分摊成本列表
|
|
|
List<Allocation> allocationList=new ArrayList<>();
|
|
List<Allocation> allocationList=new ArrayList<>();
|
|
|
// 分摊层级id
|
|
// 分摊层级id
|
|
@@ -241,15 +261,22 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
return allocationList;
|
|
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()));
|
|
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;
|
|
return allocationList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -260,25 +287,25 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
* @param shareLevelVO 分摊层级
|
|
* @param shareLevelVO 分摊层级
|
|
|
* @param responsibility 责任中心
|
|
* @param responsibility 责任中心
|
|
|
* @param respDirectCostMap 直接成本
|
|
* @param respDirectCostMap 直接成本
|
|
|
- * @param respParamValueList 分摊参数数值
|
|
|
|
|
|
|
+ * @param respParamValueGroup 分摊参数数值
|
|
|
* @param accountShareResponsibilityMap 分摊参数对应
|
|
* @param accountShareResponsibilityMap 分摊参数对应
|
|
|
* @param costAccountShareParamMap 分摊设置对应的分摊参数
|
|
* @param costAccountShareParamMap 分摊设置对应的分摊参数
|
|
|
* @param costAccountShareDetailMap 分摊设置对应的会计科目
|
|
* @param costAccountShareDetailMap 分摊设置对应的会计科目
|
|
|
- * @param allocationCostList 间接成本
|
|
|
|
|
|
|
+ * @param indirectCostMap 间接成本
|
|
|
* @param timeMillis 时间戳
|
|
* @param timeMillis 时间戳
|
|
|
*/
|
|
*/
|
|
|
public List<Allocation> allocationResponsibilityCost(StartDTO startDTO,
|
|
public List<Allocation> allocationResponsibilityCost(StartDTO startDTO,
|
|
|
CostShareLevelVO shareLevelVO,
|
|
CostShareLevelVO shareLevelVO,
|
|
|
Responsibility responsibility,
|
|
Responsibility responsibility,
|
|
|
- List<Responsibility> targetResponsibilityList,
|
|
|
|
|
|
|
+ Map<String, Responsibility> targetResponsibilityMap ,
|
|
|
Map<String, List<CostCostingGroup>> respDirectCostMap ,
|
|
Map<String, List<CostCostingGroup>> respDirectCostMap ,
|
|
|
- List<ShareParamValue> respParamValueList,
|
|
|
|
|
|
|
+ Map<String, Map<String, List<ShareParamValue>>> respParamValueGroup,
|
|
|
Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
|
|
Map<String,List<CostAccountShare>> accountShareResponsibilityMap,
|
|
|
Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
|
|
Map<Long, List<CostAccountShareParam>> costAccountShareParamMap,
|
|
|
Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
|
|
Map<Long, List<CostAccountShareDetail>> costAccountShareDetailMap,
|
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap,
|
|
|
- List<Allocation> allocationCostList,
|
|
|
|
|
- long timeMillis){
|
|
|
|
|
|
|
+ Map<String, List<Allocation>> indirectCostMap,
|
|
|
|
|
+ long timeMillis, Long hospId){
|
|
|
//分摊结果列表
|
|
//分摊结果列表
|
|
|
List<Allocation> allocationList=new ArrayList<>();
|
|
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()));
|
|
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());
|
|
List<CostCostingGroup> respDirectCostList = respDirectCostMap.get(responsibility.getResponsibilityCode());
|
|
|
//按分摊设置逐个计算
|
|
//按分摊设置逐个计算
|
|
@@ -303,7 +330,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
//分摊设置对应的间接成本
|
|
//分摊设置对应的间接成本
|
|
|
List<Allocation> paramIndirectCostList=new ArrayList<>();
|
|
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());
|
|
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) {
|
|
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)){
|
|
if(CollectionUtils.isEmpty(targetResponsibilityParamList)){
|
|
|
throw new CostException(String.format("[%s-%s]的目标责任中心找不到对应的参数数值,无法继续分摊",responsibility.getResponsibilityName(),shareParam.getShareParamName()));
|
|
throw new CostException(String.format("[%s-%s]的目标责任中心找不到对应的参数数值,无法继续分摊",responsibility.getResponsibilityName(),shareParam.getShareParamName()));
|
|
|
}
|
|
}
|
|
|
//按分摊参数计算每个会计科目分摊到的金额
|
|
//按分摊参数计算每个会计科目分摊到的金额
|
|
|
List<Allocation> allocationParamCosts = allocationParamCostCalc(startDTO, shareLevelVO, responsibility, shareTargetRespCodeList, paramDirectCostList,
|
|
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);
|
|
allocationList.addAll(allocationParamCosts);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return allocationList;
|
|
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 accountShare
|
|
|
- * @param levelTargetResponsibility
|
|
|
|
|
|
|
+ * @param levelTargetResponsibilityMap
|
|
|
* @param costAccountShareTargetMap
|
|
* @param costAccountShareTargetMap
|
|
|
* @return
|
|
* @return
|
|
|
*/
|
|
*/
|
|
|
public List<Responsibility> getShareTargetResponsibility(CostAccountShare accountShare,
|
|
public List<Responsibility> getShareTargetResponsibility(CostAccountShare accountShare,
|
|
|
- List<Responsibility> levelTargetResponsibility,
|
|
|
|
|
|
|
+ Map<String, Responsibility> levelTargetResponsibilityMap,
|
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap){
|
|
Map<Long, List<CostAccountShareTarget>> costAccountShareTargetMap){
|
|
|
//获取分摊设置对应的目标责任中心
|
|
//获取分摊设置对应的目标责任中心
|
|
|
List<CostAccountShareTarget> shareTargetResponsibilityList=costAccountShareTargetMap.get(accountShare.getId());
|
|
List<CostAccountShareTarget> shareTargetResponsibilityList=costAccountShareTargetMap.get(accountShare.getId());
|
|
|
if(CollectionUtils.isEmpty(shareTargetResponsibilityList)){
|
|
if(CollectionUtils.isEmpty(shareTargetResponsibilityList)){
|
|
|
- return levelTargetResponsibility;
|
|
|
|
|
|
|
+ return new ArrayList<>(levelTargetResponsibilityMap.values());
|
|
|
}
|
|
}
|
|
|
//筛选出指定的目标责任中心
|
|
//筛选出指定的目标责任中心
|
|
|
List<String> shareTargetRespCodeList = shareTargetResponsibilityList.stream().map(CostAccountShareTarget::getTargetResponsibilityCode).collect(Collectors.toList());
|
|
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)){
|
|
if(CollectionUtils.isEmpty(shareTargetRespList)){
|
|
|
throw new CostException(String.format("[%s-%s]找不到对应的目标责任中心,无法继续分摊",accountShare.getResponsibilityName(),accountShare.getAlias()));
|
|
throw new CostException(String.format("[%s-%s]找不到对应的目标责任中心,无法继续分摊",accountShare.getResponsibilityName(),accountShare.getAlias()));
|
|
|
}
|
|
}
|
|
|
return shareTargetRespList;
|
|
return shareTargetRespList;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 按分摊参数计算每个会计科目分摊到的金额
|
|
* 按分摊参数计算每个会计科目分摊到的金额
|
|
|
* @param startDTO 分摊年月所在对象
|
|
* @param startDTO 分摊年月所在对象
|
|
@@ -390,7 +450,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
CostAccountShare costAccountShare,
|
|
CostAccountShare costAccountShare,
|
|
|
CostAccountShareParam shareParam,
|
|
CostAccountShareParam shareParam,
|
|
|
List<ShareParamValue> targetResponsibilityParamList,
|
|
List<ShareParamValue> targetResponsibilityParamList,
|
|
|
- long timeMillis){
|
|
|
|
|
|
|
+ long timeMillis, Long hospId){
|
|
|
//重新定义一个列表用于合并直接成本和间接成本
|
|
//重新定义一个列表用于合并直接成本和间接成本
|
|
|
List<CostCostingGroup> respCostList=new ArrayList<>();
|
|
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));
|
|
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<>();
|
|
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);
|
|
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);
|
|
allocationList.add(targetAllocation);
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
|
|
+ }
|
|
|
return allocationList;
|
|
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 分摊年月所在对象
|
|
* @param startDTO 分摊年月所在对象
|
|
@@ -464,7 +681,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
|
|
|
List<AllocationQuery> directAllocationQueryList = createDirectAllocationQuery(startDTO, respCode, respCostList, responsibilityCodeMap);
|
|
List<AllocationQuery> directAllocationQueryList = createDirectAllocationQuery(startDTO, respCode, respCostList, responsibilityCodeMap);
|
|
|
allocationQueryList.addAll(directAllocationQueryList);
|
|
allocationQueryList.addAll(directAllocationQueryList);
|
|
|
});
|
|
});
|
|
|
- //处理直接成本,间接成本肯定是按会计科目汇总的,可直接生成对象
|
|
|
|
|
|
|
+ //处理间接成本,间接成本肯定是按会计科目汇总的,可直接生成对象
|
|
|
for (Allocation indirectCost : allocationCostList) {
|
|
for (Allocation indirectCost : allocationCostList) {
|
|
|
AllocationQuery indirectAllocationQuery = createIndirectAllocationQuery(startDTO, indirectCost);
|
|
AllocationQuery indirectAllocationQuery = createIndirectAllocationQuery(startDTO, indirectCost);
|
|
|
allocationQueryList.add(indirectAllocationQuery);
|
|
allocationQueryList.add(indirectAllocationQuery);
|