浏览代码

添加医院临床服务类科室全成本构成分析表相关代码

JammeyJiang 3 月之前
父节点
当前提交
b24f3bbe9c

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

@@ -61,4 +61,9 @@ public interface ParameterConstant {
      * 需要用脚本计算的科室损益及全院损益报表类型
      */
     Long SQL_CALC_REPORT_TYPE =1943243153054240768L;
+
+    /**
+     * 诊次床日分摊参数代码
+     */
+    Long VISITS_BED_DAYS_PARAM_CODE =1955568425220837376L;
 }

+ 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);
+
 }

+ 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);
 }
 

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

@@ -4,6 +4,7 @@ import com.kcim.vo.ClinicalDeptFullCostVO;
 import com.kcim.vo.DeptFullDirectCostVO;
 import com.kcim.vo.ClinicalDeptMedicalCostVO;
 import com.kcim.vo.DeptDirectMedicalCostVO;
+import com.kcim.web.reponse.ComputeProfitCollectResponse;
 
 import java.util.List;
 
@@ -34,4 +35,11 @@ public interface StandardReportService {
      * @return 报表数据
      */
     List<ClinicalDeptFullCostVO> getClinicalDeptFullCost(String computeDate);
+
+    /**
+     * 获取医院临床服务类科室全成本构成分析表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    ComputeProfitCollectResponse getClinicalDeptFullCostAnalysis(String computeDate);
 }

+ 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);
+    }
 }

+ 300 - 3
src/main/java/com/kcim/service/impl/StandardReportServiceImpl.java

@@ -4,24 +4,30 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 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.UserContext;
-import com.kcim.dao.model.Accounting;
-import com.kcim.dao.model.AllocationQuery;
-import com.kcim.dao.model.Responsibility;
+import com.kcim.dao.model.*;
 import com.kcim.dao.repository.AccountingRepository;
 import com.kcim.dao.repository.ResponsibilityRepository;
+import com.kcim.dao.repository.ShareParamValueRepository;
 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 lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
+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;
 
@@ -35,6 +41,9 @@ import java.util.stream.Collectors;
 @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;
@@ -42,6 +51,10 @@ public class StandardReportServiceImpl implements StandardReportService {
     CenterService centerService;
 
     AccountingRepository accountingRepository;
+
+    IncomeCollectionService incomeCollectionService;
+
+    ShareParamValueRepository shareParamValueRepository;
     
     /**
      * 科室直接成本表(医疗成本)
@@ -256,6 +269,265 @@ public class StandardReportServiceImpl implements StandardReportService {
         return reportList;
     }
 
+    /**
+     * 获取医院临床服务类科室全成本构成分析表数据
+     * @param computeDate 核算年月
+     * @return 报表数据
+     */
+    @Override
+    public ComputeProfitCollectResponse getClinicalDeptFullCostAnalysis(String computeDate) {
+        DateTime parse = DateUtil.parse(computeDate);
+        int year = DateUtil.year(parse);
+        int month = DateUtil.month(parse) + 1;
+
+        // 获取科室成本
+        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);
+            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 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());
+            //获取诊次参数
+            Optional<ShareParamValue> firstVisitParam = shareParamValues.stream().filter(shareParamValue -> shareParamValue.getShareParamCode().equals(visitsBedDaysParamCode[0])).findFirst();
+            if(firstVisitParam.isPresent()){
+                // 计算诊次成本=总成本/诊次数
+                item.setVisitsCost(getPercent(item.getTotal(),firstVisitParam.get().getValueNum()));
+            }else{
+                item.setVisitsCost(BigDecimal.ZERO);
+            }
+            Optional<ShareParamValue> firstBedDayParam = shareParamValues.stream().filter(shareParamValue -> shareParamValue.getShareParamCode().equals(visitsBedDaysParamCode[1])).findFirst();
+            if(firstBedDayParam.isPresent()){
+                // 床日成本=总成本/床日数
+                item.setBedDaysCost(getPercent(item.getTotal(),firstBedDayParam.get().getValueNum()));
+            }else{
+                item.setBedDaysCost(BigDecimal.ZERO);
+            }
+        }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);
+        commonResponsibility.getChild().add( amount);
+        CommonResponsibilityReportVo percent=new CommonResponsibilityReportVo();
+        percent.setResponsibilityCode(getResponsibilityPercentCode(commonResponsibility.getResponsibilityCode()));
+        percent.setResponsibilityName("占比");
+        percent.setSort(NumberConstant.ONE);
+        commonResponsibility.getChild().add( percent);
+    }
+
     /**
      * 添加临床服务类科室全成本明细
      * @param reportMap
@@ -751,6 +1023,31 @@ public class StandardReportServiceImpl implements StandardReportService {
         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;
+    }
 
 }

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

@@ -51,4 +51,24 @@ public class DeptDirectMedicalCostVO extends BaseDeptCostReportVO{
      */
     private BigDecimal total;
 
+    /**
+     * 科室收入
+     */
+    private BigDecimal income;
+
+    /**
+     * 损益=收入-成本
+     */
+    private BigDecimal profit;
+
+    /**
+     * 床日成本
+     */
+    private BigDecimal bedDaysCost;
+
+    /**
+     * 诊次成本
+     */
+    private BigDecimal visitsCost;
+
 }

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

@@ -45,4 +45,10 @@ public class StandardReportController extends AbstractController {
     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));
+    }
 }

+ 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;
+}

+ 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>