瀏覽代碼

添加获取年度科室损益数据相关接口

JammeyJiang 1 月之前
父節點
當前提交
1f0277af43

+ 15 - 0
src/main/java/com/kcim/dao/mapper/CostDepartmentProfitMapper.java

@@ -2,9 +2,12 @@ package com.kcim.dao.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.kcim.dao.model.CostDepartmentProfit;
+import com.kcim.vo.CostProfitVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+
 /**
  * 科室损益计算
  * 
@@ -18,4 +21,16 @@ public interface CostDepartmentProfitMapper extends BaseMapper<CostDepartmentPro
     Integer getMaxYear(@Param("hospId") Long hospId);
 
     Integer getMaxMonth(@Param("hospId") Long hospId, @Param("year") Integer year);
+
+
+    List<CostProfitVo> getAnnualSummaryByYearRange(@Param("startYear") Integer startYear,
+                                                @Param("endYear") Integer endYear,
+                                                @Param("hospId") Long hospId,
+                                                @Param("reportType") Integer reportType,
+                                                @Param("responsibilityCode") String responsibilityCode);
+
+    List<CostProfitVo> getAnnualSummaryByYear(@Param("year") Integer year,
+                                              @Param("hospId") Long hospId,
+                                              @Param("reportType") Integer reportType,
+                                              @Param("responsibilityCode") String responsibilityCode);
 }

+ 30 - 0
src/main/java/com/kcim/dao/model/CostDepartmentProfit.java

@@ -115,5 +115,35 @@ public class CostDepartmentProfit implements Serializable {
 
 	private BigDecimal percent;
 
+	/**
+	 * 预算金额
+	 */
+	private BigDecimal budgetAmount;
+
+	/**
+	 * 上期金额
+	 */
+	private BigDecimal prevPeriodAmount;
+
+	/**
+	 * 同期金额
+	 */
+	private BigDecimal samePeriodAmount;
+
+	/**
+	 * 完成率
+	 */
+	private BigDecimal completionRate;
+
+	/**
+	 * 环比
+	 */
+	private BigDecimal momRate;
+
+	/**
+	 * 同比
+	 */
+	private BigDecimal yoyRate;
+
 
 }

+ 2 - 0
src/main/java/com/kcim/service/CostDepartmentProfitService.java

@@ -71,5 +71,7 @@ public interface CostDepartmentProfitService extends IService<CostDepartmentProf
     Object getRedirectData(String computeDate, Long reportId, Long hospId, String reportType, String responsibilityCode);
 
     Object getComputeProfitCollect(String computeDate, Long hospId, String reportType);
+
+    Object getBatchComputeProfitListByYear(String startYear, String endYear, String reportType, String responsibilityCode);
 }
 

+ 32 - 0
src/main/java/com/kcim/service/impl/AllocationServiceImpl.java

@@ -37,6 +37,9 @@ import org.springframework.util.CollectionUtils;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
@@ -253,6 +256,35 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
                     accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap,costAccountShareTargetMap, allocationCostList, timeMillis);
             allocationList.addAll(allocationRespCosts);
         }
+        // 创建线程池
+        ExecutorService executorService = Executors.newFixedThreadPool(responsibilities.size());
+        CountDownLatch countDownLatch = new CountDownLatch(responsibilities.size());
+
+        for (Responsibility responsibility : responsibilities) {
+            executorService.submit(() -> {
+                try {
+                    // 分摊一个责任中心的成本
+                    List<Allocation> allocationRespCosts = allocationResponsibilityCost(startDTO, shareLevelVO, responsibility, targetResponsibilityList, respDirectCostMap, respParamValueList,
+                            accountShareResponsibilityMap, costAccountShareParamMap, costAccountShareDetailMap, costAccountShareTargetMap, allocationCostList, timeMillis);
+                    synchronized (allocationList) {
+                        allocationList.addAll(allocationRespCosts);
+                    }
+                } catch (Exception e) {
+                    log.error("分摊责任中心成本时发生错误", e);
+                } finally {
+                    countDownLatch.countDown();
+                }
+            });
+        }
+
+        try {
+            countDownLatch.await();
+        } catch (InterruptedException e) {
+            log.error("等待所有分摊任务完成时发生中断", e);
+        } finally {
+            executorService.shutdown();
+        }
+
         return allocationList;
     }
 

+ 179 - 32
src/main/java/com/kcim/service/impl/CostDepartmentProfitServiceImpl.java

@@ -112,7 +112,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 
     private final CostAccountShareService costAccountShareService;
 
-    private final UserResponsibilityRightService userResponsibilityRightService ;
+    private final UserResponsibilityRightService userResponsibilityRightService;
 
 
     private final SqlService sqlService;
@@ -124,7 +124,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 
     private final String PERCENT_FIELD = "percent";
 
-    public CostDepartmentProfitServiceImpl(ReportFormService reportFormService, IncomeCollectionService incomeCollectionService, CostShareLevelService costShareLevelService, ResponsibilityService responsibilityService, ReportRelationService reportRelationService, AllocationService allocationService, AllocationQueryService allocationQueryService, FileRecordService fileRecordService, MinioConfig minioConfig, MinioFileUtil minioFileUtil, CenterService centerService, CostDepartmentProfitRepository costDepartmentProfitRepository, ComputeLastProfitDateRepository computeLastProfitDateRepository, AccountingService accountingService, CostAccountShareService costAccountShareService, SqlService sqlService,UserResponsibilityRightService userResponsibilityRightService) {
+    public CostDepartmentProfitServiceImpl(ReportFormService reportFormService, IncomeCollectionService incomeCollectionService, CostShareLevelService costShareLevelService, ResponsibilityService responsibilityService, ReportRelationService reportRelationService, AllocationService allocationService, AllocationQueryService allocationQueryService, FileRecordService fileRecordService, MinioConfig minioConfig, MinioFileUtil minioFileUtil, CenterService centerService, CostDepartmentProfitRepository costDepartmentProfitRepository, ComputeLastProfitDateRepository computeLastProfitDateRepository, AccountingService accountingService, CostAccountShareService costAccountShareService, SqlService sqlService, UserResponsibilityRightService userResponsibilityRightService) {
         this.reportFormService = reportFormService;
         this.incomeCollectionService = incomeCollectionService;
         this.costShareLevelService = costShareLevelService;
@@ -141,7 +141,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         this.accountingService = accountingService;
         this.costAccountShareService = costAccountShareService;
         this.sqlService = sqlService;
-        this.userResponsibilityRightService=userResponsibilityRightService;
+        this.userResponsibilityRightService = userResponsibilityRightService;
     }
 
     /**
@@ -1113,8 +1113,13 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
     }
 
     @Override
-    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
     public void computeProfit(String computeDate, Long hospId, String reportType) {
+        computeProfitAction(computeDate, hospId, reportType);
+        execDeptProfitSql(computeDate, reportType);
+    }
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
+    public void computeProfitAction(String computeDate, Long hospId, String reportType) {
 //        DateTime parse = DateUtil.parse(computeDate);
 //        int year = DateUtil.year(parse);
 //        int month = DateUtil.month(parse) + 1;
@@ -1202,13 +1207,22 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         this.saveBatch(costDepartmentProfits);
         //记录最后一次 损益计算日期
         computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate);
+    }
 
-        Map<String,String> sqlParameter = new HashMap<>();
-        sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE,computeDate);
-        sqlParameter.put(SQLParameter.REPORT_TYPE_CODE,reportType);
-        sqlService.autoExecuteSql(CustomSqlTypeEnum.DEPT_PROFIT_CALC.getCode(),sqlParameter);
+    /**
+     * 执行科室损益后续脚本
+     *
+     * @param computeDate
+     * @param reportType
+     */
+    public void execDeptProfitSql(String computeDate, String reportType) {
+        Map<String, String> sqlParameter = new HashMap<>();
+        sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, computeDate);
+        sqlParameter.put(SQLParameter.REPORT_TYPE_CODE, reportType);
+        sqlService.autoExecuteSql(CustomSqlTypeEnum.DEPT_PROFIT_CALC.getCode(), sqlParameter);
     }
 
+
     private DictDataVo getDictDataVo(String reportType) {
         DictDataVo dict = centerService.getDict(PROFIT_REPORT_TYPE);
         if (Objects.isNull(dict)) {
@@ -1252,7 +1266,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             commonTitleReportVo.setDataType(reportForm.getDataType());
             commonTitleReportVo.setDecimalPlace(reportForm.getDecimalPlace());
             commonTitleReportVo.setPermil(reportForm.getPermil());
-            return  commonTitleReportVo;
+            return commonTitleReportVo;
         }).collect(Collectors.toList());
 //        List<CommonTitleReportVo> commonTitleReportVos = BeanUtil.convertList(reportFormList,CommonTitleReportVo.class);
         Map<Long, List<CommonTitleReportVo>> collect = commonTitleReportVos.stream().collect(Collectors.groupingBy(CommonTitleReportVo::getParentReportId));
@@ -1285,9 +1299,9 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         Map<Long, List<CostDepartmentProfit>> collectGroup = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
         for (ReportForm reportForm : reportFormList) {
             Integer hide = reportForm.getHide();
-            if(hide.equals(NumberConstant.ONE)){
+            if (hide.equals(NumberConstant.ONE)) {
                 List<CostDepartmentProfit> costDepartmentProfits = collectGroup.get(reportForm.getId());
-                if(!CollectionUtils.isEmpty(costDepartmentProfits)) {
+                if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                     filterProfit.addAll(costDepartmentProfits);
                 }
             }
@@ -1312,7 +1326,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             throw new CostException("未找到对应分摊层级责任中心");
         }
         //获取授权的责任中心
-        responsibilityList=userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
+        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
         //获取当前院区所有的责任中心
         List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                 .eq(Responsibility::getHospId, hospId));
@@ -1626,7 +1640,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             throw new CostException("未找到对应分摊层级责任中心");
         }
         //获取授权的责任中心
-        responsibilityList=userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
+        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
         List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                 .eq(Responsibility::getHospId, hospId));
         Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
@@ -1710,10 +1724,10 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
         for (ReportForm reportForm : reportFormList) {
             Integer hide = reportForm.getHide();
-            if(hide.equals(NumberConstant.ONE)){
+            if (hide.equals(NumberConstant.ONE)) {
 //                filterProfit.addAll(collect1.get(reportForm.getId()));
                 List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
-                if(!CollectionUtils.isEmpty(costDepartmentProfits)) {
+                if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                     filterProfit.addAll(costDepartmentProfits);
                 }
             }
@@ -1729,11 +1743,11 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
             profitVo.setSort(sortMap.get(profitVo.getReportId()));
             List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
-            if(!CollectionUtils.isEmpty(profitReportFormList)) {
+            if (!CollectionUtils.isEmpty(profitReportFormList)) {
                 profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                 profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                 profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
-            }else {
+            } else {
                 profitVo.setDataType(NumberConstant.ONE);
                 profitVo.setDecimalPlace(NumberConstant.TWO);
                 profitVo.setPermil(NumberConstant.ONE);
@@ -1797,10 +1811,10 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
             for (ReportForm reportForm : reportFormList) {
                 Integer hide = reportForm.getHide();
-                if(hide.equals(NumberConstant.ONE)){
+                if (hide.equals(NumberConstant.ONE)) {
 //                    filterProfit.addAll(collect1.get(reportForm.getId()));
                     List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
-                    if(!CollectionUtils.isEmpty(costDepartmentProfits)) {
+                    if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                         filterProfit.addAll(costDepartmentProfits);
                     }
                 }
@@ -1814,11 +1828,11 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
                 profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
                 profitVo.setSort(sortMap.get(profitVo.getReportId()));
                 List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
-                if(!CollectionUtils.isEmpty(profitReportFormList)) {
+                if (!CollectionUtils.isEmpty(profitReportFormList)) {
                     profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                     profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                     profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
-                }else {
+                } else {
                     profitVo.setDataType(NumberConstant.ONE);
                     profitVo.setDecimalPlace(NumberConstant.TWO);
                     profitVo.setPermil(NumberConstant.ONE);
@@ -1870,10 +1884,10 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
                     Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
                     for (ReportForm reportForm : reportFormList) {
                         Integer hide = reportForm.getHide();
-                        if(hide.equals(NumberConstant.ONE)){
+                        if (hide.equals(NumberConstant.ONE)) {
 //                            filterProfit.addAll(collect1.get(reportForm.getId()));
                             List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
-                            if(!CollectionUtils.isEmpty(costDepartmentProfits)) {
+                            if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                                 filterProfit.addAll(costDepartmentProfits);
                             }
                         }
@@ -1886,11 +1900,11 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
                         profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
                         profitVo.setSort(sortMap.get(profitVo.getReportId()));
                         List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
-                        if(!CollectionUtils.isEmpty(profitReportFormList)) {
+                        if (!CollectionUtils.isEmpty(profitReportFormList)) {
                             profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                             profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                             profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
-                        }else {
+                        } else {
                             profitVo.setDataType(NumberConstant.ONE);
                             profitVo.setDecimalPlace(NumberConstant.TWO);
                             profitVo.setPermil(NumberConstant.ONE);
@@ -2207,7 +2221,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             throw new CostException("未找到对应分摊层级责任中心");
         }
         //获取授权的责任中心
-        responsibilityList=userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
+        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
         List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                 .eq(Responsibility::getHospId, hospId));
         Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
@@ -2242,9 +2256,9 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
                 commonResponsibilityReportVo.setChild(getChildTitle(responsibilities, responsibilityGroup));
             } else {
                 //要显示占比时自动生成默认金额占比层
-                if(IsShowPercent()){
+                if (IsShowPercent()) {
                     commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
-                }else{
+                } else {
                     //不显示占比时,直接责任中心作为金额层
                     commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD);
                 }
@@ -2580,11 +2594,12 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 
     /**
      * 是否显示占比
+     *
      * @return
      */
-    public boolean IsShowPercent(){
+    public boolean IsShowPercent() {
         String parameterValue = centerService.getParameterValue(ParameterConstant.SHOW_PERCENT);
-        return  NumberConstant.ONE_S.equals(parameterValue);
+        return NumberConstant.ONE_S.equals(parameterValue);
     }
 
     private List<CommonResponsibilityReportVo> getChildTitle(List<Responsibility> responsibilities, Map<Long, List<Responsibility>> responsibilityGroup) {
@@ -2601,9 +2616,9 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 //                //添加金额占比
 //                commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
                 //要显示占比时自动生成默认金额占比层
-                if(IsShowPercent()){
+                if (IsShowPercent()) {
                     commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
-                }else{
+                } else {
                     //不显示占比时,直接责任中心作为金额层
                     commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD);
                 }
@@ -3199,4 +3214,136 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         }
         T.sort(Comparator.comparing(CostResponsibilityProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
     }
+
+    @Override
+    public Object getBatchComputeProfitListByYear(String startYear, String endYear, String reportType, String responsibilityCode) {
+        Integer integerReportType = Integer.valueOf(reportType);
+        Long hospId = UserContext.getHospId();
+        List<BatchCostProfitResponse> responses = new ArrayList<>();
+        // 解析起止年份
+        int startY = Integer.parseInt(startYear);
+        int endY = Integer.parseInt(endYear);
+
+        if (startY > endY) {
+            throw new CostException(500, "起始年份不能大于结束年份");
+        }
+        // 获取报表配置
+        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
+                .eq(ReportForm::getHospId, hospId)
+                .eq(ReportForm::getDeleteTime, NumberConstant.ZERO)
+                .eq(ReportForm::getReportType, integerReportType));
+        if (CollUtil.isEmpty(reportFormList)) {
+            throw new CostException(500, "损益表未找到");
+        }
+        Map<Long, ReportForm> reportMap = reportFormList.stream()
+                .collect(Collectors.toMap(ReportForm::getId, report -> report));
+        // 取非隐藏的报表项目ID
+        List<Long> activeReportIdList = reportFormList.stream()
+                .filter(report -> NumberConstant.ONE.equals(report.getHide()))
+                .map(ReportForm::getId)
+                .collect(Collectors.toList());
+
+        // 获取当前年份和上一年度的汇总数据(一次性查询)
+        List<CostProfitVo> summaryList = this.baseMapper.getAnnualSummaryByYearRange(startY, endY, hospId, integerReportType, responsibilityCode);
+        List<CostProfitVo> preYearSummaryList = this.baseMapper.getAnnualSummaryByYearRange(startY - 1, endY - 1, hospId, integerReportType, responsibilityCode);
+
+        // 按年份分组处理数据
+        Map<Integer, List<CostProfitVo>> currentYearMap = new HashMap<>();
+        Map<Integer, List<CostProfitVo>> preYearMap = new HashMap<>();
+
+        // 将结果按年份分组
+        if (!CollectionUtils.isEmpty(summaryList)) {
+            currentYearMap = summaryList.stream()
+                    .collect(Collectors.groupingBy(CostProfitVo::getYear));
+        }
+
+        if (!CollectionUtils.isEmpty(preYearSummaryList)) {
+            preYearMap = preYearSummaryList.stream()
+                    .collect(Collectors.groupingBy(CostProfitVo::getYear));
+        }
+
+        // 遍历每个年份进行数据处理
+        for (int year = startY; year <= endY; year++) {
+            int previousYear = year - 1;
+
+            List<CostProfitVo> currentYearList = currentYearMap.get(year);
+            List<CostProfitVo> previousYearList = preYearMap.get(previousYear);
+
+            if (CollectionUtils.isEmpty(currentYearList)) {
+                continue;
+            }
+
+            // 只处理非隐藏的项目
+            List<CostProfitVo> activeCostProfitVo = currentYearList.stream()
+                    .filter(vo -> activeReportIdList.contains(vo.getReportId()))
+                    .collect(Collectors.toList());
+            if (CollectionUtils.isEmpty(activeCostProfitVo)) {
+                continue;
+            }
+
+            // 创建映射以便快速查找上一年的数据
+            Map<Long, CostProfitVo> preYearCostProfitMap = new HashMap<>();
+            if (!CollectionUtils.isEmpty(previousYearList)) {
+                preYearCostProfitMap = previousYearList.stream()
+                        .collect(Collectors.toMap(CostProfitVo::getReportId, costProfitVo -> costProfitVo));
+            }
+
+            // 计算完成率、环比、同比
+            for (CostProfitVo vo : currentYearList) {
+                // 设置同期数据
+                if (preYearCostProfitMap.containsKey(vo.getReportId())) {
+                    vo.setSamePeriodAmount(preYearCostProfitMap.get(vo.getReportId()).getAmount());
+                } else {
+                    vo.setSamePeriodAmount(BigDecimal.ZERO);
+                }
+
+                vo.setCompletionRate(calculateRate(vo.getAmount(), vo.getBudgetAmount()));
+                vo.setMomRate(calculateRate(vo.getAmount().subtract(vo.getPrevPeriodAmount()), vo.getPrevPeriodAmount()));
+                vo.setYoyRate(calculateRate(vo.getAmount().subtract(vo.getSamePeriodAmount()), vo.getSamePeriodAmount()));
+
+                // 设置报表相关属性
+                ReportForm reportForm = reportMap.get(vo.getReportId());
+                if (reportForm != null) {
+                    vo.setDescription(reportForm.getDescription());
+                    vo.setSort(reportForm.getSort());
+                    vo.setPermil(reportForm.getPermil());
+                    vo.setDataType(reportForm.getDataType());
+                    vo.setDecimalPlace(reportForm.getDecimalPlace());
+                }
+            }
+
+            // 构建树状结构
+            Map<Long, List<CostProfitVo>> collect = currentYearList.stream()
+                    .collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
+            List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
+            collect.remove(NumberConstant.ZERO_L);
+
+            if (!CollectionUtils.isEmpty(costProfitParentVos)) {
+                costProfitParentVos.forEach(parentVo -> {
+                    parentVo.setChildren(collect.get(parentVo.getReportId()));
+                });
+                costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
+            }
+
+            BatchCostProfitResponse response = new BatchCostProfitResponse();
+            response.setComputeDate(String.valueOf(year));
+            response.setProfitVoList(costProfitParentVos);
+            responses.add(response);
+        }
+
+        return responses;
+    }
+
+
+    /**
+     * 安全地计算百分比:避免除零错误
+     */
+    private BigDecimal calculateRate(BigDecimal current, BigDecimal base) {
+        if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO;
+        }
+        BigDecimal rate = current.divide(base, 4, RoundingMode.HALF_UP);
+        return rate.setScale(4, RoundingMode.HALF_UP);
+    }
+
 }

+ 15 - 2
src/main/java/com/kcim/service/impl/HospProfitAndLossServiceImpl.java

@@ -194,8 +194,12 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
      * @param reportType 报表类型
      */
     @Override
+    public void calcHospProfit(String date, Long hospId, Integer reportType){
+        calcHospProfitAction(date,hospId,reportType);
+        execHospProfitSql(date,date);
+    }
     @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
-    public void calcHospProfit(String date, Long hospId, Integer reportType) {
+    public void calcHospProfitAction(String date, Long hospId, Integer reportType) {
         List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
         DateTime parse = DateUtil.parse(date);
         int year = DateUtil.year(parse);
@@ -392,11 +396,20 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
             i.setReportType(reportType);
         });
         this.saveBatch(list);
-        Map<String,String> sqlParameter = new HashMap<>();
 
+    }
+
+    /**
+     * 执行全院损益后续脚本
+     * @param date
+     * @param reportType
+     */
+    public void execHospProfitSql(String date,String reportType){
+        Map<String,String> sqlParameter = new HashMap<>();
         sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, DateUtils.StringToString(date, DateStyleEnum.YYYY_MM));
         sqlParameter.put(SQLParameter.REPORT_TYPE_CODE,reportType.toString());
         sqlService.autoExecuteSql(CustomSqlTypeEnum.HOSP_PROFIT_CALC.getCode(),sqlParameter);
+
     }
 
     // 计算公式中钱

+ 30 - 0
src/main/java/com/kcim/vo/CostProfitVo.java

@@ -119,4 +119,34 @@ public class CostProfitVo implements Serializable {
 	 */
 	private Integer permil;
 
+	/**
+	 * 预算金额
+	 */
+	private BigDecimal budgetAmount;
+
+	/**
+	 * 上期金额
+	 */
+	private BigDecimal prevPeriodAmount;
+
+	/**
+	 * 同期金额
+	 */
+	private BigDecimal samePeriodAmount;
+
+	/**
+	 * 完成率
+	 */
+	private BigDecimal completionRate;
+
+	/**
+	 * 环比
+	 */
+	private BigDecimal momRate;
+
+	/**
+	 * 同比
+	 */
+	private BigDecimal yoyRate;
+
 }

+ 11 - 0
src/main/java/com/kcim/web/CostDepartmentProfitController.java

@@ -179,6 +179,17 @@ public class CostDepartmentProfitController {
         return  Result.ok(costDepartmentProfitService.getBatchComputeProfitList(beginComputeDate,endComputeDate,hospId,reportType,responsibilityCode));
     }
 
+    @GetMapping("/getBatchComputeProfitListByYear")
+    @ApiOperation("多年份损益报表计算列表")
+    public Result getBatchComputeProfitListByYear(@RequestParam String startYear,
+                                            @RequestParam String endYear,
+                                            @RequestParam String reportType,
+                                            @RequestParam String responsibilityCode){
+        return  Result.ok(costDepartmentProfitService.getBatchComputeProfitListByYear(startYear,endYear,reportType,responsibilityCode));
+    }
+
+
+
     @GetMapping("/getRedirectData")
     @ApiOperation("下钻数据列表")
     public Result getRedirectData(@RequestParam @ApiParam(name = "date", value = "yyyy-MM") String computeDate,

+ 57 - 1
src/main/resources/mapper/CostDepartmentProfitMapper.xml

@@ -39,6 +39,62 @@
           and hosp_id = #{hospId}
           and `year` = #{year}
     </select>
+    <select id="getAnnualSummaryByYear" parameterType="map" resultType="com.kcim.vo.CostProfitVo">
+        SELECT
+            `year`,
+            `month`,
+            report_parent_id as reportParentId,
+            report_id as reportId,
+            report_num as reportNum,
+            report_name as reportName,
+            calc_formula as calcFormula,
+            calc_type as calcType,
+            responsibility_code as responsibilityCode,
+            responsibility_name as responsibilityName,
+            cost_type as costType,
+            income_type as incomeType,
+            share_type as shareType,
+            percent,
+            SUM(budget_amount) AS budget_amount,
+            SUM(amount) AS amount,
+            SUM(prev_period_amount) AS prev_period_amount,
+            SUM(same_period_amount) AS same_period_amount
+        FROM cost_department_profit
+        WHERE year = #{year}
+          AND hosp_id = #{hospId}
+          AND share_type = #{reportType}
+          AND responsibility_code = #{responsibilityCode}
+          AND delete_time = 0
+        GROUP BY report_id
+        ORDER BY report_num
+    </select>
 
-
+    <select id="getAnnualSummaryByYearRange" parameterType="map" resultType="com.kcim.vo.CostProfitVo">
+        SELECT
+            `year`,
+            report_parent_id as reportParentId,
+            report_id as reportId,
+            report_num as reportNum,
+            report_name as reportName,
+            calc_formula as calcFormula,
+            calc_type as calcType,
+            responsibility_code as responsibilityCode,
+            responsibility_name as responsibilityName,
+            cost_type as costType,
+            income_type as incomeType,
+            share_type as shareType,
+            percent,
+            SUM(budget_amount) AS budget_amount,
+            SUM(amount) AS amount,
+            SUM(prev_period_amount) AS prev_period_amount,
+            SUM(same_period_amount) AS same_period_amount
+        FROM cost_department_profit
+        WHERE year BETWEEN #{startYear} AND #{endYear}
+          AND hosp_id = #{hospId}
+          AND share_type = #{reportType}
+          AND responsibility_code = #{responsibilityCode}
+          AND delete_time = 0
+        GROUP BY `year`, report_id
+        ORDER BY `year`, report_num
+    </select>
 </mapper>