|
@@ -27,6 +27,7 @@ import com.kcim.dao.mapper.HospProfitAndLossMapper;
|
|
|
import com.kcim.dao.model.*;
|
|
|
import com.kcim.service.*;
|
|
|
import com.kcim.vo.*;
|
|
|
+import com.kcim.web.reponse.BatchCostProfitResponse;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.fileupload.FileItem;
|
|
|
import org.apache.commons.fileupload.FileItemFactory;
|
|
@@ -37,6 +38,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 org.springframework.web.multipart.commons.CommonsMultipartFile;
|
|
|
|
|
@@ -1538,6 +1540,250 @@ public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossM
|
|
|
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public Object getBatchHospProfitList(String beginComputeDate, String endComputeDate, Long hospId, Integer reportType) {
|
|
|
+ List<HospProfitAndLoss> hospProfitAndLossByDateRange = getHospProfitAndLossByDateRange(beginComputeDate, endComputeDate);
|
|
|
+ if (CollectionUtils.isEmpty(hospProfitAndLossByDateRange)) {
|
|
|
+ throw new CostException(500, "未进行全院损益计算");
|
|
|
+ }
|
|
|
+ //获取全院损益表配置信息
|
|
|
+ List<ReportForm> reportFormList=getReportFormList(hospId,reportType);
|
|
|
+ if (CollectionUtils.isEmpty(reportFormList)) {
|
|
|
+ throw new CostException(500, "未找到全院损益表配置");
|
|
|
+ }
|
|
|
+ //按年-月进行分组
|
|
|
+ Map<String, List<HospProfitAndLoss>> groupedByYearMonth = hospProfitAndLossByDateRange.stream()
|
|
|
+ .collect(Collectors.groupingBy(
|
|
|
+ item -> item.getDateYear() + "-" + (item.getDateMonth() < 10 ? "0" + item.getDateMonth() : item.getDateMonth())
|
|
|
+ ));
|
|
|
+ List<BatchCostProfitResponse> responses = new ArrayList<>();
|
|
|
+ List<CostProfitVo> allCostProfitVo=new ArrayList<>();
|
|
|
+ //按年-月处理科室损益数据
|
|
|
+ for (Map.Entry<String, List<HospProfitAndLoss>> entry : groupedByYearMonth.entrySet()){
|
|
|
+ List<HospProfitAndLoss> hospProfitAndLossList = entry.getValue();
|
|
|
+ List<CostProfitVo> costProfitVos = convertToCostProfitVoList(hospProfitAndLossList, reportFormList);
|
|
|
+ //记录所有月份的损益数据
|
|
|
+ allCostProfitVo.addAll(costProfitVos);
|
|
|
+ //生成出参样式
|
|
|
+ BatchCostProfitResponse response = new BatchCostProfitResponse();
|
|
|
+ if(hospProfitAndLossList.get(0).getDateMonth()==13){
|
|
|
+ response.setComputeDate(String.format("%s-%s", hospProfitAndLossList.get(0).getDateYear(), "12A"));
|
|
|
+ }else {
|
|
|
+ response.setComputeDate(entry.getKey());
|
|
|
+ }
|
|
|
+ response.setProfitVoList(costProfitVos);
|
|
|
+ response.setAllowDrillDown(false);
|
|
|
+ responses.add(response);
|
|
|
+ }
|
|
|
+ //起止年月不同时代表有多月份需要处理月累计
|
|
|
+ if(!beginComputeDate.equals(endComputeDate)){
|
|
|
+ //获取月度汇总数据
|
|
|
+ List<CostProfitVo> costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo);
|
|
|
+ if(!CollectionUtils.isEmpty(costProfitVos)){
|
|
|
+ BatchCostProfitResponse response = new BatchCostProfitResponse();
|
|
|
+ response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate));
|
|
|
+ response.setProfitVoList(costProfitVos);
|
|
|
+ response.setAllowDrillDown(false);
|
|
|
+ responses.add(NumberConstant.ZERO,response);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return responses;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成多月份汇总的科室损益数据
|
|
|
+ *
|
|
|
+ * @param allCostProfitVo 原始数据列表
|
|
|
+ * @return 汇总后的科室损益数据
|
|
|
+ */
|
|
|
+ private List<CostProfitVo> generateSummaryForMultipleMonths(List<CostProfitVo> allCostProfitVo){
|
|
|
+ // 参数校验
|
|
|
+ if (CollectionUtils.isEmpty(allCostProfitVo)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ //排除掉13月的数据
|
|
|
+ List<CostProfitVo> activeCostProfitVo = allCostProfitVo.stream().filter(profitVo -> profitVo.getMonth() != 13).collect(Collectors.toList());
|
|
|
+ if (CollectionUtils.isEmpty(activeCostProfitVo)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<CostProfitVo> profitVoList=new ArrayList<>() ;
|
|
|
+ Map<Long, List<CostProfitVo>> reportGroup = allCostProfitVo.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
|
|
|
+ reportGroup.forEach((reportId, profitVos) -> {
|
|
|
+ CostProfitVo costProfitVo = BeanUtil.convertObj(profitVos.get(NumberConstant.ZERO), CostProfitVo.class);
|
|
|
+ BigDecimal totalAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getAmount()).orElse(BigDecimal.ZERO))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ BigDecimal totalBudgetAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getBudgetAmount()).orElse(BigDecimal.ZERO))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ BigDecimal totalPrevPeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getPrevPeriodAmount()).orElse(BigDecimal.ZERO))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ costProfitVo.setAmount(totalAmount);
|
|
|
+ costProfitVo.setBudgetAmount(totalBudgetAmount);
|
|
|
+ costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount);
|
|
|
+ costProfitVo.setSamePeriodAmount(totalSamePeriodAmount);
|
|
|
+ costProfitVo.setCompletionRate(calculateProfitRate(costProfitVo.getAmount(), costProfitVo.getBudgetAmount()));
|
|
|
+ costProfitVo.setMomRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getPrevPeriodAmount()), costProfitVo.getPrevPeriodAmount()));
|
|
|
+ costProfitVo.setYoyRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getSamePeriodAmount()), costProfitVo.getSamePeriodAmount()));
|
|
|
+ profitVoList.add(costProfitVo);
|
|
|
+ });
|
|
|
+ //转成树状结构
|
|
|
+ List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(profitVoList);
|
|
|
+ return costProfitVoTree;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转换为多层级样式全院损益数据
|
|
|
+ * @param hospProfitAndLossList
|
|
|
+ * @param reportFormList
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<CostProfitVo> convertToCostProfitVoList(List<HospProfitAndLoss> hospProfitAndLossList,List<ReportForm> reportFormList ){
|
|
|
+ //全院其他收支项目
|
|
|
+ List<HospProfitAndLoss> otherHospProfitAndLoss = hospProfitAndLossList.stream().filter(i -> NumberConstant.ONE.equals(i.getOriginType())).collect(Collectors.toList());
|
|
|
+ //按报表项目编号map
|
|
|
+ Map<Integer, HospProfitAndLoss> hospProfitAndLossMap = hospProfitAndLossList.stream().collect(Collectors.toMap(HospProfitAndLoss::getReportNum, b -> b));
|
|
|
+ List<CostProfitVo> costProfitVos = BeanUtil.convertList(reportFormList, CostProfitVo.class);
|
|
|
+ //组装全院损益及报表项目信息
|
|
|
+ for (CostProfitVo profitVo : costProfitVos) {
|
|
|
+ //处理年月数据
|
|
|
+ profitVo.setYear(hospProfitAndLossList.get(0).getDateYear());
|
|
|
+ profitVo.setMonth(hospProfitAndLossList.get(0).getDateMonth());
|
|
|
+ //添加损益数据
|
|
|
+ HospProfitAndLoss hospProfitAndLoss = hospProfitAndLossMap.get(profitVo.getReportNum());
|
|
|
+ if (ObjectUtils.isEmpty(hospProfitAndLoss)) {
|
|
|
+ profitVo.setAmount(BigDecimal.ZERO);
|
|
|
+ profitVo.setSamePeriodAmount(BigDecimal.ZERO);
|
|
|
+ profitVo.setPrevPeriodAmount(BigDecimal.ZERO);
|
|
|
+ profitVo.setBudgetAmount(BigDecimal.ZERO);
|
|
|
+ profitVo.setYoyRate(BigDecimal.ZERO);
|
|
|
+ profitVo.setMomRate(BigDecimal.ZERO);
|
|
|
+ profitVo.setCompletionRate(BigDecimal.ZERO);
|
|
|
+ } else {
|
|
|
+ profitVo.setAmount(hospProfitAndLoss.getAmount());
|
|
|
+ profitVo.setSamePeriodAmount(hospProfitAndLoss.getSamePeriodAmount());
|
|
|
+ profitVo.setPrevPeriodAmount(hospProfitAndLoss.getPrevPeriodAmount());
|
|
|
+ profitVo.setBudgetAmount(hospProfitAndLoss.getBudgetAmount());
|
|
|
+ profitVo.setYoyRate(hospProfitAndLoss.getYoyRate());
|
|
|
+ profitVo.setMomRate(hospProfitAndLoss.getMomRate());
|
|
|
+ profitVo.setCompletionRate(hospProfitAndLoss.getCompletionRate());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //有全院其他收支时添加全院其他收支
|
|
|
+ if(CollectionUtils.isEmpty(otherHospProfitAndLoss)){
|
|
|
+ //找到配置的损益项目
|
|
|
+ Optional<ReportForm> firstLossReport = reportFormList.stream().filter(i -> NumberConstant.ONE.equals(i.getIsLoss())).findFirst();
|
|
|
+ if(!firstLossReport.isPresent()){
|
|
|
+ throw new CostException(500, "全院损益报表配置有误,未设置损益项目");
|
|
|
+ }
|
|
|
+ ReportForm reportForm = firstLossReport.get();
|
|
|
+ for (HospProfitAndLoss hospProfitAndLoss : otherHospProfitAndLoss) {
|
|
|
+ CostProfitVo costProfitVo = BeanUtil.convertObj(reportForm, CostProfitVo.class);
|
|
|
+ //处理年月数据
|
|
|
+ costProfitVo.setYear(hospProfitAndLoss.getDateYear());
|
|
|
+ costProfitVo.setMonth(hospProfitAndLoss.getDateMonth());
|
|
|
+ costProfitVo.setAmount(hospProfitAndLoss.getAmount());
|
|
|
+ costProfitVo.setSamePeriodAmount(hospProfitAndLoss.getSamePeriodAmount());
|
|
|
+ costProfitVo.setPrevPeriodAmount(hospProfitAndLoss.getPrevPeriodAmount());
|
|
|
+ costProfitVo.setBudgetAmount(hospProfitAndLoss.getBudgetAmount());
|
|
|
+ costProfitVo.setYoyRate(hospProfitAndLoss.getYoyRate());
|
|
|
+ costProfitVo.setMomRate(hospProfitAndLoss.getMomRate());
|
|
|
+ costProfitVo.setCompletionRate(hospProfitAndLoss.getCompletionRate());
|
|
|
+ //全院其他收支项目排在损益项目后面
|
|
|
+ costProfitVo.setSort(reportForm.getSort()+1);
|
|
|
+ costProfitVos.add(costProfitVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //转成树状结构的损益数据
|
|
|
+ List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(costProfitVos);
|
|
|
+ return costProfitVoTree;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 转成树状结构的损益数据
|
|
|
+ * @param costProfitVos
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<CostProfitVo> converToCostProfitVoTree(List<CostProfitVo> costProfitVos){
|
|
|
+ // 参数校验
|
|
|
+ if (CollectionUtils.isEmpty(costProfitVos)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
|
|
|
+ List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
|
|
|
+ collect.remove(NumberConstant.ZERO_L);
|
|
|
+ for (CostProfitVo costProfitVo : costProfitParentVos) {
|
|
|
+ List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
|
|
|
+ if (!CollectionUtils.isEmpty(costProfitVo1)) {
|
|
|
+ costProfitVo.setChildren(setChildrenProfitVo(costProfitVo1, collect));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(costProfitParentVos)) {
|
|
|
+ costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
|
|
|
+ }
|
|
|
+ return costProfitParentVos;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<CostProfitVo> setChildrenProfitVo(List<CostProfitVo> child, Map<Long, List<CostProfitVo>> collect) {
|
|
|
+ for (CostProfitVo costProfitVo : child) {
|
|
|
+ if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getReportId()))) {
|
|
|
+ costProfitVo.setChildren(setChildrenProfitVo(collect.get(costProfitVo.getReportId()), collect));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!CollectionUtils.isEmpty(child)) {
|
|
|
+ child.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
|
|
|
+ }
|
|
|
+ return child;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取全院损益表配置信息
|
|
|
+ * @param hospId
|
|
|
+ * @param reportType
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<ReportForm> getReportFormList(Long hospId,Integer reportType ) {
|
|
|
+ List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
|
|
|
+ .eq(ReportForm::getHospId, hospId)
|
|
|
+ .eq(ReportForm::getReportType, reportType)
|
|
|
+ .eq(ReportForm::getDeleteTime , NumberConstant.ZERO)
|
|
|
+ .eq(ReportForm::getHide, NumberConstant.ONE));
|
|
|
+ return reportFormList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取指定年月区间的全院损益数据
|
|
|
+ * @param beginComputeDate
|
|
|
+ * @param endComputeDate
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<HospProfitAndLoss> getHospProfitAndLossByDateRange(String beginComputeDate, String endComputeDate) {
|
|
|
+ // 解析开始和结束时间
|
|
|
+ int startYear = Integer.parseInt(beginComputeDate.split("-")[0]);
|
|
|
+ int startMonth = Integer.parseInt(beginComputeDate.split("-")[1]);
|
|
|
+ int endYear = Integer.parseInt(endComputeDate.split("-")[0]);
|
|
|
+ int endMonth = Integer.parseInt(endComputeDate.split("-")[1]);
|
|
|
+
|
|
|
+ if( startYear * 100 + startMonth> endYear * 100 + endMonth){
|
|
|
+ throw new CostException("开始时间不能大于结束时间");
|
|
|
+ }
|
|
|
+ //如果截止月份是12月要自动添加第13月的数据
|
|
|
+ if(endMonth==12)
|
|
|
+ {
|
|
|
+ endMonth=13;
|
|
|
+ }
|
|
|
+ List<HospProfitAndLoss> list = this.list(new QueryWrapper<HospProfitAndLoss>().lambda()
|
|
|
+ .eq(HospProfitAndLoss::getDeleteTime, NumberConstant.ZERO)
|
|
|
+ .eq(HospProfitAndLoss::getHospId, UserContext.getHospId())
|
|
|
+ .apply("({0} * 100 + {1}) >= {2}",
|
|
|
+ "date_year", "date_month", startYear * 100 + startMonth)
|
|
|
+ .apply("({0} * 100 + {1}) <= {2}",
|
|
|
+ "date_year", "date_month", endYear * 100 + endMonth));
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
private static @NotNull HospProfitVO getHospProfitVO(List<HospProfitAndLoss> hospAllList, int i,int reportType) {
|
|
|
HospProfitAndLoss hospProfitAndLoss = hospAllList.get(i);
|
|
|
HospProfitVO hospProfitVO1 = new HospProfitVO();
|