0
0

31 Commits a2716f4c3a ... 234cc301bc

Autor SHA1 Nachricht Datum
  JammeyJiang 234cc301bc 添加病种报表的三个分页接口 vor 3 Wochen
  JammeyJiang 853d551a7b 调整病种成本相关三个标准报表的数据生成逻辑 vor 1 Monat
  JammeyJiang 8c9f22375b 优化项目成本分摊计算逻辑 vor 1 Monat
  JammeyJiang 8895843cba 调整科室损益的会计科目金额计算逻辑 vor 1 Monat
  JammeyJiang cd0488031c 添加动态列数据类型及是否固定的字段返回 vor 1 Monat
  JammeyJiang 7d78c39ba6 按会计科目分摊时的分摊及损益计算逻辑的批量保存优化 vor 1 Monat
  JammeyJiang c00def9e81 优化分摊计算的逻辑 vor 1 Monat
  JammeyJiang 3fee003b1e 添加按会计科目计算科室损益报表数据 vor 1 Monat
  JammeyJiang 0d2b461fcb 标准成本报表-DRG报表/病种报表接口添加 vor 2 Monaten
  JammeyJiang 59dbe88805 科室标准报表和诊次/床日标准报表接口添加 vor 2 Monaten
  JammeyJiang 1b555a4f34 获取患者收费项目-患者列表添加分页入参 vor 2 Monaten
  JammeyJiang e2864c28aa 获取患者收费项目-患者列表添加分页入参 vor 2 Monaten
  JammeyJiang aec206a0f6 添加公式对应的报表列数据为空的情况处理 vor 2 Monaten
  JammeyJiang a5f118d3a6 调整配置 vor 2 Monaten
  JammeyJiang d447ad8f94 添加三个DRG成本明细表相关代码 vor 2 Monaten
  JammeyJiang 5ad11f5e67 添加医院服务单元病种成本构成明细表相关代码 vor 2 Monaten
  JammeyJiang 6f1605fa49 添加医院病种成本明细表相关代码 vor 2 Monaten
  JammeyJiang 601638aa91 添加医院服务项目成本明细表相关代码 vor 2 Monaten
  JammeyJiang b8960d4030 添加医院医疗服务项目成本汇总表相关代码 vor 2 Monaten
  JammeyJiang c4fffe8fb5 添加医院科室床日成本表相关代码 vor 3 Monaten
  JammeyJiang cb20b42a6c 添加医院科室诊次成本表相关代码 vor 3 Monaten
  JammeyJiang 1b27380249 添加医院诊次成本构成表相关代码 vor 3 Monaten
  JammeyJiang cb9644df7e 添加医院科室成本分摊汇总表相关代码 vor 3 Monaten
  JammeyJiang b24f3bbe9c 添加医院临床服务类科室全成本构成分析表相关代码 vor 3 Monaten
  JammeyJiang 1c743eee4a 添加临床科室医疗成本表(全成本)相关代码 vor 3 Monaten
  JammeyJiang a819a1b6b1 添加临床科室医疗成本表相关代码 vor 3 Monaten
  JammeyJiang 65ed2d7ac3 添加临床科室医疗成本表相关代码 vor 3 Monaten
  JammeyJiang 10a49b767c 添加标准报表-科室直接成本相关代码 vor 3 Monaten
  JammeyJiang 94da3e696b 添加多月份的全院其他收支的填充逻辑 vor 3 Monaten
  JammeyJiang b329e50929 PFM知识库导入的异常处理 vor 3 Monaten
  JammeyJiang 7237bd6b41 合并科室损益和全院损益计算的报表类型参数 vor 3 Monaten
85 geänderte Dateien mit 6744 neuen und 278 gelöschten Zeilen
  1. 4 0
      src/main/java/com/kcim/common/constants/Constant.java
  2. 4 4
      src/main/java/com/kcim/common/constants/ParameterConstant.java
  3. 31 1
      src/main/java/com/kcim/common/util/BeanUtil.java
  4. 1 3
      src/main/java/com/kcim/dao/mapper/AllocationMapper.java
  5. 27 2
      src/main/java/com/kcim/dao/mapper/AllocationQueryMapper.java
  6. 129 0
      src/main/java/com/kcim/dao/mapper/BatchInsertProvider.java
  7. 68 0
      src/main/java/com/kcim/dao/mapper/ComputePatientCostAccountMapper.java
  8. 25 0
      src/main/java/com/kcim/dao/mapper/ComputeProjectCostAccountMapper.java
  9. 1 1
      src/main/java/com/kcim/dao/mapper/ComputeProjectCostDetailMapper.java
  10. 1 2
      src/main/java/com/kcim/dao/mapper/ComputeProjectGroupCostDetailMapper.java
  11. 16 0
      src/main/java/com/kcim/dao/mapper/CostDepartmentProfitAccountMapper.java
  12. 1 2
      src/main/java/com/kcim/dao/mapper/CostDepartmentProfitMapper.java
  13. 11 4
      src/main/java/com/kcim/dao/mapper/CostIncomeGroupMapper.java
  14. 24 0
      src/main/java/com/kcim/dao/mapper/GenericBatchMapper.java
  15. 1 1
      src/main/java/com/kcim/dao/mapper/ImportPatientItemMapper.java
  16. 2 0
      src/main/java/com/kcim/dao/mapper/IncomeCollectionMapper.java
  17. 10 2
      src/main/java/com/kcim/dao/mapper/ItemMapper.java
  18. 13 5
      src/main/java/com/kcim/dao/model/AllocationQuery.java
  19. 91 0
      src/main/java/com/kcim/dao/model/ComputePatientCostAccount.java
  20. 18 0
      src/main/java/com/kcim/dao/model/ComputeProjectCost.java
  21. 104 0
      src/main/java/com/kcim/dao/model/ComputeProjectCostAccount.java
  22. 7 0
      src/main/java/com/kcim/dao/model/CostDepartmentProfit.java
  23. 87 0
      src/main/java/com/kcim/dao/model/CostDepartmentProfitAccount.java
  24. 6 0
      src/main/java/com/kcim/dao/model/Item.java
  25. 2 1
      src/main/java/com/kcim/dao/model/Responsibility.java
  26. 15 6
      src/main/java/com/kcim/dao/model/StandItem.java
  27. 47 0
      src/main/java/com/kcim/dao/model/dto/ParamContainerDTO.java
  28. 7 0
      src/main/java/com/kcim/dao/repository/AccountingRepository.java
  29. 3 4
      src/main/java/com/kcim/dao/repository/ComputeLastProfitDateRepository.java
  30. 51 0
      src/main/java/com/kcim/dao/repository/ComputePatientCostAccountRepository.java
  31. 45 0
      src/main/java/com/kcim/dao/repository/ComputeProjectCostAccountRepository.java
  32. 2 1
      src/main/java/com/kcim/dao/repository/ComputeProjectCostDetailRepository.java
  33. 2 3
      src/main/java/com/kcim/dao/repository/ComputeProjectGroupCostDetailRepository.java
  34. 50 0
      src/main/java/com/kcim/dao/repository/CostDepartmentProfitAccountRepository.java
  35. 10 2
      src/main/java/com/kcim/dao/repository/ImportPatientItemRepository.java
  36. 8 0
      src/main/java/com/kcim/dao/repository/ItemRepository.java
  37. 7 0
      src/main/java/com/kcim/service/AllocationQueryService.java
  38. 2 0
      src/main/java/com/kcim/service/IncomeCollectionService.java
  39. 1 1
      src/main/java/com/kcim/service/PatientItemImportService.java
  40. 158 0
      src/main/java/com/kcim/service/StandardReportService.java
  41. 43 5
      src/main/java/com/kcim/service/impl/AllocationQueryServiceImpl.java
  42. 275 59
      src/main/java/com/kcim/service/impl/AllocationServiceImpl.java
  43. 78 0
      src/main/java/com/kcim/service/impl/BaseBatchServiceImpl.java
  44. 1 0
      src/main/java/com/kcim/service/impl/ComputeMedicalDepartmentProfitServiceImpl.java
  45. 4 2
      src/main/java/com/kcim/service/impl/CostCostingGroupServiceImpl.java
  46. 824 34
      src/main/java/com/kcim/service/impl/CostDepartmentProfitServiceImpl.java
  47. 30 6
      src/main/java/com/kcim/service/impl/CostIncomeGroupServiceImpl.java
  48. 56 6
      src/main/java/com/kcim/service/impl/HospProfitAndLossServiceImpl.java
  49. 5 0
      src/main/java/com/kcim/service/impl/IncomeCollectionServiceImpl.java
  50. 7 5
      src/main/java/com/kcim/service/impl/PatientItemImportServiceImpl.java
  51. 264 92
      src/main/java/com/kcim/service/impl/ProjectCostServiceImpl.java
  52. 3 0
      src/main/java/com/kcim/service/impl/ReportServiceImpl.java
  53. 2424 0
      src/main/java/com/kcim/service/impl/StandardReportServiceImpl.java
  54. 14 0
      src/main/java/com/kcim/vo/AllocationQueryReportVO.java
  55. 60 0
      src/main/java/com/kcim/vo/BaseDeptCostReportVO.java
  56. 118 0
      src/main/java/com/kcim/vo/ClinicalDeptFullCostVO.java
  57. 133 0
      src/main/java/com/kcim/vo/ClinicalDeptMedicalCostVO.java
  58. 26 0
      src/main/java/com/kcim/vo/CommonResponsibilityReportVo.java
  59. 7 0
      src/main/java/com/kcim/vo/CostDepartmentProfitVO.java
  60. 74 0
      src/main/java/com/kcim/vo/DeptDirectMedicalCostVO.java
  61. 47 0
      src/main/java/com/kcim/vo/DeptFullDirectCostVO.java
  62. 197 0
      src/main/java/com/kcim/vo/DiseaseCostDetailVO.java
  63. 27 0
      src/main/java/com/kcim/vo/DynMultiLevelVo.java
  64. 42 0
      src/main/java/com/kcim/vo/HospitalDeptCostAllocationVO.java
  65. 61 0
      src/main/java/com/kcim/vo/HospitalServiceProjectCostVO.java
  66. 54 0
      src/main/java/com/kcim/vo/HospitalVisitCostCompositionVO.java
  67. 110 0
      src/main/java/com/kcim/vo/ProfitCalculationDataVo.java
  68. 5 0
      src/main/java/com/kcim/vo/ReportFormCustomVo.java
  69. 47 0
      src/main/java/com/kcim/vo/StandCostDictMapVO.java
  70. 27 0
      src/main/java/com/kcim/vo/StandardReportFormCustomVo.java
  71. 5 4
      src/main/java/com/kcim/web/CostDataController.java
  72. 157 0
      src/main/java/com/kcim/web/StandardReportController.java
  73. 21 0
      src/main/java/com/kcim/web/reponse/ClinicalDeptFullCostAnalysisResponse.java
  74. 21 0
      src/main/java/com/kcim/web/reponse/StandardDeptCostCollectResponse.java
  75. 10 10
      src/main/resources/application-prod.yml
  76. 50 1
      src/main/resources/mapper/AllocationQueryMapper.xml
  77. 0 3
      src/main/resources/mapper/ComputeDrugCostMapper.xml
  78. 2 4
      src/main/resources/mapper/ComputeItemCostMapper.xml
  79. 180 0
      src/main/resources/mapper/ComputePatientCostAccountMapper.xml
  80. 21 2
      src/main/resources/mapper/ComputeProjectCostAccountMapper.xml
  81. 78 0
      src/main/resources/mapper/CostIncomeGroupMapper.xml
  82. 8 0
      src/main/resources/mapper/GenericBatchMapper.xml
  83. 11 0
      src/main/resources/mapper/IncomeCollectionMapper.xml
  84. 24 0
      src/main/resources/mapper/ItemMapper.xml
  85. 1 0
      src/main/resources/mapper/ResponsibilityDepartmentMapper.xml

+ 4 - 0
src/main/java/com/kcim/common/constants/Constant.java

@@ -191,6 +191,10 @@ public interface Constant {
      * 会计科目类别
      */
     String ACCOUNTING_TYPE = "ACCOUNTING_TYPE";
+    /**
+     * 标准成本类别
+     */
+    String STANDARD_COST_CATEGORIES = "STANDARD_COST_CATEGORIES";
     /**
      * 标准分摊层级
      */

+ 4 - 4
src/main/java/com/kcim/common/constants/ParameterConstant.java

@@ -58,12 +58,12 @@ public interface ParameterConstant {
     Long SHOW_PERCENT=1851077044079824896L;
 
     /**
-     * 科室损益同环比计算方式 1代码计算 2脚本计算
+     * 需要用脚本计算的科室损益及全院损益报表类型
      */
-    Long DEPT_YM_CALC_TYPE =1943243153054240768L;
+    Long SQL_CALC_REPORT_TYPE =1943243153054240768L;
 
     /**
-     * 需要用脚本计算的科室损益及全院损益报表类型
+     * 诊次床日分摊参数代码
      */
-    Long SQL_CALC_REPORT_TYPE =1945667397503553536L;
+    Long VISITS_BED_DAYS_PARAM_CODE =1955568425220837376L;
 }

+ 31 - 1
src/main/java/com/kcim/common/util/BeanUtil.java

@@ -5,6 +5,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.util.CollectionUtils;
 
 import java.lang.reflect.Field;
+import java.math.BigDecimal;
 import java.util.*;
 
 @Slf4j
@@ -111,6 +112,35 @@ public final class BeanUtil {
         return target;
     }
 
+    /**
+     * 将对象中所有BigDecimal类型的字段设置为0
+     *
+     * @param target 目标对象
+     * @param <T>    对象类型
+     * @return 设置后的对象
+     */
+    public static <T> T initBigDecimalFieldsToZero(T target) {
+        if (target == null) {
+            return null;
+        }
+
+        Class<?> clazz = target.getClass();
+        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
+            Field[] fields = clazz.getDeclaredFields();
+            for (Field field : fields) {
+                if (field.getType().equals(BigDecimal.class)) {
+                    field.setAccessible(true);
+                    try {
+                        field.set(target, BigDecimal.ZERO);
+                    } catch (IllegalAccessException e) {
+                        log.error("设置BigDecimal字段默认值异常", e);
+                    }
+                }
+            }
+        }
+        return target;
+    }
+
     private static class CacheFieldMap {
         private static Map<String, Map<String, Field>> cacheMap = new HashMap<>();
 
@@ -147,4 +177,4 @@ public final class BeanUtil {
         BeanUtils.copyProperties(source, result);
         return result;
     }
-}
+}

+ 1 - 3
src/main/java/com/kcim/dao/mapper/AllocationMapper.java

@@ -2,8 +2,6 @@ package com.kcim.dao.mapper;
 
 
 import com.kcim.dao.model.Allocation;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.kcim.vo.AfterAllocationVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -18,7 +16,7 @@ import java.util.List;
  * @date 2021-08-25 08:45:06
  */
 @Mapper
-public interface AllocationMapper extends BaseMapper<Allocation> {
+public interface AllocationMapper extends GenericBatchMapper<Allocation> {
 
     /**
      * 分摊后查询列表

+ 27 - 2
src/main/java/com/kcim/dao/mapper/AllocationQueryMapper.java

@@ -1,7 +1,6 @@
 package com.kcim.dao.mapper;
 
 import com.kcim.dao.model.AllocationQuery;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.kcim.vo.CodeAndNameVO;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -16,7 +15,7 @@ import java.util.List;
  * @date 2021-08-26 08:51:45
  */
 @Mapper
-public interface AllocationQueryMapper extends BaseMapper<AllocationQuery> {
+public interface AllocationQueryMapper extends GenericBatchMapper<AllocationQuery> {
 
     BigDecimal getTotalMoney(@Param("dateYear") int dateYear, @Param("month") int month, @Param("hospId") Long hospId);
 
@@ -30,4 +29,30 @@ public interface AllocationQueryMapper extends BaseMapper<AllocationQuery> {
 
     BigDecimal getTotalByAccountAndRespCode(@Param("hospId") Long hospId, @Param("dateYear") int dateYear, @Param("month") int month, @Param("accountCode") String accountCode, @Param("responsibilityCode") String responsibilityCode);
 
+    /**
+     * 获取医院所有会计科目成本(临床层的)
+     * @param hospId
+     * @param dateYear
+     * @param month
+     * @return
+     */
+    List<AllocationQuery> getAcountAccounts(@Param("hospId") Long hospId, @Param("dateYear") int dateYear, @Param("month") int month);
+
+    /**
+     * 获取医院各责任中心所有会计科目成本
+     * @param hospId
+     * @param dateYear
+     * @param month
+     * @return
+     */
+    List<AllocationQuery> getRespAcountAccounts(@Param("hospId") Long hospId, @Param("dateYear") int dateYear, @Param("month") int month);
+
+    /**
+     * 获取医院各责任中心不同来源类型的会计科目成本
+     * @param hospId
+     * @param dateYear
+     * @param month
+     * @return
+     */
+    List<AllocationQuery> getRespOriginAcountAccounts(@Param("hospId") Long hospId, @Param("dateYear") int dateYear, @Param("month") int month);
 }

+ 129 - 0
src/main/java/com/kcim/dao/mapper/BatchInsertProvider.java

@@ -0,0 +1,129 @@
+package com.kcim.dao.mapper;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import org.apache.ibatis.annotations.Param;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 动态生成批量插入SQL,通过反射解析实体类注解
+ * 优化生成的SQL语句以提高批量插入性能
+ */
+public class BatchInsertProvider {
+
+    /**
+     * 生成批量插入SQL
+     * @param list 实体列表(必须传入非空列表,否则无法解析表结构)
+     * @param <T> 实体类型
+     * @return 动态生成的SQL语句
+     */
+    public <T> String insertBatch(@Param("list") List<T> list) {
+        // 确保我们有一个标准的ArrayList,以处理SubList等特殊情况
+        List<T> standardList = new ArrayList<>(list);
+        long timeMillis = System.currentTimeMillis();
+        if (standardList.isEmpty()) {
+            throw new IllegalArgumentException("批量插入的列表不能为空");
+        }
+
+        // 获取实体类信息
+        Class<?> entityClass = standardList.get(0).getClass();
+        // 获取表名(优先使用@TableName注解,否则用类名)
+        TableName tableNameAnnotation = entityClass.getAnnotation(TableName.class);
+        String tableName = tableNameAnnotation != null ? tableNameAnnotation.value() : entityClass.getSimpleName();
+
+        // 收集所有需要处理的字段(统一字段列表)
+        List<Field> validFields = new ArrayList<>();
+        Field[] fields = entityClass.getDeclaredFields();
+        boolean haveDelFlag = Arrays.stream(fields).anyMatch(field ->"delFlag".equals(field.getName())|| "del_flag".equals(field.getName()));
+        
+        for (Field field : fields) {
+            // 跳过static和final字段,如serialVersionUID
+            if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) || java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
+                continue;
+            }
+
+            TableField fieldAnnotation = field.getAnnotation(TableField.class);
+            // 跳过非数据库字段
+            if (fieldAnnotation != null && !fieldAnnotation.exist()) {
+                continue;
+            }
+
+            validFields.add(field);
+        }
+
+        // 解析所有数据库字段(基于统一的validFields列表)
+        StringBuilder columns = new StringBuilder();
+        for (Field field : validFields) {
+            // 获取数据库字段名(优先使用@TableField注解,否则用驼峰转下划线)
+            String columnName;
+            TableField fieldAnnotation = field.getAnnotation(TableField.class);
+            if (fieldAnnotation != null && !"".equals(fieldAnnotation.value())) {
+                columnName = fieldAnnotation.value();
+            } else {
+                columnName = camelToUnderline(field.getName());
+            }
+
+            // 为字段名添加反引号,避免MySQL保留字冲突
+            columns.append("`").append(columnName).append("`,");
+        }
+
+        // 移除最后一个逗号
+        if (columns.length() > 0) {
+            columns.setLength(columns.length() - 1);
+        }
+
+        // 生成VALUES部分 - 直接构建适合MyBatis @InsertProvider使用的SQL
+        StringBuilder valueSql = new StringBuilder();
+        valueSql.append("<foreach collection=\"list\" item=\"item\" separator=\",\">");
+        valueSql.append("(");
+        for (Field field : validFields) {
+            String fieldName = field.getName();
+
+            // 特殊字段处理逻辑
+            if ("delFlag".equals(fieldName) && haveDelFlag) {
+                // 当haveDelFlag为true时,设置del_flag=0
+                valueSql.append("0,");
+            } else if ("deleteTime".equals(fieldName) && !haveDelFlag) {
+                // 当haveDelFlag为false时,设置delete_time=0
+                valueSql.append("0,");
+            } else if (("createTime".equals(fieldName) || "updateTime".equals(fieldName))&& !haveDelFlag) {
+                // 无论haveDelFlag如何,create_time和update_time等于timeMillis
+                valueSql.append(timeMillis).append(",");
+            } else {
+                // 使用实体类属性名(MyBatis会自动映射)
+                valueSql.append("#{item.").append(fieldName).append("},");
+            }
+        }
+        // 移除最后一个逗号
+        if (valueSql.charAt(valueSql.length() - 1) == ',') {
+            valueSql.setLength(valueSql.length() - 1);
+        }
+        valueSql.append(")");
+        valueSql.append("</foreach>");
+
+        // 拼接完整SQL - 添加<script>标签确保MyBatis正确解析动态SQL
+        return "<script>INSERT INTO " + tableName + " (" + columns + ") VALUES " + valueSql + "</script>";
+    }
+
+    // 驼峰转下划线(适配数据库命名规范)
+    private String camelToUnderline(String camelCase) {
+        if (camelCase == null || camelCase.isEmpty()) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        sb.append(Character.toLowerCase(camelCase.charAt(0)));
+        for (int i = 1; i < camelCase.length(); i++) {
+            char c = camelCase.charAt(i);
+            if (Character.isUpperCase(c)) {
+                sb.append("_").append(Character.toLowerCase(c));
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+}

+ 68 - 0
src/main/java/com/kcim/dao/mapper/ComputePatientCostAccountMapper.java

@@ -0,0 +1,68 @@
+package com.kcim.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.kcim.dao.model.ComputePatientCostAccount;
+import com.kcim.vo.DiseaseCostDetailVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 患者成本的会计科目金额表
+ * 
+ * @author Wang.YS
+ * @date 2025-08-22 17:57:23
+ */
+@Mapper
+public interface ComputePatientCostAccountMapper extends BaseMapper<ComputePatientCostAccount> {
+
+
+    /**
+     * 获取疾病成本明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDiseaseCostDetailList(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+
+    /**
+     * 获取疾病成本构成明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDiseaseCostCompositionDetail(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+
+    /**
+     * 获取服务单元疾病成本构成明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDeptDiseaseCostCompositionDetail(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+
+    /**
+     * 获取DRG成本明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDrgCostDetailList(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+
+    /**
+     * 获取DRG成本构成明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDrgCostCompositionDetail(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+
+    /**
+     * 获取服务单元DRG成本构成明细
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDeptDrgCostCompositionDetail(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+}

+ 25 - 0
src/main/java/com/kcim/dao/mapper/ComputeProjectCostAccountMapper.java

@@ -0,0 +1,25 @@
+package com.kcim.dao.mapper;
+
+import com.kcim.dao.model.ComputeProjectCostAccount;
+import com.kcim.vo.HospitalServiceProjectCostVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目成本的会计科目金额表
+ * 
+ * @author Wang.YS
+ * @date 2025-08-22 17:57:23
+ */
+@Mapper
+public interface ComputeProjectCostAccountMapper extends GenericBatchMapper<ComputeProjectCostAccount> {
+
+    /**
+     * @param computeDate
+     * @param hospId
+     * @return
+     */
+    List<HospitalServiceProjectCostVO> getMedicalServiceCostDetailList(@Param("computeDate") String computeDate, @Param("hospId") Long hospId);
+}

+ 1 - 1
src/main/java/com/kcim/dao/mapper/ComputeProjectCostDetailMapper.java

@@ -15,7 +15,7 @@ import java.util.List;
  * @date 2024-01-15 20:23:56
  */
 @Mapper
-public interface ComputeProjectCostDetailMapper extends BaseMapper<ComputeProjectCostDetail> {
+public interface ComputeProjectCostDetailMapper extends GenericBatchMapper<ComputeProjectCostDetail> {
 
     List<ComputeProjectCostPageDto> getByProjectCostId(@Param("computeDate") String computeDate,
                                                        @Param("hospId") Long hospId,

+ 1 - 2
src/main/java/com/kcim/dao/mapper/ComputeProjectGroupCostDetailMapper.java

@@ -1,7 +1,6 @@
 package com.kcim.dao.mapper;
 
 import com.kcim.dao.model.ComputeProjectGroupCostDetail;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
@@ -11,6 +10,6 @@ import org.apache.ibatis.annotations.Mapper;
  * @date 2024-01-19 15:53:57
  */
 @Mapper
-public interface ComputeProjectGroupCostDetailMapper extends BaseMapper<ComputeProjectGroupCostDetail> {
+public interface ComputeProjectGroupCostDetailMapper extends GenericBatchMapper<ComputeProjectGroupCostDetail> {
 	
 }

+ 16 - 0
src/main/java/com/kcim/dao/mapper/CostDepartmentProfitAccountMapper.java

@@ -0,0 +1,16 @@
+package com.kcim.dao.mapper;
+
+import com.kcim.dao.model.CostDepartmentProfitAccount;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 科室损益的会计科目金额表
+ * 
+ * @author Wang.YS
+ * @date 2025-09-19 14:14:25
+ */
+@Mapper
+public interface CostDepartmentProfitAccountMapper extends GenericBatchMapper<CostDepartmentProfitAccount> {
+	
+}

+ 1 - 2
src/main/java/com/kcim/dao/mapper/CostDepartmentProfitMapper.java

@@ -1,6 +1,5 @@
 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;
@@ -15,7 +14,7 @@ import java.util.List;
  * @date 2021-08-24 16:24:08
  */
 @Mapper
-public interface CostDepartmentProfitMapper extends BaseMapper<CostDepartmentProfit> {
+public interface CostDepartmentProfitMapper extends GenericBatchMapper<CostDepartmentProfit> {
 
 
     Integer getMaxYear(@Param("hospId") Long hospId);

+ 11 - 4
src/main/java/com/kcim/dao/mapper/CostIncomeGroupMapper.java

@@ -1,14 +1,13 @@
 package com.kcim.dao.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.kcim.dao.model.CostIncomeGroup;
-import com.kcim.vo.CollectionVO;
-import com.kcim.vo.CommonDepartVo;
-import com.kcim.vo.CostIncomeGroupAllAmountBO;
-import com.kcim.vo.CostIncomeGroupAllAmountVO;
+import com.kcim.vo.*;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -58,4 +57,12 @@ public interface CostIncomeGroupMapper extends BaseMapper<CostIncomeGroup> {
     List<CostIncomeGroup> selectHistoryList(@Param("hospId") Long hospId,@Param("id") Long id);
 
     void reducingHistory(@Param("id") Long id,@Param("hospId") Long hospId,@Param("list") List<Long> list);
+
+    List<CostIncomeGroup>  getOrderDeptProductList(Page<PatientInfoVo> page, @Param("year") Integer year, @Param("month") Integer month, @Param("departmentCode") String departmentCode, @Param("hospId") Long hospId, @Param("filter") String filter);
+
+    List<CostIncomeGroup> getExecDeptProductList(@Param("page") Page<PatientInfoVo> page, @Param("year") Integer year, @Param("month") Integer month, @Param("departmentCode") String departmentCode, @Param("hospId") Long hospId, @Param("filter") String filter);
+
+    BigDecimal getTotalAmount(@Param("year") Integer year, @Param("month") Integer month, @Param("departmentCode") String departmentCode, @Param("hospId") Long hospId);
+
+    BigDecimal getDeptTotalAmount(@Param("year") Integer year, @Param("month") Integer month, @Param("departmentCode") String departmentCode, @Param("hospId") Long hospId);
 }

+ 24 - 0
src/main/java/com/kcim/dao/mapper/GenericBatchMapper.java

@@ -0,0 +1,24 @@
+package com.kcim.dao.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.Options;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 通用批量插入接口,继承BaseMapper保留原有CRUD功能
+ * @param <T> 实体类泛型
+ */
+public interface GenericBatchMapper<T> extends BaseMapper<T> {
+
+    /**
+     * 通用批量插入方法
+     * @param list 实体列表
+     * @return 插入成功的记录数
+     */
+    @InsertProvider(type = BatchInsertProvider.class, method = "insertBatch")
+    @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
+    int insertBatch(@Param("list") List<T> list);
+}

+ 1 - 1
src/main/java/com/kcim/dao/mapper/ImportPatientItemMapper.java

@@ -27,7 +27,7 @@ public interface ImportPatientItemMapper extends BaseMapper<ImportPatientItem> {
     List<PatientItemVo> getAllGroupByOrder(@Param("computeDate") String computeDate,
                                            @Param("hospId") Long hospId);
 
-    List<PatientInfoVo> getPatientItemPatientInfo(@Param("computeDate") String computeDate,
+    List<PatientInfoVo> getPatientItemPatientInfo(Page<PatientInfoVo> page, @Param("computeDate") String computeDate,
                                                   @Param("filter") String filter,
                                                   @Param("hospId") Long hospId);
 

+ 2 - 0
src/main/java/com/kcim/dao/mapper/IncomeCollectionMapper.java

@@ -63,4 +63,6 @@ public interface IncomeCollectionMapper extends BaseMapper<IncomeCollection> {
 
     BigDecimal getCountByResponsibilitiesAndAccounts(@Param("responsibilityCodes") List<String> responsibilityCodes, @Param("accountingCodes") List<String> accountingCodes, @Param("hospId") Long hospId, @Param("date") String date);
 
+    List<IncomeCollection> getResponsibilitiesAccounts(@Param("year") int year, @Param("month") int month, @Param("hospId") Long hospId);
+
 }

+ 10 - 2
src/main/java/com/kcim/dao/mapper/ItemMapper.java

@@ -1,8 +1,11 @@
 package com.kcim.dao.mapper;
 
-import com.kcim.dao.model.Item;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.kcim.dao.model.Item;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * 收费项目管理
@@ -12,5 +15,10 @@ import org.apache.ibatis.annotations.Mapper;
  */
 @Mapper
 public interface ItemMapper extends BaseMapper<Item> {
-	
+    /**
+     * 获取责任中心的医疗服务项目字典
+     * @param hospId
+     * @return
+     */
+	public List<Item> getRespItemList(@Param("hospId") Long hospId);
 }

+ 13 - 5
src/main/java/com/kcim/dao/model/AllocationQuery.java

@@ -3,16 +3,14 @@ package com.kcim.dao.model;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
-
-import java.math.BigDecimal;
-import java.io.Serializable;
-import java.util.Date;
-
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
+
 /**
  * 
  * 
@@ -99,4 +97,14 @@ public class AllocationQuery implements Serializable {
 
 	private Integer shareType;
 
+//	/**
+//	 * 标准科室分类(来自责任中心)
+//	 */
+//	private String standardShareLevel;
+//
+//	/**
+//	 * 费用类型(来自会计科目字典)
+//	 */
+//	private String expandOne;
+
 }

+ 91 - 0
src/main/java/com/kcim/dao/model/ComputePatientCostAccount.java

@@ -0,0 +1,91 @@
+package com.kcim.dao.model;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 患者成本的会计科目金额表
+ * 
+ * @author Wang.YS
+
+ * @date 2025-08-22 17:57:23
+ */
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("compute_patient_cost_account")
+public class ComputePatientCostAccount implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键
+	 */
+	@TableId
+	private Integer id;
+	/**
+	 * 医院id
+	 */
+	private Long hospId;
+	/**
+	 * 核算年月
+	 */
+	private String computeDate;
+	/**
+	 * 项目成本主键
+	 */
+	private Integer patientCostId;
+	/**
+	 * 成本类别
+	 */
+	private String costType;
+	/**
+	 * 会计科目类别
+	 */
+	private String accountType;
+	/**
+	 * 计算结果
+	 */
+	private BigDecimal computeResult;
+	/**
+	 * 标准法计算结果
+	 */
+	private BigDecimal standComputeResult;
+	/**
+	 * 创建人
+	 */
+	private String createUser;
+	/**
+	 * 创建时间
+	 */
+	private Date createTime;
+	/**
+	 * 更新人
+	 */
+	private String updateUser;
+	/**
+	 * 更新时间
+	 */
+	private Date updateTime;
+	/**
+	 * 删除人
+	 */
+	private String deleteUser;
+	/**
+	 * 删除时间
+	 */
+	private Date deleteTime;
+	/**
+	 * 删除标志  0正常 1作废
+	 */
+	private Integer delFlag;
+
+}

+ 18 - 0
src/main/java/com/kcim/dao/model/ComputeProjectCost.java

@@ -10,7 +10,9 @@ import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.Date;
+import java.util.Map;
 
 /**
  * 完全成本法项目成本计算表
@@ -74,6 +76,12 @@ public class ComputeProjectCost implements Serializable {
 	 * 责任中心名称
 	 */
 	private String responsibilityName;
+
+	/**
+	 * 数量
+	 */
+	private BigDecimal quantity;
+
 	/**
 	 * 创建人
 	 */
@@ -108,6 +116,16 @@ public class ComputeProjectCost implements Serializable {
 	private Integer index;
 
 
+	/**
+	 * 项目成本的会计科目表
+	 */
+	@TableField(exist = false)
+	Map<String,ComputeProjectCostAccount> projectCostAccountMap;
 
+	/**
+	 * 标准项目代码
+	 */
+	@TableField(exist = false)
+	private String standItemCode;
 
 }

+ 104 - 0
src/main/java/com/kcim/dao/model/ComputeProjectCostAccount.java

@@ -0,0 +1,104 @@
+package com.kcim.dao.model;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目成本的会计科目金额表
+ * 
+ * @author Wang.YS
+
+ * @date 2025-08-22 17:57:23
+ */
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("compute_project_cost_account")
+public class ComputeProjectCostAccount implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键
+	 */
+	@TableId
+	private Integer id;
+	/**
+	 * 医院id
+	 */
+	private Long hospId;
+	/**
+	 * 核算年月
+	 */
+	private String computeDate;
+	/**
+	 * 项目成本主键
+	 */
+	private Integer projectCostId;
+	/**
+	 * 标准项目代码
+	 */
+	private String standItemCode;
+	/**
+	 * 成本类别
+	 */
+	private String costType;
+	/**
+	 * 会计科目类别
+	 */
+	private String accountType;
+
+	/**
+	 * 计算结果
+	 */
+	private BigDecimal computeResult;
+	/**
+	 * 单个计算结果
+	 */
+	private BigDecimal computeSingleResult;
+	/**
+	 * 标准法计算结果
+	 */
+	private BigDecimal standComputeResult;
+	/**
+	 * 标准法单个计算结果
+	 */
+	private BigDecimal standComputeSingleResult;
+	/**
+	 * 创建人
+	 */
+	private String createUser;
+	/**
+	 * 创建时间
+	 */
+	private Date createTime;
+	/**
+	 * 更新人
+	 */
+	private String updateUser;
+	/**
+	 * 更新时间
+	 */
+	private Date updateTime;
+	/**
+	 * 删除人
+	 */
+	private String deleteUser;
+	/**
+	 * 删除时间
+	 */
+	private Date deleteTime;
+	/**
+	 * 删除标志  0正常 1作废
+	 */
+	private Integer delFlag;
+
+}

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

@@ -11,6 +11,7 @@ import lombok.experimental.Accessors;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * 科室损益计算
@@ -145,5 +146,11 @@ public class CostDepartmentProfit implements Serializable {
 	 */
 	private BigDecimal yoyRate;
 
+	/**
+	 * 会计科目金额列表
+	 */
+	@TableField(exist = false)
+	private List<CostDepartmentProfitAccount> costDepartmentProfitAccounts;
+
 
 }

+ 87 - 0
src/main/java/com/kcim/dao/model/CostDepartmentProfitAccount.java

@@ -0,0 +1,87 @@
+package com.kcim.dao.model;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 科室损益的会计科目金额表
+ * 
+ * @author Wang.YS
+
+ * @date 2025-09-19 14:14:25
+ */
+@Data
+@Accessors(chain = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("cost_department_profit_account")
+public class CostDepartmentProfitAccount implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键
+	 */
+	@TableId
+	private Integer id;
+	/**
+	 * 医院id
+	 */
+	private Long hospId;
+	/**
+	 * 核算年月
+	 */
+	private String computeDate;
+	/**
+	 * 项目成本主键
+	 */
+	private Long deptProfitId;
+	/**
+	 * 成本类别
+	 */
+	private String costType;
+	/**
+	 * 会计科目类别
+	 */
+	private String accountType;
+	/**
+	 * 金额
+	 */
+	private BigDecimal amount;
+	/**
+	 * 创建人
+	 */
+	private String createUser;
+	/**
+	 * 创建时间
+	 */
+	private Date createTime;
+	/**
+	 * 更新人
+	 */
+	private String updateUser;
+	/**
+	 * 更新时间
+	 */
+	private Date updateTime;
+	/**
+	 * 删除人
+	 */
+	private String deleteUser;
+	/**
+	 * 删除时间
+	 */
+	private Date deleteTime;
+	/**
+	 * 删除标志  0正常 1作废
+	 */
+	private Integer delFlag;
+
+}

+ 6 - 0
src/main/java/com/kcim/dao/model/Item.java

@@ -167,4 +167,10 @@ public class Item implements Serializable {
 	private String departmentName;
 	@TableField(exist = false)
 	private StandItem standItem;
+
+	/**
+	 * 责任中心代码
+	 */
+	@TableField(exist = false)
+	private String responsibilityCode;
 }

+ 2 - 1
src/main/java/com/kcim/dao/model/Responsibility.java

@@ -70,6 +70,7 @@ public class Responsibility implements Serializable {
 	 * 分摊级别 如果是顶层默认为0
 	 */
 	private Integer shareLevel;
+
 	/**
 	 * 分摊级别名称
 	 */
@@ -95,7 +96,7 @@ public class Responsibility implements Serializable {
 	}
 
 	/**
-	 * 标准分摊层级
+	 * 标准分摊层级 标准分摊层级代码 1.行政后勤类,2.医疗辅助类,3.医疗技术类,4.临床服务类
 	 */
 	private String standardShareLevel;
 	@TableField(exist = false)

+ 15 - 6
src/main/java/com/kcim/dao/model/StandItem.java

@@ -4,18 +4,17 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.baomidou.mybatisplus.annotation.TableName;
-
-import java.math.BigDecimal;
-import java.io.Serializable;
-import java.util.Date;
-import java.util.List;
-
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
 /**
  * 标准项目管理
  * 
@@ -90,6 +89,16 @@ public class StandItem implements Serializable {
 
 	private String itemType;
 
+	/**
+	 * 父级项目代码
+	 */
+	private String parentCode;
+
+	/**
+	 * 顺序号
+	 */
+	private Integer sort;
+
 	@TableField(exist = false)
 	private String itemTypeName;
 

+ 47 - 0
src/main/java/com/kcim/dao/model/dto/ParamContainerDTO.java

@@ -0,0 +1,47 @@
+package com.kcim.dao.model.dto;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * 泛型参数容器,可动态添加任意类型对象
+ * @author Administrator
+ */
+public class ParamContainerDTO {
+    /**
+     * 参数
+     */
+    private Map<String, Object> params = new HashMap<>();
+
+    /**
+     * 添加参数
+     * @param key
+     * @param value
+     * @param <T>
+     */
+    public <T> void put(String key, T value) {
+        params.put(key, value);
+    }
+
+    /**
+     * 获取参数(带类型转换)
+     * @param key
+     * @param <T>
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T get(String key) {
+        return (T) params.get(key);
+    }
+
+    /**
+     * 判断是否包含某个参数
+     * @param key
+     * @return
+     */
+    public boolean contains(String key) {
+        return params.containsKey(key);
+    }
+}

+ 7 - 0
src/main/java/com/kcim/dao/repository/AccountingRepository.java

@@ -41,6 +41,13 @@ public class AccountingRepository extends ServiceImpl<AccountingMapper, Accounti
         return this.list(queryWrapper);
     }
 
+    public List<Accounting> getAllCostAccounting() {
+        LambdaQueryWrapper<Accounting> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(Accounting::getHospId, UserContext.getHospId());
+        queryWrapper.eq(Accounting::getAccountingType, NumberConstant.TWO);
+        return this.list(queryWrapper);
+    }
+
     public List<Accounting> getList(Integer accountType) {
         LambdaQueryWrapper<Accounting> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(Accounting::getHospId, UserContext.getHospId());

+ 3 - 4
src/main/java/com/kcim/dao/repository/ComputeLastProfitDateRepository.java

@@ -2,7 +2,6 @@ package com.kcim.dao.repository;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.kcim.common.util.UserContext;
 import com.kcim.dao.mapper.ComputeLastProfitDateMapper;
 import com.kcim.dao.model.ComputeLastProfitDate;
 import org.springframework.stereotype.Repository;
@@ -25,13 +24,13 @@ public class ComputeLastProfitDateRepository extends ServiceImpl<ComputeLastProf
     }
 
 
-    public void saveLastComputeDate(Long hospId,String computeDate) {
+    public void saveLastComputeDate(Long hospId,String computeDate,Long userId) {
         ComputeLastProfitDate lastComputeDate = getLastComputeDate(hospId);
         if(Objects.nonNull(lastComputeDate)){
             //当前院区已有记录 更新
             lastComputeDate.setComputeDate(computeDate);
             lastComputeDate.setUpdateTime(new Date());
-            lastComputeDate.setUpdateUser(String.valueOf(UserContext.getCurrentUser().getId()));
+            lastComputeDate.setUpdateUser(String.valueOf(userId));
             this.updateById(lastComputeDate);
         }else {
             //当前院区无记录 新增
@@ -39,7 +38,7 @@ public class ComputeLastProfitDateRepository extends ServiceImpl<ComputeLastProf
             computeLastProfitDate.setHospId(hospId);
             computeLastProfitDate.setComputeDate(computeDate);
             computeLastProfitDate.setCreateTime(new Date());
-            computeLastProfitDate.setCreateUser(String.valueOf(UserContext.getCurrentUser().getId()));
+            computeLastProfitDate.setCreateUser(String.valueOf(userId));
             this.save(computeLastProfitDate);
         }
     }

+ 51 - 0
src/main/java/com/kcim/dao/repository/ComputePatientCostAccountRepository.java

@@ -0,0 +1,51 @@
+package com.kcim.dao.repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.kcim.common.util.UserContext;
+import com.kcim.dao.mapper.ComputePatientCostAccountMapper;
+import com.kcim.dao.model.ComputePatientCostAccount;
+import com.kcim.vo.DiseaseCostDetailVO;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2023-11-27 17:52
+ **/
+@Repository
+public class ComputePatientCostAccountRepository extends ServiceImpl<ComputePatientCostAccountMapper, ComputePatientCostAccount> {
+    public List<ComputePatientCostAccount> getList(String computeDate) {
+        LambdaQueryWrapper<ComputePatientCostAccount> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(ComputePatientCostAccount::getHospId, UserContext.getHospId());
+        queryWrapper.eq(ComputePatientCostAccount::getComputeDate, computeDate);
+        return this.list(queryWrapper);
+    }
+
+    public List<DiseaseCostDetailVO> getDiseaseCostDetailList(String computeDate) {
+        return this.baseMapper.getDiseaseCostDetailList(computeDate, UserContext.getHospId());
+    }
+
+    public List<DiseaseCostDetailVO> getDiseaseCostCompositionDetail(String computeDate) {
+        return this.baseMapper.getDiseaseCostCompositionDetail(computeDate, UserContext.getHospId());
+    }
+
+    public List<DiseaseCostDetailVO> getDeptDiseaseCostCompositionDetail(String computeDate) {
+        return this.baseMapper.getDeptDiseaseCostCompositionDetail(computeDate, UserContext.getHospId());
+    }
+
+    public List<DiseaseCostDetailVO> getDrgCostDetailList(String computeDate) {
+        return this.baseMapper.getDrgCostDetailList(computeDate, UserContext.getHospId());
+    }
+
+    public List<DiseaseCostDetailVO> getDrgCostCompositionDetail(String computeDate) {
+        return this.baseMapper.getDrgCostCompositionDetail(computeDate, UserContext.getHospId());
+    }
+
+    public List<DiseaseCostDetailVO> getDeptDrgCostCompositionDetail(String computeDate) {
+        return this.baseMapper.getDeptDrgCostCompositionDetail(computeDate, UserContext.getHospId());
+    }
+}

+ 45 - 0
src/main/java/com/kcim/dao/repository/ComputeProjectCostAccountRepository.java

@@ -0,0 +1,45 @@
+package com.kcim.dao.repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.kcim.common.util.UserContext;
+import com.kcim.dao.mapper.ComputeProjectCostAccountMapper;
+import com.kcim.dao.model.ComputeProjectCostAccount;
+import com.kcim.service.impl.BaseBatchServiceImpl;
+import com.kcim.vo.HospitalServiceProjectCostVO;
+import com.kcim.vo.SessionUserVO;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2023-11-27 17:52
+ **/
+@Repository
+public class ComputeProjectCostAccountRepository extends BaseBatchServiceImpl<ComputeProjectCostAccountMapper, ComputeProjectCostAccount> {
+    public List<ComputeProjectCostAccount> getList(String computeDate) {
+        LambdaQueryWrapper<ComputeProjectCostAccount> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(ComputeProjectCostAccount::getHospId, UserContext.getHospId());
+        queryWrapper.eq(ComputeProjectCostAccount::getComputeDate, computeDate);
+        return this.list(queryWrapper);
+    }
+
+    public List<HospitalServiceProjectCostVO> getMedicalServiceCostDetailList(String computeDate) {
+        return this.baseMapper.getMedicalServiceCostDetailList(computeDate, UserContext.getHospId());
+    }
+
+    public void removeByComputeDate(String computeDate, SessionUserVO currentUser) {
+        UpdateWrapper<ComputeProjectCostAccount> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.lambda().eq(ComputeProjectCostAccount::getDelFlag, 0)
+                .eq(ComputeProjectCostAccount::getHospId, currentUser.getHospId())
+                .eq(ComputeProjectCostAccount::getComputeDate, computeDate)
+                .set(ComputeProjectCostAccount::getDeleteTime,new Date())
+                .set(ComputeProjectCostAccount::getDeleteUser,String.valueOf(currentUser.getId()))
+                .set(ComputeProjectCostAccount::getDelFlag, 1);
+        this.update(updateWrapper);
+    }
+}

+ 2 - 1
src/main/java/com/kcim/dao/repository/ComputeProjectCostDetailRepository.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kcim.common.util.UserContext;
 import com.kcim.dao.mapper.ComputeProjectCostDetailMapper;
 import com.kcim.dao.model.ComputeProjectCostDetail;
+import com.kcim.service.impl.BaseBatchServiceImpl;
 import com.kcim.vo.ComputeProjectCostPageDto;
 import com.kcim.vo.SessionUserVO;
 import org.springframework.stereotype.Repository;
@@ -19,7 +20,7 @@ import java.util.List;
  * @create: 2024-01-15 20:32
  **/
 @Repository
-public class ComputeProjectCostDetailRepository extends ServiceImpl<ComputeProjectCostDetailMapper, ComputeProjectCostDetail> {
+public class ComputeProjectCostDetailRepository extends BaseBatchServiceImpl<ComputeProjectCostDetailMapper, ComputeProjectCostDetail> {
 
 
     public void removeByComputeDate(String computeDate, SessionUserVO currentUser) {

+ 2 - 3
src/main/java/com/kcim/dao/repository/ComputeProjectGroupCostDetailRepository.java

@@ -1,10 +1,9 @@
 package com.kcim.dao.repository;
 
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kcim.dao.mapper.ComputeProjectGroupCostDetailMapper;
-import com.kcim.dao.model.ComputeProjectCostDetail;
 import com.kcim.dao.model.ComputeProjectGroupCostDetail;
+import com.kcim.service.impl.BaseBatchServiceImpl;
 import com.kcim.vo.SessionUserVO;
 import org.springframework.stereotype.Repository;
 
@@ -17,7 +16,7 @@ import java.util.Date;
  * @create: 2024-01-19 15:58
  **/
 @Repository
-public class ComputeProjectGroupCostDetailRepository extends ServiceImpl<ComputeProjectGroupCostDetailMapper, ComputeProjectGroupCostDetail> {
+public class ComputeProjectGroupCostDetailRepository extends BaseBatchServiceImpl<ComputeProjectGroupCostDetailMapper, ComputeProjectGroupCostDetail> {
     public void removeByComputeDate(String computeDate, SessionUserVO currentUser) {
 
         UpdateWrapper<ComputeProjectGroupCostDetail> updateWrapper = new UpdateWrapper<>();

+ 50 - 0
src/main/java/com/kcim/dao/repository/CostDepartmentProfitAccountRepository.java

@@ -0,0 +1,50 @@
+package com.kcim.dao.repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.kcim.common.constants.NumberConstant;
+import com.kcim.common.util.UserContext;
+import com.kcim.dao.mapper.CostDepartmentProfitAccountMapper;
+import com.kcim.dao.model.CostDepartmentProfitAccount;
+import com.kcim.service.impl.BaseBatchServiceImpl;
+import org.springframework.stereotype.Repository;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2023-11-27 17:52
+ **/
+@Repository
+public class CostDepartmentProfitAccountRepository extends BaseBatchServiceImpl<CostDepartmentProfitAccountMapper, CostDepartmentProfitAccount> {
+    public List<CostDepartmentProfitAccount> getList(String computeDate) {
+        LambdaQueryWrapper<CostDepartmentProfitAccount> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(CostDepartmentProfitAccount::getHospId, UserContext.getHospId());
+        queryWrapper.eq(CostDepartmentProfitAccount::getComputeDate, computeDate);
+        return this.list(queryWrapper);
+    }
+
+
+    /**
+     * 删除科室损益的会计科目金额表
+     * @param computeDate
+     * @return
+     */
+    public boolean deleteDeptProfitAccount(String computeDate) {
+        return deleteDeptProfitAccountWithUser(UserContext.getHospId(),computeDate,UserContext.getCurrentUser().getId());
+    }
+
+    public boolean deleteDeptProfitAccountWithUser(Long hospId,String computeDate,Long userId) {
+        LambdaUpdateWrapper<CostDepartmentProfitAccount> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(CostDepartmentProfitAccount::getHospId, hospId);
+        updateWrapper.eq(CostDepartmentProfitAccount::getComputeDate, computeDate);
+        updateWrapper.eq(CostDepartmentProfitAccount::getDelFlag, NumberConstant.ZERO);
+        updateWrapper.set(CostDepartmentProfitAccount::getDelFlag, NumberConstant.ONE);
+        updateWrapper.set(CostDepartmentProfitAccount::getDeleteTime,new Date());
+        updateWrapper.set(CostDepartmentProfitAccount::getDeleteUser, userId);
+        return this.update(updateWrapper);
+    }
+}

+ 10 - 2
src/main/java/com/kcim/dao/repository/ImportPatientItemRepository.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kcim.common.constants.NumberConstant;
+import com.kcim.common.util.PageUtils;
 import com.kcim.common.util.UserContext;
 import com.kcim.dao.mapper.ImportPatientItemMapper;
 import com.kcim.dao.model.ImportPatientItem;
@@ -171,8 +172,15 @@ public class ImportPatientItemRepository extends ServiceImpl<ImportPatientItemMa
         return this.list(queryWrapper);
     }
 
-    public List<PatientInfoVo> getPatientItemPatientInfo(String computeDate, String filter) {
-        return this.baseMapper.getPatientItemPatientInfo(computeDate, filter, UserContext.getHospId());
+    public PageUtils getPatientItemPatientInfo(Integer current, Integer pageSize,String computeDate, String filter) {
+        Page<PatientInfoVo> page = new Page<>(current,pageSize);
+        List<PatientInfoVo> byPage = this.baseMapper.getPatientItemPatientInfo(page,computeDate, filter, UserContext.getHospId());
+        if(!CollectionUtils.isEmpty(byPage)){
+            page.setRecords(byPage);
+        }
+        PageUtils pageUtils = new PageUtils(page);
+        pageUtils.setList(byPage);
+        return pageUtils;
     }
 
     public void removePatientItemByFileId(String computeDate, Long fileId) {

+ 8 - 0
src/main/java/com/kcim/dao/repository/ItemRepository.java

@@ -81,6 +81,14 @@ public class ItemRepository extends ServiceImpl<ItemMapper, Item> {
         }
     }
 
+    /**
+     * 获取责任中心的医疗服务项目字典
+     * @return
+     */
+    public List<Item> getRespItemList(){
+        return this.baseMapper.getRespItemList(UserContext.getHospId());
+    }
+
     public List<Item> getList() {
         LambdaQueryWrapper<Item> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(Item::getHospId, UserContext.getHospId());

+ 7 - 0
src/main/java/com/kcim/service/AllocationQueryService.java

@@ -45,13 +45,20 @@ public interface AllocationQueryService extends IService<AllocationQuery> {
      */
     List<AllocationQuery> getAllByDate(Long hospId, int year, int month);
 
+    List<AllocationQuery> getCostByDate(Long hospId, int year, int month,int originType);
+
     List<AllocationQuery> getByDate(int year, int month, Long hospId, List<Long> levelSorts);
 
     List<AllocationQuery> getByDateAndResp(int year, int month, Long hospId, String responsibilityCode);
 
     List<AllocationQuery> getByDateRespn(int year, int month, Long hospId, List<Long> shareLevelId, String responsibilityCode);
 
+    List<AllocationQuery> getAcountAccounts(Long hospId, int dateYear, int month);
+
+    List<AllocationQuery> getRespAcountAccounts(Long hospId, int dateYear, int month);
 
+    List<AllocationQuery> getRespOriginAcountAccounts(Long hospId, int dateYear, int month);
 
+    void batchInsertAllocationQuery(List<AllocationQuery> allocationQueryList);
 }
 

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

@@ -71,5 +71,7 @@ public interface IncomeCollectionService extends IService<IncomeCollection> {
     List<IncomeCollection> getCollectionsByDate(int year, int month, Long hospId);
 
     List<IncomeCollection> getCollectionsByDateAndResp(int year, int month, Long hospId, String responsibilityCode);
+
+    List<IncomeCollection> getResponsibilitiesAccounts(int year, int month, Long hospId);
 }
 

+ 1 - 1
src/main/java/com/kcim/service/PatientItemImportService.java

@@ -43,7 +43,7 @@ public interface PatientItemImportService {
 
     void removePatientItem(String computeDate);
 
-    Object getPatientItemPatientInfo(String filter, String computeDate);
+    Object getPatientItemPatientInfo(Integer current, Integer pageSize,String filter, String computeDate);
 
     void removePatientItemByFileId(String computeDate,Long fileId);
 

+ 158 - 0
src/main/java/com/kcim/service/StandardReportService.java

@@ -0,0 +1,158 @@
+package com.kcim.service;
+
+import com.kcim.vo.*;
+import com.kcim.web.reponse.ComputeProfitCollectResponse;
+import com.kcim.web.reponse.StandardDeptCostCollectResponse;
+
+import java.util.List;
+
+public interface StandardReportService {
+
+    /**
+     * 科室直接成本表(医疗成本)
+     * @param computeDate
+     */
+    List<DeptDirectMedicalCostVO> getDeptDirectMedicalCost(String computeDate);
+    /**
+     * 科室直接成本表(全成本)
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<DeptFullDirectCostVO> getDeptFullDirectCost(String computeDate);
+
+    /**
+     * 获取临床服务类科室全成本(医疗成本)
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<ClinicalDeptMedicalCostVO> getClinicalDeptMedicalCost(String computeDate);
+
+    /**
+     * 获取临床服务类科室全成本(全成本)
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<ClinicalDeptFullCostVO> getClinicalDeptFullCost(String computeDate);
+
+    /**
+     * 获取医院临床服务类科室全成本构成分析表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    ComputeProfitCollectResponse getClinicalDeptFullCostAnalysis(String computeDate);
+
+    /**
+     * 获取医院科室成本分摊汇总表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<HospitalDeptCostAllocationVO> getHospitalDeptCostAllocation(String computeDate) ;
+
+    /**
+     * 获取医院诊次成本构成表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<HospitalVisitCostCompositionVO> getHospitalVisitCostComposition(String computeDate);
+
+    /**
+     * 获取医院科室诊次成本表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<HospitalVisitCostCompositionVO> getHospitalDeptVisitCost(String computeDate);
+    /**
+     * 获取医院床日成本构成表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<HospitalVisitCostCompositionVO> getHospitalBedDayCostComposition(String computeDate);
+    /**
+     * 获取医院科室床日成本表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    List<HospitalVisitCostCompositionVO> getHospitalDeptBedDayCost(String computeDate);
+
+    /**
+     * 获取医院服务项目成本表数据
+     * @param computeDate
+     * @return
+     */
+    List<HospitalServiceProjectCostVO> getHospitalServiceProjectCost(String computeDate);
+
+    /**
+     * 获取医院服务项目成本明细表数据
+     * @param computeDate
+     * @return
+     */
+    List<HospitalServiceProjectCostVO> getMedicalServiceCostDetail(String computeDate);
+
+    /**
+     * 获取病种成本明细表数据
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDiseaseCostDetail(String computeDate);
+
+    /**
+     * 分页获取病种成本明细表数据
+     * @param current 当前页码
+     * @param pageSize 每页大小
+     * @param computeDate 核算年月
+     * @return 分页数据
+     */
+    Object getDiseaseCostDetailByPage(Integer current, Integer pageSize, String computeDate);
+
+    /**
+     * 获取病种成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDiseaseCostCompositionDetail(String computeDate);
+
+    /**
+     * 分页获取病种成本构成明细表数据
+     * @param current 当前页码
+     * @param pageSize 每页大小
+     * @param computeDate 核算年月
+     * @return 分页数据
+     */
+    Object getDiseaseCostCompositionDetailByPage(Integer current, Integer pageSize, String computeDate);
+
+    /**
+     * 获取服务单元病种成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    StandardDeptCostCollectResponse getDeptDiseaseCostCompositionDetail(String computeDate);
+    
+    /**
+     * 分页获取服务单元病种成本构成明细表数据
+     * @param current 当前页码
+     * @param pageSize 每页大小
+     * @param computeDate 核算年月
+     * @return 分页数据
+     */
+    Object getDeptDiseaseCostCompositionDetailByPage(Integer current, Integer pageSize, String computeDate);
+
+    /**
+     * 获取DRG成本明细表数据
+     * @param computeDate
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDrgCostDetail(String computeDate);
+
+    /**
+     * 获取DRG成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    List<DiseaseCostDetailVO> getDrgCostCompositionDetail(String computeDate);
+
+    /**
+     * 获取服务单元DRG成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    StandardDeptCostCollectResponse getDeptDrgCostCompositionDetail(String computeDate);
+}

+ 43 - 5
src/main/java/com/kcim/service/impl/AllocationQueryServiceImpl.java

@@ -1,13 +1,11 @@
 package com.kcim.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.kcim.vo.CodeAndNameVO;
 import com.kcim.dao.mapper.AllocationQueryMapper;
+import com.kcim.dao.model.AllocationQuery;
 import com.kcim.service.AllocationQueryService;
+import com.kcim.vo.CodeAndNameVO;
 import org.springframework.stereotype.Service;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-
-import com.kcim.dao.model.AllocationQuery;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -15,7 +13,7 @@ import java.util.stream.Collectors;
 
 
 @Service("allocationQueryService")
-public class AllocationQueryServiceImpl extends ServiceImpl<AllocationQueryMapper, AllocationQuery> implements AllocationQueryService {
+public class AllocationQueryServiceImpl extends BaseBatchServiceImpl<AllocationQueryMapper, AllocationQuery> implements AllocationQueryService {
 
 
     /**
@@ -58,6 +56,26 @@ public class AllocationQueryServiceImpl extends ServiceImpl<AllocationQueryMappe
         return baseMapper.getTotalByAccountAndRespCode(hospId, dateYear, month, accountCode, responsibilityCode);
     }
 
+    @Override
+    public List<AllocationQuery> getAcountAccounts(Long hospId, int dateYear, int month) {
+        return baseMapper.getAcountAccounts(hospId, dateYear, month);
+    }
+
+    @Override
+    public List<AllocationQuery> getRespAcountAccounts(Long hospId, int dateYear, int month) {
+        return baseMapper.getRespAcountAccounts(hospId, dateYear, month);
+    }
+
+    @Override
+    public List<AllocationQuery> getRespOriginAcountAccounts(Long hospId, int dateYear, int month) {
+        return baseMapper.getRespOriginAcountAccounts(hospId, dateYear, month);
+    }
+
+    @Override
+    public void batchInsertAllocationQuery(List<AllocationQuery> allocationQueryList) {
+         this.batchInsert(allocationQueryList);
+    }
+
     /**
      * 获取这个月的分摊数据
      *
@@ -77,6 +95,26 @@ public class AllocationQueryServiceImpl extends ServiceImpl<AllocationQueryMappe
         return list;
     }
 
+    /**
+     * 获取指定类型的成本数据
+     * @param hospId
+     * @param year
+     * @param month
+     * @param originType 来源类型:1.分摊前,2.分摊后
+     * @return
+     */
+    @Override
+    public List<AllocationQuery> getCostByDate(Long hospId, int year, int month, int originType) {
+        List<AllocationQuery> list = this.list(
+                new LambdaQueryWrapper<AllocationQuery>()
+                        .eq(AllocationQuery::getDateYear, year)
+                        .eq(AllocationQuery::getDateMonth, month)
+                        .eq(AllocationQuery::getHospId, hospId)
+                        .eq(AllocationQuery::getOriginType, originType)
+        );
+        return list;
+    }
+
     @Override
     public List<AllocationQuery> getByDate(int year, int month, Long hospId, List<Long> levelSorts) {
         return this.list(

+ 275 - 59
src/main/java/com/kcim/service/impl/AllocationServiceImpl.java

@@ -7,7 +7,6 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.poi.excel.ExcelWriter;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kcim.common.constants.NumberConstant;
 import com.kcim.common.constants.ParameterConstant;
 import com.kcim.common.constants.SQLParameter;
@@ -33,17 +32,19 @@ 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
 @AllArgsConstructor
 @Service("allocationService")
-public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocation> implements AllocationService {
+public class AllocationServiceImpl extends BaseBatchServiceImpl<AllocationMapper, Allocation> implements AllocationService {
     //    @Value("${file.serverPath}")
 //    private String fileTempPath;
 //
@@ -120,6 +121,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 +183,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);
         }
         //没有任何分摊数据
@@ -189,11 +195,24 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
         // 删除该年月已经分摊过的数据
         removeData(startDTO, hospId);
         //保存分摊结果信息
-        this.saveBatch(allocationCostList);
+        this.batchInsert(allocationCostList);
         //保存分摊结果查询表
         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 +220,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 +232,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 +260,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 +286,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 +319,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 +329,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 +354,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 +449,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 +469,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 +680,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);
@@ -474,7 +690,7 @@ public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocat
             return;
         }
         //保存分摊结果查询对象信息
-        allocationQueryService.saveBatch(allocationQueryList);
+        allocationQueryService.batchInsertAllocationQuery(allocationQueryList);
     }
 
     /**

+ 78 - 0
src/main/java/com/kcim/service/impl/BaseBatchServiceImpl.java

@@ -0,0 +1,78 @@
+package com.kcim.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.kcim.dao.mapper.GenericBatchMapper;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.function.BiFunction;
+
+/**
+ * 通用批量插入服务基类
+ * @param <T> 实体类类型
+ * @param <M> Mapper接口类型(需继承GenericBatchMapper)
+ */
+public abstract class BaseBatchServiceImpl<M extends GenericBatchMapper<T>, T>
+        extends ServiceImpl<M, T>{
+
+    /**
+     * 默认批次大小(可根据表结构调整)
+     */
+    private int batchSize = 1000;
+
+    /**
+     * 设置批次大小
+     */
+    public void setBatchSize(int batchSize) {
+        this.batchSize = batchSize;
+    }
+
+    /**
+     * 批量插入数据(适合中等数据量)
+     * @param dataList 要插入的数据列表
+     * @return 总插入条数
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public int batchInsert(List<T> dataList) {
+        if (dataList == null || dataList.isEmpty()) {
+            return 0;
+        }
+
+        int total = dataList.size();
+        int batches = (total + batchSize - 1) / batchSize;
+
+        for (int i = 0; i < batches; i++) {
+            int start = i * batchSize;
+            int end = Math.min(start + batchSize, total);
+            baseMapper.insertBatch(dataList.subList(start, end));
+        }
+
+        return total;
+    }
+
+    /**
+     * 分页加载并插入大数据量(避免OOM)
+     * @param dataProvider 数据提供器(分页加载数据的回调函数)
+     * @return 总插入条数
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public int batchInsertByPage(BiFunction<Integer, Integer, List<T>> dataProvider) {
+        int page = 0;
+        int total = 0;
+
+        while (true) {
+            // 调用回调函数加载当前页数据
+            List<T> dataBatch = dataProvider.apply(page, batchSize);
+            if (dataBatch.isEmpty()) {
+                break; // 数据加载完成
+            }
+
+            // 插入当前页数据
+            baseMapper.insertBatch(dataBatch);
+            total += dataBatch.size();
+            page++;
+        }
+
+        return total;
+    }
+}

+ 1 - 0
src/main/java/com/kcim/service/impl/ComputeMedicalDepartmentProfitServiceImpl.java

@@ -380,6 +380,7 @@ public class ComputeMedicalDepartmentProfitServiceImpl implements ComputeMedical
         //通过查询的最下层责任中心 找到其所有父类责任中心
         List<MedicalResponsibilityVo> parentResponseList = new ArrayList<>();
         for (MedicalResponsibilityVo responsibility : computeResponsibityList) {
+            log.info(String.format("查询责任中心{%s}的父级ID{%s}", responsibility.getResponsibilityCode(),responsibility.getParentId()));
             if (responsibility.getParentId().equals(NumberConstant.ZERO_L)) {
                 parentResponseList.add(responsibility);
             } else {

+ 4 - 2
src/main/java/com/kcim/service/impl/CostCostingGroupServiceImpl.java

@@ -24,6 +24,7 @@ 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 org.springframework.web.multipart.MultipartFile;
 
 import java.math.BigDecimal;
@@ -124,11 +125,12 @@ public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMap
 
         List<AllocationVO> list = baseMapper.queryAllocation(startIndex, pageSize, year, month, hospId);
         list.forEach(i -> {
-            List<Allocation> collections = allocationMapper.selectList(new LambdaQueryWrapper<Allocation>().eq(Allocation::getDateYear, i.getYear())
+            Allocation allocation = allocationMapper.selectOne(new LambdaQueryWrapper<Allocation>().eq(Allocation::getDateYear, i.getYear())
                     .eq(Allocation::getDateMonth, i.getMonth())
                     .eq(Allocation::getHospId, hospId)
+                    .last("LIMIT 1")
             );
-            if (!collections.isEmpty()) {
+            if (!ObjectUtils.isEmpty(allocation)) {
                 i.setIsAllocation(true);
             }
         });

+ 824 - 34
src/main/java/com/kcim/service/impl/CostDepartmentProfitServiceImpl.java

@@ -12,12 +12,8 @@ import cn.hutool.poi.excel.ExcelWriter;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.ImmutableMap;
-import com.kcim.common.constants.NumberConstant;
-import com.kcim.common.constants.ParameterConstant;
-import com.kcim.common.constants.SQLParameter;
-import com.kcim.common.constants.SplitConstant;
+import com.kcim.common.constants.*;
 import com.kcim.common.enums.CustomSqlTypeEnum;
 import com.kcim.common.enums.DateStyleEnum;
 import com.kcim.common.enums.ErrorCodeEnum;
@@ -30,14 +26,14 @@ import com.kcim.common.util.excel.entity.ColEntity;
 import com.kcim.common.util.excel.entity.TitleEntity;
 import com.kcim.dao.mapper.CostDepartmentProfitMapper;
 import com.kcim.dao.model.*;
-import com.kcim.dao.repository.ComputeLastProfitDateRepository;
-import com.kcim.dao.repository.CostDepartmentProfitRepository;
+import com.kcim.dao.repository.*;
 import com.kcim.service.*;
 import com.kcim.vo.*;
 import com.kcim.web.reponse.BatchCostProfitResponse;
 import com.kcim.web.reponse.ComputeProfitCollectResponse;
 import com.kcim.web.reponse.CostProfitRedirectResponse;
 import com.kcim.web.reponse.ProfitReportResponse;
+import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemFactory;
@@ -53,6 +49,7 @@ 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 org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
@@ -75,7 +72,8 @@ import static com.kcim.common.constants.ParameterConstant.MEDICAL_TECHNIQUES_SHA
 
 @Service("costDepartmentProfitService")
 @Slf4j
-public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentProfitMapper, CostDepartmentProfit> implements CostDepartmentProfitService {
+@AllArgsConstructor
+public class CostDepartmentProfitServiceImpl extends BaseBatchServiceImpl<CostDepartmentProfitMapper, CostDepartmentProfit> implements CostDepartmentProfitService {
 
 //    @Value("${file.filelocal}")
 //    private String hospProfitReportUrl;
@@ -115,6 +113,10 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 
     private final UserResponsibilityRightService userResponsibilityRightService;
 
+    ResponsibilityRepository responsibilityRepository;
+
+    CostDepartmentProfitAccountRepository costDepartmentProfitAccountRepository;
+    AccountingRepository accountingRepository;
 
     private final SqlService sqlService;
     private final String AMOUNT = "金额";
@@ -124,26 +126,26 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
     private final String AMOUNT_FIELD = "amount";
 
     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) {
-        this.reportFormService = reportFormService;
-        this.incomeCollectionService = incomeCollectionService;
-        this.costShareLevelService = costShareLevelService;
-        this.responsibilityService = responsibilityService;
-        this.reportRelationService = reportRelationService;
-        this.allocationService = allocationService;
-        this.allocationQueryService = allocationQueryService;
-        this.fileRecordService = fileRecordService;
-        this.minioConfig = minioConfig;
-        this.minioFileUtil = minioFileUtil;
-        this.centerService = centerService;
-        this.costDepartmentProfitRepository = costDepartmentProfitRepository;
-        this.computeLastProfitDateRepository = computeLastProfitDateRepository;
-        this.accountingService = accountingService;
-        this.costAccountShareService = costAccountShareService;
-        this.sqlService = sqlService;
-        this.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;
+//        this.responsibilityService = responsibilityService;
+//        this.reportRelationService = reportRelationService;
+//        this.allocationService = allocationService;
+//        this.allocationQueryService = allocationQueryService;
+//        this.fileRecordService = fileRecordService;
+//        this.minioConfig = minioConfig;
+//        this.minioFileUtil = minioFileUtil;
+//        this.centerService = centerService;
+//        this.costDepartmentProfitRepository = costDepartmentProfitRepository;
+//        this.computeLastProfitDateRepository = computeLastProfitDateRepository;
+//        this.accountingService = accountingService;
+//        this.costAccountShareService = costAccountShareService;
+//        this.sqlService = sqlService;
+//        this.userResponsibilityRightService = userResponsibilityRightService;
+//    }
 
     /**
      * 查询科室损益数据
@@ -348,7 +350,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
                 i.setAmount(setSubtotal(i, costShareLevelList, listMap, list, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
             } else if (NumberConstant.FOUR.equals(calcType)) {
                 // TODO 按照计算公式进行计算
-//                i.setAmount(setCalculation(i, list, costShareLevelList, listMap, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
+                i.setAmount(setCalculation(i, list, costShareLevelList, listMap, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
             } else if (NumberConstant.FIVE.equals(calcType)) {
                 // TODO  按照责任中心进行计算
                 i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList));
@@ -1117,8 +1119,14 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
     public void computeProfit(String computeDate, Long hospId, String reportType) {
         //需要用代码计算时
         if(IsNeedCalc(reportType)){
-            //计算科室损益
-            computeProfitAction(computeDate, hospId, reportType);
+            String parameterValue = centerService.getParameterValue(ParameterConstant.ALLOCATION_TYPE);
+            if (NumberConstant.ONE_S.equals(parameterValue)) {
+                //按责任中心分摊的科室损益计算
+                computeProfitAction(computeDate, hospId, reportType);
+            }else if (NumberConstant.TWO_S.equals(parameterValue)) {
+                //按会计科目分摊的科室损益计算
+                calcDeptProfit(computeDate, hospId, reportType);
+            }
             //计算同环比
             handleSpecificMonthsCalculation(hospId, computeDate, reportType);
         }
@@ -1130,6 +1138,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 //        DateTime parse = DateUtil.parse(computeDate);
 //        int year = DateUtil.year(parse);
 //        int month = DateUtil.month(parse) + 1;
+        Long userId = UserContext.getCurrentUser().getId();
         Integer year = ComputeDateUtils.getComputeYear(computeDate);
         Integer month = ComputeDateUtils.getComputeMonth(computeDate);
         // 先查询指定条件的报表数据  查询损益表的数据
@@ -1213,7 +1222,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
 
         this.saveBatch(costDepartmentProfits);
         //记录最后一次 损益计算日期
-        computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate);
+        computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate,userId);
     }
 
     /**
@@ -3603,7 +3612,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             }
 
             // 计算完成率、环比、同比
-            for (CostProfitVo vo : currentYearList) {
+            for (CostProfitVo vo : activeCostProfitVo) {
                 // 设置同期数据
                 if (preYearCostProfitMap.containsKey(vo.getReportId())) {
                     vo.setSamePeriodAmount(preYearCostProfitMap.get(vo.getReportId()).getAmount());
@@ -3627,7 +3636,7 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
             }
 
             // 构建树状结构
-            Map<Long, List<CostProfitVo>> collect = currentYearList.stream()
+            Map<Long, List<CostProfitVo>> collect = activeCostProfitVo.stream()
                     .collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
             List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
             collect.remove(NumberConstant.ZERO_L);
@@ -3661,4 +3670,785 @@ public class CostDepartmentProfitServiceImpl extends ServiceImpl<CostDepartmentP
         return rate.setScale(4, RoundingMode.HALF_UP);
     }
 
+    /**
+     * 计算科室损益
+     * @param computeDate
+     * @param hospId
+     * @param reportType
+     */
+    private void calcDeptProfit(String computeDate, Long hospId, String reportType) {
+        //获取科室损益计算所需的数据
+        ProfitCalculationDataVo profitCalculationData = getProfitCalculationData(computeDate, hospId, reportType);
+        //计算科室损益
+        List<CostDepartmentProfitVO> costDepartmentProfitVOS = calcDeptProfit(profitCalculationData);
+        // 添加数据
+        List<CostDepartmentProfit> costDepartmentProfits = BeanUtil.convertList(costDepartmentProfitVOS, CostDepartmentProfit.class);
+        //统一创建时间
+        long l = System.currentTimeMillis();
+        costDepartmentProfits.forEach(i -> {
+            i.setCreateTime(l);
+        });
+        // 删除这个年月的数据
+        deleteDeptProfit(profitCalculationData.getYear(),profitCalculationData.getMonth(),reportType ,hospId);
+        costDepartmentProfitAccountRepository.deleteDeptProfitAccountWithUser(hospId,computeDate,profitCalculationData.getCurrentUserID());
+        //保存科室损益数据
+        this.batchInsert(costDepartmentProfits);
+        //处理科室损益的会计科目金额数据
+        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts=new ArrayList<>();
+        for (CostDepartmentProfit deptProfit : costDepartmentProfits) {
+            deptProfit.getCostDepartmentProfitAccounts().forEach(account -> {
+                account.setDeptProfitId(deptProfit.getId());
+                account.setComputeDate(computeDate);
+                account.setHospId(hospId);
+            });
+            costDepartmentProfitAccounts.addAll(deptProfit.getCostDepartmentProfitAccounts());
+        }
+        //保存科室损益的会计科目金额数据
+        costDepartmentProfitAccountRepository.batchInsert(costDepartmentProfitAccounts);
+        //记录最后一次 损益计算日期
+        computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate,profitCalculationData.getCurrentUserID());
+    }
+
+    /**
+     * 获取科室损益计算所需的数据
+     * @param computeDate
+     * @param hospId
+     * @param reportType
+     * @return
+     */
+    public ProfitCalculationDataVo getProfitCalculationData(String computeDate, Long hospId, String reportType) {
+        ProfitCalculationDataVo profitCalculationData = new ProfitCalculationDataVo();
+        profitCalculationData.setCurrentUserID(UserContext.getCurrentUser().getId());
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取指定类型的报表配置
+        List<ReportForm> reportFormList = getReportForm(reportType);
+        if (CollUtil.isEmpty(reportFormList)) {
+            throw new CostException(500, "损益表未找到");
+        }
+        //获取报表设置明细
+        List<ReportRelation> reportRelation = getReportRelation();
+        Map<Long, List<ReportRelation>> reportRelationMap = reportRelation.stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
+
+        // 查询最后一个层级的责任中心
+        List<CostShareLevel> costShareLevelList = getCostShareLevelList();
+        if (CollUtil.isEmpty(costShareLevelList)) {
+            throw new CostException(500, "分摊层级未设置");
+        }
+
+        //获取指定报表对应的责任中心
+        List<Responsibility> responsibilityList = getReportResponsibilityList(reportType);
+
+        // 获取归集后的收入数据
+        List<IncomeCollection> incomeList = getIncomeCollectionList(year,month);
+        if (CollUtil.isEmpty(incomeList)) {
+            throw new CostException(500, "归集后数据不存在");
+        }
+        Map<String, Map<String, List<IncomeCollection>>> respIncomeGroup = incomeList.stream()
+                .collect(Collectors.groupingBy(
+                        IncomeCollection::getResponsibilityCode,
+                        Collectors.groupingBy(IncomeCollection::getAccountingCode)
+                ));
+
+
+        // 获取分摊后数据
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(hospId,year,month);
+        if (CollUtil.isEmpty(allocationQueryList)) {
+            throw new CostException(500, "分摊后数据不存在");
+        }
+
+        DictDataVo accountingTypeDict = centerService.getDict(Constant.ACCOUNTING_TYPE);
+        DictDataVo costTypeDict = centerService.getDict(Constant.STANDARD_COST_CATEGORIES);
+        List<Accounting> allCostAccounting = accountingRepository.getAllCostAccounting();
+
+        // 创建一个映射,用于快速查找会计科目的类型,过滤掉 null 对象,过滤掉 accountingCode 为 null 的对象
+        Map<String, Accounting> accountingMap = allCostAccounting.stream()
+                .filter(Objects::nonNull)
+                .filter(a -> a.getAccountingCode() != null)
+                .collect(Collectors.toMap(Accounting::getAccountingCode, o -> o));
+
+        List<DictDataVo> accountingTypeDictList = (accountingTypeDict != null && accountingTypeDict.getDataVoList() != null)
+                ? accountingTypeDict.getDataVoList() : new ArrayList<>();
+
+        List<DictDataVo> costTypeDictList = (costTypeDict != null && costTypeDict.getDataVoList() != null)
+                ? costTypeDict.getDataVoList() : new ArrayList<>();
+
+        // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
+        Map<String, DictDataVo> accountingTypeMap = accountingTypeDictList.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> d.getCode() != null)
+                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
+
+        // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
+        Map<String, DictDataVo> costTypeMap = costTypeDictList.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> d.getCode() != null)
+                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
+
+        // 封装数据
+        List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class);
+        allocationQueryReportVOList.forEach(i -> {
+            i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
+            i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
+            //构建会计科目的成本类型及会计科目类型
+            Accounting accounting = accountingMap.get(i.getAccountingCode());
+            if(ObjectUtils.isEmpty( accounting)){
+                return;
+            }
+            DictDataVo costType = costTypeMap.get(String.valueOf(accounting.getCostType()));
+            if(!ObjectUtils.isEmpty( costType)){
+                i.setCostType(costType.getExpandOne());
+            }
+            DictDataVo accountingType = accountingTypeMap.get(String.valueOf(accounting.getCostType()));
+            if(!ObjectUtils.isEmpty( accountingType)){
+                i.setAccountType(accountingType.getExpandOne());
+            }
+        });
+
+        //责任中心+会计科目分组
+        Map<String, Map<String, List<AllocationQueryReportVO>>> respAccountCostGroup = allocationQueryReportVOList.stream()
+                .collect(Collectors.groupingBy(
+                        AllocationQueryReportVO::getTargetResponsibilityCode,
+                        Collectors.groupingBy(AllocationQueryReportVO::getAccountingCode)
+                ));
+
+        //责任中心+来源责任中心分组
+        Map<String, Map<String, List<AllocationQueryReportVO>>> respSourceCostGroup = allocationQueryReportVOList.stream()
+                .collect(Collectors.groupingBy(
+                        AllocationQueryReportVO::getTargetResponsibilityCode,
+                        Collectors.groupingBy(AllocationQueryReportVO::getResponsibilityCode)
+                ));
+        //责任中心+分摊层级分组
+        Map<String, Map<Long, List<AllocationQueryReportVO>>> respShareLevelCostGroup = allocationQueryReportVOList.stream()
+                .collect(Collectors.groupingBy(
+                        AllocationQueryReportVO::getTargetResponsibilityCode,
+                        Collectors.groupingBy(AllocationQueryReportVO::getShareLevelId)
+                ));
+
+        // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
+        List<Allocation> allocationList = allocationService.getByDate( year, month, hospId);
+        if (CollUtil.isEmpty(allocationList)) {
+            throw new CostException(500, "分摊报表数据不存在");
+        }
+        profitCalculationData.setComputeDate(computeDate);
+        profitCalculationData.setYear(year);
+        profitCalculationData.setMonth(month);
+        profitCalculationData.setHospId(hospId);
+        profitCalculationData.setReportType(reportType);
+        profitCalculationData.setReportFormList(reportFormList);
+        profitCalculationData.setReportRelationList(reportRelation);
+        profitCalculationData.setReportRelationMap(reportRelationMap);
+        profitCalculationData.setCostShareLevelList(costShareLevelList);
+        profitCalculationData.setResponsibilityList(responsibilityList);
+        profitCalculationData.setRespIncomeGroup(respIncomeGroup);
+        profitCalculationData.setRespAccountCostGroup(respAccountCostGroup);
+        profitCalculationData.setRespSourceCostGroup(respSourceCostGroup);
+        profitCalculationData.setRespShareLevelCostGroup(respShareLevelCostGroup);
+        return profitCalculationData;
+    }
+
+    /**
+     * 计算科室损益
+     * @param profitCalculationData
+     * @return
+     */
+    private List<CostDepartmentProfitVO> calcDeptProfit(ProfitCalculationDataVo profitCalculationData) {
+        List<ReportForm> firstLevelReports = profitCalculationData.getReportFormList().stream().filter(i -> NumberConstant.ZERO.equals(i.getParentId().intValue())).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(firstLevelReports)){
+            throw new CostException(500, "未找到第一层报表项目,请检查报表配置");
+        }
+        //按顺序号排序
+        firstLevelReports.sort(Comparator.comparing(ReportForm::getSort, Comparator.nullsLast(Integer::compareTo)));
+        Map<Long, List<ReportForm>> reportParentGroup = profitCalculationData.getReportFormList().stream().collect(Collectors.groupingBy(ReportForm::getParentId));
+        List<CostDepartmentProfitVO> costDepartmentProfitVOList = new ArrayList<>();
+        //循环设置子级报表项目
+        for (ReportForm reportForm : firstLevelReports) {
+            setChildReport(reportForm,reportParentGroup);
+        }
+        //虚拟一个最上层的节点方便循环嵌套计算
+        ReportForm baseReport=new ReportForm();
+        baseReport.setId(NumberConstant.ZERO_L);
+        baseReport.setChild(firstLevelReports);
+        //按责任中心计算科室损益
+//        for (Responsibility responsibility : profitCalculationData.getResponsibilityList()) {
+//            Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap=new HashMap<>();
+//            //计算责任中心的所有报表项目
+//            for (ReportForm reportForm : firstLevelReports) {
+//                calcRespReportAmount(responsibility, reportForm,profitCalculationData, costDepartmentProfitMap);
+//            }
+//            //添加到结果集合
+//            costDepartmentProfitVOList.addAll(costDepartmentProfitMap.values());
+//        }
+        //按责任中心计算科室损益(并行)
+        List<CostDepartmentProfitVO> result = profitCalculationData.getResponsibilityList().parallelStream()
+                .map(responsibility -> {
+                    Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap = new HashMap<>();
+                    // 计算责任中心的所有报表项目
+                    calcRespReportAmount(responsibility, baseReport, profitCalculationData, costDepartmentProfitMap);
+                    return new ArrayList<>(costDepartmentProfitMap.values());
+                })
+                .flatMap(List::stream)
+                .collect(Collectors.toList());
+
+        costDepartmentProfitVOList.addAll(result);
+        return costDepartmentProfitVOList;
+    }
+
+    /**
+     * 循环设置子级报表项目
+     * @param reportForm
+     * @param reportParentGroup
+     */
+    public void setChildReport(ReportForm reportForm ,Map<Long, List<ReportForm>> reportParentGroup){
+        List<ReportForm> childReportForms = reportParentGroup.get(reportForm.getId());
+        if(CollUtil.isEmpty(childReportForms)){
+            return;
+        }
+        reportForm.setChild(childReportForms);
+        for (ReportForm cildReportForm : childReportForms) {
+            setChildReport(cildReportForm,reportParentGroup);
+        }
+    }
+
+
+    /**
+     * 计算指定责任中心指定报表项目的金额(优先计算子级,再按顺序号计算非公式项,最后计算公式项)
+     * @param profitCalculationData
+     * @param costDepartmentProfitMap
+     * @param parentReport
+     * @param responsibility
+     */
+    public void calcRespReportAmount(Responsibility responsibility,
+                                 ReportForm parentReport ,
+                                 ProfitCalculationDataVo profitCalculationData,
+                                 Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap){
+        //有子级的优先计算子级
+        if(!CollUtil.isEmpty(parentReport.getChild())){
+            //计算报表项目的金额
+            for (ReportForm reportForm : parentReport.getChild()) {
+                //计算子级的金额
+                calcRespReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
+            }
+            //找出所有类型不是计算公式且不是不设置的报表项
+            List<ReportForm> calcReportList = parentReport.getChild().stream().filter(i ->!NumberConstant.ZERO.equals(i.getCalcType())&& !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
+            //优先计算类型为非计算公式的报表项
+            if (!CollUtil.isEmpty(calcReportList)){
+                for (ReportForm reportForm : calcReportList) {
+                    calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
+                }
+            }
+            //找出所有类型为计算公式的报表项
+            List<ReportForm> formulaReportList = parentReport.getChild().stream().filter(i -> NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
+            //再计算类型为计算公式的报表项
+            if (!CollUtil.isEmpty(formulaReportList)){
+                for (ReportForm reportForm : formulaReportList) {
+                    calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
+                }
+            }
+        }
+        //虚拟的最上层不需要计算
+        if(!NumberConstant.ZERO_L.equals(parentReport.getId())) {
+            //再计算自己
+            calcReportAmount(responsibility, parentReport, profitCalculationData, costDepartmentProfitMap);
+        }
+    }
+
+
+    /**
+     * 计算一个报表项目的金额
+     * @param profitCalculationData
+     * @param costDepartmentProfitMap
+     * @param reportForm
+     */
+    public void calcReportAmount(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData,Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap){
+        Integer calcType = reportForm.getCalcType();
+        CostDepartmentProfitVO costDepartmentProfitVO = createCostDepartmentProfitVO(responsibility,reportForm,profitCalculationData);
+        switch (calcType){
+            case 1:
+                if(NumberConstant.ONE.equals(reportForm.getCostType())){
+                    //按收入会计科目计算
+                    setIncomeAccountReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm);
+                }else{
+                    //按成本会计科目计算
+                    setCostAccountReportValue(costDepartmentProfitVO,profitCalculationData, responsibility, reportForm);
+                }
+                break;
+            case 2:
+                //按分摊层级计算
+                setShareLevelReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm);
+                break;
+            case 4:
+                //按公式计算
+                setFormulaReportValue(costDepartmentProfitVO,costDepartmentProfitMap,responsibility,reportForm);
+                break;
+            case 5:
+                //按责任中心计算
+                setResponsibilityReportValue(costDepartmentProfitVO,profitCalculationData,costDepartmentProfitMap,responsibility,reportForm);
+                break;
+        }
+        //记录下已计算好的报表项目
+        if(!costDepartmentProfitMap.containsKey(reportForm.getNum())){
+            costDepartmentProfitMap.put(reportForm.getNum(),costDepartmentProfitVO);
+        }
+    }
+
+    /**
+     * 创建一个科室损益计算结果对象
+     * @param responsibility
+     * @param reportForm
+     * @param profitCalculationData
+     * @return
+     */
+    public CostDepartmentProfitVO createCostDepartmentProfitVO(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData){
+        CostDepartmentProfitVO costDepartmentProfitVO = new CostDepartmentProfitVO();
+        costDepartmentProfitVO.setYear(profitCalculationData.getYear());
+        costDepartmentProfitVO.setMonth(profitCalculationData.getMonth());
+        costDepartmentProfitVO.setReportId(reportForm.getId());
+        costDepartmentProfitVO.setReportNum(reportForm.getNum());
+        costDepartmentProfitVO.setCalcType(reportForm.getCalcType());
+        costDepartmentProfitVO.setReportName(reportForm.getReportName());
+        costDepartmentProfitVO.setCalcFormula(reportForm.getCalcFormula());
+        costDepartmentProfitVO.setReportParentId(reportForm.getParentId());
+        costDepartmentProfitVO.setResponsibilityCode(responsibility.getResponsibilityCode());
+        costDepartmentProfitVO.setResponsibilityName(responsibility.getResponsibilityName());
+        costDepartmentProfitVO.setCostType(NumberConstant.ONE);
+        costDepartmentProfitVO.setIncomeType(NumberConstant.ONE);
+        costDepartmentProfitVO.setHospId(profitCalculationData.getHospId());
+        costDepartmentProfitVO.setShareType(Integer.valueOf(profitCalculationData.getReportType()));
+        costDepartmentProfitVO.setType(reportForm.getCostType());
+        costDepartmentProfitVO.setFraction(reportForm.getFraction());
+        costDepartmentProfitVO.setAmount(BigDecimal.ZERO);
+        costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
+        return costDepartmentProfitVO;
+    }
+
+    /**
+     * 获取按责任中心计算结果
+     * @param profitCalculationData
+     * @param costDepartmentProfitMap
+     * @param reportForm
+     * @return
+     */
+    private void setResponsibilityReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap, Responsibility responsibility, ReportForm reportForm) {
+        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
+        if(CollectionUtils.isEmpty(reportRelationList)){
+            return ;
+        }
+        // 获取对应的会计科目信息  筛选会计科目的Code
+        List<String> responsibilityCodeList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
+        // 获取指定责任中心的分摊数据
+        Map<String, List<AllocationQueryReportVO>> respSourceCostMap = profitCalculationData.getRespSourceCostGroup().get(responsibility.getResponsibilityCode());
+        if(ObjectUtils.isEmpty(respSourceCostMap) || respSourceCostMap.isEmpty()){
+            return ;
+        }
+        //获取指定会计科目的分摊数据
+        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
+        responsibilityCodeList.forEach(respCode -> {
+            if(respSourceCostMap.containsKey(respCode)){
+                reportVOList.addAll(respSourceCostMap.get(respCode));
+            }
+        });
+        if(CollectionUtils.isEmpty(reportVOList)){
+            return ;
+        }
+        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
+        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
+                .map(CostDepartmentProfitAccount::getAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        costDepartmentProfitVO.setAmount(totalAmount);
+        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
+    }
+
+    /**
+     * 获取按公式计算结果
+     * @param responsibility
+     * @param costDepartmentProfitMap
+     * @param reportForm
+     * @return
+     */
+    private void setFormulaReportValue(CostDepartmentProfitVO costDepartmentProfitVO,Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap,Responsibility responsibility, ReportForm reportForm) {
+        // 获取当前报表的计算方式  [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2]
+        String formula = reportForm.getCalcFormula();
+        if (StrUtil.isBlank(formula)) {
+            costDepartmentProfitVO.setAmount(BigDecimal.ZERO);
+            costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
+            return ;
+        }
+
+        String responsibilityCode = responsibility.getResponsibilityCode();
+
+        // 找出公式当中所有代码
+        String replace = formula.replace("[", "")
+                .replace("]", "")
+                .replace("-", ",")
+                .replace("+", ",")
+                .replace("*", ",")
+                .replace("/", ",");
+
+        ArrayList<String> codeList = CollUtil.newArrayList(replace.split(","));
+        Map<Integer, String> codeMap = new ConcurrentHashMap<>();
+        for (int j = 0; j < codeList.size(); j++) {
+            codeMap.put(j, codeList.get(j));
+        }
+
+        List<String> expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "")
+                        .replace("]", "").trim(), 0)
+                .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
+
+        // 得到预算表达式 得到所有表达式的Map  +  -  *  / 相关的
+        Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
+        for (int k = 0; k < expressions.size(); k++) {
+            expressionMap.put(k, expressions.get(k));
+        }
+
+        // 数字的索引和表达式的索引累加计算
+        Set<Integer> codeSet = codeMap.keySet();
+        List<Integer> codes = new ArrayList<>(codeSet);
+        AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(BigDecimal.ZERO);
+        List<CostDepartmentProfitAccount> baseDeptProfitAccounts=new ArrayList<>();
+        for (int i = 0; i < codes.size(); i++) {
+            // 编号
+            String code = codeMap.get(i);
+            CostDepartmentProfitVO reportData = costDepartmentProfitMap.get(Integer.valueOf(code));
+
+            // 检查报表数据是否存在且属于当前责任中心
+            if (reportData == null || !responsibilityCode.equals(reportData.getResponsibilityCode())) {
+                continue;
+            }
+
+            BigDecimal amount = reportData.getAmount();
+            if (amount == null) {
+                amount = BigDecimal.ZERO;
+            }
+
+            String str = expressionMap.get(i);
+            if (str.equals("+")) {
+                baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.ONE);
+                totalAmount.set(totalAmount.get().add(amount));
+            } else if (str.contains("-")) {
+                baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.NEGATIVE);
+                totalAmount.set(totalAmount.get().subtract(amount));
+            } else if (str.contains("*")) {
+                totalAmount.set(totalAmount.get().multiply(amount));
+            } else if (str.contains("/")) {
+                if (amount.compareTo(BigDecimal.ZERO) == 0) {
+                    log.error("报表项【" + reportForm.getReportName() + "】公式除数为0,报表编号为【" + code + "】");
+                    totalAmount.set(BigDecimal.ZERO);
+                    break;
+                } else {
+                    totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP));
+                }
+            }
+        }
+        //有乘除算法的只要赋值,不用设置会计科目金额
+        if(formula.contains("*")||formula.contains("/")){
+            costDepartmentProfitVO.setAmount(totalAmount.get());
+            costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
+        }else{
+            costDepartmentProfitVO.setAmount(totalAmount.get());
+            costDepartmentProfitVO.setCostDepartmentProfitAccounts(baseDeptProfitAccounts);
+        }
+
+    }
+
+    /**
+     * 对两个CostDepartmentProfitVO对象的costDepartmentProfitAccounts列表进行加减运算
+     * 按照相同的costType和accountType进行合并计算,只处理amount字段
+     *
+     * @param firstList 第一个CostDepartmentProfitVO对象
+     * @param secondList 第二个CostDepartmentProfitVO对象
+     * @param operation 运算符,1表示加法,-1表示减法
+     * @return 运算结果列表
+     */
+    public List<CostDepartmentProfitAccount> calculateAccountAmounts(
+            List<CostDepartmentProfitAccount> firstList,
+            List<CostDepartmentProfitAccount> secondList,
+            int operation) {
+
+        // 处理空列表情况
+        firstList = firstList != null ?firstList : new ArrayList<>();
+        secondList = secondList != null ?secondList: new ArrayList<>();
+
+        // 创建结果列表,先复制第一个列表的所有元素
+        List<CostDepartmentProfitAccount> result = firstList.stream()
+                .map(account -> {
+                    CostDepartmentProfitAccount copy = new CostDepartmentProfitAccount();
+                    copy.setCostType(account.getCostType());
+                    copy.setAccountType(account.getAccountType());
+                    copy.setAmount(account.getAmount() != null ? account.getAmount() : BigDecimal.ZERO);
+                    return copy;
+                })
+                .collect(Collectors.toList());
+
+        // 处理第二个列表中的每个元素
+        for (CostDepartmentProfitAccount secondAccount : secondList) {
+            if (secondAccount.getAmount() == null) {
+                continue; // 跳过金额为空的记录
+            }
+
+            // 查找是否在结果列表中已有相同costType和accountType的记录
+            boolean found = false;
+            for (CostDepartmentProfitAccount resultAccount : result) {
+                if (Objects.equals(resultAccount.getCostType(), secondAccount.getCostType()) &&
+                        Objects.equals(resultAccount.getAccountType(), secondAccount.getAccountType())) {
+
+                    // 找到匹配项,进行加减运算
+                    BigDecimal firstAmount = resultAccount.getAmount() != null ? resultAccount.getAmount() : BigDecimal.ZERO;
+                    BigDecimal secondAmount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO;
+
+                    if (operation == 1) {
+                        resultAccount.setAmount(firstAmount.add(secondAmount));
+                    } else if (operation == -1) {
+                        resultAccount.setAmount(firstAmount.subtract(secondAmount));
+                    }
+
+                    found = true;
+                    break;
+                }
+            }
+
+            // 如果未找到匹配项,则添加新记录
+            if (!found) {
+                CostDepartmentProfitAccount newAccount = new CostDepartmentProfitAccount();
+                newAccount.setCostType(secondAccount.getCostType());
+                newAccount.setAccountType(secondAccount.getAccountType());
+
+                // 加法直接添加金额,减法添加负金额
+                if (operation == 1) {
+                    newAccount.setAmount(secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO);
+                } else if (operation == -1) {
+                    BigDecimal amount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO;
+                    newAccount.setAmount(amount.negate()); // 设置为负值
+                }
+                result.add(newAccount);
+            }
+        }
+
+        return result;
+    }
+
+
+    /**
+     * 获取按分摊层级计算结果
+     * @param profitCalculationData
+     * @param reportForm
+     * @return
+     */
+    private void setShareLevelReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) {
+        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
+        if(CollectionUtils.isEmpty(reportRelationList)){
+            return ;
+        }
+        // 获取对应的会计科目信息  筛选会计科目的Code
+        List<Long> shareLevelIdList = reportRelationList.stream().map(o->Long.valueOf(o.getRelationCode())).collect(Collectors.toList());
+        // 获取指定责任中心的分摊数据
+        Map<Long, List<AllocationQueryReportVO>> respShareLevelCostMap = profitCalculationData.getRespShareLevelCostGroup().get(responsibility.getResponsibilityCode());
+        if(ObjectUtils.isEmpty(respShareLevelCostMap) || respShareLevelCostMap.isEmpty()){
+            return ;
+        }
+        //获取指定会计科目的分摊数据
+        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
+        shareLevelIdList.forEach(shareLevelId -> {
+            if(respShareLevelCostMap.containsKey(shareLevelId)){
+                reportVOList.addAll(respShareLevelCostMap.get(shareLevelId));
+            }
+        });
+        if(CollectionUtils.isEmpty(reportVOList)){
+            return ;
+        }
+        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
+        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
+                .map(CostDepartmentProfitAccount::getAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        costDepartmentProfitVO.setAmount(totalAmount);
+        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
+    }
+
+
+    /**
+     * 按收入会计科目计算
+     * @param costDepartmentProfitVO
+     * @param profitCalculationData
+     * @param responsibility
+     * @param reportForm
+     */
+    private void setIncomeAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO,ProfitCalculationDataVo profitCalculationData, Responsibility responsibility,ReportForm reportForm) {
+        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
+        if(CollectionUtils.isEmpty(reportRelationList)){
+            return ;
+        }
+        // 获取对应的会计科目信息  筛选会计科目的Code
+        List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
+        // 获取指定责任中心的收入数据
+        Map<String, List<IncomeCollection>> respAccountIncomeMap = profitCalculationData.getRespIncomeGroup().get(responsibility.getResponsibilityCode());
+        if(ObjectUtils.isEmpty(respAccountIncomeMap) || respAccountIncomeMap.isEmpty()){
+            return ;
+        }
+        //获取指定会计科目的收入数据
+        List<IncomeCollection> reportVOList=new ArrayList<>();
+        accountList.forEach(accountCode -> {
+            if(respAccountIncomeMap.containsKey(accountCode)){
+                reportVOList.addAll(respAccountIncomeMap.get(accountCode));
+            }
+        });
+        if(CollectionUtils.isEmpty(reportVOList)){
+            return ;
+        }
+        BigDecimal totalAmount = reportVOList.stream()
+                .map(IncomeCollection::getAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        costDepartmentProfitVO.setAmount(totalAmount);
+    }
+
+    /**
+     *获取按成本会计科目计算的结果
+     * @param profitCalculationData
+     * @param responsibility
+     * @param reportForm
+     * @return
+     */
+    private void setCostAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) {
+        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
+        if(CollectionUtils.isEmpty(reportRelationList)){
+            return ;
+        }
+        // 获取对应的会计科目信息  筛选会计科目的Code
+        List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
+        // 获取指定责任中心的分摊数据
+        Map<String, List<AllocationQueryReportVO>> respAccountCostMap = profitCalculationData.getRespAccountCostGroup().get(responsibility.getResponsibilityCode());
+        if(ObjectUtils.isEmpty(respAccountCostMap) || respAccountCostMap.isEmpty()){
+            return ;
+        }
+        //获取指定会计科目的分摊数据
+        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
+        accountList.forEach(accountCode -> {
+            if(respAccountCostMap.containsKey(accountCode)){
+                reportVOList.addAll(respAccountCostMap.get(accountCode));
+            }
+        });
+        if(CollectionUtils.isEmpty(reportVOList)){
+            return ;
+        }
+        //获取指定成本类别(全部/直接/间接)的分摊数据
+        List<AllocationQueryReportVO> collect = reportVOList.stream().filter(m -> NumberConstant.ZERO.equals(reportForm.getCostType()) || reportForm.getCostType().equals(m.getOriginType().intValue())).collect(Collectors.toList());
+        if (CollUtil.isEmpty(reportVOList)) {
+            return ;
+        }
+        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
+        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
+                .map(CostDepartmentProfitAccount::getAmount)
+                .filter(Objects::nonNull)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        costDepartmentProfitVO.setAmount(totalAmount);
+        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
+    }
+
+    /**
+     * 将分摊结果按会计科目类别+成本类别分组汇总
+     * @param reportVOList
+     * @return
+     */
+    public List<CostDepartmentProfitAccount> calculateCostByTypeAndAccount(List<AllocationQueryReportVO> reportVOList) {
+        // 按costType+accountType分组计算各组的金额amount
+        Map<String, BigDecimal> groupedAmounts = reportVOList.stream()
+                .collect(Collectors.groupingBy(
+                        vo -> vo.getCostType() + "_" + vo.getAccountType(),
+                        Collectors.reducing(
+                                BigDecimal.ZERO,
+                                AllocationQueryReportVO::getAmount,
+                                BigDecimal::add
+                        )
+                ));
+
+        // 按组生成CostDepartmentProfitAccount对象
+        return groupedAmounts.entrySet().stream()
+                .map(entry -> {
+                    String[] keys = entry.getKey().split("_", 2);
+                    CostDepartmentProfitAccount account = new CostDepartmentProfitAccount();
+                    account.setCostType(keys[0]);
+                    account.setAccountType(keys[1]);
+                    account.setAmount(entry.getValue());
+                    return account;
+                })
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 获取指定类型的报表配置
+     * @param reportType
+     * @return
+     */
+    public List<ReportForm> getReportForm(String reportType){
+        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
+                .eq(ReportForm::getHospId,  UserContext.getHospId())
+                .eq(ReportForm::getReportType, reportType));
+        return reportFormList;
+    }
+
+    /**
+     * 获取报表关系
+     * @return
+     */
+    public List<ReportRelation> getReportRelation(){
+        List<ReportRelation> list = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, UserContext.getHospId()));
+        return list;
+    }
+
+    /**
+     * 获取指定报表对应的责任中心
+     * @param reportType
+     * @return
+     */
+    public List<Responsibility> getReportResponsibilityList(String reportType){
+        DictDataVo dataVo = getDictDataVo(reportType);
+        Long id = Long.valueOf(dataVo.getExpandOne());
+        List<Responsibility> list = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
+                .eq(Responsibility::getHospId, UserContext.getHospId())
+                .eq(Responsibility::getIsGatherCenter, 2)
+                .eq(Responsibility::getDeleteTime, 0)
+                .eq(Responsibility::getShareId, id));
+        return list;
+    }
+
+
+    /**
+     * 获取分摊层级字典
+     * @return
+     */
+    public List<CostShareLevel> getCostShareLevelList(){
+        List<CostShareLevel> costShareLevelList =  costShareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
+                .eq(CostShareLevel::getHospId, UserContext.getHospId()).orderByDesc(CostShareLevel::getLeverSort));
+        return costShareLevelList;
+    }
+
+    /**
+     * 获取归集后的收入数据
+     * @param year
+     * @param month
+     * @return
+     */
+    public List<IncomeCollection> getIncomeCollectionList(Integer year, Integer month) {
+        List<IncomeCollection> list = incomeCollectionService.list(new QueryWrapper<IncomeCollection>().lambda()
+                .eq(IncomeCollection::getHospId, UserContext.getHospId())
+                .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month));
+        return list;
+    }
+
+
+    /**
+     * 删除指定月份的科室损益数据
+     * @param year
+     * @param month
+     * @param reportType
+     */
+    public void deleteDeptProfit(Integer year, Integer month,String reportType,Long hospId) {
+        // 删除这个年月的数据
+        this.remove(new QueryWrapper<CostDepartmentProfit>().lambda().eq(CostDepartmentProfit::getHospId, hospId)
+                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, Integer.valueOf(reportType)));
+    }
+
 }

+ 30 - 6
src/main/java/com/kcim/service/impl/CostIncomeGroupServiceImpl.java

@@ -18,10 +18,7 @@ import com.kcim.common.util.*;
 import com.kcim.dao.mapper.CostIncomeGroupMapper;
 import com.kcim.dao.model.*;
 import com.kcim.service.*;
-import com.kcim.vo.CommonDepartVo;
-import com.kcim.vo.CostIncomeGroupAllAmountVO;
-import com.kcim.vo.CostIncomeGroupBeforeVO;
-import com.kcim.vo.IncomeErrorMessage;
+import com.kcim.vo.*;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
@@ -96,6 +93,12 @@ public class CostIncomeGroupServiceImpl extends ServiceImpl<CostIncomeGroupMappe
      */
     @Override
     public PageUtils queryList(Integer current, Integer pageSize, String dateTime, String responsibilityCode, String productCode, Long hospId, Integer type, String filter, String departmentCode) {
+//       return getDeptIncomeList(current, pageSize, dateTime, responsibilityCode, productCode, hospId, type, filter, departmentCode);
+        return getDeptProductList(current, pageSize, dateTime, departmentCode, productCode, hospId, type, filter);
+    }
+
+
+    public PageUtils getDeptIncomeList(Integer current, Integer pageSize, String dateTime, String responsibilityCode, String productCode, Long hospId, Integer type, String filter, String departmentCode) {
         // 先检验当前年月是否存在数据
         int year = 0;
         int month = 0;
@@ -107,7 +110,7 @@ public class CostIncomeGroupServiceImpl extends ServiceImpl<CostIncomeGroupMappe
         Page<CostIncomeGroup> costIncomeGroupPage = new Page<>(current, pageSize);
         Page<CostIncomeGroup> pages = new Page<>();
         if(type.equals(NumberConstant.ONE)){
-             pages = this.page(costIncomeGroupPage, new QueryWrapper<CostIncomeGroup>().lambda()
+            pages = this.page(costIncomeGroupPage, new QueryWrapper<CostIncomeGroup>().lambda()
                     .eq(Objects.nonNull(hospId), CostIncomeGroup::getHospId, hospId)
                     .eq(!NumberConstant.ZERO.equals(year), CostIncomeGroup::getDateYear, year)
                     .eq(!NumberConstant.ZERO.equals(month), CostIncomeGroup::getDateMonth, month)
@@ -138,7 +141,7 @@ public class CostIncomeGroupServiceImpl extends ServiceImpl<CostIncomeGroupMappe
         }
         List<CostIncomeGroup> list = new ArrayList<>();
         if(type.equals(NumberConstant.ONE)) {
-             list = this.list(new QueryWrapper<CostIncomeGroup>().lambda()
+            list = this.list(new QueryWrapper<CostIncomeGroup>().lambda()
                     .eq(Objects.nonNull(hospId), CostIncomeGroup::getHospId, hospId)
                     .eq(!NumberConstant.ZERO.equals(year), CostIncomeGroup::getDateYear, year)
                     .eq(!NumberConstant.ZERO.equals(month), CostIncomeGroup::getDateMonth, month)
@@ -185,6 +188,27 @@ public class CostIncomeGroupServiceImpl extends ServiceImpl<CostIncomeGroupMappe
         return pageUtils;
     }
 
+
+    public PageUtils getDeptProductList(Integer current, Integer pageSize, String computeDate, String departmentCode, String productCode, Long hospId, Integer type, String filter) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        Page<PatientInfoVo> page = new Page<>(current,pageSize);
+        List<CostIncomeGroup> orderDeptProductList;
+        //按开单科室查询
+        if(NumberConstant.ONE.equals( type)){
+            orderDeptProductList = this.baseMapper.getOrderDeptProductList(page, year, month, departmentCode, hospId, filter);
+        }else{
+            orderDeptProductList = this.baseMapper.getExecDeptProductList(page, year, month, departmentCode, hospId, filter);
+        }
+        BigDecimal totalAmount=this.baseMapper.getTotalAmount(year, month, departmentCode, hospId);
+        BigDecimal departmentAmount=this.baseMapper.getDeptTotalAmount(year, month, departmentCode, hospId);
+        PageUtils pageUtils = new PageUtils(page);
+        pageUtils.setList(orderDeptProductList);
+        pageUtils.setTotalAmount(totalAmount);
+        pageUtils.setDepartmentAmount(departmentAmount);
+        return pageUtils;
+    }
     private static AtomicReference<BigDecimal> setAmount(List<CostIncomeGroupAllAmountVO> costIncomeGroupAllAmountVoS) {
         AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(new BigDecimal("0.0000"));
         costIncomeGroupAllAmountVoS.forEach(i -> {

+ 56 - 6
src/main/java/com/kcim/service/impl/HospProfitAndLossServiceImpl.java

@@ -1582,9 +1582,7 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
         for (Map.Entry<String, List<HospProfitAndLoss>> entry : groupedByYearMonth.entrySet()){
             List<HospProfitAndLoss> hospProfitAndLossList = entry.getValue();
             //转换成成本损益数据
-            List<CostProfitVo> costProfitVos = convertToCostProfitVoList(hospProfitAndLossList, reportFormList);
-            //记录所有月份的损益数据
-            allCostProfitVo.addAll(costProfitVos);
+            List<CostProfitVo> costProfitVos = convertToCostProfitVoList(hospProfitAndLossList, reportFormList,allCostProfitVo);
             //生成出参样式
             BatchCostProfitResponse response = new BatchCostProfitResponse();
             //第13月为审计月份
@@ -1606,6 +1604,8 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
         if(!beginComputeDate.equals(endComputeDate)){
             //获取月度汇总数据
             List<CostProfitVo> costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo);
+            //填充全院其他收支
+            fillHopsOhterProfit(costProfitVos,responses);
             if(!CollectionUtils.isEmpty(costProfitVos)){
                 BatchCostProfitResponse response = new BatchCostProfitResponse();
                 response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate));
@@ -1620,6 +1620,48 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
         return responses;
     }
 
+    /**
+     * 填充全院其他收支
+     * @param multipleMonthsProfitVos
+     * @param responses
+     */
+    public void fillHopsOhterProfit(List<CostProfitVo> multipleMonthsProfitVos,List<BatchCostProfitResponse> responses) {
+        //获取累计月全院其他收支节点
+        Optional<CostProfitVo> firstHopsOhterProfit = multipleMonthsProfitVos.stream().filter(costProfitVo -> costProfitVo.getReportId().equals(-1L)).findFirst();
+        if(!firstHopsOhterProfit.isPresent()||CollectionUtils.isEmpty(firstHopsOhterProfit.get().getChildren())){
+            return;
+        }
+        CostProfitVo standCostProfitVo = firstHopsOhterProfit.get();
+        for (BatchCostProfitResponse response : responses) {
+            //获取月度的全院其他收支节点
+            Optional<CostProfitVo> firstOhterProfit = response.getProfitVoList().stream().filter(costProfitVo -> costProfitVo.getReportId().equals(-1L)).findFirst();
+            //没有全院其他收支的添加一个空数据的全院其他收支
+            if(!firstOhterProfit.isPresent()||CollectionUtils.isEmpty(firstOhterProfit.get().getChildren())){
+                CostProfitVo costProfitVo = BeanUtil.convertObj(standCostProfitVo, CostProfitVo.class);
+                costProfitVo.setChildren(new ArrayList<>());
+                //添加缺失的全院其他收支项目到月度数据中
+                for (CostProfitVo missChildCostProfitVo : standCostProfitVo.getChildren()) {
+                    CostProfitVo newCostProfitVo = BeanUtil.convertObj(missChildCostProfitVo, CostProfitVo.class);
+                    combineReportAndProfitAmount(newCostProfitVo,null);
+                    costProfitVo.getChildren().add(newCostProfitVo);
+                }
+                response.getProfitVoList().add(costProfitVo);
+                continue;
+            }
+            //找出月度缺失的全院其他收支
+            List<CostProfitVo> missChilds = standCostProfitVo.getChildren().stream().filter(standChildCostProfitVo -> !firstOhterProfit.get().getChildren().stream().anyMatch(childCostProfitVo -> standChildCostProfitVo.getReportId().equals(childCostProfitVo.getReportId()))).collect(Collectors.toList());
+            if(CollectionUtils.isEmpty(missChilds)){
+                continue;
+            }
+            //添加缺失的全院其他收支项目到月度数据中
+            for (CostProfitVo missChildCostProfitVo : missChilds) {
+                CostProfitVo costProfitVo = BeanUtil.convertObj(missChildCostProfitVo, CostProfitVo.class);
+                combineReportAndProfitAmount(costProfitVo,null);
+                firstOhterProfit.get().getChildren().add(costProfitVo);
+            }
+        }
+    }
+
     /**
      * 生成多月份汇总的科室损益数据
      *
@@ -1648,6 +1690,7 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
             BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO))
                     .reduce(BigDecimal.ZERO, BigDecimal::add);
+            costProfitVo.setChildren(null);
             costProfitVo.setAmount(totalAmount);
             costProfitVo.setBudgetAmount(totalBudgetAmount);
             costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount);
@@ -1668,7 +1711,7 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
      * @param reportFormList
      * @return
      */
-    public  List<CostProfitVo> convertToCostProfitVoList(List<HospProfitAndLoss> hospProfitAndLossList,List<ReportForm> reportFormList ){
+    public  List<CostProfitVo> convertToCostProfitVoList(List<HospProfitAndLoss> hospProfitAndLossList,List<ReportForm> reportFormList,List<CostProfitVo> allCostProfitVo ){
         //全院其他收支项目
         List<HospProfitAndLoss> otherHospProfitAndLoss = hospProfitAndLossList.stream().filter(i -> NumberConstant.ONE.equals(i.getOriginType())).collect(Collectors.toList());
         //按报表项目编号map
@@ -1709,12 +1752,18 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
                 costProfitVo.setMonth(hospProfitAndLoss.getDateMonth());
                 //全院其他收支项目放在虚拟的全院其他收支下
                 costProfitVo.setSort(i);
-                costProfitVo.setReportNum(hospProfitAndLoss.getReportNum());
-                costProfitVo.setReportId(hospProfitAndLoss.getReportNum().longValue());
+                //添加一个负数作为虚拟的报表项目编号
+                Integer reportNum =hospProfitAndLoss.getReportNum();
+                costProfitVo.setReportNum(reportNum);
+                costProfitVo.setId(reportNum.longValue());
+                costProfitVo.setReportId(reportNum.longValue());
+                costProfitVo.setReportName(hospProfitAndLoss.getReportName());
                 costProfitVo.setReportParentId(otherProfit.getReportId());
                 costProfitVos.add(costProfitVo);
             }
         }
+        //记录所有月份的损益数据
+        allCostProfitVo.addAll(costProfitVos);
         //转成树状结构的损益数据
         List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(costProfitVos);
         return costProfitVoTree;
@@ -1744,6 +1793,7 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
      */
     public CostProfitVo reportFormToProfitVo(ReportForm reportForm){
         CostProfitVo profitVo = new CostProfitVo();
+        profitVo.setId(reportForm.getId());
         profitVo.setReportId(reportForm.getId());
         profitVo.setReportName(reportForm.getReportName());
         profitVo.setReportParentId(reportForm.getParentId());

+ 5 - 0
src/main/java/com/kcim/service/impl/IncomeCollectionServiceImpl.java

@@ -440,4 +440,9 @@ public class IncomeCollectionServiceImpl
         );
         return list;
     }
+
+    @Override
+    public List<IncomeCollection> getResponsibilitiesAccounts(int year, int month, Long hospId) {
+        return baseMapper.getResponsibilitiesAccounts(year, month, hospId);
+    }
 }

+ 7 - 5
src/main/java/com/kcim/service/impl/PatientItemImportServiceImpl.java

@@ -24,11 +24,10 @@ import com.kcim.service.CenterService;
 import com.kcim.service.CostIncomeFileService;
 import com.kcim.service.PatientItemImportService;
 import com.kcim.vo.DictDataVo;
-import com.kcim.vo.PatientInfoVo;
 import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
@@ -41,7 +40,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
 import java.net.URLEncoder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import static com.kcim.common.constants.Constant.CHARGE_ITEM_TYPE;
@@ -259,8 +261,8 @@ public class PatientItemImportServiceImpl implements PatientItemImportService {
     }
 
     @Override
-    public List<PatientInfoVo> getPatientItemPatientInfo(String filter, String computeDate) {
-        return repository.getPatientItemPatientInfo(computeDate,filter);
+    public PageUtils getPatientItemPatientInfo(Integer current, Integer pageSize, String filter, String computeDate) {
+        return repository.getPatientItemPatientInfo(current, pageSize, computeDate,filter);
     }
 
     /**

+ 264 - 92
src/main/java/com/kcim/service/impl/ProjectCostServiceImpl.java

@@ -19,6 +19,7 @@ import com.kcim.service.ResponsibilityDepartmentService;
 import com.kcim.service.SqlService;
 import com.kcim.vo.*;
 import com.kcim.web.reponse.ProjectCostResponse;
+import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Service;
@@ -47,6 +48,7 @@ import static com.kcim.service.impl.DrugMaterialCalculateServiceImpl.getVisitNoR
  **/
 @Service("ProjectCostService")
 @Slf4j
+@AllArgsConstructor
 public class ProjectCostServiceImpl implements ProjectCostService {
     private static final Integer LIMIT = 1000;
     ResponsibilityRepository responsibilityRepository;
@@ -69,6 +71,8 @@ public class ProjectCostServiceImpl implements ProjectCostService {
      * 科室损益
      */
     CostDepartmentProfitRepository costDepartmentProfitRepository;
+
+    CostDepartmentProfitAccountRepository costDepartmentProfitAccountRepository;
     /**
      * 项目分摊参数设置
      */
@@ -76,6 +80,8 @@ public class ProjectCostServiceImpl implements ProjectCostService {
 
     ComputeShareParamRepository computeShareParamRepository;
 
+    ComputeProjectCostAccountRepository projectCostAccountRepository;
+
     ItemRepository itemRepository;
 
     ResponsibilityDepartmentRepository responsibilityDepartmentRepository;
@@ -104,34 +110,34 @@ public class ProjectCostServiceImpl implements ProjectCostService {
 
     ResponsibilityDepartmentService responsibilityDepartmentService;
 
-    public ProjectCostServiceImpl(ResponsibilityDepartmentService responsibilityDepartmentService,SqlService sqlService,ResponsibilityRepository responsibilityRepository, ComputeProjectCostRepository repository, ComputeProjectCostDetailRepository detailRepository, ComputeProjectGroupCostDetailRepository groupDetailRepository, ImportPatientItemRepository importPatientItemRepository, ShareParamCostRepository shareParamCostRepository, ShareParamCostDetailRepository shareParamCostDetailRepository, CostDepartmentProfitRepository costDepartmentProfitRepository, ShareParamTypeMapRepository shareParamTypeMapRepository, ComputeShareParamRepository computeShareParamRepository, ItemRepository itemRepository, ResponsibilityDepartmentRepository responsibilityDepartmentRepository, CenterService centerService, ComputePatientProjectCostRepository computePatientProjectCostRepository, ComputePatientProjectCostDetailRepository computePatientProjectCostDetailRepository, ComputePatientProjectGroupCostDetailRepository computePatientProjectGroupCostDetailRepository, ComputeStandShareParamRepository computeStandShareParamRepository, ComputeStandProjectCostRepository standProjectCostRepository, ComputeStandProjectCostDetailRepository standProjectCostDetailRepository, ComputeStandProjectGroupCostDetailRepository standProjectGroupCostDetailRepository, ComputeStandPatientProjectCostRepository computeStandPatientProjectCostRepository, ComputeStandPatientProjectCostDetailRepository computeStandPatientProjectCostDetailRepository, ComputeStandPatientProjectGroupCostDetailRepository computeStandPatientProjectGroupCostDetailRepository) {
-        this.responsibilityRepository = responsibilityRepository;
-        this.repository = repository;
-        this.sqlService = sqlService;
-
-        this.detailRepository = detailRepository;
-        this.groupDetailRepository = groupDetailRepository;
-        this.importPatientItemRepository = importPatientItemRepository;
-        this.shareParamCostRepository = shareParamCostRepository;
-        this.shareParamCostDetailRepository = shareParamCostDetailRepository;
-        this.costDepartmentProfitRepository = costDepartmentProfitRepository;
-        this.shareParamTypeMapRepository = shareParamTypeMapRepository;
-        this.computeShareParamRepository = computeShareParamRepository;
-        this.itemRepository = itemRepository;
-        this.responsibilityDepartmentRepository = responsibilityDepartmentRepository;
-        this.centerService = centerService;
-        this.computePatientProjectCostRepository = computePatientProjectCostRepository;
-        this.computePatientProjectCostDetailRepository = computePatientProjectCostDetailRepository;
-        this.computePatientProjectGroupCostDetailRepository = computePatientProjectGroupCostDetailRepository;
-        this.computeStandShareParamRepository = computeStandShareParamRepository;
-        this.standProjectCostRepository = standProjectCostRepository;
-        this.standProjectCostDetailRepository = standProjectCostDetailRepository;
-        this.standProjectGroupCostDetailRepository = standProjectGroupCostDetailRepository;
-        this.computeStandPatientProjectCostRepository = computeStandPatientProjectCostRepository;
-        this.computeStandPatientProjectCostDetailRepository = computeStandPatientProjectCostDetailRepository;
-        this.computeStandPatientProjectGroupCostDetailRepository = computeStandPatientProjectGroupCostDetailRepository;
-        this.responsibilityDepartmentService=responsibilityDepartmentService;
-    }
+//    public ProjectCostServiceImpl(ResponsibilityDepartmentService responsibilityDepartmentService,SqlService sqlService,ResponsibilityRepository responsibilityRepository, ComputeProjectCostRepository repository, ComputeProjectCostDetailRepository detailRepository, ComputeProjectGroupCostDetailRepository groupDetailRepository, ImportPatientItemRepository importPatientItemRepository, ShareParamCostRepository shareParamCostRepository, ShareParamCostDetailRepository shareParamCostDetailRepository, CostDepartmentProfitRepository costDepartmentProfitRepository, ShareParamTypeMapRepository shareParamTypeMapRepository, ComputeShareParamRepository computeShareParamRepository, ItemRepository itemRepository, ResponsibilityDepartmentRepository responsibilityDepartmentRepository, CenterService centerService, ComputePatientProjectCostRepository computePatientProjectCostRepository, ComputePatientProjectCostDetailRepository computePatientProjectCostDetailRepository, ComputePatientProjectGroupCostDetailRepository computePatientProjectGroupCostDetailRepository, ComputeStandShareParamRepository computeStandShareParamRepository, ComputeStandProjectCostRepository standProjectCostRepository, ComputeStandProjectCostDetailRepository standProjectCostDetailRepository, ComputeStandProjectGroupCostDetailRepository standProjectGroupCostDetailRepository, ComputeStandPatientProjectCostRepository computeStandPatientProjectCostRepository, ComputeStandPatientProjectCostDetailRepository computeStandPatientProjectCostDetailRepository, ComputeStandPatientProjectGroupCostDetailRepository computeStandPatientProjectGroupCostDetailRepository) {
+//        this.responsibilityRepository = responsibilityRepository;
+//        this.repository = repository;
+//        this.sqlService = sqlService;
+//
+//        this.detailRepository = detailRepository;
+//        this.groupDetailRepository = groupDetailRepository;
+//        this.importPatientItemRepository = importPatientItemRepository;
+//        this.shareParamCostRepository = shareParamCostRepository;
+//        this.shareParamCostDetailRepository = shareParamCostDetailRepository;
+//        this.costDepartmentProfitRepository = costDepartmentProfitRepository;
+//        this.shareParamTypeMapRepository = shareParamTypeMapRepository;
+//        this.computeShareParamRepository = computeShareParamRepository;
+//        this.itemRepository = itemRepository;
+//        this.responsibilityDepartmentRepository = responsibilityDepartmentRepository;
+//        this.centerService = centerService;
+//        this.computePatientProjectCostRepository = computePatientProjectCostRepository;
+//        this.computePatientProjectCostDetailRepository = computePatientProjectCostDetailRepository;
+//        this.computePatientProjectGroupCostDetailRepository = computePatientProjectGroupCostDetailRepository;
+//        this.computeStandShareParamRepository = computeStandShareParamRepository;
+//        this.standProjectCostRepository = standProjectCostRepository;
+//        this.standProjectCostDetailRepository = standProjectCostDetailRepository;
+//        this.standProjectGroupCostDetailRepository = standProjectGroupCostDetailRepository;
+//        this.computeStandPatientProjectCostRepository = computeStandPatientProjectCostRepository;
+//        this.computeStandPatientProjectCostDetailRepository = computeStandPatientProjectCostDetailRepository;
+//        this.computeStandPatientProjectGroupCostDetailRepository = computeStandPatientProjectGroupCostDetailRepository;
+//        this.responsibilityDepartmentService=responsibilityDepartmentService;
+//    }
 
     /**
      * 项目成本计算分页查询
@@ -467,20 +473,44 @@ public class ProjectCostServiceImpl implements ProjectCostService {
         if (CollectionUtils.isEmpty(shareParamCostVos)){
             throw new CostException("没有项目分摊配置信息无法分摊,请联系管理员");
         }
+        //按成本列代码分组
+        Map<String, List<ShareParamCostVo>> shareParamCostMap = shareParamCostVos.stream().collect(Collectors.groupingBy(ShareParamCostVo::getColumnCode));
 
         //获取科室损益报表数据
         List<CostDepartmentProfit> costDepartmentProfits = costDepartmentProfitRepository.getDepartmentProfit(computeDate);
         if (CollectionUtils.isEmpty(costDepartmentProfits)){
             throw new CostException("未进行科室损益计算,请先进行科室损益计算,当前计算中止");
         }
+        //按报表类型+报表编码+责任中心分组
+        Map<String, List<CostDepartmentProfit>> deptProfitGroup =costDepartmentProfits.stream().collect(Collectors.groupingBy(
+                                cost ->String.format("%s-%s-%s",cost.getShareType(),cost.getReportNum(),cost.getResponsibilityCode())));
+
+        //获取科室损益的会计科目金额
+        List<CostDepartmentProfitAccount> deptPriftAccountList = costDepartmentProfitAccountRepository.getList(computeDate);
+        Map<Long, List<CostDepartmentProfitAccount>> deptPriftAccountMap;
+        if(CollectionUtils.isEmpty(deptPriftAccountList)){
+            deptPriftAccountMap = new HashMap<>();
+        }else{
+            deptPriftAccountMap= deptPriftAccountList.stream().collect(Collectors.groupingBy(CostDepartmentProfitAccount::getDeptProfitId));
+        }
 
+        //获取责任中心的医疗服务项目字典
+        List<Item> itemList = itemRepository.getRespItemList();
+        Map<String, Map<String, List<Item>>> respItemGroup = itemList.stream()
+                .collect(Collectors.groupingBy(Item::getResponsibilityCode,
+                        Collectors.groupingBy(Item::getCode)));
 
         //项目成本分摊配置主表信息(项目成本列配置)
         List<ShareParamCost> ShareParamCosts = shareParamCostRepository.getList(null);
+        Map<String, List<ShareParamCost>> shareParamCostGroup = ShareParamCosts.stream().collect(Collectors.groupingBy(ShareParamCost::getItemType));
         //分摊参数信息
         List<ComputeShareParamDetailVo> computeShareParamDetails = computeShareParamRepository.getComputeShareParamDetail(computeDate);
+        Map<String, List<ComputeShareParamDetailVo>> shareParamDetailValueGroup = computeShareParamDetails.stream().collect(Collectors.groupingBy(
+                cost -> String.format("%s-%s-%s", cost.getResponsibilityCode(), cost.getItemType(), cost.getCode())));
         //分摊参数按责任中心汇总信息
         List<ComputeShareParamDetailVo> computeShareParamDetailGroup = computeShareParamRepository.getComputeShareParamDetailGroup(computeDate);
+        Map<String, List<ComputeShareParamDetailVo>> shareParamDetailGroup = computeShareParamDetailGroup.stream().collect(Collectors.groupingBy(
+                cost -> String.format("%s-%s-%s", cost.getItemType(), cost.getShareParamCode(), cost.getResponsibilityCode())));
         //要计算的科室收费项目
         List<ComputeShareParamDetailVo> computeResponsibilityItems = computeShareParamRepository.getComputeResponsibilityItem(computeDate);
 
@@ -493,16 +523,17 @@ public class ProjectCostServiceImpl implements ProjectCostService {
         //按项目类别+责任中心代码+项目代码逐个计算项目分摊金额
         computeResponsibilityItems.stream().forEach(responsibilityItem->{
             //创建项目成本主表对象
-            ComputeProjectCost projectCost = createComputeProjectCost(computeDate, currentUser, responsibilityItem);
+            ComputeProjectCost projectCost = createComputeProjectCost(computeDate, currentUser, responsibilityItem,respItemGroup);
             computeProjectCosts.add(projectCost);
+            String shareParamDetailValueKey = String.format("%s-%s-%s", projectCost.getResponsibilityCode(),projectCost.getItemType(), projectCost.getCode());
             //获取项目对应分摊参数数值
-            List<ComputeShareParamDetailVo> itemShareParams = computeShareParamDetails.stream().filter(shareParamGroup -> shareParamGroup.getResponsibilityCode().equals(projectCost.getResponsibilityCode())
-                    && shareParamGroup.getCode().equals(projectCost.getCode()) && shareParamGroup.getItemType().equals(projectCost.getItemType())).collect(Collectors.toList());
+            List<ComputeShareParamDetailVo> itemShareParams =shareParamDetailValueGroup.get(shareParamDetailValueKey);
             if (CollectionUtils.isEmpty(itemShareParams)){
                 throw new CostException(String.format("找不到项目的[%s-%s]对应的分摊分摊参数,请重新计算分摊参数",projectCost.getItemType(),projectCost.getName()));
             }
+            Map<String, List<ComputeShareParamDetailVo>> respShareParamValueMap = itemShareParams.stream().collect(Collectors.groupingBy(ComputeShareParamDetailVo::getShareParamCode));
             //取项目对应的分摊配置
-            List<ShareParamCost> itemShareParamCost = ShareParamCosts.stream().filter(shareParamCost -> shareParamCost.getItemType().equals(projectCost.getItemType())).collect(Collectors.toList());
+            List<ShareParamCost> itemShareParamCost =shareParamCostGroup.get(projectCost.getItemType());
             if (CollectionUtils.isEmpty(itemShareParamCost)){
                 throw new CostException(String.format("类型[%s]没有对应分摊配置,请联系管理员",projectCost.getItemType()));
             }
@@ -510,7 +541,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
             //按项目分摊配置计算项目的所有项目成本列的分摊金额
             itemShareParamCost.stream().forEach(shareParamCost->{
                 ComputeProjectCostDetail cmputeProjectCostDetail=createComputeProjectCostDetail(computeDate, currentUser,incomeShareParam,responsibilityItem,projectCost,
-                        shareParamCost,shareParamCostVos,itemShareParams,computeShareParamDetailGroup,costDepartmentProfits);
+                                                        shareParamCost,shareParamCostMap,respShareParamValueMap,shareParamDetailGroup, deptProfitGroup, deptPriftAccountMap);
                 computeProjectCostDetailChilds.add(cmputeProjectCostDetail);
             });
             computeProjectCostDetails.addAll(computeProjectCostDetailChilds);
@@ -537,22 +568,54 @@ public class ProjectCostServiceImpl implements ProjectCostService {
         repository.removeByComputeDate(computeDate, currentUser);
         detailRepository.removeByComputeDate(computeDate, currentUser);
         groupDetailRepository.removeByComputeDate(computeDate, currentUser);
+        projectCostAccountRepository.removeByComputeDate(computeDate, currentUser);
 
         //保存项目分摊主表对象数据
         repository.saveBatch(computeProjectCosts, 500);
         if (!CollectionUtils.isEmpty(computeProjectCostDetails)) {
             //保存项目分摊明细表对象数据
             computeProjectCostDetails.stream().forEach(projectCostDetail->projectCostDetail.setProjectCostId(projectCostDetail.getComputeProjectCost().getId()));
-            detailRepository.saveBatch(computeProjectCostDetails, 500);
+            detailRepository.batchInsert(computeProjectCostDetails);
         }
         if (!CollectionUtils.isEmpty(computeProjectGroupCostDetails)) {
             //保存项目分摊汇总表对象数据
             computeProjectGroupCostDetails.stream().forEach(projectCostDetail->projectCostDetail.setProjectCostId(projectCostDetail.getComputeProjectCost().getId()));
-            groupDetailRepository.saveBatch(computeProjectGroupCostDetails, 500);
+            groupDetailRepository.batchInsert(computeProjectGroupCostDetails);
         }
+        //保存项目成本对应的会计科目信息
+        saveProjectCostAccountList(computeProjectCosts);
 
+    }
 
+    /**
+     * 保存项目成本对应的会计科目信息
+     * @param computeProjectCosts
+     */
+    public void saveProjectCostAccountList(List<ComputeProjectCost> computeProjectCosts){
+        List<ComputeProjectCostAccount> projectCostAccountList=new ArrayList<>();
+        for (ComputeProjectCost projectCost : computeProjectCosts) {
+            List<ComputeProjectCostAccount> itemAccountList =new ArrayList<>();
+            itemAccountList.addAll(projectCost.getProjectCostAccountMap().values());
+            if (CollectionUtils.isEmpty(itemAccountList)) {
+                continue;
+            }
+            itemAccountList.forEach(itemAccount->{
+                itemAccount.setProjectCostId(projectCost.getId());
+                //计算单个项目的金额
+                if(BigDecimal.ZERO.compareTo(projectCost.getQuantity()) == NumberConstant.ZERO){
+                    itemAccount.setComputeSingleResult(BigDecimal.ZERO);
+                }else{
+                    BigDecimal divide = itemAccount.getComputeResult().divide(projectCost.getQuantity(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+                    itemAccount.setComputeSingleResult(divide);
+                }
+            });
+            projectCostAccountList.addAll(itemAccountList);
+        }
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            return;
+        }
 
+        projectCostAccountRepository.batchInsert(projectCostAccountList);
     }
 
     /**
@@ -579,7 +642,7 @@ public class ProjectCostServiceImpl implements ProjectCostService {
      * @param responsibilityItem
      * @return
      */
-    public ComputeProjectCost createComputeProjectCost(String computeDate,SessionUserVO currentUser,ComputeShareParamDetailVo responsibilityItem){
+    public ComputeProjectCost createComputeProjectCost(String computeDate,SessionUserVO currentUser,ComputeShareParamDetailVo responsibilityItem,Map<String, Map<String, List<Item>>> respItemGroup){
         //主表公共对象
         ComputeProjectCost computeProjectCost = new ComputeProjectCost();
         computeProjectCost.setComputeDate(computeDate);
@@ -589,8 +652,14 @@ public class ProjectCostServiceImpl implements ProjectCostService {
         computeProjectCost.setCode(responsibilityItem.getCode());
         computeProjectCost.setName(responsibilityItem.getName());
         computeProjectCost.setItemType(responsibilityItem.getItemType());
+        computeProjectCost.setQuantity(responsibilityItem.getNum());
         computeProjectCost.setResponsibilityCode(responsibilityItem.getResponsibilityCode());
         computeProjectCost.setResponsibilityName(responsibilityItem.getResponsibilityName());
+        Map<String, List<Item>> stringListMap = respItemGroup.get(responsibilityItem.getResponsibilityCode());
+        if(stringListMap!=null&&stringListMap.containsKey(responsibilityItem.getCode())){
+            computeProjectCost.setStandItemCode(stringListMap.get(responsibilityItem.getCode()).get(NumberConstant.ZERO).getStandItemCode());
+        }
+        computeProjectCost.setProjectCostAccountMap(new HashMap<>());
         return computeProjectCost;
     }
 
@@ -607,9 +676,17 @@ public class ProjectCostServiceImpl implements ProjectCostService {
      * @param costDepartmentProfits 科室损益数据
      * @return
      */
-    public ComputeProjectCostDetail createComputeProjectCostDetail(String computeDate,SessionUserVO currentUser,ShareParamTypeMap incomeShareParam,ComputeShareParamDetailVo responsibilityItem,ComputeProjectCost computeProjectCost,ShareParamCost shareParamCost,
-                                                                   List<ShareParamCostVo> shareParamCostVos,List<ComputeShareParamDetailVo> computeShareParamDetails ,
-                                                                   List<ComputeShareParamDetailVo> computeShareParamDetailGroup,List<CostDepartmentProfit> costDepartmentProfits){
+    public ComputeProjectCostDetail createComputeProjectCostDetail(String computeDate,
+                                                                   SessionUserVO currentUser,
+                                                                   ShareParamTypeMap incomeShareParam,
+                                                                   ComputeShareParamDetailVo responsibilityItem,
+                                                                   ComputeProjectCost computeProjectCost,
+                                                                   ShareParamCost shareParamCost,
+                                                                   Map<String, List<ShareParamCostVo>> shareParamCostVos,
+                                                                   Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetails ,
+                                                                   Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetailGroup,
+                                                                   Map<String, List<CostDepartmentProfit>> costDepartmentProfits,
+                                                                   Map<Long, List<CostDepartmentProfitAccount>> deptPriftAccountMap){
         //明细表公共对象
         ComputeProjectCostDetail costDetail = new ComputeProjectCostDetail();
         costDetail.setComputeDate(computeDate);
@@ -620,16 +697,15 @@ public class ProjectCostServiceImpl implements ProjectCostService {
         costDetail.setCostColumnCode(shareParamCost.getColumnCode());
         costDetail.setCostColumnType(shareParamCost.getColumnType());
         //获取对应分摊配置明细
-        List<ShareParamCostVo> shareParamDetails = shareParamCostVos.stream().filter(shareParamDetail -> shareParamDetail.getColumnCode().equals(shareParamCost.getColumnCode())).collect(Collectors.toList());
+        List<ShareParamCostVo> shareParamDetails = shareParamCostVos.get(shareParamCost.getColumnCode());
         if (CollectionUtils.isEmpty(shareParamDetails)){
             throw new CostException(String.format("[%s]没有对应分摊配置,请联系管理员",shareParamCost.getColumnName()));
         }
+        String profitKey = String.format("%s-%s-%s",shareParamCost.getReportType(),shareParamCost.getProfitNum(),computeProjectCost.getResponsibilityCode());
         //根据主表配置找到对应的科室损益数据
-        Optional<CostDepartmentProfit> firstDepartmentProfit = costDepartmentProfits.stream().filter(departmentProfit -> String.valueOf(departmentProfit.getShareType()).equals(shareParamCost.getReportType()) &&
-                String.valueOf(departmentProfit.getReportNum()).equals(shareParamCost.getProfitNum()) &&
-                departmentProfit.getResponsibilityCode().equals(computeProjectCost.getResponsibilityCode())).findFirst();
+        List<CostDepartmentProfit> departmentProfitList = costDepartmentProfits.get(profitKey);
         //没有对应的损益项目数据或者损益项目金额为0
-        if(!firstDepartmentProfit.isPresent()||firstDepartmentProfit.get().getAmount().equals(BigDecimal.ZERO)){
+        if(CollectionUtils.isEmpty(departmentProfitList)|| departmentProfitList.get(NumberConstant.ZERO).getAmount().equals(BigDecimal.ZERO)){
             costDetail.setComputeResult(BigDecimal.ZERO);
             costDetail.setComputeSingleResult(BigDecimal.ZERO);
             costDetail.setStandComputeResult(BigDecimal.ZERO);
@@ -637,13 +713,13 @@ public class ProjectCostServiceImpl implements ProjectCostService {
             return costDetail;
         }
         //按项目分摊配置计算项目的一个项目成本列的分摊金额
-        BigDecimal itemAllocationAmount=calcItemAllocationAmount(incomeShareParam,computeProjectCost,firstDepartmentProfit.get(),
-                shareParamDetails,computeShareParamDetailGroup,computeShareParamDetails);
+        BigDecimal itemAllocationAmount=calcItemAllocationAmount(incomeShareParam,computeProjectCost, departmentProfitList.get(NumberConstant.ZERO),
+                shareParamDetails,computeShareParamDetailGroup,computeShareParamDetails,deptPriftAccountMap);
         costDetail.setComputeResult(itemAllocationAmount);
 
         //按项目分摊配置计算项目的一个项目成本列的标准法分摊金额
-        BigDecimal itemStandAllocationAmount=calcItemStandAllocationAmount(incomeShareParam,computeProjectCost,firstDepartmentProfit.get(),
-                shareParamDetails,computeShareParamDetailGroup,computeShareParamDetails);
+        BigDecimal itemStandAllocationAmount=calcItemStandAllocationAmount(incomeShareParam,computeProjectCost, departmentProfitList.get(NumberConstant.ZERO),
+                shareParamDetails,computeShareParamDetailGroup,computeShareParamDetails,deptPriftAccountMap);
         costDetail.setStandComputeResult(itemStandAllocationAmount);
 
         //项目没有数量时,单个项目的分摊金额为0
@@ -667,44 +743,118 @@ public class ProjectCostServiceImpl implements ProjectCostService {
      * @param computeShareParamDetails 分摊参数计算明细
      * @return
      */
-    public  BigDecimal calcItemAllocationAmount(ShareParamTypeMap incomeShareParam,ComputeProjectCost computeProjectCost,CostDepartmentProfit costDepartmentProfit,List<ShareParamCostVo> shareParamCostVos,
-                                                List<ComputeShareParamDetailVo> computeShareParamDetailGroup,List<ComputeShareParamDetailVo> computeShareParamDetails){
+    public BigDecimal calcItemAllocationAmount(ShareParamTypeMap incomeShareParam,
+                                               ComputeProjectCost computeProjectCost,
+                                               CostDepartmentProfit costDepartmentProfit,
+                                               List<ShareParamCostVo> shareParamCostVos,
+                                               Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetailGroup,
+                                               Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetails,
+                                               Map<Long, List<CostDepartmentProfitAccount>> deptPriftAccountMap) {
         BigDecimal itemAllocationAmount=BigDecimal.ZERO;
         //按配置计算每个参数分摊金额
-        for (ShareParamCostVo shareParamCostVo : shareParamCostVos) {//获取参数对应的责任中心汇总数据
-            Optional<ComputeShareParamDetailVo> firstShareParamGroup = computeShareParamDetailGroup.stream().filter(shareParamGroup -> shareParamGroup.getItemType().equals(computeProjectCost.getItemType()) &&
-                    shareParamGroup.getResponsibilityCode().equals(computeProjectCost.getResponsibilityCode()) && shareParamGroup.getShareParamCode().equals(shareParamCostVo.getShareParamCode())).findFirst();
+        for (ShareParamCostVo shareParamCostVo : shareParamCostVos) {
+            //获取参数对应的责任中心汇总数据
+            String shareParamKey = String.format("%s-%s-%s",computeProjectCost.getItemType(),shareParamCostVo.getShareParamCode(),computeProjectCost.getResponsibilityCode());
+            List<ComputeShareParamDetailVo> shareParamTotalValueList = computeShareParamDetailGroup.get(shareParamKey);
             //责任中心的汇总数据为0时,按项目收入分摊
-            if (!firstShareParamGroup.isPresent() || firstShareParamGroup.get().getComputeResult().compareTo(BigDecimal.ZERO) == NumberConstant.ZERO) {
+            if (CollectionUtils.isEmpty(shareParamTotalValueList)|| shareParamTotalValueList.get(NumberConstant.ZERO).getComputeResult().compareTo(BigDecimal.ZERO) == NumberConstant.ZERO) {
                 //获取项目对应的收入数据
-                Optional<ComputeShareParamDetailVo> firstComputeShareParamDetail = computeShareParamDetails.stream().filter(computeShareParamDetailVo ->
-                        computeShareParamDetailVo.getShareParamCode().equals(incomeShareParam.getShareParamCode())).findFirst();
-                if (!firstComputeShareParamDetail.isPresent()) {
+                List<ComputeShareParamDetailVo> computeShareParamDetailList = computeShareParamDetails.get(incomeShareParam.getShareParamCode());
+                if (CollectionUtils.isEmpty(computeShareParamDetailList)) {
                     throw new CostException(String.format("[%s-%s]没有收入数据无法分摊,请检查对应的收费项目数据及分摊参数计算结果数据", computeProjectCost.getResponsibilityName(), computeProjectCost.getName()));
                 }
-                //找到项目收入的责任中心汇总数据
-                ComputeShareParamDetailVo incomeShareParamGroup = computeShareParamDetailGroup.stream().filter(shareParamGroup -> shareParamGroup.getItemType().equals(computeProjectCost.getItemType()) &&
-                        shareParamGroup.getResponsibilityCode().equals(computeProjectCost.getResponsibilityCode()) && shareParamGroup.getShareParamCode().equals(incomeShareParam.getShareParamCode())).findFirst().get();
-                //分摊金额=损益项目金额*分摊参数占比*收入/责任中心总收入
-                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(firstComputeShareParamDetail.get().getComputeResult())
-                        .divide(incomeShareParamGroup.getComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
-                itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                String incomeShareParamKey = String.format("%s-%s-%s",computeProjectCost.getItemType(),incomeShareParam.getShareParamCode(),computeProjectCost.getResponsibilityCode());
+                //有对应的收入数据
+                if(computeShareParamDetailGroup.containsKey(incomeShareParamKey)){
+                    //找到项目收入的责任中心汇总数据
+                    List<ComputeShareParamDetailVo> incomeShareParamGroup = computeShareParamDetailGroup.get(incomeShareParamKey);
+                    //分摊金额=损益项目金额*分摊参数占比*收入/责任中心总收入
+                    BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(computeShareParamDetailList.get(NumberConstant.ZERO).getComputeResult())
+                            .divide(incomeShareParamGroup.get(NumberConstant.ZERO).getComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+                    itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                    //计算项目对应的会计科目金额
+                    calcProjectAccountAmount( computeProjectCost, costDepartmentProfit, shareParamCostVo, computeShareParamDetailList.get(NumberConstant.ZERO),incomeShareParamGroup.get(NumberConstant.ZERO), deptPriftAccountMap,NumberConstant.ONE ) ;
+                }
             } else {
+
                 //获取项目对应的分摊参数数据
-                Optional<ComputeShareParamDetailVo> firstComputeShareParamDetail = computeShareParamDetails.stream().filter(computeShareParamDetailVo ->
-                        computeShareParamDetailVo.getShareParamCode().equals(shareParamCostVo.getShareParamCode())).findFirst();
-                if (!firstComputeShareParamDetail.isPresent()) {
+                List<ComputeShareParamDetailVo> computeShareParamDetailList = computeShareParamDetails.get(shareParamCostVo.getShareParamCode());
+                if (CollectionUtils.isEmpty(computeShareParamDetailList)) {
                     throw new CostException(String.format("[%s-%s]没有收入数据无法分摊,请检查对应的收费项目数据", computeProjectCost.getResponsibilityName(), computeProjectCost.getName()));
                 }
                 //分摊金额=损益项目金额*分摊参数占比*分摊参数数值/责任中心总分摊参数数值
-                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(firstComputeShareParamDetail.get().getComputeResult())
-                        .divide(firstShareParamGroup.get().getComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(computeShareParamDetailList.get(NumberConstant.ZERO).getComputeResult())
+                        .divide(shareParamTotalValueList.get(NumberConstant.ZERO).getComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
                 itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                //计算项目对应的会计科目金额
+                calcProjectAccountAmount( computeProjectCost, costDepartmentProfit, shareParamCostVo, computeShareParamDetailList.get(NumberConstant.ZERO), shareParamTotalValueList.get(NumberConstant.ZERO), deptPriftAccountMap,NumberConstant.ONE );
             }
         }
         return  itemAllocationAmount;
     }
 
+    /**
+     * 计算项目对应的会计科目金额
+     * @param computeProjectCost
+     * @param costDepartmentProfit
+     * @param shareParamCostVo
+     * @param shareParamValueVo
+     * @param shareParamTotalValueVo
+     * @param deptPriftAccountMap
+     * @param calcType 1:计算项目金额 2:计算项目标准金额
+     */
+    public void calcProjectAccountAmount(ComputeProjectCost computeProjectCost,
+                                         CostDepartmentProfit costDepartmentProfit,
+                                         ShareParamCostVo shareParamCostVo,
+                                         ComputeShareParamDetailVo shareParamValueVo,
+                                         ComputeShareParamDetailVo shareParamTotalValueVo,
+                                         Map<Long,List<CostDepartmentProfitAccount>> deptPriftAccountMap,
+                                         Integer calcType){
+        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = deptPriftAccountMap.get(costDepartmentProfit.getId());
+        if(CollectionUtils.isEmpty(costDepartmentProfitAccounts)){
+            return;
+        }
+        //排除掉无效数据
+        if(StringUtils.isEmpty(computeProjectCost.getStandItemCode())){
+            return;
+        }
+        for (CostDepartmentProfitAccount costDepartmentProfitAccount : costDepartmentProfitAccounts) {
+            ComputeProjectCostAccount computeProjectCostAccount = new ComputeProjectCostAccount();
+            computeProjectCostAccount.setProjectCostId(computeProjectCost.getId())
+                    .setStandItemCode(computeProjectCost.getStandItemCode())
+                    .setAccountType(costDepartmentProfitAccount.getAccountType())
+                    .setCostType(costDepartmentProfitAccount.getCostType())
+                    .setHospId(costDepartmentProfit.getHospId())
+                    .setComputeDate(computeProjectCost.getComputeDate())
+                    .setCreateUser(computeProjectCost.getCreateUser())
+                    .setCreateTime(new Date())
+                    .setUpdateUser(computeProjectCost.getUpdateUser())
+                    .setUpdateTime(new Date())
+                    .setDelFlag(NumberConstant.ZERO);
+
+            BigDecimal paramAllocationAmount = BigDecimal.ZERO;
+            if(BigDecimal.ZERO.compareTo(shareParamTotalValueVo.getComputeResult())!=NumberConstant.ZERO){
+                paramAllocationAmount = costDepartmentProfitAccount.getAmount().multiply(shareParamCostVo.getPercent()).multiply(shareParamValueVo.getComputeResult())
+                        .divide(shareParamTotalValueVo.getComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+            }
+            computeProjectCostAccount.setComputeResult(paramAllocationAmount);
+            String accountKey=String.format("%s-%s",computeProjectCostAccount.getCostType(),computeProjectCostAccount.getAccountType());
+            //判断当前科目是否已经存在
+            if(computeProjectCost.getProjectCostAccountMap().containsKey(accountKey)){
+                ComputeProjectCostAccount itemAccount = computeProjectCost.getProjectCostAccountMap().get(accountKey);
+                if(NumberConstant.ONE.equals(calcType)){
+                    itemAccount.setComputeResult(itemAccount.getComputeResult().add(computeProjectCostAccount.getComputeResult()));
+                }else {
+                    itemAccount.setStandComputeResult(itemAccount.getStandComputeResult().add(computeProjectCostAccount.getComputeResult()));
+                }
+            }else{
+                computeProjectCost.getProjectCostAccountMap().put(accountKey,computeProjectCostAccount);
+            }
+        }
+
+    }
+
+
     /**
      * 计算项目标准法的分摊金额
      * @param computeProjectCost 主表对象
@@ -714,40 +864,50 @@ public class ProjectCostServiceImpl implements ProjectCostService {
      * @param computeShareParamDetails 分摊参数计算明细
      * @return
      */
-    public  BigDecimal calcItemStandAllocationAmount(ShareParamTypeMap incomeShareParam,ComputeProjectCost computeProjectCost,CostDepartmentProfit costDepartmentProfit,List<ShareParamCostVo> shareParamCostVos,
-                                                List<ComputeShareParamDetailVo> computeShareParamDetailGroup,List<ComputeShareParamDetailVo> computeShareParamDetails){
+    public  BigDecimal calcItemStandAllocationAmount(ShareParamTypeMap incomeShareParam,
+                                                     ComputeProjectCost computeProjectCost,
+                                                     CostDepartmentProfit costDepartmentProfit,
+                                                     List<ShareParamCostVo> shareParamCostVos,
+                                                     Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetailGroup,
+                                                     Map<String, List<ComputeShareParamDetailVo>> computeShareParamDetails,
+                                                     Map<Long, List<CostDepartmentProfitAccount>> deptPriftAccountMap){
         BigDecimal itemAllocationAmount=BigDecimal.ZERO;
         //按配置计算每个参数分摊金额
         for (ShareParamCostVo shareParamCostVo : shareParamCostVos) {
             //获取参数对应的责任中心汇总数据
-            Optional<ComputeShareParamDetailVo> firstShareParamGroup = computeShareParamDetailGroup.stream().filter(shareParamGroup -> shareParamGroup.getItemType().equals(computeProjectCost.getItemType()) &&
-                    shareParamGroup.getResponsibilityCode().equals(computeProjectCost.getResponsibilityCode()) && shareParamGroup.getShareParamCode().equals(shareParamCostVo.getShareParamCode())).findFirst();
+            String shareParamKey = String.format("%s-%s-%s",computeProjectCost.getItemType(),shareParamCostVo.getShareParamCode(),computeProjectCost.getResponsibilityCode());
+            List<ComputeShareParamDetailVo> shareParamTotalValueList = computeShareParamDetailGroup.get(shareParamKey);
             //责任中心的汇总数据为0时,按项目收入分摊
-            if (!firstShareParamGroup.isPresent() || firstShareParamGroup.get().getStandComputeResult().compareTo(BigDecimal.ZERO) == NumberConstant.ZERO) {
+            if (CollectionUtils.isEmpty(shareParamTotalValueList)|| shareParamTotalValueList.get(NumberConstant.ZERO).getStandComputeResult().compareTo(BigDecimal.ZERO) == NumberConstant.ZERO) {
                 //获取项目对应的收入数据
-                Optional<ComputeShareParamDetailVo> firstComputeShareParamDetail = computeShareParamDetails.stream().filter(computeShareParamDetailVo ->
-                        computeShareParamDetailVo.getShareParamCode().equals(incomeShareParam.getShareParamCode())).findFirst();
-                if (!firstComputeShareParamDetail.isPresent()) {
+                List<ComputeShareParamDetailVo> computeShareParamDetailList = computeShareParamDetails.get(incomeShareParam.getShareParamCode());
+                if (CollectionUtils.isEmpty(computeShareParamDetailList)) {
                     throw new CostException(String.format("[%s-%s]没有收入数据无法分摊,请检查对应的收费项目数据及分摊参数计算结果数据", computeProjectCost.getResponsibilityName(), computeProjectCost.getName()));
                 }
-                //找到项目收入的责任中心汇总数据
-                ComputeShareParamDetailVo incomeShareParamGroup = computeShareParamDetailGroup.stream().filter(shareParamGroup -> shareParamGroup.getItemType().equals(computeProjectCost.getItemType()) &&
-                        shareParamGroup.getResponsibilityCode().equals(computeProjectCost.getResponsibilityCode()) && shareParamGroup.getShareParamCode().equals(incomeShareParam.getShareParamCode())).findFirst().get();
-                //分摊金额=损益项目金额*分摊参数占比*收入/责任中心总收入
-                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(firstComputeShareParamDetail.get().getStandComputeResult())
-                        .divide(incomeShareParamGroup.getStandComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
-                itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                String incomeShareParamKey = String.format("%s-%s-%s",computeProjectCost.getItemType(),incomeShareParam.getShareParamCode(),computeProjectCost.getResponsibilityCode());
+                //有对应的收入数据
+                if(computeShareParamDetailGroup.containsKey(incomeShareParamKey)){
+                    //找到项目收入的责任中心汇总数据
+                    List<ComputeShareParamDetailVo> incomeShareParamGroup = computeShareParamDetailGroup.get(incomeShareParamKey);
+                    //分摊金额=损益项目金额*分摊参数占比*收入/责任中心总收入
+                    BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(computeShareParamDetailList.get(NumberConstant.ZERO).getStandComputeResult())
+                            .divide(incomeShareParamGroup.get(NumberConstant.ZERO).getStandComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+                    itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                    //计算项目对应的会计科目金额
+                    calcProjectAccountAmount( computeProjectCost, costDepartmentProfit, shareParamCostVo, computeShareParamDetailList.get(NumberConstant.ZERO),incomeShareParamGroup.get(NumberConstant.ZERO), deptPriftAccountMap,NumberConstant.ONE ) ;
+                }
             } else {
                 //获取项目对应的分摊参数数据
-                Optional<ComputeShareParamDetailVo> firstComputeShareParamDetail = computeShareParamDetails.stream().filter(computeShareParamDetailVo ->
-                        computeShareParamDetailVo.getShareParamCode().equals(shareParamCostVo.getShareParamCode())).findFirst();
-                if (!firstComputeShareParamDetail.isPresent()) {
+                List<ComputeShareParamDetailVo> computeShareParamDetailList = computeShareParamDetails.get(shareParamCostVo.getShareParamCode());
+                if (CollectionUtils.isEmpty(computeShareParamDetailList)) {
                     throw new CostException(String.format("[%s-%s]没有收入数据无法分摊,请检查对应的收费项目数据", computeProjectCost.getResponsibilityName(), computeProjectCost.getName()));
                 }
                 //分摊金额=损益项目金额*分摊参数占比*分摊参数数值/责任中心总分摊参数数值
-                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(firstComputeShareParamDetail.get().getStandComputeResult())
-                        .divide(firstShareParamGroup.get().getStandComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
+                BigDecimal paramAllocationAmount = costDepartmentProfit.getAmount().multiply(shareParamCostVo.getPercent()).multiply(computeShareParamDetailList.get(NumberConstant.ZERO).getStandComputeResult())
+                        .divide(shareParamTotalValueList.get(NumberConstant.ZERO).getStandComputeResult(), NumberConstant.FOUR, RoundingMode.HALF_UP);
                 itemAllocationAmount = itemAllocationAmount.add(paramAllocationAmount);
+                //计算项目对应的会计科目金额
+                calcProjectAccountAmount( computeProjectCost, costDepartmentProfit, shareParamCostVo, computeShareParamDetailList.get(NumberConstant.ZERO), shareParamTotalValueList.get(NumberConstant.ZERO), deptPriftAccountMap,NumberConstant.ONE );
             }
         }
         return  itemAllocationAmount;
@@ -1124,11 +1284,23 @@ public class ProjectCostServiceImpl implements ProjectCostService {
                 } else if (titleVo.getCode().equals(PATIENT_NAME.getCode())) {
                     dataList.add(getData(titleVo.getCode(), itemCode.getPatientName()));
                 } else if (titleVo.getCode().equals(ITEM_INCOME.getCode())) {
-                    dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(ITEM_INCOME.getCode())));
+                    if(computeResultDepartmentMap.isEmpty()){
+                        dataList.add(getData(titleVo.getCode(),BigDecimal.ZERO));
+                    }else{
+                        dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(ITEM_INCOME.getCode())));
+                    }
                 } else if (titleVo.getCode().equals(ITEM_COST.getCode())) {
-                    dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(ITEM_COST.getCode())));
+                    if(computeResultDepartmentMap.isEmpty()){
+                        dataList.add(getData(titleVo.getCode(),BigDecimal.ZERO));
+                    }else{
+                        dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(ITEM_COST.getCode())));
+                    }
                 } else {
-                    dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(titleVo.getCode())));
+                    if(computeResultDepartmentMap.isEmpty()){
+                        dataList.add(getData(titleVo.getCode(),BigDecimal.ZERO));
+                    }else{
+                        dataList.add(getData(titleVo.getCode(), computeResultDepartmentMap.get(itemCode.getDepartmentCode()).get(itemCode.getCode()).get(itemCode.getVisitNo()).get(titleVo.getCode())));
+                    }
                 }
             }
             returnList.add(dataList);

+ 3 - 0
src/main/java/com/kcim/service/impl/ReportServiceImpl.java

@@ -371,6 +371,9 @@ public class ReportServiceImpl implements ReportService {
             if (Objects.isNull(o)) {
                 continue;
             }
+            if (StringUtils.isEmpty(o)) {
+                o=BigDecimal.ZERO;
+            }
             BigDecimal amount = new BigDecimal(o.toString());
             String str = expressionMap.get(i);
             if (str.equals("+")) {

+ 2424 - 0
src/main/java/com/kcim/service/impl/StandardReportServiceImpl.java

@@ -0,0 +1,2424 @@
+package com.kcim.service.impl;
+
+import com.kcim.common.constants.Constant;
+import com.kcim.common.constants.NumberConstant;
+import com.kcim.common.constants.ParameterConstant;
+import com.kcim.common.constants.SplitConstant;
+import com.kcim.common.exception.CostException;
+import com.kcim.common.util.BeanUtil;
+import com.kcim.common.util.ComputeDateUtils;
+import com.kcim.common.util.PageUtils;
+import com.kcim.common.util.UserContext;
+import com.kcim.dao.model.*;
+import com.kcim.dao.repository.*;
+import com.kcim.service.AllocationQueryService;
+import com.kcim.service.CenterService;
+import com.kcim.service.IncomeCollectionService;
+import com.kcim.service.StandardReportService;
+import com.kcim.vo.*;
+import com.kcim.web.reponse.ComputeProfitCollectResponse;
+import com.kcim.web.reponse.StandardDeptCostCollectResponse;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2024-03-19 11:10
+ **/
+@Service("StandardReportService")
+@Slf4j
+@AllArgsConstructor
+public class StandardReportServiceImpl implements StandardReportService {
+    private static final String AMOUNT_FIELD = "amount";
+    private static final String PERCENT_FIELD = "percent" ;
+
+    ResponsibilityRepository responsibilityRepository;
+
+    AllocationQueryService allocationQueryService;
+
+    CenterService centerService;
+
+    AccountingRepository accountingRepository;
+
+    IncomeCollectionService incomeCollectionService;
+
+    ShareParamValueRepository shareParamValueRepository;
+
+    StandItemRepository standItemRepository;
+
+    ItemRepository itemRepository;
+
+    ComputeProjectCostAccountRepository computeProjectCostAccountRepository;
+
+    ComputePatientCostAccountRepository computePatientCostAccountRepository;
+
+    ResponsibilityDepartmentRepository responsibilityDepartmentRepository;
+    
+    /**
+     * 科室直接成本表(医疗成本)
+     * @param computeDate 核算年月
+     * @return
+     */
+    @Override
+    public List<DeptDirectMedicalCostVO> getDeptDirectMedicalCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+        //获取科室直接成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getCostByDate(UserContext.getCurrentLoginHospId(), year, month, NumberConstant.ONE);
+        if(CollectionUtils.isEmpty(allocationQueryList)){
+            return new ArrayList<>();
+        }
+        //获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        // 处理 allocationQueryList 数据
+        Map<String ,DeptDirectMedicalCostVO> deptDirectMedicalCostMap = new HashMap<>();
+        //转换为DeptDirectMedicalCostVO(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addDeptDirectMedicalCostVO(deptDirectMedicalCostMap,allocationQuery, standCostDictMaps);
+        }
+        // 转成List便于处理
+        List<DeptDirectMedicalCostVO> deptDirectMedicalCostList = deptDirectMedicalCostMap.values().stream().collect(Collectors.toList());
+        //创建医疗业务成本合计
+        DeptDirectMedicalCostVO medicalBusinessTotal = createSubtotalVo(deptDirectMedicalCostList.get(NumberConstant.ZERO), "医疗业务成本合计", DeptDirectMedicalCostVO.class);
+        //创建总计
+        DeptDirectMedicalCostVO grandTotal = createSubtotalVo(deptDirectMedicalCostList.get(NumberConstant.ZERO), "总计", DeptDirectMedicalCostVO.class);
+        //按responsibilitySort正序排序
+        deptDirectMedicalCostList.sort(Comparator.comparing(DeptDirectMedicalCostVO::getResponsibilitySort,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        // 按标准分级分组
+        Map<String, List<DeptDirectMedicalCostVO>> shareLevelGroup = deptDirectMedicalCostList.stream().collect(Collectors.groupingBy(DeptDirectMedicalCostVO::getStandardShareLevel));
+        // 科室标准分级按顺序号倒序排序
+        List<DictDataVo> standardShareLevelList = standCostDictMaps.getStandardShareLevelDict();
+        standardShareLevelList.sort(Comparator.comparing(DictDataVo::getSort,Comparator.nullsLast(Comparator.reverseOrder())));
+        // 创建各层级小计并按正确顺序插入
+        List<DeptDirectMedicalCostVO> result = new ArrayList<>();
+        for (DictDataVo shareLevel : standardShareLevelList) {
+            List<DeptDirectMedicalCostVO> deptDirectMedicalCostVOS = shareLevelGroup.get(shareLevel.getCode());
+            if(CollectionUtils.isEmpty(deptDirectMedicalCostVOS)){
+                continue;
+            }
+            // 添加该分类下的所有记录
+            result.addAll(deptDirectMedicalCostVOS);
+            // 创建小计对象
+            DeptDirectMedicalCostVO subtotalVo = createSubtotalVo(deptDirectMedicalCostVOS.get(NumberConstant.ZERO),String.format("%s小计", shareLevel.getName()), DeptDirectMedicalCostVO.class);
+            //将科室的金额加到小计对象中
+            deptDirectMedicalCostVOS.forEach(item -> addBigDecimalFields(item, subtotalVo));
+            // 如果属于医疗业务成本的科室,则小计的金额加到医疗业务成本
+            if(NumberConstant.ONE_S.equals(shareLevel.getValue())){
+                addBigDecimalFields(subtotalVo, medicalBusinessTotal);
+            }
+            // 小计的金额加到总计
+            addBigDecimalFields(subtotalVo, grandTotal);
+            // 添加小计行
+            result.add(subtotalVo);
+            // 医疗业务成本加入到医疗辅助类小计后面
+            if(NumberConstant.TWO_S.equals(shareLevel.getCode())){
+                result.add(medicalBusinessTotal);
+            }
+        }
+        // 总计加到列表最后面
+        result.add(grandTotal);
+        return result;
+    }
+
+    /**
+     * 科室直接成本表(全成本)
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<DeptFullDirectCostVO> getDeptFullDirectCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+        
+        // 获取科室直接成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getCostByDate(UserContext.getCurrentLoginHospId(), year, month, NumberConstant.ONE);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            return new ArrayList<>();
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        // 处理 allocationQueryList 数据
+        Map<String, DeptFullDirectCostVO> reportMap = new HashMap<>();
+        // 转换为DeptDirectAllCostVO(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addDeptDirectAllCostVO(reportMap, allocationQuery, standCostDictMaps);
+        }
+        // 转成List便于处理
+        List<DeptFullDirectCostVO> reportList = reportMap.values().stream().collect(Collectors.toList());
+        // 按responsibilitySort正序排序
+        reportList.sort(Comparator.comparing(DeptFullDirectCostVO::getResponsibilitySort, Comparator.nullsLast(Comparator.naturalOrder())));
+        // 按标准分级分组
+        Map<String, List<DeptFullDirectCostVO>> shareLevelGroup = reportList.stream().collect(Collectors.groupingBy(DeptFullDirectCostVO::getStandardShareLevel));
+        // 科室标准分级按顺序号倒序排序
+        List<DictDataVo> standardShareLevelList = standCostDictMaps.getStandardShareLevelDict();
+        standardShareLevelList.sort(Comparator.comparing(DictDataVo::getSort, Comparator.nullsLast(Comparator.reverseOrder())));
+        //创建医疗业务成本合计
+        DeptFullDirectCostVO medicalBusinessTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "医疗业务成本合计", DeptFullDirectCostVO.class);
+        //创建总计
+        DeptFullDirectCostVO grandTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "总计", DeptFullDirectCostVO.class);
+        // 创建各层级小计并按正确顺序插入
+        List<DeptFullDirectCostVO> result = new ArrayList<>();
+        for (DictDataVo shareLevel : standardShareLevelList) {
+            List<DeptFullDirectCostVO> reportVOS = shareLevelGroup.get(shareLevel.getCode());
+            if (CollectionUtils.isEmpty(reportVOS)) {
+                continue;
+            }
+            // 添加该分类下的所有记录
+            result.addAll(reportVOS);
+            // 创建小计对象
+            DeptFullDirectCostVO subtotalVo = createSubtotalVo(reportVOS.get(NumberConstant.ZERO),String.format("%s小计", shareLevel.getName()), DeptFullDirectCostVO.class);
+            //将科室的金额加到小计对象中
+            reportVOS.forEach(item -> addBigDecimalFields(item, subtotalVo));
+            // 如果属于医疗业务成本的科室,则小计的金额加到医疗业务成本
+            if(NumberConstant.ONE_S.equals(shareLevel.getValue())){
+                addBigDecimalFields(subtotalVo, medicalBusinessTotal);
+            }
+            // 小计的金额加到总计
+            addBigDecimalFields(subtotalVo, grandTotal);
+            // 添加小计行
+            result.add(subtotalVo);
+            // 医疗业务成本加入到医疗辅助类小计后面
+            if(NumberConstant.TWO_S.equals(shareLevel.getCode())){
+                result.add(medicalBusinessTotal);
+            }
+        }
+        // 总计加到列表最后面
+        result.add(grandTotal);
+        return result;
+    }
+
+    /**
+     * 获取科室成本明细数据
+     * @param computeDate 核算年月
+     * @return
+     */
+    @Override
+    public List<ClinicalDeptMedicalCostVO> getClinicalDeptMedicalCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+        // 获取科室直接成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            return new ArrayList<>();
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        // 处理 allocationQueryList 数据
+        Map<String, ClinicalDeptMedicalCostVO> reportMap = new HashMap<>();
+        // 添加科室成本明细(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addDeptCostDetailVO(reportMap, allocationQuery, standCostDictMaps);
+        }
+        // 转成List便于处理
+        List<ClinicalDeptMedicalCostVO> reportList = reportMap.values().stream().collect(Collectors.toList());
+        // 创建合计对象
+        ClinicalDeptMedicalCostVO subtotalVo = createSubtotalVo(reportList.get(NumberConstant.ZERO),"科室全成本合计",ClinicalDeptMedicalCostVO.class);
+        //将科室的金额加到合计对象中
+        reportList.forEach(item -> addBigDecimalFields(item, subtotalVo));
+        // 合计加到列表最后面
+        reportList.add(subtotalVo);
+        return reportList;
+    }
+
+    /**
+     * 获取临床服务类科室全成本报表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<ClinicalDeptFullCostVO> getClinicalDeptFullCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室直接成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            return new ArrayList<>();
+        }
+
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+
+        // 处理 allocationQueryList 数据
+        Map<String, ClinicalDeptFullCostVO> reportMap = new HashMap<>();
+
+        // 转换为ClinicalDeptFullCostVO(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addClinicalDeptFullCostVO(reportMap, allocationQuery, standCostDictMaps);
+        }
+
+        // 转成List便于处理
+        List<ClinicalDeptFullCostVO> reportList = reportMap.values().stream().collect(Collectors.toList());
+
+        // 创建合计对象
+        ClinicalDeptFullCostVO subtotalVo = createSubtotalVo(reportList.get(NumberConstant.ZERO), "科室全成本合计", ClinicalDeptFullCostVO.class);
+
+        // 将科室的金额加到合计对象中
+        reportList.forEach(item -> addBigDecimalFields(item, subtotalVo));
+
+        // 合计加到列表最后面
+        reportList.add(subtotalVo);
+
+        return reportList;
+    }
+
+    /**
+     * 获取医院临床服务类科室全成本构成分析表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public ComputeProfitCollectResponse getClinicalDeptFullCostAnalysis(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+        //获取科室收入
+        List<IncomeCollection> responsibilityIncomeList = incomeCollectionService.getResponsibilitiesAccounts(year, month, UserContext.getCurrentLoginHospId());
+        if (CollectionUtils.isEmpty(responsibilityIncomeList)) {
+            throw new CostException("医院未归集本月收入数据");
+        }
+        Map<String, BigDecimal> responsibilityIncomeMap = responsibilityIncomeList.stream().collect(Collectors.toMap(IncomeCollection::getResponsibilityCode, IncomeCollection::getAmount));
+        //获取分摊参数
+        List<ShareParamValue> shareParamValueList = shareParamValueRepository.getList(computeDate);
+        if (CollectionUtils.isEmpty(shareParamValueList)) {
+            throw new CostException("未获取医院本月分摊参数数据");
+        }
+        Map<String, List<ShareParamValue>> responsibilityParamValueMap = shareParamValueList.stream().collect(Collectors.groupingBy(ShareParamValue::getResponsibilityCode));
+        //获取诊次床日分摊参数代码
+        String[] visitsBedDaysParamCode = getVisitsBedDaysParamCode();
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+
+        // 处理 allocationQueryList 数据
+        Map<String ,DeptDirectMedicalCostVO> deptDirectMedicalCostMap = new HashMap<>();
+        //转换为DeptDirectMedicalCostVO(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addDeptDirectMedicalCostVO(deptDirectMedicalCostMap,allocationQuery, standCostDictMaps);
+        }
+
+        // 转成List便于处理
+        List<DeptDirectMedicalCostVO> reportList = deptDirectMedicalCostMap.values().stream().collect(Collectors.toList());
+        // 创建合计对象
+        DeptDirectMedicalCostVO subtotalVo = createSubtotalVo(reportList.get(NumberConstant.ZERO), "科室合计", DeptDirectMedicalCostVO.class);
+        subtotalVo.setResponsibilityCode("deptSubtotal");
+        for (DeptDirectMedicalCostVO item : reportList) {
+            //计算科室的收入及损益+床日成本及诊次成本
+            calcDeptExpandCost(item, responsibilityIncomeMap, responsibilityParamValueMap, visitsBedDaysParamCode);
+            // 将科室的金额加到合计对象中
+            addBigDecimalFields(item, subtotalVo);
+        }
+        // 合计加到列表最后面
+        reportList.add(subtotalVo);
+
+        // 创建成本项目列表
+        List<String> costItems = Arrays.asList(
+                "人员经费", "卫生材料费", "药品费", "固定资产折旧费", "无形资产摊销费",
+                "提取医疗风险基金", "其他医疗费用", "科室全成本合计","科室收入","收入-成本","床日成本","诊次成本"
+        );
+        //不要计算占比的项目列表
+        List<String> noPercentCostItems = Arrays.asList(
+                "科室收入","收入-成本","床日成本","诊次成本"
+        );
+
+        // 创建结果列表
+        List<ReportFormCustomVo> resultData = new ArrayList<>();
+        List<CommonResponsibilityReportVo> titleList = new ArrayList<>();
+
+        // 提取科室名称作为列标题
+        for (DeptDirectMedicalCostVO dept : reportList) {
+            CommonResponsibilityReportVo title = new CommonResponsibilityReportVo();
+            title.setResponsibilityName(dept.getResponsibilityName());
+            title.setResponsibilityCode(dept.getResponsibilityCode());
+            title.setSort(dept.getResponsibilitySort());
+            //添加子级标题
+            addCommonResponsibilityChild(title);
+            //科室合计列需固定
+            if(dept.getResponsibilityCode().equals(subtotalVo.getResponsibilityCode())){
+                title.getChild().forEach(item -> item.setIsFixed(NumberConstant.ONE));
+            }
+            titleList.add(title);
+        }
+
+        // 遍历每个成本项目(列转行)
+        for (String costItem : costItems) {
+            ReportFormCustomVo itemVo = new ReportFormCustomVo();
+            itemVo.setReportName(costItem);
+            itemVo.setData(new ArrayList<>());
+            // 遍历每个科室
+            for (DeptDirectMedicalCostVO dept : reportList)  {
+                //金额对象
+                ReportVo amountReportVo = new ReportVo();
+                amountReportVo.setCode(getResponsibilityAmountCode(dept.getResponsibilityCode()));
+                //占比对象
+                ReportVo percentReportVo = new ReportVo();
+                percentReportVo.setCode(getResponsibilityPercentCode(dept.getResponsibilityCode()));
+                //获取金额
+                BigDecimal deptAmount = getDeptAmount(dept, costItem);
+                // 设置金额和百分比
+                amountReportVo.setValue(deptAmount);
+                //要显示占比的字段才计算占比
+                if(!noPercentCostItems.contains(costItem)){
+                    //计算百分比
+                    BigDecimal percent = getPercent(deptAmount, dept.getTotal());
+                    percentReportVo.setValue(percent);
+                }
+                // 添加金额和百分比
+                itemVo.getData().add(amountReportVo);
+                itemVo.getData().add(percentReportVo);
+            }
+            resultData.add(itemVo);
+        }
+
+        ComputeProfitCollectResponse response = new ComputeProfitCollectResponse();
+        response.setTitle(titleList);
+        response.setData(resultData);
+
+        return response;
+    }
+
+    /**
+     * 获取医院科室成本分摊汇总表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalDeptCostAllocationVO> getHospitalDeptCostAllocation(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+
+        // 处理 allocationQueryList 数据
+        Map<String, HospitalDeptCostAllocationVO> deptCostAllocationMap = new HashMap<>();
+
+        // 转换为HospitalDeptCostAllocationVO(一个责任中心只一条记录)
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            addHospitalDeptCostAllocationVO(deptCostAllocationMap, allocationQuery, standCostDictMaps);
+        }
+
+        // 转成List便于处理
+        List<HospitalDeptCostAllocationVO> reportList = new ArrayList<>(deptCostAllocationMap.values());
+        //创建总计
+        HospitalDeptCostAllocationVO grandTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "总计", HospitalDeptCostAllocationVO.class);
+        // 按responsibilitySort正序排序
+        reportList.sort(Comparator.comparing(HospitalDeptCostAllocationVO::getResponsibilitySort,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+
+        // 按标准分级分组
+        Map<String, List<HospitalDeptCostAllocationVO>> shareLevelGroup = reportList.stream()
+                .collect(Collectors.groupingBy(HospitalDeptCostAllocationVO::getStandardShareLevel));
+
+        // 科室标准分级按顺序号倒序排序
+        List<DictDataVo> standardShareLevelList = standCostDictMaps.getStandardShareLevelDict();
+        standardShareLevelList.sort(Comparator.comparing(DictDataVo::getSort, Comparator.nullsLast(Comparator.reverseOrder())));
+
+        // 创建各层级小计并按正确顺序插入
+        List<HospitalDeptCostAllocationVO> result = new ArrayList<>();
+        for (DictDataVo shareLevel : standardShareLevelList) {
+            List<HospitalDeptCostAllocationVO> deptCostAllocationVOS = shareLevelGroup.get(shareLevel.getCode());
+            if (CollectionUtils.isEmpty(deptCostAllocationVOS)) {
+                continue;
+            }
+            // 添加该分类下的所有记录
+            result.addAll(deptCostAllocationVOS);
+            // 创建小计对象
+            HospitalDeptCostAllocationVO subtotalVo = createSubtotalVo(deptCostAllocationVOS.get(NumberConstant.ZERO), String.format("%s小计", shareLevel.getName()), HospitalDeptCostAllocationVO.class);
+            //将科室的金额加到小计对象中
+            deptCostAllocationVOS.forEach(item -> addBigDecimalFields(item, subtotalVo));
+            // 小计的金额加到总计
+            addBigDecimalFields(subtotalVo, grandTotal);
+            // 添加小计行
+            result.add(subtotalVo);
+        }
+        // 总计加到列表最后面
+        result.add(grandTotal);
+        return result;
+    }
+
+    /**
+     * 获取医院诊次成本构成表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalVisitCostCompositionVO> getHospitalVisitCostComposition(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAcountAccounts(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+        //获取分摊参数
+        List<ShareParamValue> shareParamValueList = shareParamValueRepository.getList(computeDate);
+        if (CollectionUtils.isEmpty(shareParamValueList)) {
+            throw new CostException("未获取医院本月分摊参数数据");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        //获取成本会计科目字典
+        List<DictDataVo> accountingTypeDict = standCostDictMaps.getAccountingTypeDict();
+        List<DictDataVo> costAccountingTypeDict = accountingTypeDict.stream().filter(dictDataVo -> NumberConstant.TWO_S.equals(dictDataVo.getValue())).collect(Collectors.toList());
+        // 初始化成本项目映射
+        Map<String, HospitalVisitCostCompositionVO> costItemMap =createHospitalVisitCostCompositionVO(costAccountingTypeDict);
+        // 处理分配查询数据
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            String accountingCode = allocationQuery.getAccountingCode();
+            Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+            if (account == null) {
+                continue;
+            }
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+            HospitalVisitCostCompositionVO vo = costItemMap.get(account.getType());
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(allocationQuery.getAmount()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(allocationQuery.getAmount()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(allocationQuery.getAmount()));
+        }
+        //获取诊次床日分摊参数代码
+        String[] visitsBedDaysParamCode = getVisitsBedDaysParamCode();
+
+        // 诊次分摊参数值
+        BigDecimal visitParamValue = getParamValue(shareParamValueList, visitsBedDaysParamCode[NumberConstant.ZERO]);
+//        // 床日分摊参数值
+//        BigDecimal bedDaysParamValue = getParamValue(shareParamValueList, visitsBedDaysParamCode[NumberConstant.ONE]);
+
+        //处理总计和药品小计
+        HospitalVisitCostCompositionVO totalVo = new HospitalVisitCostCompositionVO();
+        totalVo.setCostItem("总计");
+        HospitalVisitCostCompositionVO drugTotalVo = new HospitalVisitCostCompositionVO();
+        drugTotalVo.setCostItem("药品费");
+        drugTotalVo.setChildren(new ArrayList<>());
+        // 转成List便于处理
+        List<HospitalVisitCostCompositionVO> reportList = costItemMap.values().stream().collect(Collectors.toList());
+        for (HospitalVisitCostCompositionVO item : reportList) {
+            //计算每诊次的医疗成本
+            item.setMedicalCost(getPercent(item.getMedicalCost(),visitParamValue));
+            //计算每诊次的医疗全成本
+            item.setMedicalFullCost(getPercent(item.getMedicalFullCost(),visitParamValue));
+            //计算每诊次的医院全成本
+            item.setHospitalFullCost(getPercent(item.getHospitalFullCost(),visitParamValue));
+            // 将金额加到总计对象中
+            addBigDecimalFields(item, totalVo);
+            /// 将金额加到药品对象中
+            if(NumberConstant.THREE_S.equals(item.getCostType())){
+                addBigDecimalFields(item, drugTotalVo);
+                drugTotalVo.getChildren().add(item);
+            }
+        }
+        drugTotalVo.getChildren().forEach(item -> reportList.remove(item));
+        //添加到列表的指定位置
+        reportList.add(NumberConstant.TWO,drugTotalVo);
+        reportList.add(NumberConstant.ZERO,totalVo);
+        return reportList;
+    }
+    /**
+     * 获取医院科室诊次成本表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalVisitCostCompositionVO> getHospitalDeptVisitCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getRespAcountAccounts(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+
+        // 获取分摊参数
+        List<ShareParamValue> shareParamValueList = shareParamValueRepository.getList(computeDate);
+        if (CollectionUtils.isEmpty(shareParamValueList)) {
+            throw new CostException("未获取医院本月分摊参数数据");
+        }
+        // 获取诊次床日分摊参数代码
+        String[] visitsBedDaysParamCode = getVisitsBedDaysParamCode();
+        BigDecimal visitParamValue = getParamValue(shareParamValueList, visitsBedDaysParamCode[NumberConstant.ZERO]);
+        Map<String, List<ShareParamValue>> respParamValueList = shareParamValueList.stream()
+                .collect(Collectors.groupingBy(item -> item.getResponsibilityCode()));
+        // 处理 allocationQueryList 数据
+        Map<String, HospitalVisitCostCompositionVO> deptVisitCostMap = new HashMap<>();
+
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            String responsibilityCode = allocationQuery.getResponsibilityCode();
+            Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+            if (responsibility == null) {
+                continue;
+            }
+            String accountingCode = allocationQuery.getAccountingCode();
+            Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+            if (account == null) {
+                continue;
+            }
+            //只处理临床科室
+            if(NumberConstant.FOUR.equals(responsibility.getStandardShareLevel())){
+                continue;
+            }
+
+            HospitalVisitCostCompositionVO vo = new HospitalVisitCostCompositionVO();
+            if (deptVisitCostMap.containsKey(responsibilityCode)) {
+                vo = deptVisitCostMap.get(responsibilityCode);
+            } else {
+                // 初始化科室信息
+                vo.setResponsibilityCode(responsibility.getResponsibilityCode());
+                vo.setResponsibilityName(responsibility.getResponsibilityName());
+                vo.setResponsibilitySort(responsibility.getSort());
+                // 初始化所有费用字段为0
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                deptVisitCostMap.put(responsibilityCode, vo);
+            }
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(allocationQuery.getAmount()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(allocationQuery.getAmount()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(allocationQuery.getAmount()));
+        }
+
+        // 转成List便于处理
+        List<HospitalVisitCostCompositionVO> reportList = new ArrayList<>(deptVisitCostMap.values());
+        // 创建总计对象
+        HospitalVisitCostCompositionVO grandTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "总计", HospitalVisitCostCompositionVO.class);
+        // 计算每诊次成本
+        for (HospitalVisitCostCompositionVO item : reportList) {
+            List<ShareParamValue> respShareParamValues = respParamValueList.get(item.getResponsibilityCode());
+            if(CollectionUtils.isEmpty(respShareParamValues)){
+                item.setServiceCount(BigDecimal.ZERO);
+                item.setMedicalCost(BigDecimal.ZERO);
+                item.setMedicalFullCost(BigDecimal.ZERO);
+                item.setHospitalFullCost(BigDecimal.ZERO);
+                continue;
+            }
+            BigDecimal respParamValue = getParamValue(respShareParamValues, visitsBedDaysParamCode[NumberConstant.ZERO]);
+            item.setServiceCount(respParamValue);
+            //计算每诊次的医疗成本
+            item.setMedicalCost(getPercent(item.getMedicalCost(),respParamValue));
+            //计算每诊次的医疗全成本
+            item.setMedicalFullCost(getPercent(item.getMedicalFullCost(),respParamValue));
+            //计算每诊次的医院全成本
+            item.setHospitalFullCost(getPercent(item.getHospitalFullCost(),respParamValue));
+            // 将各科室金额累加到总计对象
+            addBigDecimalFields(item, grandTotal);
+        }
+        // 按responsibilitySort正序排序
+        reportList.sort(Comparator.comparing(HospitalVisitCostCompositionVO::getResponsibilitySort,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        // 添加总计行
+        reportList.add(NumberConstant.ZERO,grandTotal);
+        return reportList;
+    }
+
+    /**
+     * 获取医院床日成本构成表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalVisitCostCompositionVO> getHospitalBedDayCostComposition(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getAcountAccounts(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+        //获取分摊参数
+        List<ShareParamValue> shareParamValueList = shareParamValueRepository.getList(computeDate);
+        if (CollectionUtils.isEmpty(shareParamValueList)) {
+            throw new CostException("未获取医院本月分摊参数数据");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        //获取成本会计科目字典
+        List<DictDataVo> accountingTypeDict = standCostDictMaps.getAccountingTypeDict();
+        List<DictDataVo> costAccountingTypeDict = accountingTypeDict.stream().filter(dictDataVo -> NumberConstant.TWO_S.equals(dictDataVo.getValue())).collect(Collectors.toList());
+        // 初始化成本项目映射
+        Map<String, HospitalVisitCostCompositionVO> costItemMap =createHospitalVisitCostCompositionVO(costAccountingTypeDict);
+        // 处理分配查询数据
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            String accountingCode = allocationQuery.getAccountingCode();
+            Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+            if (account == null) {
+                continue;
+            }
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+            HospitalVisitCostCompositionVO vo = costItemMap.get(account.getType());
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(allocationQuery.getAmount()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(allocationQuery.getAmount()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(allocationQuery.getAmount()));
+        }
+        //获取诊次床日分摊参数代码
+        String[] visitsBedDaysParamCode = getVisitsBedDaysParamCode();
+
+        // 床日分摊参数值
+        BigDecimal bedDaysParamValue = getParamValue(shareParamValueList, visitsBedDaysParamCode[NumberConstant.ONE]);
+
+        //处理总计和药品小计
+        HospitalVisitCostCompositionVO totalVo = new HospitalVisitCostCompositionVO();
+        totalVo.setCostItem("总计");
+        HospitalVisitCostCompositionVO drugTotalVo = new HospitalVisitCostCompositionVO();
+        drugTotalVo.setCostItem("药品费");
+        drugTotalVo.setChildren(new ArrayList<>());
+        // 转成List便于处理
+        List<HospitalVisitCostCompositionVO> reportList = costItemMap.values().stream().collect(Collectors.toList());
+        for (HospitalVisitCostCompositionVO item : reportList) {
+            //计算每诊次的医疗成本
+            item.setMedicalCost(getPercent(item.getMedicalCost(),bedDaysParamValue));
+            //计算每诊次的医疗全成本
+            item.setMedicalFullCost(getPercent(item.getMedicalFullCost(),bedDaysParamValue));
+            //计算每诊次的医院全成本
+            item.setHospitalFullCost(getPercent(item.getHospitalFullCost(),bedDaysParamValue));
+            // 将金额加到总计对象中
+            addBigDecimalFields(item, totalVo);
+            /// 将金额加到药品对象中
+            if(NumberConstant.THREE_S.equals(item.getCostType())){
+                addBigDecimalFields(item, drugTotalVo);
+                drugTotalVo.getChildren().add(item);
+            }
+        }
+        //移除掉药品费(避免重复)
+        drugTotalVo.getChildren().forEach(item -> reportList.remove(item));
+        //添加到列表的指定位置
+        reportList.add(NumberConstant.TWO,drugTotalVo);
+        reportList.add(NumberConstant.ZERO,totalVo);
+        return reportList;
+    }
+
+    /**
+     * 获取医院科室床日成本表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalVisitCostCompositionVO> getHospitalDeptBedDayCost(String computeDate) {
+        Integer year = ComputeDateUtils.getComputeYear(computeDate);
+        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
+
+        // 获取科室成本
+        List<AllocationQuery> allocationQueryList = allocationQueryService.getRespAcountAccounts(UserContext.getCurrentLoginHospId(), year, month);
+        if (CollectionUtils.isEmpty(allocationQueryList)) {
+            throw new CostException("医院未分摊本月数据");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+
+        // 获取分摊参数
+        List<ShareParamValue> shareParamValueList = shareParamValueRepository.getList(computeDate);
+        if (CollectionUtils.isEmpty(shareParamValueList)) {
+            throw new CostException("未获取医院本月分摊参数数据");
+        }
+
+        // 处理 allocationQueryList 数据
+        Map<String, HospitalVisitCostCompositionVO> deptVisitCostMap = new HashMap<>();
+
+        for (AllocationQuery allocationQuery : allocationQueryList) {
+            String responsibilityCode = allocationQuery.getResponsibilityCode();
+            Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+            if (responsibility == null) {
+                continue;
+            }
+            String accountingCode = allocationQuery.getAccountingCode();
+            Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+            if (account == null) {
+                continue;
+            }
+            //只处理临床科室
+            if(NumberConstant.FOUR.equals(responsibility.getStandardShareLevel())){
+                continue;
+            }
+
+            HospitalVisitCostCompositionVO vo = new HospitalVisitCostCompositionVO();
+            if (deptVisitCostMap.containsKey(responsibilityCode)) {
+                vo = deptVisitCostMap.get(responsibilityCode);
+            } else {
+                // 初始化科室信息
+                vo.setResponsibilityCode(responsibility.getResponsibilityCode());
+                vo.setResponsibilityName(responsibility.getResponsibilityName());
+                vo.setResponsibilitySort(responsibility.getSort());
+                // 初始化所有费用字段为0
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                deptVisitCostMap.put(responsibilityCode, vo);
+            }
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(allocationQuery.getAmount()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(allocationQuery.getAmount()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(allocationQuery.getAmount()));
+        }
+
+        // 转成List便于处理
+        List<HospitalVisitCostCompositionVO> reportList = new ArrayList<>(deptVisitCostMap.values());
+        // 获取诊次床日分摊参数代码
+        String[] visitsBedDaysParamCode = getVisitsBedDaysParamCode();
+        BigDecimal bedDaysParamValue = getParamValue(shareParamValueList, visitsBedDaysParamCode[NumberConstant.ONE]);
+        Map<String, List<ShareParamValue>> respParamValueList = shareParamValueList.stream()
+                .collect(Collectors.groupingBy(item -> item.getResponsibilityCode()));
+        // 创建总计对象
+        HospitalVisitCostCompositionVO grandTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "总计", HospitalVisitCostCompositionVO.class);
+        // 计算每诊次成本
+        for (HospitalVisitCostCompositionVO item : reportList) {
+            List<ShareParamValue> respShareParamValues = respParamValueList.get(item.getResponsibilityCode());
+            if(CollectionUtils.isEmpty(respShareParamValues)){
+                item.setServiceCount(BigDecimal.ZERO);
+                item.setMedicalCost(BigDecimal.ZERO);
+                item.setMedicalFullCost(BigDecimal.ZERO);
+                item.setHospitalFullCost(BigDecimal.ZERO);
+                continue;
+            }
+            BigDecimal respParamValue = getParamValue(respShareParamValues, visitsBedDaysParamCode[NumberConstant.ZERO]);
+            item.setServiceCount(respParamValue);
+            //计算每诊次的医疗成本
+            item.setMedicalCost(getPercent(item.getMedicalCost(),respParamValue));
+            //计算每诊次的医疗全成本
+            item.setMedicalFullCost(getPercent(item.getMedicalFullCost(),respParamValue));
+            //计算每诊次的医院全成本
+            item.setHospitalFullCost(getPercent(item.getHospitalFullCost(),respParamValue));
+            // 将各科室金额累加到总计对象
+            addBigDecimalFields(item, grandTotal);
+        }
+        // 按responsibilitySort正序排序
+        reportList.sort(Comparator.comparing(HospitalVisitCostCompositionVO::getResponsibilitySort,
+                Comparator.nullsLast(Comparator.naturalOrder())));
+        // 添加总计行
+        reportList.add(NumberConstant.ZERO,grandTotal);
+        return reportList;
+    }
+
+
+    /**
+     * 获取医院医疗服务项目成本汇总表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public List<HospitalServiceProjectCostVO> getHospitalServiceProjectCost(String computeDate) {
+        List<StandItem> standItemList = standItemRepository.getList();
+        if(CollectionUtils.isEmpty(standItemList)){
+            throw new CostException("标准医疗服务项目未维护,请先添加标准医疗服务项目");
+        }
+        List<Item> itemList = itemRepository.getList();
+        if(CollectionUtils.isEmpty(itemList)){
+            throw new CostException("医疗服务项目未维护,请先添加医疗服务项目");
+        }
+        //获取项目成本数据
+        List<ComputeProjectCostAccount> projectCostAccountList = computeProjectCostAccountRepository.getList(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算项目成本");
+        }
+        //把标准服务项目字典转成Map(第一层+第二层)
+        List<Map<String, StandItem>> standItemMapDict = getStandItemMapDict(standItemList);
+        // 记录项目类别对象
+        Map<String, HospitalServiceProjectCostVO> projectCostMap = new HashMap<>();
+        for (ComputeProjectCostAccount projectCostAccount : projectCostAccountList) {
+            // 获取项目归属的项目类型
+            StandItem projectItemType = getProjectItemType(projectCostAccount.getStandItemCode(),standItemMapDict);
+            if(ObjectUtils.isEmpty(projectItemType)){
+                continue;
+            }
+            //按项目类型累加数据
+            String costType = projectCostAccount.getCostType();
+            HospitalServiceProjectCostVO vo ;
+            //已有的项目类别
+            if (projectCostMap.containsKey(projectItemType.getCode())) {
+                vo = projectCostMap.get(projectItemType.getCode());
+            } else {
+                //新建一个项目类别对象
+                vo = convertToHospitalServiceProjectCostVO(projectItemType);
+                projectCostMap.put(projectItemType.getCode(), vo);
+            }
+            //没有数据时跳过
+            if(ObjectUtils.isEmpty(projectCostAccount.getComputeResult())){
+                continue;
+            }
+            // 医疗成本
+            if ("1".equals(costType)) {
+                vo.setMedicalCost(vo.getMedicalCost().add(projectCostAccount.getComputeResult()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType)) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(projectCostAccount.getComputeResult()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(projectCostAccount.getComputeResult()));
+        }
+        // 创建项目类别对象并组装层级
+        List<HospitalServiceProjectCostVO> reportList = createProjectCategory(standItemMapDict,projectCostMap);
+        return reportList;
+    }
+
+    /**
+     * 获取医院医疗服务项目成本明细表数据
+     *
+     * @return 医疗服务项目成本明细列表
+     */
+    @Override
+    public List<HospitalServiceProjectCostVO> getMedicalServiceCostDetail(String computeDate) {
+
+        List<HospitalServiceProjectCostVO> projectCostAccountList = computeProjectCostAccountRepository.getMedicalServiceCostDetailList(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算项目成本");
+        }
+        // 记录项目类别对象
+        Map<String, HospitalServiceProjectCostVO> projectCostMap = new HashMap<>();
+        for (HospitalServiceProjectCostVO projectCostAccount : projectCostAccountList) {
+            //按项目类型累加数据
+            String costType = projectCostAccount.getCostTypeCode();
+            HospitalServiceProjectCostVO vo = new HospitalServiceProjectCostVO();
+            //已有的项目类别
+            if (projectCostMap.containsKey(projectCostAccount.getItemCode())) {
+                vo = projectCostMap.get(projectCostAccount.getItemCode());
+            } else {
+                //新建一个项目类别对象
+                vo = BeanUtil.convertObj(projectCostAccount, HospitalServiceProjectCostVO.class) ;
+                // 初始化所有费用字段为0
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                projectCostMap.put(projectCostAccount.getItemCode(), vo);
+            }
+            //没有数据时跳过
+            if(ObjectUtils.isEmpty(projectCostAccount.getHospitalFullCost())){
+                continue;
+            }
+            // 医疗成本
+            if ("1".equals(costType)) {
+                vo.setMedicalCost(vo.getMedicalCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType)) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            //服务量
+            if(!ObjectUtils.isEmpty(projectCostAccount.getServiceVolume())){
+                vo.setServiceVolume(projectCostAccount.getServiceVolume());
+            }
+
+        }
+        List<HospitalServiceProjectCostVO> medServiceCostDetailList =new ArrayList<>(projectCostMap.values());
+        // 计算每项目成本
+        for (HospitalServiceProjectCostVO item : medServiceCostDetailList) {
+            BigDecimal serviceVolume = item.getServiceVolume();
+            if(ObjectUtils.isEmpty(serviceVolume)){
+                item.setMedicalCost(BigDecimal.ZERO);
+                item.setMedicalFullCost(BigDecimal.ZERO);
+                item.setHospitalFullCost(BigDecimal.ZERO);
+                continue;
+            }
+            //计算每项目的医疗成本
+            item.setMedicalCost(getPercent(item.getMedicalCost(),serviceVolume));
+            //计算每项目的医疗全成本
+            item.setMedicalFullCost(getPercent(item.getMedicalFullCost(),serviceVolume));
+            //计算每项目的医院全成本
+            item.setHospitalFullCost(getPercent(item.getHospitalFullCost(),serviceVolume));
+        }
+        return medServiceCostDetailList;
+    }
+
+
+    /**
+     * 获取医院病种成本明细表数据
+     *
+     * @return 病种成本明细列表
+     */
+    @Override
+    public List<DiseaseCostDetailVO> getDiseaseCostDetail(String computeDate) {
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDiseaseCostDetailList(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        // 记录项目类别对象
+        Map<String, DiseaseCostDetailVO> diseaseCostMap = new HashMap<>();
+        for (DiseaseCostDetailVO projectCostAccount : projectCostAccountList) {
+            //按项目类型累加数据
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(projectCostAccount.getCostTypeCode());
+            DiseaseCostDetailVO vo = new DiseaseCostDetailVO();
+            //已有的项目类别
+            if (diseaseCostMap.containsKey(projectCostAccount.getItemCode())) {
+                vo = diseaseCostMap.get(projectCostAccount.getItemCode());
+            } else {
+                vo= BeanUtil.convertObj(projectCostAccount, DiseaseCostDetailVO.class) ;
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                //新建一个项目类别对象
+                diseaseCostMap.put(projectCostAccount.getItemCode(), vo);
+            }
+            //没有数据时跳过
+            if(ObjectUtils.isEmpty(projectCostAccount.getHospitalFullCost())){
+                continue;
+            }
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            if(!ObjectUtils.isEmpty(projectCostAccount.getServiceVolume())){
+                // 服务量
+                vo.setServiceVolume(projectCostAccount.getServiceVolume());
+            }
+        }
+        List<DiseaseCostDetailVO> medServiceCostDetailList =new ArrayList<>(diseaseCostMap.values());
+        try {
+            //计算单个病种的成本
+            medServiceCostDetailList.forEach(vo -> {
+                vo.setMedicalCost(getPercent(vo.getMedicalCost(),vo.getServiceVolume()));
+                vo.setMedicalFullCost(getPercent(vo.getMedicalFullCost(),vo.getServiceVolume()));
+                vo.setHospitalFullCost(getPercent(vo.getHospitalFullCost(),vo.getServiceVolume()));
+            });
+        }catch (Exception e){
+            log.error("计算病种成本时发生异常",e);
+        }
+        medServiceCostDetailList.sort(Comparator.comparing(DiseaseCostDetailVO::getItemCode));
+        return medServiceCostDetailList;
+    }
+
+
+    /**
+     * 获取病种成本构成明细表数据
+     *
+     * @return 病种成本明细列表,包含各病种的成本明细及总计行
+     */
+    @Override
+    public List<DiseaseCostDetailVO> getDiseaseCostCompositionDetail(String computeDate) {
+
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDiseaseCostCompositionDetail(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+        // 记录项目类别对象
+        Map<String, DiseaseCostDetailVO> diseaseCostMap = new HashMap<>();
+        for (DiseaseCostDetailVO projectCostAccount : projectCostAccountList) {
+            //按项目类型累加数据
+            String accountType = projectCostAccount.getCostTypeCode();
+            DiseaseCostDetailVO vo ;
+            //已有的项目类别
+            if (diseaseCostMap.containsKey(projectCostAccount.getItemCode())) {
+                vo = diseaseCostMap.get(projectCostAccount.getItemCode());
+            } else {
+                vo = new DiseaseCostDetailVO();
+                vo.setItemCode(projectCostAccount.getItemCode());
+                vo.setItemName(projectCostAccount.getItemName());
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                //新建一个项目类别对象
+                diseaseCostMap.put(projectCostAccount.getItemCode(), vo);
+            }
+            //按会计科目类型累加费用
+            addAccountTypeExpense(accountType, projectCostAccount.getHospitalFullCost(), vo);
+            //累加数量
+            vo.setServiceVolume(vo.getServiceVolume().add(projectCostAccount.getServiceVolume()));
+        }
+        List<DiseaseCostDetailVO> diseaseCostDetailList =new ArrayList<>(diseaseCostMap.values());
+        //按会计科目类型计算占比
+        diseaseCostDetailList.forEach(vo -> setAccountTypeExpenseRatio(vo));
+        return diseaseCostDetailList;
+    }
+
+    /**
+     * 获取服务单元病种成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    @Override
+    public StandardDeptCostCollectResponse getDeptDiseaseCostCompositionDetail(String computeDate) {
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDeptDiseaseCostCompositionDetail(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+        //科室责任中心对照数据
+        List<ResponsibilityDepartIdVO> responsibilityDepartment = responsibilityDepartmentRepository.getResponsibility(UserContext.getHospId());
+        Map<String, List<ResponsibilityDepartIdVO>> deptRespMap = responsibilityDepartment.stream()
+                .filter(r -> r.getDepartmentCode() != null) // 过滤掉departmentCode为null的记录
+                .collect(Collectors.groupingBy(ResponsibilityDepartIdVO::getDepartmentCode));
+        //设置科室对应的责任中心
+        for (DiseaseCostDetailVO diseaseCostDetailVO : projectCostAccountList) {
+            List<ResponsibilityDepartIdVO> responsibilityDepartIdVOList = deptRespMap.get(diseaseCostDetailVO.getDepartmentCode());
+            if(CollectionUtils.isEmpty(responsibilityDepartIdVOList)){
+                continue;
+            }
+            ResponsibilityDepartIdVO responsibilityDepartVO = responsibilityDepartIdVOList.get(NumberConstant.ZERO);
+            diseaseCostDetailVO.setResponsibilityCode(responsibilityDepartVO.getResponsibilityCode());
+            diseaseCostDetailVO.setResponsibilityName(responsibilityDepartVO.getResponsibilityName());
+        }
+        //按责任中心分组
+        Map<String, List<DiseaseCostDetailVO>> deptPtAccountGroup = projectCostAccountList.stream()
+                .filter(d -> d.getResponsibilityCode() != null) // 过滤掉responsibilityCode为null的记录
+                .collect(Collectors.groupingBy(DiseaseCostDetailVO::getResponsibilityCode));
+
+        List<CommonResponsibilityReportVo> titleList = new ArrayList<>();
+        // 提取科室名称作为列标题
+        deptPtAccountGroup.forEach((deptCode, deptPtAccountList) -> {
+            if(!CollectionUtils.isEmpty(deptPtAccountList)){
+                CommonResponsibilityReportVo title = new CommonResponsibilityReportVo();
+                DiseaseCostDetailVO vo = deptPtAccountList.get(NumberConstant.ZERO);
+                title.setResponsibilityName(vo.getResponsibilityName());
+                title.setResponsibilityCode(vo.getResponsibilityCode());
+                title.setSort(NumberConstant.ONE);
+                //添加子级标题
+                addCommonResponsibilityChild(title);
+                titleList.add(title);
+            }
+
+        });
+        //按科室名称排序
+        titleList.sort(Comparator.comparing(CommonResponsibilityReportVo::getResponsibilityName));
+        // 记录项目类别对象
+        Map<String, StandardReportFormCustomVo> diseaseCostMap = new HashMap<>();
+        // 遍历每个项目生成科室金额
+        for (DiseaseCostDetailVO costItem : projectCostAccountList) {
+            StandardReportFormCustomVo itemVo ;
+            if(diseaseCostMap.containsKey(costItem.getItemCode())){
+                itemVo=diseaseCostMap.get(costItem.getItemCode());
+            }else{
+                itemVo = new StandardReportFormCustomVo();
+                itemVo.setReportName(costItem.getItemName());
+                itemVo.setReportCode(costItem.getItemCode());
+                itemVo.setData(new ArrayList<>());
+                itemVo.setTotalValue(BigDecimal.ZERO);
+                diseaseCostMap.put(costItem.getItemCode(),itemVo);
+            }
+            Optional<ReportVo> respItem = itemVo.getData().stream().filter(vo -> vo.getCode().equals(getResponsibilityAmountCode(costItem.getResponsibilityCode()))).findFirst();
+            //已包含此责任中心的项目,直接将金额加到已有的项目上
+            if(respItem.isPresent()){
+                BigDecimal value = (BigDecimal) respItem.get().getValue();
+                respItem.get().setValue(value.add(costItem.getHospitalFullCost()));
+            }else{
+                //金额对象
+                ReportVo amountReportVo = new ReportVo();
+                amountReportVo.setCode(getResponsibilityAmountCode(costItem.getResponsibilityCode()));
+                // 设置金额
+                amountReportVo.setValue(costItem.getHospitalFullCost());
+                // 添加金额
+                itemVo.getData().add(amountReportVo);
+            }
+            //计算总额
+            itemVo.setTotalValue(itemVo.getTotalValue().add(costItem.getHospitalFullCost()));
+        }
+
+        List<StandardReportFormCustomVo> diseaseCostDetailList =new ArrayList<>(diseaseCostMap.values());
+
+        diseaseCostDetailList.sort(Comparator.comparing(StandardReportFormCustomVo::getReportCode));
+
+        // 遍历每个成本项目(列转行)
+        for (StandardReportFormCustomVo costItem : diseaseCostDetailList) {
+            if(CollectionUtils.isEmpty(costItem.getData())){
+                continue;
+            }
+            List<ReportVo> dataList =new ArrayList<>();
+            dataList.addAll(costItem.getData());
+            for (ReportVo amountReportVo : dataList) {
+                //占比对象
+                ReportVo percentReportVo = new ReportVo();
+                percentReportVo.setCode(amountReportVo.getCode().replace(AMOUNT_FIELD, PERCENT_FIELD));
+                //计算百分比
+                BigDecimal percent = getPercent((BigDecimal)amountReportVo.getValue() , costItem.getTotalValue());
+                percentReportVo.setValue(percent);
+                // 添加百分比
+                costItem.getData().add(percentReportVo);
+            }
+        }
+        StandardDeptCostCollectResponse response = new StandardDeptCostCollectResponse();
+        response.setTitle(titleList);
+        response.setData(diseaseCostDetailList);
+
+        return response;
+    }
+
+    /**
+     * 获取医院DRG成本明细表数据
+     *
+     * @param computeDate 核算年月
+     * @return DRG成本明细列表
+     */
+    @Override
+    public List<DiseaseCostDetailVO> getDrgCostDetail(String computeDate) {
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDrgCostDetailList(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+        // 获取所有的标准字典数据
+        StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
+        // 记录项目类别对象
+        Map<String, DiseaseCostDetailVO> drgeCostMap = new HashMap<>();
+        for (DiseaseCostDetailVO projectCostAccount : projectCostAccountList) {
+            //按项目类型累加数据
+            DictDataVo costType = standCostDictMaps.getCostTypeMap().get(projectCostAccount.getCostTypeCode());
+            DiseaseCostDetailVO vo ;
+            //已有的项目类别
+            if (drgeCostMap.containsKey(projectCostAccount.getItemCode())) {
+                vo = drgeCostMap.get(projectCostAccount.getItemCode());
+            } else {
+                vo=BeanUtil.convertObj(projectCostAccount,DiseaseCostDetailVO.class);
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                //新建一个项目类别对象
+                drgeCostMap.put(projectCostAccount.getItemCode(), vo);
+            }
+            //没有数据时跳过
+            if(ObjectUtils.isEmpty(projectCostAccount.getHospitalFullCost())){
+                continue;
+            }
+            // 医疗成本
+            if ("1".equals(costType.getExpandOne())) {
+                vo.setMedicalCost(vo.getMedicalCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医疗全成本
+            if (!"3".equals(costType.getExpandOne())) {
+                vo.setMedicalFullCost(vo.getMedicalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            }
+            // 医院全成本
+            vo.setHospitalFullCost(vo.getHospitalFullCost().add(projectCostAccount.getHospitalFullCost()));
+            // 服务量
+            vo.setServiceVolume(projectCostAccount.getServiceVolume());
+        }
+        List<DiseaseCostDetailVO> drgeCostDetailList = new ArrayList<>(drgeCostMap.values());
+        //计算单个DRG的成本
+        drgeCostDetailList.forEach(vo -> {
+            vo.setMedicalCost(getPercent( vo.getMedicalCost(),vo.getServiceVolume()));
+            vo.setMedicalFullCost(getPercent(vo.getMedicalFullCost(),vo.getServiceVolume()));
+            vo.setHospitalFullCost(getPercent(vo.getHospitalFullCost(),vo.getServiceVolume()));
+        });
+        drgeCostDetailList.sort(Comparator.comparing(DiseaseCostDetailVO::getItemCode));
+        return drgeCostDetailList;
+    }
+
+    /**
+     * 获取DRG成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    @Override
+    public List<DiseaseCostDetailVO> getDrgCostCompositionDetail(String computeDate) {
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDrgCostCompositionDetail(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+        // 记录项目类别对象
+        Map<String, DiseaseCostDetailVO> diseaseCostMap = new HashMap<>();
+        for (DiseaseCostDetailVO projectCostAccount : projectCostAccountList) {
+            //按项目类型累加数据
+            String accountType = projectCostAccount.getCostTypeCode();
+            DiseaseCostDetailVO vo ;
+            //已有的项目类别
+            if (diseaseCostMap.containsKey(projectCostAccount.getItemCode())) {
+                vo = diseaseCostMap.get(projectCostAccount.getItemCode());
+            } else {
+                vo = new DiseaseCostDetailVO();
+                vo.setItemCode(projectCostAccount.getItemCode());
+                vo.setItemName(projectCostAccount.getItemName());
+                BeanUtil.initBigDecimalFieldsToZero(vo);
+                //新建一个项目类别对象
+                diseaseCostMap.put(projectCostAccount.getItemCode(), vo);
+            }
+            //按会计科目类型累加费用
+            addAccountTypeExpense(accountType, projectCostAccount.getHospitalFullCost(), vo);
+            //累加数量
+            vo.setServiceVolume(vo.getServiceVolume().add(projectCostAccount.getServiceVolume()));
+        }
+        List<DiseaseCostDetailVO> diseaseCostDetailList =new ArrayList<>(diseaseCostMap.values());
+        //按会计科目类型计算占比
+        diseaseCostDetailList.forEach(vo -> setAccountTypeExpenseRatio(vo));
+        return diseaseCostDetailList;
+    }
+
+    /**
+     * 获取科室DRG成本构成明细表数据
+     * @param computeDate
+     * @return
+     */
+    @Override
+    public StandardDeptCostCollectResponse getDeptDrgCostCompositionDetail(String computeDate) {
+        List<DiseaseCostDetailVO> projectCostAccountList = computePatientCostAccountRepository.getDeptDrgCostCompositionDetail(computeDate);
+        if(CollectionUtils.isEmpty(projectCostAccountList)){
+            throw new CostException("请先计算患者成本");
+        }
+
+        //科室责任中心对照数据
+        List<ResponsibilityDepartIdVO> responsibilityDepartment = responsibilityDepartmentRepository.getResponsibility(UserContext.getHospId());
+        Map<String, List<ResponsibilityDepartIdVO>> deptRespMap = responsibilityDepartment.stream().filter(r -> r.getDepartmentCode() != null).collect(Collectors.groupingBy(ResponsibilityDepartIdVO::getDepartmentCode));
+        //设置科室对应的责任中心
+        for (DiseaseCostDetailVO diseaseCostDetailVO : projectCostAccountList) {
+            List<ResponsibilityDepartIdVO> responsibilityDepartIdVOList = deptRespMap.get(diseaseCostDetailVO.getDepartmentCode());
+            if(CollectionUtils.isEmpty(responsibilityDepartIdVOList)){
+                continue;
+            }
+            ResponsibilityDepartIdVO responsibilityDepartVO = responsibilityDepartIdVOList.get(NumberConstant.ZERO);
+            diseaseCostDetailVO.setResponsibilityCode(responsibilityDepartVO.getResponsibilityCode());
+            diseaseCostDetailVO.setResponsibilityName(responsibilityDepartVO.getResponsibilityName());
+        }
+
+        Map<String, List<DiseaseCostDetailVO>> deptPtAccountGroup = projectCostAccountList.stream().filter(r -> r.getResponsibilityCode() != null).collect(Collectors.groupingBy(DiseaseCostDetailVO::getResponsibilityCode));
+
+        List<CommonResponsibilityReportVo> titleList = new ArrayList<>();
+        // 提取科室名称作为列标题
+        deptPtAccountGroup.forEach((deptCode, deptPtAccountList) -> {
+            if(!CollectionUtils.isEmpty(deptPtAccountList)){
+                CommonResponsibilityReportVo title = new CommonResponsibilityReportVo();
+                DiseaseCostDetailVO vo = deptPtAccountList.get(NumberConstant.ZERO);
+                title.setResponsibilityName(vo.getDepartmentName());
+                title.setResponsibilityCode(vo.getResponsibilityCode());
+                title.setSort(NumberConstant.ONE);
+                //添加子级标题
+                addCommonResponsibilityChild(title);
+                titleList.add(title);
+            }
+        });
+        //按科室名称排序
+        titleList.sort(Comparator.comparing(CommonResponsibilityReportVo::getResponsibilityName));
+
+        // 记录项目类别对象
+        Map<String, StandardReportFormCustomVo> diseaseCostMap = new HashMap<>();
+        // 遍历每个项目生成科室金额
+        for (DiseaseCostDetailVO costItem : projectCostAccountList) {
+            StandardReportFormCustomVo itemVo ;
+            if(diseaseCostMap.containsKey(costItem.getItemCode())){
+                itemVo=diseaseCostMap.get(costItem.getItemCode());
+            }else{
+                itemVo = new StandardReportFormCustomVo();
+                itemVo.setReportName(costItem.getItemName());
+                itemVo.setReportCode(costItem.getItemCode());
+                itemVo.setData(new ArrayList<>());
+                itemVo.setTotalValue(BigDecimal.ZERO);
+                diseaseCostMap.put(costItem.getItemCode(), itemVo);
+            }
+            //金额对象
+            ReportVo amountReportVo = new ReportVo();
+            amountReportVo.setCode(getResponsibilityAmountCode(costItem.getResponsibilityCode()));
+            // 设置金额
+            amountReportVo.setValue(costItem.getHospitalFullCost());
+            // 添加金额
+            itemVo.getData().add(amountReportVo);
+            //计算总额
+            itemVo.setTotalValue(itemVo.getTotalValue().add(costItem.getHospitalFullCost()));
+        }
+
+        List<StandardReportFormCustomVo> diseaseCostDetailList =new ArrayList<>(diseaseCostMap.values());
+
+        // 遍历每个成本项目(列转行)
+        for (StandardReportFormCustomVo costItem : diseaseCostDetailList) {
+            if(CollectionUtils.isEmpty(costItem.getData())){
+                continue;
+            }
+            List<ReportVo> dataList =new ArrayList<>();
+            dataList.addAll(costItem.getData());
+            for (ReportVo amountReportVo :dataList) {
+                //占比对象
+                ReportVo percentReportVo = new ReportVo();
+                percentReportVo.setCode(amountReportVo.getCode().replace(AMOUNT_FIELD, PERCENT_FIELD));
+                //计算百分比
+                BigDecimal percent = getPercent((BigDecimal)amountReportVo.getValue() , costItem.getTotalValue());
+                percentReportVo.setValue(percent);
+                // 添加百分比
+                costItem.getData().add(percentReportVo);
+            }
+        }
+        StandardDeptCostCollectResponse response = new StandardDeptCostCollectResponse();
+        response.setTitle(titleList);
+        response.setData(diseaseCostDetailList);
+
+        return response;
+    }
+
+    /**
+     * 按会计科目类型计算占比
+     * @param vo
+     */
+    public void setAccountTypeExpenseRatio(DiseaseCostDetailVO vo){
+        vo.setPersonnelExpenseRatio(getPercent(vo.getPersonnelExpense(),vo.getTotalCost()));
+        vo.setDrugExpenseRatio(getPercent(vo.getDrugExpense(),vo.getTotalCost()));
+        vo.setMedicalMaterialExpenseRatio(getPercent(vo.getMedicalMaterialExpense(),vo.getTotalCost()));
+        vo.setFixedAssetDepreciationRatio(getPercent(vo.getFixedAssetDepreciation(),vo.getTotalCost()));
+        vo.setIntangibleAssetAmortizationRatio(getPercent(vo.getIntangibleAssetAmortization(),vo.getTotalCost()));
+        vo.setMedicalRiskFundRatio(getPercent(vo.getMedicalRiskFund(),vo.getTotalCost()));
+        vo.setOtherMedicalExpensesRatio(getPercent(vo.getOtherMedicalExpenses(),vo.getTotalCost()));
+    }
+
+    /**
+     * 按会计科目类型累加费用
+     * @param accountType
+     * @param expense
+     * @param vo
+     */
+    public void addAccountTypeExpense(String accountType, BigDecimal expense,DiseaseCostDetailVO vo) {
+        // 根据费用类型累加到对应字段
+        switch (accountType) {
+            case "1":
+                vo.setPersonnelExpense(vo.getPersonnelExpense().add(expense));
+                break;
+            case "2":
+                vo.setMedicalMaterialExpense(vo.getMedicalMaterialExpense().add(expense));
+                break;
+            case "3":
+                vo.setDrugExpense(vo.getDrugExpense().add(expense));
+                break;
+            case "4":
+                vo.setFixedAssetDepreciation(vo.getFixedAssetDepreciation().add(expense));
+                break;
+            case "5":
+                vo.setIntangibleAssetAmortization(vo.getIntangibleAssetAmortization().add(expense));
+                break;
+            case "6":
+                vo.setMedicalRiskFund(vo.getMedicalRiskFund().add(expense));
+                break;
+            case "7":
+                vo.setOtherMedicalExpenses(vo.getOtherMedicalExpenses().add(expense));
+                break;
+            default:
+                break;
+        }
+        vo.setTotalCost(vo.getTotalCost().add(expense));
+    }
+
+    /**
+     * 获取项目归属的项目类型
+     * @param standItemCode
+     * @param standItemMapDict
+     * @return
+     */
+    public StandItem getProjectItemType(String standItemCode,List<Map<String, StandItem>> standItemMapDict) {
+        //不在完整字典里 返回null
+        if(!standItemMapDict.get(NumberConstant.ZERO).containsKey(standItemCode)){
+            return null;
+        }
+        //第一层的项目
+        if(standItemMapDict.get(NumberConstant.ONE).containsKey(standItemCode)){
+            return standItemMapDict.get(NumberConstant.ONE).get(standItemCode);
+        }
+        //第二层的项目
+        if(standItemMapDict.get(NumberConstant.TWO).containsKey(standItemCode)){
+            return standItemMapDict.get(NumberConstant.TWO).get(standItemCode);
+        }
+        //其他层的项目需要递归找到所属的第二层
+        StandItem standItem = standItemMapDict.get(NumberConstant.ZERO).get(standItemCode);
+        return  getProjectItemType(standItem.getParentCode(),standItemMapDict);
+    }
+
+
+
+    /**
+     * 生成完整字典、第一层、第二层的code映射字典
+     * @param standItemList
+     * @return
+     */
+    public List<Map<String,StandItem>> getStandItemMapDict(List<StandItem> standItemList) {
+        List<Map<String,StandItem>> mapList=new ArrayList<>();
+        if(CollectionUtils.isEmpty(standItemList)){
+            Map<String,StandItem> map = new HashMap<>();
+            Map<String,StandItem> firstMap = new HashMap<>();
+            Map<String,StandItem> secondMap = new HashMap<>();
+            mapList.add(map);
+            mapList.add(firstMap);
+            mapList.add(secondMap);
+            return mapList;
+        }
+        // 构建完整字典code到StandItem的映射
+        Map<String, StandItem> standItemMap = standItemList.stream()
+                .collect(Collectors.toMap(StandItem::getCode, item -> item));
+        mapList.add(standItemMap);
+        List<StandItem> firstLevel = standItemList.stream().filter(item -> NumberConstant.ZERO_S.equals(item.getParentCode())).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(firstLevel)){
+            Map<String,StandItem> firstMap = new HashMap<>();
+            Map<String,StandItem> secondMap = new HashMap<>();
+            mapList.add(firstMap);
+            mapList.add(secondMap);
+            return mapList;
+        }
+        // 构建第一层code到StandItem的映射
+        Map<String, StandItem> firstLevelMap = firstLevel.stream()
+                .collect(Collectors.toMap(StandItem::getCode, item -> item));
+        mapList.add(firstLevelMap);
+        List<StandItem> secondLevel= standItemList.stream().filter(item -> firstLevelMap.containsKey(item.getParentCode())).collect(Collectors.toList());
+        if(CollectionUtils.isEmpty(secondLevel)){
+            Map<String,StandItem> secondMap = new HashMap<>();
+            mapList.add(secondMap);
+            return mapList;
+        }
+        // 构建第二层code到StandItem的映射
+        Map<String, StandItem> secondLevelMap = secondLevel.stream()
+                .collect(Collectors.toMap(StandItem::getCode, item -> item));
+        mapList.add(secondLevelMap);
+        return mapList;
+    }
+    
+
+
+    /**
+     * 根据标准项目字典创建项目类别
+     * @param standItemMapDict 标准项目字典
+     * @return 项目类别
+     */
+    private List<HospitalServiceProjectCostVO> createProjectCategory(List<Map<String, StandItem>> standItemMapDict,Map<String, HospitalServiceProjectCostVO> projectCostMap ) {
+        if(CollectionUtils.isEmpty(standItemMapDict.get(NumberConstant.ONE))){
+            return new ArrayList<>();
+        }
+        List<StandItem> sencodLevel=new ArrayList<>(standItemMapDict.get(NumberConstant.TWO).values());
+        List<StandItem> firstLevel =new ArrayList<>(standItemMapDict.get(NumberConstant.ONE).values());
+        //按序号排序
+        firstLevel.sort(Comparator.comparing(StandItem::getSort));
+        List<HospitalServiceProjectCostVO> hospitalServiceProjectCostVOS =firstLevel.stream().map( item->convertToHospitalServiceProjectCostVO(item)).collect(Collectors.toList());
+        for (HospitalServiceProjectCostVO item : hospitalServiceProjectCostVOS) {
+            //先加自己的
+            if(projectCostMap.containsKey(item.getItemCode())){
+                addBigDecimalFields(projectCostMap.get(item.getItemCode()), item);
+            }
+            if(CollectionUtils.isEmpty(sencodLevel)){
+                continue;
+            }
+            //第一层对应的第二层数据
+            List<StandItem> children = sencodLevel.stream().filter(child -> item.getItemCode().equals(child.getParentCode())).collect(Collectors.toList());
+            if(CollectionUtils.isEmpty( children)){
+                continue;
+            }
+            //按序号排序
+            children.sort(Comparator.comparing(StandItem::getSort));
+            item.setChildren(new ArrayList<>());
+            for (StandItem child : children) {
+                HospitalServiceProjectCostVO childProject ;
+                //优先取已有的数据
+                if(projectCostMap.containsKey(child.getCode())){
+                    childProject=projectCostMap.get(child.getCode());
+                }else{
+                    childProject = convertToHospitalServiceProjectCostVO(child);
+                }
+                //加给第一层
+                addBigDecimalFields(childProject, item);
+                item.getChildren().add(childProject);
+            }
+        }
+        return  hospitalServiceProjectCostVOS;
+    }
+
+    public HospitalServiceProjectCostVO convertToHospitalServiceProjectCostVO(StandItem standItem){
+        HospitalServiceProjectCostVO vo = new HospitalServiceProjectCostVO();
+        vo.setItemCode(standItem.getCode());
+        vo.setItemName(standItem.getName());
+        // 初始化所有费用字段为0
+        BeanUtil.initBigDecimalFieldsToZero(vo);
+        return vo;
+    }
+
+    /**
+     * 获取可是指定项目的金额
+     * @param dept
+     * @param costItem
+     * @return
+     */
+    public  BigDecimal getDeptAmount(DeptDirectMedicalCostVO dept,String costItem) {
+        BigDecimal amount = BigDecimal.ZERO;
+        switch (costItem) {
+            case "人员经费":
+                amount = dept.getPersonnelExpense();
+                break;
+            case "卫生材料费":
+                amount = dept.getHealthMaterialFee();
+                break;
+            case "药品费":
+                amount = dept.getDrugFee();
+                break;
+            case "固定资产折旧费":
+                amount =dept.getFixedAssetDepreciation();
+                break;
+            case "无形资产摊销费":
+                amount = dept.getIntangibleAssetAmortization();
+                break;
+            case "提取医疗风险基金":
+                amount = dept.getMedicalRiskFundExtraction();
+                break;
+            case "其他医疗费用":
+                amount = dept.getOtherMedicalExpenses();
+                break;
+            case "科室全成本合计":
+                amount = dept.getTotal();
+                break;
+            case "科室收入":
+                amount = dept.getIncome();
+                break;
+            case "收入-成本":
+                amount = dept.getProfit();
+                break;
+            case "诊次成本":
+                amount = dept.getVisitsCost();
+                break;
+            case "床日成本":
+                amount = dept.getBedDaysCost();
+                break;
+            default:
+                break;
+        }
+        return amount;
+    }
+
+    /**
+     * 计算科室的收入及损益+床日成本及诊次成本
+     * @param item
+     * @param responsibilityIncomeMap
+     * @param responsibilityParamValueMap
+     * @param visitsBedDaysParamCode
+     */
+    private void calcDeptExpandCost(DeptDirectMedicalCostVO item,
+                                    Map<String, BigDecimal> responsibilityIncomeMap,
+                                    Map<String, List<ShareParamValue>> responsibilityParamValueMap,
+                                    String[] visitsBedDaysParamCode) {
+        //计算科室的收入及损益
+        if(responsibilityIncomeMap.containsKey(item.getResponsibilityCode())){
+            item.setIncome(responsibilityIncomeMap.get(item.getResponsibilityCode()));
+            item.setProfit(item.getIncome().subtract(item.getTotal()));
+        }else{
+            item.setIncome(BigDecimal.ZERO);
+            item.setProfit(BigDecimal.ZERO);
+        }
+        //计算科室的床日成本及诊次成本
+        if(responsibilityParamValueMap.containsKey(item.getResponsibilityCode())){
+            List<ShareParamValue> shareParamValues = responsibilityParamValueMap.get(item.getResponsibilityCode());
+
+            // 诊次分摊参数值
+            BigDecimal visitParamValue = getParamValue(shareParamValues, visitsBedDaysParamCode[NumberConstant.ZERO]);
+            // 床日分摊参数值
+            BigDecimal bedDaysParamValue = getParamValue(shareParamValues, visitsBedDaysParamCode[NumberConstant.ONE]);
+            // 计算诊次成本及床日成本
+            item.setVisitsCost(getPercent(item.getTotal(),visitParamValue));
+            item.setBedDaysCost(getPercent(item.getTotal(),bedDaysParamValue));
+        }else{
+            item.setBedDaysCost(BigDecimal.ZERO);
+            item.setVisitsCost(BigDecimal.ZERO);
+        }
+    }
+
+
+    /**
+     * 获取百分比
+     * @param amount
+     * @param total
+     * @return
+     */
+    public BigDecimal getPercent(BigDecimal amount,BigDecimal total){
+        if(total.compareTo(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP)) == 0){
+            return BigDecimal.ZERO;
+        }
+        return amount.divide(total,4, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 获取责任中心金额字段
+     * @param responsibilityCode
+     * @return
+     */
+    public String getResponsibilityAmountCode(String responsibilityCode){
+        return String.format("%s_%s", responsibilityCode, AMOUNT_FIELD);
+    }
+
+    /**
+     * 获取责任中心占比字段
+     * @param responsibilityCode
+     * @return
+     */
+    public String getResponsibilityPercentCode(String responsibilityCode){
+        return String.format("%s_%s", responsibilityCode, PERCENT_FIELD);
+    }
+
+    /**
+     * 添加全成本构成表标题的子级标题
+     * @param commonResponsibility
+     */
+    public void addCommonResponsibilityChild(CommonResponsibilityReportVo commonResponsibility) {
+        commonResponsibility.setChild(new ArrayList<>());
+        CommonResponsibilityReportVo amount=new CommonResponsibilityReportVo();
+        amount.setResponsibilityCode(getResponsibilityAmountCode(commonResponsibility.getResponsibilityCode() ));
+        amount.setResponsibilityName("金额");
+        amount.setSort(NumberConstant.ZERO);
+        amount.setDataType(NumberConstant.ONE);
+        amount.setDataTypeName("数值");
+        amount.setDecimalPlace(NumberConstant.TWO);
+        amount.setPermil(NumberConstant.ONE);
+        amount.setIsFixed(NumberConstant.ZERO);
+        commonResponsibility.getChild().add( amount);
+        CommonResponsibilityReportVo percent=new CommonResponsibilityReportVo();
+        percent.setResponsibilityCode(getResponsibilityPercentCode(commonResponsibility.getResponsibilityCode()));
+        percent.setResponsibilityName("占比");
+        percent.setSort(NumberConstant.ONE);
+        percent.setDataType(NumberConstant.TWO);
+        percent.setDataTypeName("百分比");
+        percent.setDecimalPlace(NumberConstant.TWO);
+        percent.setPermil(NumberConstant.ZERO);
+        percent.setIsFixed(NumberConstant.ZERO);
+        commonResponsibility.getChild().add( percent);
+    }
+
+    /**
+     * 添加临床服务类科室全成本明细
+     * @param reportMap
+     * @param allocationQuery
+     * @param standCostDictMaps
+     */
+    private void addClinicalDeptFullCostVO(Map<String, ClinicalDeptFullCostVO> reportMap, AllocationQuery allocationQuery, StandCostDictMapVO standCostDictMaps) {
+        String responsibilityCode = allocationQuery.getTargetResponsibilityCode();
+        Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+        if (responsibility == null) {
+            return; // 添加 null 检查
+        }
+
+        String accountingCode = allocationQuery.getAccountingCode();
+        Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+        if (account == null) {
+            return; // 添加 null 检查
+        }
+
+        DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
+        if (accountType == null) {
+            return; // 添加 null 检查
+        }
+        DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+        DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
+
+        ClinicalDeptFullCostVO reportVO = new ClinicalDeptFullCostVO();
+        if (reportMap.containsKey(allocationQuery.getResponsibilityCode())) {
+            reportVO = reportMap.get(allocationQuery.getResponsibilityCode());
+        } else {
+            // 生成科室成本报表信息
+            initDeptCostReport(reportVO, responsibility, accountType, costType, standardShareLevel);
+            // 初始化所有费用字段为0
+            BeanUtil.initBigDecimalFieldsToZero(reportVO);
+            reportMap.put(allocationQuery.getResponsibilityCode(), reportVO);
+        }
+
+        // 根据费用类型累加到对应字段
+        switch (costType.getValue()) {
+            case "1":
+                if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                    reportVO.setMedicalCostTotalDirect(reportVO.getMedicalCostTotalDirect().add(allocationQuery.getAmount()));
+                } else {
+                    reportVO.setMedicalCostTotalIndirect(reportVO.getMedicalCostTotalIndirect().add(allocationQuery.getAmount()));
+                }
+                reportVO.setMedicalCostTotal(reportVO.getMedicalCostTotal().add(allocationQuery.getAmount()));
+                break;
+            case "2":
+                if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                    reportVO.setFinancialProjectFundsDirect(reportVO.getFinancialProjectFundsDirect().add(allocationQuery.getAmount()));
+                } else {
+                    reportVO.setFinancialProjectFundsIndirect(reportVO.getFinancialProjectFundsIndirect().add(allocationQuery.getAmount()));
+                }
+                reportVO.setFinancialProjectFunds(reportVO.getFinancialProjectFunds().add(allocationQuery.getAmount()));
+                break;
+            case "3":
+                if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                    reportVO.setNonPeerFinancialFundsDirect(reportVO.getNonPeerFinancialFundsDirect().add(allocationQuery.getAmount()));
+                } else {
+                    reportVO.setNonPeerFinancialFundsIndirect(reportVO.getNonPeerFinancialFundsIndirect().add(allocationQuery.getAmount()));
+                }
+                reportVO.setNonPeerFinancialFunds(reportVO.getNonPeerFinancialFunds().add(allocationQuery.getAmount()));
+                break;
+            case "4":
+                if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                    reportVO.setEducationalExpensesDirect(reportVO.getEducationalExpensesDirect().add(allocationQuery.getAmount()));
+                } else {
+                    reportVO.setEducationalExpensesIndirect(reportVO.getEducationalExpensesIndirect().add(allocationQuery.getAmount()));
+                }
+                reportVO.setEducationalExpenses(reportVO.getEducationalExpenses().add(allocationQuery.getAmount()));
+                break;
+            case "5":
+                if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                    reportVO.setAssetDisposalFeesDirect(reportVO.getAssetDisposalFeesDirect().add(allocationQuery.getAmount()));
+                } else {
+                    reportVO.setAssetDisposalFeesIndirect(reportVO.getAssetDisposalFeesIndirect().add(allocationQuery.getAmount()));
+                }
+                reportVO.setAssetDisposalFees(reportVO.getAssetDisposalFees().add(allocationQuery.getAmount()));
+                break;
+            default:
+                break;
+        }
+
+        // 不是医院全成本的都是医疗全成本
+        if (!NumberConstant.THREE_S.equals(costType.getExpandOne())) {
+            if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+                reportVO.setMedicalTotalCostDirect(reportVO.getMedicalTotalCostDirect().add(allocationQuery.getAmount()));
+            } else {
+                reportVO.setMedicalTotalCostIndirect(reportVO.getMedicalTotalCostIndirect().add(allocationQuery.getAmount()));
+            }
+            reportVO.setMedicalTotalCost(reportVO.getMedicalTotalCost().add(allocationQuery.getAmount()));
+        }
+
+        // 医院全成本合计
+        if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+            reportVO.setHospitalTotalCostDirect(reportVO.getHospitalTotalCostDirect().add(allocationQuery.getAmount()));
+        } else {
+            reportVO.setHospitalTotalCostIndirect(reportVO.getHospitalTotalCostIndirect().add(allocationQuery.getAmount()));
+        }
+        reportVO.setHospitalTotalCost(reportVO.getHospitalTotalCost().add(allocationQuery.getAmount()));
+    }
+
+    /**
+     * 添加科室成本明细
+     * @param reportMap 
+     * @param allocationQuery
+     * @param standCostDictMaps
+     */
+    private void addDeptCostDetailVO(Map<String, ClinicalDeptMedicalCostVO> reportMap, AllocationQuery allocationQuery, StandCostDictMapVO standCostDictMaps) {
+        String responsibilityCode = allocationQuery.getTargetResponsibilityCode();
+        Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+        if (responsibility == null) {
+            return; // 添加 null 检查
+        }
+
+        String accountingCode = allocationQuery.getAccountingCode();
+        Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+        if (account == null) {
+            return; // 添加 null 检查
+        }
+
+        DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
+        if (accountType == null) {
+            return; // 添加 null 检查
+        }
+        DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+        DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
+
+        ClinicalDeptMedicalCostVO reportVO = new ClinicalDeptMedicalCostVO();
+        if (reportMap.containsKey(allocationQuery.getResponsibilityCode())) {
+            reportVO = reportMap.get(allocationQuery.getResponsibilityCode());
+        } else {
+            //生成科室成本报表信息
+            initDeptCostReport(reportVO, responsibility, accountType, costType, standardShareLevel);
+            // 初始化所有费用字段为0
+            BeanUtil.initBigDecimalFieldsToZero(reportVO);
+            reportMap.put(allocationQuery.getResponsibilityCode(), reportVO);
+        }
+
+        // 根据费用类型累加到对应字段
+        switch (accountType.getExpandOne())  {
+            case "1":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setPersonnelDirectCost(reportVO.getPersonnelDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setPersonnelIndirectCost(reportVO.getPersonnelIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setPersonnelTotalCost(reportVO.getPersonnelTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "2":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setHealthMaterialDirectCost(reportVO.getHealthMaterialDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setHealthMaterialIndirectCost(reportVO.getHealthMaterialIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setHealthMaterialTotalCost(reportVO.getHealthMaterialTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "3":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setMedicineDirectCost(reportVO.getMedicineDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setMedicineIndirectCost(reportVO.getMedicineIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setMedicineTotalCost(reportVO.getMedicineTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "4":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setFixedAssetDepreciationDirectCost(reportVO.getFixedAssetDepreciationDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setFixedAssetDepreciationIndirectCost(reportVO.getFixedAssetDepreciationIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setFixedAssetDepreciationTotalCost(reportVO.getFixedAssetDepreciationTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "5":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setIntangibleAssetAmortizationDirectCost(reportVO.getIntangibleAssetAmortizationDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setIntangibleAssetAmortizationIndirectCost(reportVO.getIntangibleAssetAmortizationIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setIntangibleAssetAmortizationTotalCost(reportVO.getIntangibleAssetAmortizationTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "6":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setMedicalRiskReserveDirectCost(reportVO.getMedicalRiskReserveDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setMedicalRiskReserveIndirectCost(reportVO.getMedicalRiskReserveIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setMedicalRiskReserveTotalCost(reportVO.getMedicalRiskReserveTotalCost().add(allocationQuery.getAmount()));
+                break;
+            case "7":
+                if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+                    reportVO.setOtherMedicalExpensesDirectCost(reportVO.getOtherMedicalExpensesDirectCost().add(allocationQuery.getAmount()));
+                }else{
+                    reportVO.setOtherMedicalExpensesIndirectCost(reportVO.getOtherMedicalExpensesIndirectCost().add(allocationQuery.getAmount()));
+                }
+                reportVO.setOtherMedicalExpensesTotalCost(reportVO.getOtherMedicalExpensesTotalCost().add(allocationQuery.getAmount()));
+                break;
+            default:
+                break;
+        }
+        //添加合计
+        if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
+            reportVO.setTotalDirectCost(reportVO.getTotalDirectCost().add(allocationQuery.getAmount()));
+        }else{
+            reportVO.setTotalIndirectCost(reportVO.getTotalIndirectCost().add(allocationQuery.getAmount()));
+        }
+        reportVO.setTotalCost(reportVO.getTotalCost().add(allocationQuery.getAmount()));
+    }
+
+
+    /**
+     * 生成科室成本报表信息
+     * @param reportVO
+     * @param responsibility
+     * @param accountType
+     * @param costType
+     * @param standardShareLevel
+     */
+    private void initDeptCostReport(BaseDeptCostReportVO reportVO,
+                                    Responsibility responsibility,
+                                    DictDataVo accountType,
+                                    DictDataVo costType,
+                                    DictDataVo standardShareLevel) {
+        reportVO.setStandardShareLevel(responsibility.getStandardShareLevel());
+        reportVO.setResponsibilityName(responsibility.getResponsibilityName());
+        reportVO.setResponsibilityCode(responsibility.getResponsibilityCode());
+        reportVO.setResponsibilitySort(responsibility.getSort());
+        reportVO.setCostType(costType.getCode());
+        reportVO.setStandCostType(costType.getExpandOne());
+        reportVO.setAccountType(accountType.getCode());
+        reportVO.setStandAccountType(accountType.getExpandOne());
+        reportVO.setShareLevelSort(standardShareLevel.getSort());
+    }
+
+    /**
+     * 获取所有的标准字典数据并转换所有需要的映射数据
+     * @return 包含所有映射数据的DTO对象
+     */
+    private StandCostDictMapVO getStandCostDictMaps() {
+        StandCostDictMapVO dataMaps = new StandCostDictMapVO();
+        List<Responsibility> responsibilityList = responsibilityRepository.getList(UserContext.getCurrentLoginHospId());
+        DictDataVo accountingTypeDict = centerService.getDict(Constant.ACCOUNTING_TYPE);
+        DictDataVo costTypeDict = centerService.getDict(Constant.STANDARD_COST_CATEGORIES);
+        DictDataVo standardShareLevelDict = centerService.getDict(Constant.STANDARD_SHARE_LEVEL);
+        List<Accounting> allCostAccounting = accountingRepository.getAllCostAccounting();
+
+        // 添加 null 检查
+        if (responsibilityList == null) {
+            responsibilityList = new ArrayList<>();
+        }
+        if (allCostAccounting == null) {
+            allCostAccounting = new ArrayList<>();
+        }
+
+        // 创建一个映射,用于快速查找责任中心的科室类型,过滤掉 null 对象,过滤掉 responsibilityCode 为 null 的对象
+        Map<String, Responsibility> responsibilityMap = responsibilityList.stream()
+                .filter(Objects::nonNull)
+                .filter(r -> r.getResponsibilityCode() != null)
+                .collect(Collectors.toMap(Responsibility::getResponsibilityCode, o -> o));
+
+        // 创建一个映射,用于快速查找会计科目的类型,过滤掉 null 对象,过滤掉 accountingCode 为 null 的对象
+        Map<String, Accounting> accountingMap = allCostAccounting.stream()
+                .filter(Objects::nonNull)
+                .filter(a -> a.getAccountingCode() != null)
+                .collect(Collectors.toMap(Accounting::getAccountingCode, o -> o));
+
+        // 添加 null 检查并创建映射
+        List<DictDataVo> accountingTypeDictList = (accountingTypeDict != null && accountingTypeDict.getDataVoList() != null)
+                ? accountingTypeDict.getDataVoList() : new ArrayList<>();
+
+        List<DictDataVo> costTypeDictList = (costTypeDict != null && costTypeDict.getDataVoList() != null)
+                ? costTypeDict.getDataVoList() : new ArrayList<>();
+
+        List<DictDataVo> standardShareLevelDictList = (standardShareLevelDict != null && standardShareLevelDict.getDataVoList() != null)
+                ? standardShareLevelDict.getDataVoList() : new ArrayList<>();
+
+        // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
+        Map<String, DictDataVo> accountingTypeMap = accountingTypeDictList.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> d.getCode() != null)
+                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
+
+        // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
+        Map<String, DictDataVo> costTypeMap = costTypeDictList.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> d.getCode() != null)
+                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
+
+        // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
+        Map<String, DictDataVo> standardShareLevelMap = standardShareLevelDictList.stream()
+                .filter(Objects::nonNull)
+                .filter(d -> d.getCode() != null)
+                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
+
+        dataMaps.setResponsibilityDict(responsibilityList);
+        dataMaps.setCostAccountingDict(allCostAccounting);
+        dataMaps.setCostTypeDict(costTypeDictList);
+        dataMaps.setAccountingTypeDict(accountingTypeDictList);
+        dataMaps.setStandardShareLevelDict(standardShareLevelDictList);
+        dataMaps.setAccountingMap(accountingMap);
+        dataMaps.setCostTypeMap(costTypeMap);
+        dataMaps.setResponsibilityMap(responsibilityMap);
+        dataMaps.setStandardShareLevelMap(standardShareLevelMap);
+        dataMaps.setAccountingTypeMap(accountingTypeMap);
+        return dataMaps;
+    }
+
+
+    /**
+     *  转换为DeptDirectMedicalCostVO(一个责任中心只一条记录)
+     * @param allocationQuery
+     * @param standCostDictMaps
+     * @return
+     */
+    public void addDeptDirectMedicalCostVO(Map<String ,DeptDirectMedicalCostVO> deptDirectMedicalCostMap,
+                                           AllocationQuery allocationQuery,
+                                           StandCostDictMapVO standCostDictMaps) {
+        String responsibilityCode = allocationQuery.getTargetResponsibilityCode();
+        Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+        if (responsibility == null) {
+            return; // 添加 null 检查
+        }
+        String accountingCode = allocationQuery.getAccountingCode();
+        Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+        if (account == null) {
+            return; // 添加 null 检查
+        }
+        DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
+        if (accountType == null) {
+            return; // 添加 null 检查
+        }
+        //只处理医疗成本
+        if(!NumberConstant.ONE_S.equals(accountType.getExpandOne()) ){
+            return;
+        }
+        DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+        DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
+        DeptDirectMedicalCostVO deptDirectMedicalCostVO= new DeptDirectMedicalCostVO();
+        if(deptDirectMedicalCostMap.containsKey(allocationQuery.getResponsibilityCode())){
+            deptDirectMedicalCostVO=deptDirectMedicalCostMap.get(allocationQuery.getResponsibilityCode());
+        }else{
+            initDeptCostReport(deptDirectMedicalCostVO, responsibility,accountType, costType,standardShareLevel);
+            // 初始化所有费用字段为0
+            BeanUtil.initBigDecimalFieldsToZero(deptDirectMedicalCostVO);
+            deptDirectMedicalCostMap.put(allocationQuery.getResponsibilityCode(),deptDirectMedicalCostVO);
+        }
+        // 根据费用类型累加到对应字段
+        switch (accountType.getExpandOne()) {
+            case "1":
+                deptDirectMedicalCostVO.setPersonnelExpense(deptDirectMedicalCostVO.getPersonnelExpense().add((allocationQuery.getAmount())));
+                break;
+            case "2":
+                deptDirectMedicalCostVO.setHealthMaterialFee(deptDirectMedicalCostVO.getHealthMaterialFee().add((allocationQuery.getAmount())));
+                break;
+            case "3":
+                deptDirectMedicalCostVO.setDrugFee(deptDirectMedicalCostVO.getDrugFee().add((allocationQuery.getAmount())));
+                break;
+            case "4":
+                deptDirectMedicalCostVO.setFixedAssetDepreciation(deptDirectMedicalCostVO.getFixedAssetDepreciation().add((allocationQuery.getAmount())));
+                break;
+            case "5":
+                deptDirectMedicalCostVO.setIntangibleAssetAmortization(deptDirectMedicalCostVO.getIntangibleAssetAmortization().add((allocationQuery.getAmount())));
+                break;
+            case "6":
+                deptDirectMedicalCostVO.setMedicalRiskFundExtraction(deptDirectMedicalCostVO.getMedicalRiskFundExtraction().add((allocationQuery.getAmount())));
+                break;
+            case "7":
+                deptDirectMedicalCostVO.setOtherMedicalExpenses(deptDirectMedicalCostVO.getOtherMedicalExpenses().add((allocationQuery.getAmount())));
+                break;
+            default:
+                break;
+        }
+        // 更新总计
+        deptDirectMedicalCostVO.setTotal(deptDirectMedicalCostVO.getTotal().add(allocationQuery.getAmount()));
+    }
+
+
+
+    /**
+     * 转换为DeptDirectAllCostVO(一个责任中心只一条记录)
+     * @param reportMap
+     * @param allocationQuery
+     * @param standCostDictMaps
+     */
+    private void addDeptDirectAllCostVO(Map<String, DeptFullDirectCostVO> reportMap, AllocationQuery allocationQuery, StandCostDictMapVO standCostDictMaps) {
+        String responsibilityCode = allocationQuery.getTargetResponsibilityCode();
+        Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+        if (responsibility == null) {
+            return; // 添加 null 检查
+        }
+        
+        String accountingCode = allocationQuery.getAccountingCode();
+        Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+        if (account == null) {
+            return; // 添加 null 检查
+        }
+        
+        DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
+        if (accountType == null) {
+            return; // 添加 null 检查
+        }
+        DictDataVo costType = standCostDictMaps.getCostTypeMap().get(String.valueOf(account.getCostType()));
+        DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
+
+        DeptFullDirectCostVO reportVO = new DeptFullDirectCostVO();
+        if (reportMap.containsKey(allocationQuery.getResponsibilityCode())) {
+            reportVO = reportMap.get(allocationQuery.getResponsibilityCode());
+        } else {
+            initDeptCostReport(reportVO, responsibility,accountType, costType,standardShareLevel);
+            // 初始化所有费用字段为0
+            BeanUtil.initBigDecimalFieldsToZero(reportVO);
+            reportMap.put(allocationQuery.getResponsibilityCode(),reportVO);
+        }
+
+        // 根据费用类型累加到对应字段
+        switch (costType.getValue()) {
+            case "1":
+                reportVO.setMedicalCostTotal(reportVO.getMedicalCostTotal().add(allocationQuery.getAmount()));
+                break;
+            case "2":
+                reportVO.setFinancialProjectFunds(reportVO.getFinancialProjectFunds().add(allocationQuery.getAmount()));
+                break;
+            case "3":
+                reportVO.setNonPeerFinancialFunds(reportVO.getNonPeerFinancialFunds().add(allocationQuery.getAmount()));
+                break;
+            case "4":
+                reportVO.setEducationalExpenses(reportVO.getEducationalExpenses().add(allocationQuery.getAmount()));
+                break;
+            case "5":
+                reportVO.setAssetDisposalFees(reportVO.getAssetDisposalFees().add(allocationQuery.getAmount()));
+                break;
+            default:
+                break;
+        }
+        //不是医院全成本的都是医疗全成本
+        if(!NumberConstant.THREE_S.equals(costType.getExpandOne())){
+            // 医疗全成本合计
+            reportVO.setMedicalTotalCost(reportVO.getMedicalTotalCost().add(allocationQuery.getAmount()));
+        }
+        // 医院全成本合计
+        reportVO.setHospitalTotalCost(reportVO.getHospitalTotalCost().add(allocationQuery.getAmount()));
+    }
+    
+
+    /**
+     * 合并两个科室成本
+     * @param source 源对象
+     * @param target 目标对象
+     */
+    public <T> void addBigDecimalFields(T source, T target) {
+        if (source == null || target == null) {
+            return;
+        }
+        Class<?> clazz = target.getClass();
+        Field[] fields = clazz.getDeclaredFields();
+
+        for (Field field : fields) {
+            if (field.getType().equals(BigDecimal.class)) {
+                field.setAccessible(true);
+                try {
+                    BigDecimal sourceValue = (BigDecimal) field.get(source);
+                    BigDecimal targetValue = (BigDecimal) field.get(target);
+
+                    BigDecimal result = (targetValue == null ? BigDecimal.ZERO : targetValue)
+                            .add(sourceValue == null ? BigDecimal.ZERO : sourceValue);
+
+                    field.set(target, result);
+                } catch (IllegalAccessException e) {
+                    log.error("合并科室成本时发生错误", e);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 通用创建小计对象方法
+     * @param source 源对象
+     * @param totalName 小计名称
+     * @param clazz 目标类类型
+     * @return 小计对象
+     */
+    public <T> T createSubtotalVo(T source, String totalName, Class<T> clazz) {
+        if (source == null) {
+            return null;
+        }
+        T target = BeanUtil.convertObj(source, clazz);
+        // 使用反射设置责任代码和名称
+        try {
+            clazz.getMethod("setResponsibilityCode", String.class).invoke(target, totalName);
+            clazz.getMethod("setResponsibilityName", String.class).invoke(target, totalName);
+        } catch (Exception e) {
+            log.error("设置责任代码和名称时发生错误", e);
+        }
+        // 初始化所有费用字段为0
+        BeanUtil.initBigDecimalFieldsToZero(target);
+        return target;
+    }
+
+    // 新增方法,用于设置科室金额
+    private void putDepartmentAmount(ClinicalDeptFullCostVO vo, String deptName, BigDecimal amount) {
+        try {
+            Field field = vo.getClass().getDeclaredField(deptName);
+            field.setAccessible(true);
+            field.set(vo, amount);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            log.error("设置科室金额时发生错误", e);
+        }
+    }
+
+    /**
+     * 获取诊次床日分摊参数代码
+     * @return
+     */
+    public String[] getVisitsBedDaysParamCode(){
+        String parameterValue = centerService.getParameterValue(ParameterConstant.VISITS_BED_DAYS_PARAM_CODE);
+        if(StringUtils.isEmpty(parameterValue)||Constant.EMPTY_STR.equals(parameterValue)){
+            throw new CostException("请配置诊次床日分摊参数代码");
+        }
+        String[] split = parameterValue.split(SplitConstant.SEPARATOR_VERTICALLINE);
+        if(!NumberConstant.TWO.equals(split.length)){
+            throw new CostException("配置的诊次床日分摊参数代码不正确");
+        }
+        return split;
+    }
+
+    /**
+     * 添加医院科室成本分摊数据
+     * @param deptCostAllocationMap 科室成本分摊Map
+     * @param allocationQuery 分摊查询对象
+     * @param standCostDictMaps 标准字典数据
+     */
+    private void addHospitalDeptCostAllocationVO(Map<String, HospitalDeptCostAllocationVO> deptCostAllocationMap,
+                                                 AllocationQuery allocationQuery,
+                                                 StandCostDictMapVO standCostDictMaps) {
+        String responsibilityCode = allocationQuery.getTargetResponsibilityCode();
+        String sourceResponsibilityCode = allocationQuery.getResponsibilityCode();
+        Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
+        if (responsibility == null) {
+            return;
+        }
+
+        Responsibility sourceResponsibility = standCostDictMaps.getResponsibilityMap().get(sourceResponsibilityCode);
+        if (sourceResponsibility == null) {
+            return;
+        }
+
+        String accountingCode = allocationQuery.getAccountingCode();
+        Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
+        if (account == null) {
+            return;
+        }
+
+        DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
+        if (accountType == null) {
+            return;
+        }
+
+        HospitalDeptCostAllocationVO costAllocationVO = new HospitalDeptCostAllocationVO();
+        if (deptCostAllocationMap.containsKey(responsibilityCode)) {
+            costAllocationVO = deptCostAllocationMap.get(responsibilityCode);
+        } else {
+            // 初始化VO对象
+            costAllocationVO.setResponsibilityName(responsibility.getResponsibilityName());
+            costAllocationVO.setResponsibilityCode(responsibility.getResponsibilityCode());
+            costAllocationVO.setResponsibilitySort(responsibility.getSort());
+            costAllocationVO.setStandardShareLevel(responsibility.getStandardShareLevel());
+
+            // 初始化所有费用字段为0
+            BeanUtil.initBigDecimalFieldsToZero(costAllocationVO);
+            deptCostAllocationMap.put(responsibilityCode, costAllocationVO);
+        }
+
+        // 直接成本
+        if (NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())) {
+            costAllocationVO.setDirectCost(
+                    (costAllocationVO.getDirectCost() == null ? BigDecimal.ZERO : costAllocationVO.getDirectCost())
+                            .add(allocationQuery.getAmount()));
+        }else{
+            //如果分摊层级和目标层级一样加到直接成本
+            if(sourceResponsibility.getStandardShareLevel().equals(responsibility.getStandardShareLevel())){
+                costAllocationVO.setDirectCost(
+                        (costAllocationVO.getDirectCost() == null ? BigDecimal.ZERO : costAllocationVO.getDirectCost())
+                                .add(allocationQuery.getAmount()));
+            }else{
+                switch (sourceResponsibility.getStandardShareLevel())
+                {
+                    case "1":
+                        // 行政后勤类科室成本
+                        costAllocationVO.setAllocatedAdminCost(
+                                (costAllocationVO.getAllocatedAdminCost() == null ? BigDecimal.ZERO : costAllocationVO.getAllocatedAdminCost())
+                                        .add(allocationQuery.getAmount()));
+                        break;
+                    case "2":
+                        // 辅助支持类科室成本
+                        costAllocationVO.setAllocatedSupportCost(
+                                (costAllocationVO.getAllocatedSupportCost() == null ? BigDecimal.ZERO : costAllocationVO.getAllocatedSupportCost())
+                                        .add(allocationQuery.getAmount()));
+                        break;
+                    case "3":
+                        // 技术类科室成本
+                        costAllocationVO.setAllocatedTechCost(
+                                (costAllocationVO.getAllocatedTechCost() == null ? BigDecimal.ZERO : costAllocationVO.getAllocatedTechCost())
+                                        .add(allocationQuery.getAmount()));
+                        break;
+                }
+                //小计
+                costAllocationVO.setSubtotal(
+                        (costAllocationVO.getSubtotal() == null ? BigDecimal.ZERO : costAllocationVO.getSubtotal())
+                                .add(allocationQuery.getAmount()));
+            }
+        }
+        // 医疗类科室成本
+        costAllocationVO.setMedicalCost(
+                (costAllocationVO.getMedicalCost() == null ? BigDecimal.ZERO : costAllocationVO.getMedicalCost())
+                        .add(allocationQuery.getAmount()));
+        deptCostAllocationMap.put(responsibilityCode, costAllocationVO);
+    }
+
+
+    /**
+     * 获取指定分摊参数的数值
+     * @param shareParamValues
+     * @param paramCode
+     * @return
+     */
+    public BigDecimal getParamValue(List<ShareParamValue> shareParamValues, String paramCode){
+        BigDecimal sum = shareParamValues.stream()
+                .filter(shareParamValue -> shareParamValue.getShareParamCode().equals(paramCode))
+                .map(ShareParamValue::getValueNum)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        return sum;
+    }
+
+    /**
+     * 创建医院诊次成本构成表数据
+     * @param costAccountingTypeDict
+     * @return
+     */
+    public Map<String, HospitalVisitCostCompositionVO> createHospitalVisitCostCompositionVO(List<DictDataVo> costAccountingTypeDict) {
+        // 初始化成本项目映射
+        Map<String, HospitalVisitCostCompositionVO> costItemMap = new HashMap<>();
+        for (DictDataVo dictDataVo : costAccountingTypeDict) {
+            HospitalVisitCostCompositionVO vo = new HospitalVisitCostCompositionVO();
+            vo.setCostCode(dictDataVo.getCode());
+            vo.setCostItem(dictDataVo.getName());
+            vo.setCostType(dictDataVo.getExpandOne());
+            vo.setMedicalCost(BigDecimal.ZERO);
+            vo.setMedicalFullCost(BigDecimal.ZERO);
+            vo.setHospitalFullCost(BigDecimal.ZERO);
+            costItemMap.put(dictDataVo.getCode(), vo);
+        }
+        return costItemMap;
+    }
+
+    @Override
+    public Object getDiseaseCostDetailByPage(Integer current, Integer pageSize, String computeDate) {
+        // 获取完整数据列表
+        List<DiseaseCostDetailVO> fullList = getDiseaseCostDetail(computeDate);
+        
+        // 手动分页
+        int total = fullList.size();
+        int startIndex = (current - 1) * pageSize;
+        int endIndex = Math.min(startIndex + pageSize, total);
+        
+        // 获取当前页数据
+        List<DiseaseCostDetailVO> pageList = new ArrayList<>();
+        if (startIndex < total) {
+            pageList = fullList.subList(startIndex, endIndex);
+        }
+        
+        return new PageUtils(pageList, total, pageSize, current);
+    }
+
+    @Override
+    public Object getDiseaseCostCompositionDetailByPage(Integer current, Integer pageSize, String computeDate) {
+        // 获取完整数据列表
+        List<DiseaseCostDetailVO> fullList = getDiseaseCostCompositionDetail(computeDate);
+        
+        // 手动分页
+        int total = fullList.size();
+        int startIndex = (current - 1) * pageSize;
+        int endIndex = Math.min(startIndex + pageSize, total);
+        
+        // 获取当前页数据
+        List<DiseaseCostDetailVO> pageList = new ArrayList<>();
+        if (startIndex < total) {
+            pageList = fullList.subList(startIndex, endIndex);
+        }
+        
+        return new PageUtils(pageList, total, pageSize, current);
+    }
+
+    @Override
+    public Object getDeptDiseaseCostCompositionDetailByPage(Integer current, Integer pageSize, String computeDate) {
+        // 获取完整数据
+        StandardDeptCostCollectResponse fullData = getDeptDiseaseCostCompositionDetail(computeDate);
+        
+        // 对数据进行分页
+        List<StandardReportFormCustomVo> fullList = fullData.getData();
+        int total = fullList.size();
+        int startIndex = (current - 1) * pageSize;
+        int endIndex = Math.min(startIndex + pageSize, total);
+        
+        // 获取当前页数据
+        List<StandardReportFormCustomVo> pageList = new ArrayList<>();
+        if (startIndex < total) {
+            pageList = fullList.subList(startIndex, endIndex);
+        }
+        
+        // 构造分页结果
+        StandardDeptCostCollectResponse pageData = new StandardDeptCostCollectResponse();
+        pageData.setTitle(fullData.getTitle());
+        pageData.setData(pageList);
+        
+        return new PageUtils(pageList, total, pageSize, current);
+    }
+
+
+}

+ 14 - 0
src/main/java/com/kcim/vo/AllocationQueryReportVO.java

@@ -67,4 +67,18 @@ public class AllocationQueryReportVO {
      * 会计科目名称集合
      */
     private List<String> accountingNames;
+
+    /**
+     * 成本类别
+     */
+    private String costType;
+    /**
+     * 会计科目类别
+     */
+    private String accountType;
+
+    /**
+     * 来源分摊层级ID
+     */
+    private Long shareLevelId;
 }

+ 60 - 0
src/main/java/com/kcim/vo/BaseDeptCostReportVO.java

@@ -0,0 +1,60 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+/**
+ * 科室成本明细视图对象
+ */
+@Data
+public class BaseDeptCostReportVO {
+    /**
+     * 科室标准分级
+     */
+    private String standardShareLevel;
+
+    /**
+     * 科室名称
+     */
+    private String responsibilityName;
+
+    /**
+     * 科室代码
+     */
+    private String responsibilityCode;
+
+    /**
+     * 科室排序
+     */
+    private Integer responsibilitySort;
+
+    /**
+     * 成本类型代码
+     */
+    private String costType;
+
+    /**
+     * 标准成本类型
+     */
+    private String standCostType;
+
+    /**
+     * 会计类型代码
+     */
+    private String accountType;
+
+    /**
+     * 标准会计类型
+     */
+    private String standAccountType;
+
+    /**
+     * 标准分级排序
+     */
+    private Integer shareLevelSort;
+
+    /**
+     * 来源类型:1.分摊前,2.分摊后
+     */
+    private Long originType;
+
+}

+ 118 - 0
src/main/java/com/kcim/vo/ClinicalDeptFullCostVO.java

@@ -0,0 +1,118 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 临床服务类科室全成本报表VO类
+ * 用于封装临床科室的各类成本数据,包括医疗成本、财政项目拨款经费、非同级财政拨款项目经费等
+ */
+@Data
+public class ClinicalDeptFullCostVO extends BaseDeptCostReportVO {
+
+    /**
+     * 医疗成本合计 - 直接成本
+     */
+    private BigDecimal medicalCostTotalDirect = BigDecimal.ZERO;
+
+    /**
+     * 医疗成本合计 - 间接成本
+     */
+    private BigDecimal medicalCostTotalIndirect = BigDecimal.ZERO;
+
+    /**
+     * 医疗成本合计 - 全成本
+     */
+    private BigDecimal medicalCostTotal = BigDecimal.ZERO;
+
+    /**
+     * 财政项目拨款经费形成的各项费用 - 直接成本
+     */
+    private BigDecimal financialProjectFundsDirect = BigDecimal.ZERO;
+
+    /**
+     * 财政项目拨款经费形成的各项费用 - 间接成本
+     */
+    private BigDecimal financialProjectFundsIndirect = BigDecimal.ZERO;
+
+    /**
+     * 财政项目拨款经费形成的各项费用 - 全成本
+     */
+    private BigDecimal financialProjectFunds = BigDecimal.ZERO;
+
+    /**
+     * 非同级财政拨款项目经费形成的各项费用 - 直接成本
+     */
+    private BigDecimal nonPeerFinancialFundsDirect = BigDecimal.ZERO;
+
+    /**
+     * 非同级财政拨款项目经费形成的各项费用 - 间接成本
+     */
+    private BigDecimal nonPeerFinancialFundsIndirect = BigDecimal.ZERO;
+
+    /**
+     * 非同级财政拨款项目经费形成的各项费用 - 全成本
+     */
+    private BigDecimal nonPeerFinancialFunds = BigDecimal.ZERO;
+
+    /**
+     * 医疗全成本合计 - 直接成本
+     */
+    private BigDecimal medicalTotalCostDirect = BigDecimal.ZERO;
+
+    /**
+     * 医疗全成本合计 - 间接成本
+     */
+    private BigDecimal medicalTotalCostIndirect = BigDecimal.ZERO;
+
+    /**
+     * 医疗全成本合计 - 全成本
+     */
+    private BigDecimal medicalTotalCost = BigDecimal.ZERO;
+
+    /**
+     * 科教经费形成的各项费用 - 直接成本
+     */
+    private BigDecimal educationalExpensesDirect = BigDecimal.ZERO;
+
+    /**
+     * 科教经费形成的各项费用 - 间接成本
+     */
+    private BigDecimal educationalExpensesIndirect = BigDecimal.ZERO;
+
+    /**
+     * 科教经费形成的各项费用 - 全成本
+     */
+    private BigDecimal educationalExpenses = BigDecimal.ZERO;
+
+    /**
+     * 资产处置费用、上缴上级费用、对附属单位补助费用、其他费用等 - 直接成本
+     */
+    private BigDecimal assetDisposalFeesDirect = BigDecimal.ZERO;
+
+    /**
+     * 资产处置费用、上缴上级费用、对附属单位补助费用、其他费用等 - 间接成本
+     */
+    private BigDecimal assetDisposalFeesIndirect = BigDecimal.ZERO;
+
+    /**
+     * 资产处置费用、上缴上级费用、对附属单位补助费用、其他费用等 - 全成本
+     */
+    private BigDecimal assetDisposalFees = BigDecimal.ZERO;
+
+    /**
+     * 医院全成本合计 - 直接成本
+     */
+    private BigDecimal hospitalTotalCostDirect = BigDecimal.ZERO;
+
+    /**
+     * 医院全成本合计 - 间接成本
+     */
+    private BigDecimal hospitalTotalCostIndirect = BigDecimal.ZERO;
+
+    /**
+     * 医院全成本合计 - 全成本
+     */
+    private BigDecimal hospitalTotalCost = BigDecimal.ZERO;
+}

+ 133 - 0
src/main/java/com/kcim/vo/ClinicalDeptMedicalCostVO.java

@@ -0,0 +1,133 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 科室成本明细视图对象
+ */
+@Data
+public class ClinicalDeptMedicalCostVO extends BaseDeptCostReportVO{
+
+    /**
+     * 人员经费(直接成本)
+     */
+    private BigDecimal personnelDirectCost;
+
+    /**
+     * 人员经费(间接成本)
+     */
+    private BigDecimal personnelIndirectCost;
+
+    /**
+     * 人员经费(全成本)
+     */
+    private BigDecimal personnelTotalCost;
+
+    /**
+     * 卫生材料费(直接成本)
+     */
+    private BigDecimal healthMaterialDirectCost;
+
+    /**
+     * 卫生材料费(间接成本)
+     */
+    private BigDecimal healthMaterialIndirectCost;
+
+    /**
+     * 卫生材料费(全成本)
+     */
+    private BigDecimal healthMaterialTotalCost;
+
+    /**
+     * 药品费(直接成本)
+     */
+    private BigDecimal medicineDirectCost;
+
+    /**
+     * 药品费(间接成本)
+     */
+    private BigDecimal medicineIndirectCost;
+
+    /**
+     * 药品费(全成本)
+     */
+    private BigDecimal medicineTotalCost;
+
+    /**
+     * 固定资产折旧费(直接成本)
+     */
+    private BigDecimal fixedAssetDepreciationDirectCost;
+
+    /**
+     * 固定资产折旧费(间接成本)
+     */
+    private BigDecimal fixedAssetDepreciationIndirectCost;
+
+    /**
+     * 固定资产折旧费(全成本)
+     */
+    private BigDecimal fixedAssetDepreciationTotalCost;
+
+    /**
+     * 无形资产摊销费(直接成本)
+     */
+    private BigDecimal intangibleAssetAmortizationDirectCost;
+
+    /**
+     * 无形资产摊销费(间接成本)
+     */
+    private BigDecimal intangibleAssetAmortizationIndirectCost;
+
+    /**
+     * 无形资产摊销费(全成本)
+     */
+    private BigDecimal intangibleAssetAmortizationTotalCost;
+
+    /**
+     * 提取医疗风险基金(直接成本)
+     */
+    private BigDecimal medicalRiskReserveDirectCost;
+
+    /**
+     * 提取医疗风险基金(间接成本)
+     */
+    private BigDecimal medicalRiskReserveIndirectCost;
+
+    /**
+     * 提取医疗风险基金(全成本)
+     */
+    private BigDecimal medicalRiskReserveTotalCost;
+
+    /**
+     * 其他医疗费用(直接成本)
+     */
+    private BigDecimal otherMedicalExpensesDirectCost;
+
+    /**
+     * 其他医疗费用(间接成本)
+     */
+    private BigDecimal otherMedicalExpensesIndirectCost;
+
+    /**
+     * 其他医疗费用(全成本)
+     */
+    private BigDecimal otherMedicalExpensesTotalCost;
+
+    /**
+     * 合计(直接成本)
+     */
+    private BigDecimal totalDirectCost;
+
+    /**
+     * 合计(间接成本)
+     */
+    private BigDecimal totalIndirectCost;
+
+    /**
+     * 合计(全成本)
+     */
+    private BigDecimal totalCost;
+
+}

+ 26 - 0
src/main/java/com/kcim/vo/CommonResponsibilityReportVo.java

@@ -18,5 +18,31 @@ public class CommonResponsibilityReportVo {
 
     private Integer sort;
 
+    /**
+     * 数据类型:0未知 1数值 2百分比
+     */
+    private Integer dataType;
+
+
+    /**
+     * 数据类型名称
+     */
+    private String dataTypeName;
+
+    /**
+     * 小数位
+     */
+    private Integer decimalPlace;
+
+    /**
+     * 是否有千分号
+     */
+    private Integer permil;
+
+    /**
+     * 是否固定 0不固定 1固定
+     */
+    private Integer isFixed;
+
     private List<CommonResponsibilityReportVo> child;
 }

+ 7 - 0
src/main/java/com/kcim/vo/CostDepartmentProfitVO.java

@@ -1,10 +1,12 @@
 package com.kcim.vo;
 
+import com.kcim.dao.model.CostDepartmentProfitAccount;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @author 李加喜
@@ -72,4 +74,9 @@ public class CostDepartmentProfitVO {
     private Integer type;
 
     private Integer fraction;
+
+    /**
+     * 会计科目金额列表
+     */
+    private List<CostDepartmentProfitAccount> costDepartmentProfitAccounts;
 }

+ 74 - 0
src/main/java/com/kcim/vo/DeptDirectMedicalCostVO.java

@@ -0,0 +1,74 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 科室直接成本表(医疗成本)
+ * @author Administrator
+ */
+@Data
+public class DeptDirectMedicalCostVO extends BaseDeptCostReportVO{
+
+    /**
+     * 人员经费
+     */
+    private BigDecimal personnelExpense;
+
+    /**
+     * 卫生材料费
+     */
+    private BigDecimal healthMaterialFee;
+
+    /**
+     * 药品费
+     */
+    private BigDecimal drugFee;
+
+    /**
+     * 固定资产折旧费
+     */
+    private BigDecimal fixedAssetDepreciation;
+
+    /**
+     * 无形资产摊销费
+     */
+    private BigDecimal intangibleAssetAmortization;
+
+    /**
+     * 提取医疗风险基金
+     */
+    private BigDecimal medicalRiskFundExtraction;
+
+    /**
+     * 其他医疗费用
+     */
+    private BigDecimal otherMedicalExpenses;
+
+    /**
+     * 合计
+     */
+    private BigDecimal total;
+
+    /**
+     * 科室收入
+     */
+    private BigDecimal income;
+
+    /**
+     * 损益=收入-成本
+     */
+    private BigDecimal profit;
+
+    /**
+     * 床日成本
+     */
+    private BigDecimal bedDaysCost;
+
+    /**
+     * 诊次成本
+     */
+    private BigDecimal visitsCost;
+
+}

+ 47 - 0
src/main/java/com/kcim/vo/DeptFullDirectCostVO.java

@@ -0,0 +1,47 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 截图报表数据封装类
+ */
+@Data
+public class DeptFullDirectCostVO extends BaseDeptCostReportVO {
+
+    /**
+     * 医疗成本合计
+     */
+    private BigDecimal medicalCostTotal;
+
+    /**
+     * 财政项目拨款经费形成的各项费用
+     */
+    private BigDecimal financialProjectFunds;
+
+    /**
+     * 非同级财政拨款项目经费形成的各项费用
+     */
+    private BigDecimal nonPeerFinancialFunds;
+
+    /**
+     * 医疗全成本合计
+     */
+    private BigDecimal medicalTotalCost;
+
+    /**
+     * 科教经费形成的各项费用
+     */
+    private BigDecimal educationalExpenses;
+
+    /**
+     * 资产处置费用、上缴上级费用、对附属单位补助费用、其他费用等
+     */
+    private BigDecimal assetDisposalFees;
+
+    /**
+     * 医院全成本合计
+     */
+    private BigDecimal hospitalTotalCost;
+}

+ 197 - 0
src/main/java/com/kcim/vo/DiseaseCostDetailVO.java

@@ -0,0 +1,197 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 医院病种成本明细表 VO 类
+ * <p>
+ * 用于封装病种成本明细数据,包括病种的基础信息和各项费用明细
+ * 该类主要用于医院病种成本构成明细表的展示
+ * </p>
+ * 
+ * @author system
+ * @since 1.0.0
+ */
+@Data
+public class DiseaseCostDetailVO {
+    /**
+     * 病种编码
+     * <p>
+     * 病种的唯一标识编码,用于区分不同的病种类型
+     * </p>
+     */
+    private String itemCode;
+
+    /**
+     * 病种名称
+     * <p>
+     * 病种的中文名称描述
+     * </p>
+     */
+    private String itemName;
+
+    /**
+     * 科室代码
+     */
+    private String departmentCode;
+
+    /**
+     * 科室名称
+     */
+    private String departmentName;
+
+    /**
+     * 成本类型代码
+     */
+    private String costTypeCode;
+
+    /**
+     * 服务量
+     * <p>
+     * 该病种的服务次数或数量统计
+     * </p>
+     */
+    private BigDecimal serviceVolume;
+
+    /**
+     * 每诊次医疗成本金额
+     */
+    private BigDecimal medicalCost;
+
+
+    /**
+     * 每诊次医疗全成本金额
+     */
+    private BigDecimal medicalFullCost;
+
+    /**
+     * 每诊次医院全成本金额
+     */
+    private BigDecimal hospitalFullCost;
+    
+    /**
+     * 总费用
+     * <p>
+     * 该病种产生的所有费用总和
+     * </p>
+     */
+    private BigDecimal totalCost;
+
+    /**
+     * 人员经费
+     * <p>
+     * 用于支付医务人员工资、奖金、津贴等的费用
+     * </p>
+     */
+    private BigDecimal personnelExpense;
+    
+    /**
+     * 人员经费占比
+     * <p>
+     * 人员经费占总费用的比例
+     * </p>
+     */
+    private BigDecimal personnelExpenseRatio;
+
+    /**
+     * 药品费
+     */
+    private BigDecimal drugExpense;
+
+    /**
+     * 药品费占比
+     */
+    private BigDecimal drugExpenseRatio;
+
+    /**
+     * 卫生材料费
+     * <p>
+     * 消耗性医疗用品、一次性医疗器材等材料费用
+     * </p>
+     */
+    private BigDecimal medicalMaterialExpense;
+    
+    /**
+     * 卫生材料费占比
+     * <p>
+     * 卫生材料费占总费用的比例
+     * </p>
+     */
+    private BigDecimal medicalMaterialExpenseRatio;
+
+    /**
+     * 固定资产折旧
+     * <p>
+     * 医疗设备、房屋建筑等固定资产的折旧费用
+     * </p>
+     */
+    private BigDecimal fixedAssetDepreciation;
+    
+    /**
+     * 固定资产折旧占比
+     * <p>
+     * 固定资产折旧占总费用的比例
+     * </p>
+     */
+    private BigDecimal fixedAssetDepreciationRatio;
+
+    /**
+     * 无形资产摊销
+     * <p>
+     * 软件、专利权等无形资产的摊销费用
+     * </p>
+     */
+    private BigDecimal intangibleAssetAmortization;
+    
+    /**
+     * 无形资产摊销占比
+     * <p>
+     * 无形资产摊销占总费用的比例
+     * </p>
+     */
+    private BigDecimal intangibleAssetAmortizationRatio;
+
+    /**
+     * 医疗风险基金
+     * <p>
+     * 为应对医疗风险而提取的专项基金
+     * </p>
+     */
+    private BigDecimal medicalRiskFund;
+    
+    /**
+     * 医疗风险基金占比
+     * <p>
+     * 医疗风险基金占总费用的比例
+     * </p>
+     */
+    private BigDecimal medicalRiskFundRatio;
+
+    /**
+     * 其他医疗费用
+     * <p>
+     * 除上述费用外的其他医疗相关费用
+     * </p>
+     */
+    private BigDecimal otherMedicalExpenses;
+    
+    /**
+     * 其他医疗费用占比
+     * <p>
+     * 其他医疗费用占总费用的比例
+     * </p>
+     */
+    private BigDecimal otherMedicalExpensesRatio;
+
+    /**
+     * 科室对应的责任中心代码
+     */
+    private String responsibilityCode;
+
+    /**
+     * 科室对应的责任中心名称
+     */
+    private String responsibilityName;
+}

+ 27 - 0
src/main/java/com/kcim/vo/DynMultiLevelVo.java

@@ -0,0 +1,27 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2024-09-19 16:29
+ **/
+@Data
+public class DynMultiLevelVo {
+
+    private String itemCode ;
+
+    private String itemName;
+
+    private BigDecimal itemValue ;
+
+    private List<ReportVo> data;
+
+    private List<DynMultiLevelVo> children;
+
+}

+ 42 - 0
src/main/java/com/kcim/vo/HospitalDeptCostAllocationVO.java

@@ -0,0 +1,42 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 医院科室成本分摊汇总表VO
+ */
+@Data
+public class HospitalDeptCostAllocationVO extends BaseDeptCostReportVO {
+
+    /**
+     * 医疗成本
+     */
+    private BigDecimal medicalCost;
+
+    /**
+     * 直接成本
+     */
+    private BigDecimal directCost;
+
+    /**
+     * 小计
+     */
+    private BigDecimal subtotal;
+
+    /**
+     * 分摊行政后勤类科室成本
+     */
+    private BigDecimal allocatedAdminCost;
+
+    /**
+     * 分摊医疗辅助类科室成本
+     */
+    private BigDecimal allocatedSupportCost;
+
+    /**
+     * 分摊医疗技术类科室成本
+     */
+    private BigDecimal allocatedTechCost;
+}

+ 61 - 0
src/main/java/com/kcim/vo/HospitalServiceProjectCostVO.java

@@ -0,0 +1,61 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @ClassName:HospitalServiceProjectCostVO
+ * @Author: jiangyongmin
+ * @Date: 2025-08-22 16:39
+ * @Description: TODO
+ */
+@Data
+public class HospitalServiceProjectCostVO {
+    /**
+     * 项目代码
+     */
+    private String itemCode;
+
+    /**
+     * 项目名称
+     */
+    private String itemName;
+
+    /**
+     * 成本项目类型代码
+     */
+    private String costTypeCode;
+
+    /**
+     * 成本项目类型名称
+     */
+    private String costTypeName;
+
+    /**
+     * 服务量
+     */
+    private BigDecimal serviceVolume;
+
+    /**
+     * 每诊次医疗成本金额
+     */
+    private BigDecimal medicalCost;
+
+
+    /**
+     * 每诊次医疗全成本金额
+     */
+    private BigDecimal medicalFullCost;
+
+    /**
+     * 每诊次医院全成本金额
+     */
+    private BigDecimal hospitalFullCost;
+
+    /**
+     *  子项
+     */
+    private List<HospitalServiceProjectCostVO> children;
+}

+ 54 - 0
src/main/java/com/kcim/vo/HospitalVisitCostCompositionVO.java

@@ -0,0 +1,54 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 医院科室成本分摊汇总表VO
+ * @author Administrator
+ */
+@Data
+public class HospitalVisitCostCompositionVO extends BaseDeptCostReportVO{
+
+    /**
+     * 成本项目代码
+     */
+    private String costCode;
+
+    /**
+     * 成本项目名称
+     */
+    private String costItem;
+
+    /**
+     * 成本项目类型
+     */
+    private String costType;
+
+    /**
+     * 每诊次医疗成本金额
+     */
+    private BigDecimal medicalCost;
+
+    /**
+     * 每诊次医疗全成本金额
+     */
+    private BigDecimal medicalFullCost;
+
+    /**
+     * 每诊次医院全成本金额
+     */
+    private BigDecimal hospitalFullCost;
+
+    /**
+     * 服务量
+     */
+    private BigDecimal serviceCount;
+
+    /**
+     * 子级成本项目
+     */
+    private List<HospitalVisitCostCompositionVO> children;
+}

+ 110 - 0
src/main/java/com/kcim/vo/ProfitCalculationDataVo.java

@@ -0,0 +1,110 @@
+package com.kcim.vo;
+
+import com.kcim.dao.model.*;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 科室损益计算数据封装类
+ * 用于封装计算科室损益所需的所有数据
+ */
+@Data
+public class ProfitCalculationDataVo {
+    /**
+     * 计算日期
+     */
+    private String computeDate;
+
+    /**
+     * 当前用户ID
+     */
+    private Long currentUserID;
+
+    /**
+     * 年份
+     */
+    private Integer year;
+    
+    /**
+     * 月份
+     */
+    private Integer month;
+    
+    /**
+     * 医院ID
+     */
+    private Long hospId;
+    
+    /**
+     * 报表类型
+     */
+    private String reportType;
+    
+    /**
+     * 报表配置列表
+     */
+    private List<ReportForm> reportFormList;
+    
+    /**
+     * 报表关系列表
+     */
+    private List<ReportRelation> reportRelationList;
+    
+    /**
+     * 报表关系映射(按报表ID分组)
+     */
+    private Map<Long, List<ReportRelation>> reportRelationMap;
+    
+    /**
+     * 分摊层级列表
+     */
+    private List<CostShareLevel> costShareLevelList;
+    
+    /**
+     * 责任中心列表
+     */
+    private List<Responsibility> responsibilityList;
+    
+    /**
+     * 收入归集数据列表
+     */
+    private List<IncomeCollection> incomeList;
+    
+    /**
+     * 分摊后查询数据列表
+     */
+    private List<AllocationQuery> allocationQueryList;
+    
+    /**
+     * 分摊后查询数据VO列表
+     */
+    private List<AllocationQueryReportVO> allocationQueryReportVOList;
+    
+    /**
+     * 分摊数据列表
+     */
+    private List<Allocation> allocationList;
+
+    /**
+     *  科室收入归集数据分组
+     */
+    private Map<String, Map<String, List<IncomeCollection>>> respIncomeGroup;
+
+
+    /**
+     * 责任中心+会计科目分组
+     */
+    Map<String, Map<String, List<AllocationQueryReportVO>>> respAccountCostGroup;
+
+    /**
+     * 责任中心+来源责任中心分组
+     */
+    Map<String, Map<String, List<AllocationQueryReportVO>>> respSourceCostGroup;
+
+    /**
+     * 责任中心+分摊层级分组
+     */
+    Map<String, Map<Long, List<AllocationQueryReportVO>>> respShareLevelCostGroup;
+}

+ 5 - 0
src/main/java/com/kcim/vo/ReportFormCustomVo.java

@@ -3,6 +3,7 @@ package com.kcim.vo;
 import com.kcim.dao.model.ReportForm;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -14,6 +15,10 @@ import java.util.List;
 @Data
 public class ReportFormCustomVo extends ReportForm {
 
+    private String reportCode ;
+
+    private BigDecimal totalValue ;
+
     private List<ReportVo> data;
 
     private List<ReportFormCustomVo> children;

+ 47 - 0
src/main/java/com/kcim/vo/StandCostDictMapVO.java

@@ -0,0 +1,47 @@
+package com.kcim.vo;
+
+import com.kcim.dao.model.Accounting;
+import com.kcim.dao.model.Responsibility;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2023-09-20 10:16
+ **/
+@Data
+public class StandCostDictMapVO {
+
+    /**
+     * 责任中心字典
+     */
+    private List<Responsibility> responsibilityDict;
+
+    /**
+     * 会计科目字典
+     */
+    private List<Accounting> costAccountingDict ;
+
+    /**
+     * 会计科目类型字典
+     */
+    private List<DictDataVo> accountingTypeDict;
+    /**
+     * 成本类型字典
+     */
+    private List<DictDataVo> costTypeDict;
+    /**
+     * 标准分摊级别字典
+     */
+    private List<DictDataVo> standardShareLevelDict;
+
+    private Map<String, Responsibility> responsibilityMap;
+    private Map<String, Accounting> accountingMap;
+    private Map<String, DictDataVo> accountingTypeMap;
+    private Map<String, DictDataVo> costTypeMap;
+    private Map<String, DictDataVo> standardShareLevelMap;
+}

+ 27 - 0
src/main/java/com/kcim/vo/StandardReportFormCustomVo.java

@@ -0,0 +1,27 @@
+package com.kcim.vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2024-09-19 16:29
+ **/
+@Data
+public class StandardReportFormCustomVo{
+
+    private String reportCode ;
+
+    private String reportName ;
+
+    private BigDecimal totalValue ;
+
+    private List<ReportVo> data;
+
+    private List<StandardReportFormCustomVo> children;
+
+}

+ 5 - 4
src/main/java/com/kcim/web/CostDataController.java

@@ -2,7 +2,6 @@ package com.kcim.web;
 
 import com.kcim.common.constants.NumberConstant;
 import com.kcim.common.util.Result;
-import com.kcim.dao.repository.ImportPatientInfoRepository;
 import com.kcim.service.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -127,8 +126,10 @@ public class CostDataController {
 
     @ApiOperation("月度数据采集-患者收费项目-患者信息")
     @GetMapping("getPatientItemPatientInfo")
-    public Result getPatientItemPatientInfo( @RequestParam String computeDate,
-                                            @RequestParam(required = false) String filter) {
-        return Result.ok(patientItemImportService.getPatientItemPatientInfo(filter,computeDate));
+    public Result getPatientItemPatientInfo( @RequestParam(defaultValue = "1", name = "current", required = false) Integer current,
+                                             @RequestParam(defaultValue = "10", name = "pageSize", required = false) Integer pageSize,
+                                             @RequestParam String computeDate,
+                                             @RequestParam(required = false) String filter) {
+        return Result.ok(patientItemImportService.getPatientItemPatientInfo(current,pageSize,filter,computeDate));
     }
 }

+ 157 - 0
src/main/java/com/kcim/web/StandardReportController.java

@@ -0,0 +1,157 @@
+package com.kcim.web;
+
+import com.kcim.common.util.Result;
+import com.kcim.service.StandardReportService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 相关导入导出操作
+ */
+@Slf4j
+@Api(tags = "标准成本报表")
+@RestController
+@RequestMapping("standardReport")
+@AllArgsConstructor
+public class StandardReportController extends AbstractController {
+
+    private StandardReportService standardReportService;
+
+    @ApiOperation("医院科室直接成本表(医疗成本)")
+    @GetMapping("/getDeptDirectMedicalCost")
+    public Result getDeptDirectMedicalCost(@RequestParam String computeDate){
+        return Result.ok(standardReportService.getDeptDirectMedicalCost(computeDate));
+    }
+    @ApiOperation("医院科室直接成本表(全成本)")
+    @GetMapping("/getDeptFullDirectCost")
+    public Result getDeptFullDirectCost(@RequestParam String computeDate){
+        return Result.ok(standardReportService.getDeptFullDirectCost(computeDate));
+    }
+
+    @ApiOperation("临床服务类科室全成本(医疗成本)")
+    @GetMapping("/getClinicalDeptMedicalCost")
+    public Result getClinicalDeptMedicalCost(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getClinicalDeptMedicalCost(computeDate));
+    }
+
+    @ApiOperation("临床服务类科室全成本(全成本)")
+    @GetMapping("/getClinicalDeptFullCost")
+    public Result getClinicalDeptFullCost(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getClinicalDeptFullCost(computeDate));
+    }
+
+    @ApiOperation("临床服务类科室全成本构成分析表")
+    @GetMapping("/getClinicalDeptFullCostAnalysis")
+    public Result getClinicalDeptFullCostAnalysis(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getClinicalDeptFullCostAnalysis(computeDate));
+    }
+
+    @ApiOperation("医院科室成本分摊汇总表")
+    @GetMapping("/getHospitalDeptCostAllocation")
+    public Result getHospitalDeptCostAllocation(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalDeptCostAllocation(computeDate));
+    }
+
+    @ApiOperation("医院诊次成本构成表")
+    @GetMapping("/getHospitalVisitCostComposition")
+    public Result getHospitalVisitCostComposition(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalVisitCostComposition(computeDate));
+    }
+
+    @ApiOperation("医院科室诊次成本表")
+    @GetMapping("/getHospitalDeptVisitCost")
+    public Result getHospitalDeptVisitCost(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalDeptVisitCost(computeDate));
+    }
+
+
+    @ApiOperation("医院床日成本构成表")
+    @GetMapping("/getHospitalBedDayCostComposition")
+    public Result getHospitalBedDayCostComposition(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalBedDayCostComposition(computeDate));
+    }
+
+    @ApiOperation("医院科室床日成本表")
+    @GetMapping("/getHospitalDeptBedDayCost")
+    public Result getHospitalDeptBedDayCost(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalDeptBedDayCost(computeDate));
+    }
+
+    @ApiOperation("医院医疗服务项目成本汇总表")
+    @GetMapping("/getHospitalServiceProjectCost")
+    public Result getHospitalServiceProjectCost(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getHospitalServiceProjectCost(computeDate));
+    }
+
+    @ApiOperation("医院医疗服务项目成本明细表")
+    @GetMapping("/getMedicalServiceCostDetail")
+    public Result getMedicalServiceCostDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getMedicalServiceCostDetail(computeDate));
+    }
+
+    @ApiOperation("医院病种成本明细表")
+    @GetMapping("/getDiseaseCostDetail")
+    public Result getDiseaseCostDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDiseaseCostDetail(computeDate));
+    }
+
+    @ApiOperation("医院病种成本明细表(分页)")
+    @GetMapping("/getDiseaseCostDetailByPage")
+    public Result getDiseaseCostDetailByPage(@RequestParam(defaultValue = "1") Integer current,
+                                             @RequestParam(defaultValue = "10") Integer pageSize,
+                                             @RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDiseaseCostDetailByPage(current, pageSize, computeDate));
+    }
+
+    @ApiOperation("医院病种成本构成明细表")
+    @GetMapping("/getDiseaseCostCompositionDetail")
+    public Result getDiseaseCostCompositionDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDiseaseCostCompositionDetail(computeDate));
+    }
+
+    @ApiOperation("医院病种成本构成明细表(分页)")
+    @GetMapping("/getDiseaseCostCompositionDetailByPage")
+    public Result getDiseaseCostCompositionDetailByPage(@RequestParam(defaultValue = "1") Integer current,
+                                                        @RequestParam(defaultValue = "10") Integer pageSize,
+                                                        @RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDiseaseCostCompositionDetailByPage(current, pageSize, computeDate));
+    }
+
+    @ApiOperation("医院服务单元病种成本构成明细表")
+    @GetMapping("/getDeptDiseaseCostCompositionDetail")
+    public Result getDeptDiseaseCostCompositionDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDeptDiseaseCostCompositionDetail(computeDate));
+    }
+
+    @ApiOperation("医院服务单元病种成本构成明细表(分页)")
+    @GetMapping("/getDeptDiseaseCostCompositionDetailByPage")
+    public Result getDeptDiseaseCostCompositionDetailByPage(@RequestParam(defaultValue = "1") Integer current,
+                                                            @RequestParam(defaultValue = "10") Integer pageSize,
+                                                            @RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDeptDiseaseCostCompositionDetailByPage(current, pageSize, computeDate));
+    }
+
+    @ApiOperation("医院DRG成本明细表")
+    @GetMapping("/getDrgCostDetail")
+    public Result getDrgCostDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDrgCostDetail(computeDate));
+    }
+
+    @ApiOperation("医院DRG成本构成明细表")
+    @GetMapping("/getDrgCostCompositionDetail")
+    public Result getDrgCostCompositionDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDrgCostCompositionDetail(computeDate));
+    }
+
+    @ApiOperation("医院服务单元DRG成本构成明细表")
+    @GetMapping("/getDeptDrgCostCompositionDetail")
+    public Result getDeptDrgCostCompositionDetail(@RequestParam String computeDate) {
+        return Result.ok(standardReportService.getDeptDrgCostCompositionDetail(computeDate));
+    }
+}

+ 21 - 0
src/main/java/com/kcim/web/reponse/ClinicalDeptFullCostAnalysisResponse.java

@@ -0,0 +1,21 @@
+package com.kcim.web.reponse;
+
+import com.kcim.vo.CommonResponsibilityReportVo;
+import com.kcim.vo.ReportFormCustomVo;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2024-09-19 16:40
+ **/
+@Data
+public class ClinicalDeptFullCostAnalysisResponse {
+
+    private List<CommonResponsibilityReportVo> title;
+
+    private List<ReportFormCustomVo> data;
+}

+ 21 - 0
src/main/java/com/kcim/web/reponse/StandardDeptCostCollectResponse.java

@@ -0,0 +1,21 @@
+package com.kcim.web.reponse;
+
+import com.kcim.vo.CommonResponsibilityReportVo;
+import com.kcim.vo.StandardReportFormCustomVo;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @program: CostAccount
+ * @description:
+ * @author: Wang.YS
+ * @create: 2024-09-19 16:40
+ **/
+@Data
+public class StandardDeptCostCollectResponse {
+
+    private List<CommonResponsibilityReportVo> title;
+
+    private List<StandardReportFormCustomVo> data;
+}

+ 10 - 10
src/main/resources/application-prod.yml

@@ -1,12 +1,12 @@
 server:
-  port: 8082
+  port: 8084
   servlet:
     context-path: /costAccount
 spring:
   datasource:
     type: com.zaxxer.hikari.HikariDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.96.149.190:3306/cost_account?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
+    url: jdbc:mysql://172.20.218.234:3306/cost_account_youyi?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
     username: root
     password: xywl2021!
     hikari:
@@ -24,10 +24,10 @@ spring:
       discovery:
         service: ${spring.application.name}
         server-addr: 120.27.235.181:8848
-#        group: prod
-#        namespace: 1814ad0c-58c5-4de8-a786-6f12aee361cd
-        namespace: 060cc0fe-193f-4a94-bbca-6d48a4f95ac2
-        group: dev
+        group: prod
+        namespace: 1814ad0c-58c5-4de8-a786-6f12aee361cd
+        #namespace: 060cc0fe-193f-4a94-bbca-6d48a4f95ac2
+        #group: dev
         # sentinel:
         # enabled: true
         # transport:
@@ -40,7 +40,7 @@ spring:
   #redis
   redis:
     port: 6379
-    host: 47.96.149.190
+    host: 172.20.218.234
     password: xywl2021!
     jedis:
       pool:
@@ -81,7 +81,7 @@ logging:
 ####本地文件相关配置
 
 sa-token:
-  jwt-secret-key: kcim-oauth
+  jwt-secret-key: imedstic
   #  kcim-oauth
   ## 前后端分离不设置会有奇怪的问题
   ## 默认采用的获取token 是从请求头默认名称为Sa-token的地方获取,如果没有会从Cookie中获取,会造成奇怪的问题!!
@@ -91,13 +91,13 @@ sa-token:
   ##token 有效期 默认30天,到期强制登录
   timeout: 2592000
   ## 30分钟无操作就失效 不适用
-  activity-timeout: 1800
+  #activity-timeout: 1800
   # 配置 Sa-Token 单独使用的 Redis 连接
   alone-redis:
     # Redis数据库索引(默认为0) 先固定2,后续有钱开另外的单独的db
     database: 1
     # Redis服务器地址
-    host: 47.96.149.190
+    host: 172.20.218.234
     # Redis服务器连接端口
     port: 6379
     # Redis服务器连接密码(默认为空)

+ 50 - 1
src/main/resources/mapper/AllocationQueryMapper.xml

@@ -86,5 +86,54 @@
           and delete_time = 0
     </select>
 
-
+    <select id="getAcountAccounts" resultType="com.kcim.dao.model.AllocationQuery">
+        SELECT
+            accounting_code,
+            IFNULL( sum( amount ), 0 ) AS amount
+        FROM
+            cost_allocation_query a
+            INNER JOIN cost_responsibility b on a.target_responsibility_code=b.responsibility_code AND b.delete_time=0 AND b.hosp_id= #{hospId}
+        WHERE
+            a.date_year = #{dateYear}
+          AND a.date_month = #{month}
+          AND a.hosp_id = #{hospId}
+          AND a.delete_time = 0
+          AND b.standard_share_level=4
+        GROUP BY
+            a.accounting_code
+    </select>
+    <select id="getRespAcountAccounts" resultType="com.kcim.dao.model.AllocationQuery">
+        SELECT
+            target_responsibility_code as responsibility_code,
+            accounting_code,
+            IFNULL( sum( amount ), 0 ) AS amount
+        FROM
+            cost_allocation_query
+        WHERE
+            date_year = #{dateYear}
+          AND date_month = #{month}
+          AND hosp_id = #{hospId}
+          AND delete_time = 0
+        GROUP BY
+            responsibility_code,
+            accounting_code
+    </select>
+    <select id="getRespOriginAcountAccounts" resultType="com.kcim.dao.model.AllocationQuery">
+        SELECT
+            responsibility_code,
+            origin_type,
+            accounting_code,
+            IFNULL( sum( amount ), 0 ) AS amount
+        FROM
+            cost_allocation_query
+        WHERE
+            date_year = #{dateYear}
+          AND date_month = #{month}
+          AND hosp_id = #{hospId}
+          AND delete_time = 0
+        GROUP BY
+            responsibility_code,
+            origin_type,
+            accounting_code
+    </select>
 </mapper>

+ 0 - 3
src/main/resources/mapper/ComputeDrugCostMapper.xml

@@ -58,8 +58,5 @@
            and (a.code like concat('%',#{filter,jdbcType=VARCHAR},'%') or a.name like concat('%',#{filter,jdbcType=VARCHAR},'%'))
         </if>
         GROUP BY visit_no,code,item_type_code
-
     </select>
-
-
 </mapper>

+ 2 - 4
src/main/resources/mapper/ComputeItemCostMapper.xml

@@ -43,20 +43,18 @@
         sum((IF(b.type = '9', b.compute_result, 0.00))) as spaceCost
         FROM
         compute_item_cost a
-        LEFT JOIN compute_item_cost_detail b ON a.id = b.item_cost_id
+        LEFT JOIN compute_item_cost_detail b ON a.id = b.item_cost_id AND b.del_flag = 0
         WHERE
         a.hosp_id = #{hospId}
-        AND b.hosp_id=#{hospId}
         AND a.del_flag = 0
         AND a.compute_date = #{computeDate}
-        AND b.del_flag = 0
         <if test="itemType != null and itemType != ''">
            and item_type_code = #{itemType,jdbcType=VARCHAR}
         </if>
         <if test="itemName != null and itemType != ''">
             and name like concat('%',#{itemName,jdbcType=VARCHAR},'%')
         </if>
-        GROUP BY visit_no,code,item_type_code
+        GROUP BY a.code
     </select>
     <select id="getListGroupByVisitNo" resultType="com.kcim.dao.model.dto.ComputeItemGroupByVisitNoDto">
         SELECT

+ 180 - 0
src/main/resources/mapper/ComputePatientCostAccountMapper.xml

@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.kcim.dao.mapper.ComputePatientCostAccountMapper">
+
+	<!-- 可根据自己的需求,是否要使用 -->
+    <resultMap type="com.kcim.dao.model.ComputePatientCostAccount" id="computePatientCostAccountMap">
+        <result property="id" column="id"/>
+        <result property="hospId" column="hosp_id"/>
+        <result property="computeDate" column="compute_date"/>
+        <result property="patientCostId" column="patient_cost_id"/>
+        <result property="costType" column="cost_type"/>
+        <result property="accountType" column="account_type"/>
+        <result property="computeResult" column="compute_result"/>
+        <result property="standComputeResult" column="stand_compute_result"/>
+        <result property="createUser" column="create_user"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateUser" column="update_user"/>
+        <result property="updateTime" column="update_time"/>
+        <result property="deleteUser" column="delete_user"/>
+        <result property="deleteTime" column="delete_time"/>
+        <result property="delFlag" column="del_flag"/>
+    </resultMap>
+
+    <select id="getDiseaseCostDetailList" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            SUBSTR(c.`primary_diag_code`,1,3) as itemCode,
+            c.`primary_diag_name` as itemName ,
+            b.cost_type as costTypeCode,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`primary_diag_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+--             c.`primary_diag_code`,
+            SUBSTR(c.`primary_diag_code`,1,3),
+            b.cost_type
+    </select>
+    <select id="getDiseaseCostCompositionDetail" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            SUBSTR(c.`primary_diag_code`,1,3) as itemCode,
+            c.`primary_diag_name` as itemName ,
+            b.account_type as costTypeCode,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`primary_diag_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+--             c.`primary_diag_code`,
+            SUBSTR(c.`primary_diag_code`,1,3),
+            b.account_type
+    </select>
+    <select id="getDeptDiseaseCostCompositionDetail" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            SUBSTR(c.`primary_diag_code`,1,3) as itemCode,
+            c.`primary_diag_name` as itemName ,
+            a.department_code as departmentCode,
+            a.department_name as departmentName,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`primary_diag_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+--             c.`primary_diag_code`,
+            SUBSTR(c.`primary_diag_code`,1,3),
+            a.department_code
+    </select>
+    <select id="getDrgCostDetailList" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            c.`group_code` as itemCode,
+            c.`group_name` as itemName ,
+            b.cost_type as costTypeCode,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`group_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+            c.`group_code`,
+            b.cost_type
+    </select>
+    <select id="getDrgCostCompositionDetail" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            c.`group_code` as itemCode,
+            c.`group_name` as itemName ,
+            b.account_type as costTypeCode,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`group_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+            c.`group_code`,
+            b.account_type
+    </select>
+    <select id="getDeptDrgCostCompositionDetail" resultType="com.kcim.vo.DiseaseCostDetailVO">
+        SELECT
+            c.`group_code` as itemCode,
+            c.`group_name` as itemName ,
+            a.department_code as departmentCode,
+            a.department_name as departmentName,
+            COUNT(1) AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_patient_cost a
+                INNER JOIN compute_patient_cost_account b ON a.id = b.patient_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+                INNER JOIN import_patient_info c on a.visit_no=c.visit_no
+                AND c.hosp_id = #{hospId,jdbcType=BIGINT}
+                AND c.del_flag = 0
+                AND c.compute_date = #{computeDate,jdbcType=VARCHAR}
+                AND IFNULL(c.`group_code`,'')!=''
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+            c.`group_code`,
+            a.department_code
+    </select>
+</mapper>

+ 21 - 2
src/main/resources/mapper/SqlMapper.xml → src/main/resources/mapper/ComputeProjectCostAccountMapper.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 
-<mapper namespace="com.kcim.dao.mapper.SqlMapper">
+<mapper namespace="com.kcim.dao.mapper.ComputeProjectCostAccountMapper">
 
 	<!-- 可根据自己的需求,是否要使用 -->
     <resultMap type="com.kcim.dao.model.Sql" id="sqlMap">
@@ -23,5 +23,24 @@
         <result property="delFlag" column="del_flag"/>
     </resultMap>
 
-
+    <select id="getMedicalServiceCostDetailList" resultType="com.kcim.vo.HospitalServiceProjectCostVO">
+        SELECT
+            a.`code` as itemCode,
+            a.`name` as itemName ,
+            b.cost_type as costTypeCode,
+            a.quantity  AS serviceVolume,
+            SUM( b.compute_result ) AS hospitalFullCost
+        FROM
+            compute_project_cost a
+                INNER JOIN compute_project_cost_account b ON a.id = b.project_cost_id
+                AND b.del_flag = 0
+                AND b.hosp_id = #{hospId,jdbcType=BIGINT}
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId,jdbcType=BIGINT}
+          AND a.compute_date = #{computeDate,jdbcType=VARCHAR}
+        GROUP BY
+            a.`code`,
+            b.cost_type
+    </select>
 </mapper>

+ 78 - 0
src/main/resources/mapper/CostIncomeGroupMapper.xml

@@ -139,6 +139,84 @@
         and delete_time != 0
         and file_id = #{id}
     </select>
+    <select id="getOrderDeptProductList" resultType="com.kcim.dao.model.CostIncomeGroup">
+        SELECT
+            product_code,
+            product_name,
+            account_code,
+            account_name,
+            open_department_code,
+            open_department_name,
+            start_department_code,
+            start_department_name,
+            SUM( amount ) AS amount
+        FROM
+            cost_income_group
+        WHERE
+            hosp_id = #{hospId}
+          AND delete_time = 0
+          AND date_year = #{year}
+          AND date_month = #{month}
+          AND open_department_code = #{departmentCode}
+        <if test="filter != null and filter != ''">
+            and (product_code like concat('%',#{filter,jdbcType=VARCHAR},'%') or `product_name` like
+            concat('%',#{filter,jdbcType=VARCHAR},'%') )
+        </if>
+        GROUP BY
+            product_code,
+            start_department_code
+    </select>
+
+    <select id="getExecDeptProductList" resultType="com.kcim.dao.model.CostIncomeGroup">
+        SELECT
+        product_code,
+        product_name,
+        account_code,
+        account_name,
+        open_department_code,
+        open_department_name,
+        start_department_code,
+        start_department_name,
+        SUM( amount ) AS amount
+        FROM
+        cost_income_group
+        WHERE
+        hosp_id = #{hospId}
+        AND delete_time = 0
+        AND date_year = #{year}
+        AND date_month = #{month}
+        AND start_department_code = #{departmentCode}
+        <if test="filter != null and filter != ''">
+            and (product_code like concat('%',#{filter,jdbcType=VARCHAR},'%') or `product_name` like
+            concat('%',#{filter,jdbcType=VARCHAR},'%') )
+        </if>
+        GROUP BY
+        product_code,
+        open_department_code
+    </select>
+    <select id="getTotalAmount" resultType="java.math.BigDecimal">
+        SELECT
+        SUM( amount ) AS amount
+        FROM
+        cost_income_group
+        WHERE
+        hosp_id = #{hospId}
+        AND delete_time = 0
+        AND date_year = #{year}
+        AND date_month = #{month}
+    </select>
+    <select id="getDeptTotalAmount" resultType="java.math.BigDecimal">
+        SELECT
+        SUM( amount ) AS amount
+        FROM
+        cost_income_group
+        WHERE
+        hosp_id = #{hospId}
+        AND delete_time = 0
+        AND date_year = #{year}
+        AND date_month = #{month}
+        AND open_department_code = #{departmentCode}
+    </select>
 
 
 </mapper>

+ 8 - 0
src/main/resources/mapper/GenericBatchMapper.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kcim.dao.mapper.GenericBatchMapper">
+    <!-- 通用批量插入语句,通过Provider动态生成SQL -->
+    <insert id="insertBatch" useGeneratedKeys="true" keyProperty="id">
+        ${@com.kcim.dao.mapper.BatchInsertProvider@insertBatch(list)}
+    </insert>
+</mapper>

+ 11 - 0
src/main/resources/mapper/IncomeCollectionMapper.xml

@@ -136,5 +136,16 @@
         </foreach>
     </select>
 
+    <select id="getResponsibilitiesAccounts" resultType="com.kcim.dao.model.IncomeCollection">
+        select responsibility_code,IFNULL(sum(amount), 0) as amount
+        from cost_income_collection
+        where delete_time = 0
+            and hosp_id = #{hospId}
+            and `year` =#{year}
+            and `month` = #{month}
+        GROUP BY
+        responsibility_code
+    </select>
+
 
 </mapper>

+ 24 - 0
src/main/resources/mapper/ItemMapper.xml

@@ -23,6 +23,30 @@
         <result property="deleteTime" column="delete_time"/>
         <result property="delFlag" column="del_flag"/>
     </resultMap>
+    <select id="getRespItemList" resultType="com.kcim.dao.model.Item" parameterType="com.kcim.dao.model.Item">
+        SELECT
+            a.`code`,
+            a.`name`,
+            a.`type`,
+            a.`item_type`,
+            a.`price`,
+            a.`national_code`,
+            a.`kc_code`,
+            a.`stand_item_code`,
+            a.`stand_item_name`,
+            a.`department_code`,
+            a.`department_name`,
+            b.responsibility_code
+        FROM
+            com_item a
+                INNER JOIN cost_responsibility_department b ON a.department_code = b.department_code
+        WHERE
+            a.del_flag = 0
+          AND a.hosp_id = #{hospId}
+        GROUP BY
+            a.`code`,
+            a.department_code
+    </select>
 
 
 </mapper>

+ 1 - 0
src/main/resources/mapper/ResponsibilityDepartmentMapper.xml

@@ -22,6 +22,7 @@
     <select id="getResponsibility" resultType="com.kcim.vo.ResponsibilityDepartIdVO">
         SELECT
             b.department_id,
+            b.department_code,
             b.responsibility_id,
             a.responsibility_code,
             a.responsibility_name,