StandardReportServiceImpl.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. package com.kcim.service.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUtil;
  4. import com.kcim.common.constants.Constant;
  5. import com.kcim.common.constants.NumberConstant;
  6. import com.kcim.common.util.BeanUtil;
  7. import com.kcim.common.util.UserContext;
  8. import com.kcim.dao.model.Accounting;
  9. import com.kcim.dao.model.AllocationQuery;
  10. import com.kcim.dao.model.Responsibility;
  11. import com.kcim.dao.repository.AccountingRepository;
  12. import com.kcim.dao.repository.ResponsibilityRepository;
  13. import com.kcim.service.AllocationQueryService;
  14. import com.kcim.service.CenterService;
  15. import com.kcim.service.StandardReportService;
  16. import com.kcim.vo.*;
  17. import lombok.AllArgsConstructor;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.springframework.stereotype.Service;
  20. import org.springframework.util.CollectionUtils;
  21. import java.lang.reflect.Field;
  22. import java.math.BigDecimal;
  23. import java.util.*;
  24. import java.util.stream.Collectors;
  25. /**
  26. * @program: CostAccount
  27. * @description:
  28. * @author: Wang.YS
  29. * @create: 2024-03-19 11:10
  30. **/
  31. @Service("StandardReportService")
  32. @Slf4j
  33. @AllArgsConstructor
  34. public class StandardReportServiceImpl implements StandardReportService {
  35. ResponsibilityRepository responsibilityRepository;
  36. AllocationQueryService allocationQueryService;
  37. CenterService centerService;
  38. AccountingRepository accountingRepository;
  39. /**
  40. * 科室直接成本表(医疗成本)
  41. * @param computeDate 核算年月
  42. * @return
  43. */
  44. @Override
  45. public List<DeptDirectMedicalCostVO> getDeptDirectMedicalCost(String computeDate) {
  46. DateTime parse = DateUtil.parse(computeDate);
  47. int year = DateUtil.year(parse);
  48. int month = DateUtil.month(parse) + 1;
  49. //获取科室直接成本
  50. List<AllocationQuery> allocationQueryList = allocationQueryService.getCostByDate(UserContext.getCurrentLoginHospId(), year, month, NumberConstant.ONE);
  51. if(CollectionUtils.isEmpty(allocationQueryList)){
  52. return new ArrayList<>();
  53. }
  54. //获取所有的标准字典数据
  55. StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
  56. // 处理 allocationQueryList 数据
  57. Map<String ,DeptDirectMedicalCostVO> deptDirectMedicalCostMap = new HashMap<>();
  58. //转换为DeptDirectMedicalCostVO(一个责任中心只一条记录)
  59. for (AllocationQuery allocationQuery : allocationQueryList) {
  60. addDeptDirectMedicalCostVO(deptDirectMedicalCostMap,allocationQuery, standCostDictMaps);
  61. }
  62. // 转成List便于处理
  63. List<DeptDirectMedicalCostVO> deptDirectMedicalCostList = deptDirectMedicalCostMap.values().stream().collect(Collectors.toList());
  64. //创建医疗业务成本合计
  65. DeptDirectMedicalCostVO medicalBusinessTotal = createSubtotalVo(deptDirectMedicalCostList.get(NumberConstant.ZERO), "医疗业务成本合计", DeptDirectMedicalCostVO.class);
  66. //创建总计
  67. DeptDirectMedicalCostVO grandTotal = createSubtotalVo(deptDirectMedicalCostList.get(NumberConstant.ZERO), "总计", DeptDirectMedicalCostVO.class);
  68. //按responsibilitySort正序排序
  69. deptDirectMedicalCostList.sort(Comparator.comparing(DeptDirectMedicalCostVO::getResponsibilitySort,
  70. Comparator.nullsLast(Comparator.naturalOrder())));
  71. // 按标准分级分组
  72. Map<String, List<DeptDirectMedicalCostVO>> shareLevelGroup = deptDirectMedicalCostList.stream().collect(Collectors.groupingBy(DeptDirectMedicalCostVO::getStandardShareLevel));
  73. // 科室标准分级按顺序号倒序排序
  74. List<DictDataVo> standardShareLevelList = standCostDictMaps.getStandardShareLevelDict();
  75. standardShareLevelList.sort(Comparator.comparing(DictDataVo::getSort,Comparator.nullsLast(Comparator.reverseOrder())));
  76. // 创建各层级小计并按正确顺序插入
  77. List<DeptDirectMedicalCostVO> result = new ArrayList<>();
  78. for (DictDataVo shareLevel : standardShareLevelList) {
  79. List<DeptDirectMedicalCostVO> deptDirectMedicalCostVOS = shareLevelGroup.get(shareLevel.getCode());
  80. if(CollectionUtils.isEmpty(deptDirectMedicalCostVOS)){
  81. continue;
  82. }
  83. // 添加该分类下的所有记录
  84. result.addAll(deptDirectMedicalCostVOS);
  85. // 创建小计对象
  86. DeptDirectMedicalCostVO subtotalVo = createSubtotalVo(deptDirectMedicalCostVOS.get(NumberConstant.ZERO),String.format("%s小计", shareLevel.getName()), DeptDirectMedicalCostVO.class);
  87. //将科室的金额加到小计对象中
  88. deptDirectMedicalCostVOS.forEach(item -> addBigDecimalFields(item, subtotalVo));
  89. // 如果属于医疗业务成本的科室,则小计的金额加到医疗业务成本
  90. if(NumberConstant.ONE_S.equals(shareLevel.getValue())){
  91. addBigDecimalFields(subtotalVo, medicalBusinessTotal);
  92. }
  93. // 小计的金额加到总计
  94. addBigDecimalFields(subtotalVo, grandTotal);
  95. // 添加小计行
  96. result.add(subtotalVo);
  97. // 医疗业务成本加入到医疗辅助类小计后面
  98. if(NumberConstant.TWO_S.equals(shareLevel.getCode())){
  99. result.add(medicalBusinessTotal);
  100. }
  101. }
  102. // 总计加到列表最后面
  103. result.add(grandTotal);
  104. return result;
  105. }
  106. /**
  107. * 科室直接成本表(全成本)
  108. * @param computeDate 核算年月
  109. * @return 报表数据
  110. */
  111. @Override
  112. public List<DeptFullDirectCostVO> getDeptFullDirectCost(String computeDate) {
  113. DateTime parse = DateUtil.parse(computeDate);
  114. int year = DateUtil.year(parse);
  115. int month = DateUtil.month(parse) + 1;
  116. // 获取科室直接成本
  117. List<AllocationQuery> allocationQueryList = allocationQueryService.getCostByDate(UserContext.getCurrentLoginHospId(), year, month, NumberConstant.ONE);
  118. if (CollectionUtils.isEmpty(allocationQueryList)) {
  119. return new ArrayList<>();
  120. }
  121. // 获取所有的标准字典数据
  122. StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
  123. // 处理 allocationQueryList 数据
  124. Map<String, DeptFullDirectCostVO> reportMap = new HashMap<>();
  125. // 转换为DeptDirectAllCostVO(一个责任中心只一条记录)
  126. for (AllocationQuery allocationQuery : allocationQueryList) {
  127. addDeptDirectAllCostVO(reportMap, allocationQuery, standCostDictMaps);
  128. }
  129. // 转成List便于处理
  130. List<DeptFullDirectCostVO> reportList = reportMap.values().stream().collect(Collectors.toList());
  131. // 按responsibilitySort正序排序
  132. reportList.sort(Comparator.comparing(DeptFullDirectCostVO::getResponsibilitySort, Comparator.nullsLast(Comparator.naturalOrder())));
  133. // 按标准分级分组
  134. Map<String, List<DeptFullDirectCostVO>> shareLevelGroup = reportList.stream().collect(Collectors.groupingBy(DeptFullDirectCostVO::getStandardShareLevel));
  135. // 科室标准分级按顺序号倒序排序
  136. List<DictDataVo> standardShareLevelList = standCostDictMaps.getStandardShareLevelDict();
  137. standardShareLevelList.sort(Comparator.comparing(DictDataVo::getSort, Comparator.nullsLast(Comparator.reverseOrder())));
  138. //创建医疗业务成本合计
  139. DeptFullDirectCostVO medicalBusinessTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "医疗业务成本合计", DeptFullDirectCostVO.class);
  140. //创建总计
  141. DeptFullDirectCostVO grandTotal = createSubtotalVo(reportList.get(NumberConstant.ZERO), "总计", DeptFullDirectCostVO.class);
  142. // 创建各层级小计并按正确顺序插入
  143. List<DeptFullDirectCostVO> result = new ArrayList<>();
  144. for (DictDataVo shareLevel : standardShareLevelList) {
  145. List<DeptFullDirectCostVO> reportVOS = shareLevelGroup.get(shareLevel.getCode());
  146. if (CollectionUtils.isEmpty(reportVOS)) {
  147. continue;
  148. }
  149. // 添加该分类下的所有记录
  150. result.addAll(reportVOS);
  151. // 创建小计对象
  152. DeptFullDirectCostVO subtotalVo = createSubtotalVo(reportVOS.get(NumberConstant.ZERO),String.format("%s小计", shareLevel.getName()), DeptFullDirectCostVO.class);
  153. //将科室的金额加到小计对象中
  154. reportVOS.forEach(item -> addBigDecimalFields(item, subtotalVo));
  155. // 如果属于医疗业务成本的科室,则小计的金额加到医疗业务成本
  156. if(NumberConstant.ONE_S.equals(shareLevel.getValue())){
  157. addBigDecimalFields(subtotalVo, medicalBusinessTotal);
  158. }
  159. // 小计的金额加到总计
  160. addBigDecimalFields(subtotalVo, grandTotal);
  161. // 添加小计行
  162. result.add(subtotalVo);
  163. // 医疗业务成本加入到医疗辅助类小计后面
  164. if(NumberConstant.TWO_S.equals(shareLevel.getCode())){
  165. result.add(medicalBusinessTotal);
  166. }
  167. }
  168. // 总计加到列表最后面
  169. result.add(grandTotal);
  170. return result;
  171. }
  172. /**
  173. * 获取科室成本明细数据
  174. * @param computeDate 核算年月
  175. * @return
  176. */
  177. @Override
  178. public List<ClinicalDeptMedicalCostVO> getClinicalDeptMedicalCost(String computeDate) {
  179. DateTime parse = DateUtil.parse(computeDate);
  180. int year = DateUtil.year(parse);
  181. int month = DateUtil.month(parse) + 1;
  182. // 获取科室直接成本
  183. List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(UserContext.getCurrentLoginHospId(), year, month);
  184. if (CollectionUtils.isEmpty(allocationQueryList)) {
  185. return new ArrayList<>();
  186. }
  187. // 获取所有的标准字典数据
  188. StandCostDictMapVO standCostDictMaps = getStandCostDictMaps();
  189. // 处理 allocationQueryList 数据
  190. Map<String, ClinicalDeptMedicalCostVO> reportMap = new HashMap<>();
  191. // 添加科室成本明细(一个责任中心只一条记录)
  192. for (AllocationQuery allocationQuery : allocationQueryList) {
  193. addDeptCostDetailVO(reportMap, allocationQuery, standCostDictMaps);
  194. }
  195. // 转成List便于处理
  196. List<ClinicalDeptMedicalCostVO> reportList = reportMap.values().stream().collect(Collectors.toList());
  197. // 创建小计对象
  198. ClinicalDeptMedicalCostVO subtotalVo = createSubtotalVo(reportList.get(NumberConstant.ZERO),"科室全成本合计",ClinicalDeptMedicalCostVO.class);
  199. //将科室的金额加到小计对象中
  200. reportList.forEach(item -> addBigDecimalFields(item, subtotalVo));
  201. // 总计加到列表最后面
  202. reportList.add(subtotalVo);
  203. return reportList;
  204. }
  205. /**
  206. * 添加科室成本明细
  207. * @param reportMap
  208. * @param allocationQuery
  209. * @param standCostDictMaps
  210. */
  211. private void addDeptCostDetailVO(Map<String, ClinicalDeptMedicalCostVO> reportMap, AllocationQuery allocationQuery, StandCostDictMapVO standCostDictMaps) {
  212. String responsibilityCode = allocationQuery.getResponsibilityCode();
  213. Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
  214. if (responsibility == null) {
  215. return; // 添加 null 检查
  216. }
  217. String accountingCode = allocationQuery.getAccountingCode();
  218. Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
  219. if (account == null) {
  220. return; // 添加 null 检查
  221. }
  222. DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
  223. if (accountType == null) {
  224. return; // 添加 null 检查
  225. }
  226. DictDataVo costType = standCostDictMaps.getCostTypeMap().get(account.getCostType());
  227. DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
  228. ClinicalDeptMedicalCostVO reportVO = new ClinicalDeptMedicalCostVO();
  229. if (reportMap.containsKey(allocationQuery.getResponsibilityCode())) {
  230. reportVO = reportMap.get(allocationQuery.getResponsibilityCode());
  231. } else {
  232. //生成科室成本报表信息
  233. initDeptCostReport(reportVO, responsibility, accountType, costType, standardShareLevel);
  234. // 初始化所有费用字段为0
  235. BeanUtil.initBigDecimalFieldsToZero(reportVO);
  236. }
  237. // 根据费用类型累加到对应字段
  238. switch (accountType.getExpandOne()) {
  239. case "1":
  240. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  241. reportVO.setPersonnelDirectCost(reportVO.getPersonnelDirectCost().add(allocationQuery.getAmount()));
  242. }else{
  243. reportVO.setPersonnelIndirectCost(reportVO.getPersonnelIndirectCost().add(allocationQuery.getAmount()));
  244. }
  245. reportVO.setPersonnelTotalCost(reportVO.getPersonnelTotalCost().add(allocationQuery.getAmount()));
  246. break;
  247. case "2":
  248. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  249. reportVO.setHealthMaterialDirectCost(reportVO.getHealthMaterialDirectCost().add(allocationQuery.getAmount()));
  250. }else{
  251. reportVO.setHealthMaterialIndirectCost(reportVO.getHealthMaterialIndirectCost().add(allocationQuery.getAmount()));
  252. }
  253. reportVO.setHealthMaterialTotalCost(reportVO.getHealthMaterialTotalCost().add(allocationQuery.getAmount()));
  254. break;
  255. case "3":
  256. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  257. reportVO.setMedicineDirectCost(reportVO.getMedicineDirectCost().add(allocationQuery.getAmount()));
  258. }else{
  259. reportVO.setMedicineIndirectCost(reportVO.getMedicineIndirectCost().add(allocationQuery.getAmount()));
  260. }
  261. reportVO.setMedicineTotalCost(reportVO.getMedicineTotalCost().add(allocationQuery.getAmount()));
  262. break;
  263. case "4":
  264. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  265. reportVO.setFixedAssetDepreciationDirectCost(reportVO.getFixedAssetDepreciationDirectCost().add(allocationQuery.getAmount()));
  266. }else{
  267. reportVO.setFixedAssetDepreciationIndirectCost(reportVO.getFixedAssetDepreciationIndirectCost().add(allocationQuery.getAmount()));
  268. }
  269. reportVO.setFixedAssetDepreciationTotalCost(reportVO.getFixedAssetDepreciationTotalCost().add(allocationQuery.getAmount()));
  270. break;
  271. case "5":
  272. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  273. reportVO.setIntangibleAssetAmortizationDirectCost(reportVO.getIntangibleAssetAmortizationDirectCost().add(allocationQuery.getAmount()));
  274. }else{
  275. reportVO.setIntangibleAssetAmortizationIndirectCost(reportVO.getIntangibleAssetAmortizationIndirectCost().add(allocationQuery.getAmount()));
  276. }
  277. reportVO.setIntangibleAssetAmortizationTotalCost(reportVO.getIntangibleAssetAmortizationTotalCost().add(allocationQuery.getAmount()));
  278. break;
  279. case "6":
  280. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  281. reportVO.setMedicalRiskReserveDirectCost(reportVO.getMedicalRiskReserveDirectCost().add(allocationQuery.getAmount()));
  282. }else{
  283. reportVO.setMedicalRiskReserveIndirectCost(reportVO.getMedicalRiskReserveIndirectCost().add(allocationQuery.getAmount()));
  284. }
  285. reportVO.setMedicalRiskReserveTotalCost(reportVO.getMedicalRiskReserveTotalCost().add(allocationQuery.getAmount()));
  286. break;
  287. case "7":
  288. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  289. reportVO.setOtherMedicalExpensesDirectCost(reportVO.getOtherMedicalExpensesDirectCost().add(allocationQuery.getAmount()));
  290. }else{
  291. reportVO.setOtherMedicalExpensesIndirectCost(reportVO.getOtherMedicalExpensesIndirectCost().add(allocationQuery.getAmount()));
  292. }
  293. reportVO.setOtherMedicalExpensesTotalCost(reportVO.getOtherMedicalExpensesTotalCost().add(allocationQuery.getAmount()));
  294. break;
  295. default:
  296. break;
  297. }
  298. //添加合计
  299. if(NumberConstant.ONE.equals(allocationQuery.getOriginType().intValue())){
  300. reportVO.setTotalDirectCost(reportVO.getTotalDirectCost().add(allocationQuery.getAmount()));
  301. }else{
  302. reportVO.setTotalIndirectCost(reportVO.getTotalIndirectCost().add(allocationQuery.getAmount()));
  303. }
  304. reportVO.setTotalCost(reportVO.getTotalCost().add(allocationQuery.getAmount()));
  305. }
  306. /**
  307. * 生成科室成本报表信息
  308. * @param reportVO
  309. * @param responsibility
  310. * @param accountType
  311. * @param costType
  312. * @param standardShareLevel
  313. */
  314. private void initDeptCostReport(BaseDeptCostReportVO reportVO,
  315. Responsibility responsibility,
  316. DictDataVo accountType,
  317. DictDataVo costType,
  318. DictDataVo standardShareLevel) {
  319. reportVO.setStandardShareLevel(responsibility.getStandardShareLevel());
  320. reportVO.setResponsibilityName(responsibility.getResponsibilityName());
  321. reportVO.setResponsibilityCode(responsibility.getResponsibilityCode());
  322. reportVO.setResponsibilitySort(responsibility.getSort());
  323. reportVO.setCostType(costType.getCode());
  324. reportVO.setStandCostType(costType.getExpandOne());
  325. reportVO.setAccountType(accountType.getCode());
  326. reportVO.setStandAccountType(accountType.getExpandOne());
  327. reportVO.setShareLevelSort(standardShareLevel.getSort());
  328. }
  329. /**
  330. * 获取所有的标准字典数据并转换所有需要的映射数据
  331. * @return 包含所有映射数据的DTO对象
  332. */
  333. private StandCostDictMapVO getStandCostDictMaps() {
  334. StandCostDictMapVO dataMaps = new StandCostDictMapVO();
  335. List<Responsibility> responsibilityList = responsibilityRepository.getList(UserContext.getCurrentLoginHospId());
  336. DictDataVo accountingTypeDict = centerService.getDict(Constant.ACCOUNTING_TYPE);
  337. DictDataVo costTypeDict = centerService.getDict(Constant.STANDARD_COST_CATEGORIES);
  338. DictDataVo standardShareLevelDict = centerService.getDict(Constant.STANDARD_SHARE_LEVEL);
  339. List<Accounting> allCostAccounting = accountingRepository.getAllCostAccounting();
  340. // 添加 null 检查
  341. if (responsibilityList == null) {
  342. responsibilityList = new ArrayList<>();
  343. }
  344. if (allCostAccounting == null) {
  345. allCostAccounting = new ArrayList<>();
  346. }
  347. // 创建一个映射,用于快速查找责任中心的科室类型,过滤掉 null 对象,过滤掉 responsibilityCode 为 null 的对象
  348. Map<String, Responsibility> responsibilityMap = responsibilityList.stream()
  349. .filter(Objects::nonNull)
  350. .filter(r -> r.getResponsibilityCode() != null)
  351. .collect(Collectors.toMap(Responsibility::getResponsibilityCode, o -> o));
  352. // 创建一个映射,用于快速查找会计科目的类型,过滤掉 null 对象,过滤掉 accountingCode 为 null 的对象
  353. Map<String, Accounting> accountingMap = allCostAccounting.stream()
  354. .filter(Objects::nonNull)
  355. .filter(a -> a.getAccountingCode() != null)
  356. .collect(Collectors.toMap(Accounting::getAccountingCode, o -> o));
  357. // 添加 null 检查并创建映射
  358. List<DictDataVo> accountingTypeDictList = (accountingTypeDict != null && accountingTypeDict.getDataVoList() != null)
  359. ? accountingTypeDict.getDataVoList() : new ArrayList<>();
  360. List<DictDataVo> costTypeDictList = (costTypeDict != null && costTypeDict.getDataVoList() != null)
  361. ? costTypeDict.getDataVoList() : new ArrayList<>();
  362. List<DictDataVo> standardShareLevelDictList = (standardShareLevelDict != null && standardShareLevelDict.getDataVoList() != null)
  363. ? standardShareLevelDict.getDataVoList() : new ArrayList<>();
  364. // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
  365. Map<String, DictDataVo> accountingTypeMap = accountingTypeDictList.stream()
  366. .filter(Objects::nonNull)
  367. .filter(d -> d.getCode() != null)
  368. .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
  369. // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
  370. Map<String, DictDataVo> costTypeMap = costTypeDictList.stream()
  371. .filter(Objects::nonNull)
  372. .filter(d -> d.getCode() != null)
  373. .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
  374. // 创建一个映射,用于快速查找会计科目类型的扩展字段,过滤掉 null 对象,过滤掉 code 为 null 的对象
  375. Map<String, DictDataVo> standardShareLevelMap = standardShareLevelDictList.stream()
  376. .filter(Objects::nonNull)
  377. .filter(d -> d.getCode() != null)
  378. .collect(Collectors.toMap(DictDataVo::getCode, o -> o));
  379. dataMaps.setResponsibilityDict(responsibilityList);
  380. dataMaps.setCostAccountingDict(allCostAccounting);
  381. dataMaps.setCostTypeDict(costTypeDictList);
  382. dataMaps.setAccountingTypeDict(accountingTypeDictList);
  383. dataMaps.setStandardShareLevelDict(standardShareLevelDictList);
  384. dataMaps.setAccountingMap(accountingMap);
  385. dataMaps.setCostTypeMap(costTypeMap);
  386. dataMaps.setResponsibilityMap(responsibilityMap);
  387. dataMaps.setStandardShareLevelMap(standardShareLevelMap);
  388. dataMaps.setAccountingTypeMap(accountingTypeMap);
  389. return dataMaps;
  390. }
  391. /**
  392. * 转换为DeptDirectMedicalCostVO(一个责任中心只一条记录)
  393. * @param allocationQuery
  394. * @param standCostDictMaps
  395. * @return
  396. */
  397. public void addDeptDirectMedicalCostVO(Map<String ,DeptDirectMedicalCostVO> deptDirectMedicalCostMap,
  398. AllocationQuery allocationQuery,
  399. StandCostDictMapVO standCostDictMaps) {
  400. String responsibilityCode = allocationQuery.getResponsibilityCode();
  401. Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
  402. if (responsibility == null) {
  403. return; // 添加 null 检查
  404. }
  405. String accountingCode = allocationQuery.getAccountingCode();
  406. Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
  407. if (account == null) {
  408. return; // 添加 null 检查
  409. }
  410. DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
  411. if (accountType == null) {
  412. return; // 添加 null 检查
  413. }
  414. //只处理医疗成本
  415. if(!NumberConstant.ONE_S.equals(accountType.getExpandOne()) ){
  416. return;
  417. }
  418. DictDataVo costType = standCostDictMaps.getCostTypeMap().get(account.getCostType());
  419. DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
  420. DeptDirectMedicalCostVO deptDirectMedicalCostVO= new DeptDirectMedicalCostVO();
  421. if(deptDirectMedicalCostMap.containsKey(allocationQuery.getResponsibilityCode())){
  422. deptDirectMedicalCostVO=deptDirectMedicalCostMap.get(allocationQuery.getResponsibilityCode());
  423. }else{
  424. initDeptCostReport(deptDirectMedicalCostVO, responsibility,accountType, costType,standardShareLevel);
  425. // 初始化所有费用字段为0
  426. BeanUtil.initBigDecimalFieldsToZero(deptDirectMedicalCostVO);
  427. }
  428. // 根据费用类型累加到对应字段
  429. switch (accountType.getExpandOne()) {
  430. case "1":
  431. deptDirectMedicalCostVO.setPersonnelExpense(deptDirectMedicalCostVO.getPersonnelExpense().add((allocationQuery.getAmount())));
  432. break;
  433. case "2":
  434. deptDirectMedicalCostVO.setHealthMaterialFee(deptDirectMedicalCostVO.getHealthMaterialFee().add((allocationQuery.getAmount())));
  435. break;
  436. case "3":
  437. deptDirectMedicalCostVO.setDrugFee(deptDirectMedicalCostVO.getDrugFee().add((allocationQuery.getAmount())));
  438. break;
  439. case "4":
  440. deptDirectMedicalCostVO.setFixedAssetDepreciation(deptDirectMedicalCostVO.getFixedAssetDepreciation().add((allocationQuery.getAmount())));
  441. break;
  442. case "5":
  443. deptDirectMedicalCostVO.setIntangibleAssetAmortization(deptDirectMedicalCostVO.getIntangibleAssetAmortization().add((allocationQuery.getAmount())));
  444. break;
  445. case "6":
  446. deptDirectMedicalCostVO.setMedicalRiskFundExtraction(deptDirectMedicalCostVO.getMedicalRiskFundExtraction().add((allocationQuery.getAmount())));
  447. break;
  448. case "7":
  449. deptDirectMedicalCostVO.setOtherMedicalExpenses(deptDirectMedicalCostVO.getOtherMedicalExpenses().add((allocationQuery.getAmount())));
  450. break;
  451. default:
  452. break;
  453. }
  454. // 更新总计
  455. deptDirectMedicalCostVO.setTotal(deptDirectMedicalCostVO.getTotal().add(allocationQuery.getAmount()));
  456. }
  457. /**
  458. * 转换为DeptDirectAllCostVO(一个责任中心只一条记录)
  459. * @param reportMap
  460. * @param allocationQuery
  461. * @param standCostDictMaps
  462. */
  463. private void addDeptDirectAllCostVO(Map<String, DeptFullDirectCostVO> reportMap, AllocationQuery allocationQuery, StandCostDictMapVO standCostDictMaps) {
  464. String responsibilityCode = allocationQuery.getResponsibilityCode();
  465. Responsibility responsibility = standCostDictMaps.getResponsibilityMap().get(responsibilityCode);
  466. if (responsibility == null) {
  467. return; // 添加 null 检查
  468. }
  469. String accountingCode = allocationQuery.getAccountingCode();
  470. Accounting account = standCostDictMaps.getAccountingMap().get(accountingCode);
  471. if (account == null) {
  472. return; // 添加 null 检查
  473. }
  474. DictDataVo accountType = standCostDictMaps.getAccountingTypeMap().get(account.getType());
  475. if (accountType == null) {
  476. return; // 添加 null 检查
  477. }
  478. DictDataVo costType = standCostDictMaps.getCostTypeMap().get(account.getCostType());
  479. DictDataVo standardShareLevel = standCostDictMaps.getStandardShareLevelMap().get(responsibility.getStandardShareLevel());
  480. DeptFullDirectCostVO reportVO = new DeptFullDirectCostVO();
  481. if (reportMap.containsKey(allocationQuery.getResponsibilityCode())) {
  482. reportVO = reportMap.get(allocationQuery.getResponsibilityCode());
  483. } else {
  484. initDeptCostReport(reportVO, responsibility,accountType, costType,standardShareLevel);
  485. // 初始化所有费用字段为0
  486. BeanUtil.initBigDecimalFieldsToZero(reportVO);
  487. }
  488. // 根据费用类型累加到对应字段
  489. switch (costType.getValue()) {
  490. case "1":
  491. reportVO.setMedicalCostTotal(reportVO.getMedicalCostTotal().add(allocationQuery.getAmount()));
  492. break;
  493. case "2":
  494. reportVO.setFinancialProjectFunds(reportVO.getFinancialProjectFunds().add(allocationQuery.getAmount()));
  495. break;
  496. case "3":
  497. reportVO.setNonPeerFinancialFunds(reportVO.getNonPeerFinancialFunds().add(allocationQuery.getAmount()));
  498. break;
  499. case "4":
  500. reportVO.setEducationalExpenses(reportVO.getEducationalExpenses().add(allocationQuery.getAmount()));
  501. break;
  502. case "5":
  503. reportVO.setAssetDisposalFees(reportVO.getAssetDisposalFees().add(allocationQuery.getAmount()));
  504. break;
  505. default:
  506. break;
  507. }
  508. //不是医院全成本的都是医疗全成本
  509. if(!NumberConstant.THREE_S.equals(costType.getExpandOne())){
  510. // 医疗全成本合计
  511. reportVO.setMedicalTotalCost(reportVO.getMedicalTotalCost().add(allocationQuery.getAmount()));
  512. }
  513. // 医院全成本合计
  514. reportVO.setHospitalTotalCost(reportVO.getHospitalTotalCost().add(allocationQuery.getAmount()));
  515. }
  516. /**
  517. * 合并两个科室成本
  518. * @param source 源对象
  519. * @param target 目标对象
  520. */
  521. public <T> void addBigDecimalFields(T source, T target) {
  522. if (source == null || target == null) {
  523. return;
  524. }
  525. Class<?> clazz = target.getClass();
  526. Field[] fields = clazz.getDeclaredFields();
  527. for (Field field : fields) {
  528. if (field.getType().equals(BigDecimal.class)) {
  529. field.setAccessible(true);
  530. try {
  531. BigDecimal sourceValue = (BigDecimal) field.get(source);
  532. BigDecimal targetValue = (BigDecimal) field.get(target);
  533. BigDecimal result = (targetValue == null ? BigDecimal.ZERO : targetValue)
  534. .add(sourceValue == null ? BigDecimal.ZERO : sourceValue);
  535. field.set(target, result);
  536. } catch (IllegalAccessException e) {
  537. log.error("合并科室成本时发生错误", e);
  538. }
  539. }
  540. }
  541. }
  542. /**
  543. * 通用创建小计对象方法
  544. * @param source 源对象
  545. * @param totalName 小计名称
  546. * @param clazz 目标类类型
  547. * @return 小计对象
  548. */
  549. public <T> T createSubtotalVo(T source, String totalName, Class<T> clazz) {
  550. if (source == null) {
  551. return null;
  552. }
  553. T target = BeanUtil.convertObj(source, clazz);
  554. // 使用反射设置责任代码和名称
  555. try {
  556. clazz.getMethod("setResponsibilityCode", String.class).invoke(target, totalName);
  557. clazz.getMethod("setResponsibilityName", String.class).invoke(target, totalName);
  558. } catch (Exception e) {
  559. log.error("设置责任代码和名称时发生错误", e);
  560. }
  561. // 初始化所有费用字段为0
  562. BeanUtil.initBigDecimalFieldsToZero(target);
  563. return target;
  564. }
  565. }