HospProfitAndLossServiceImpl.java 91 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690
  1. package com.kcim.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.date.DatePattern;
  4. import cn.hutool.core.date.DateTime;
  5. import cn.hutool.core.date.DateUtil;
  6. import cn.hutool.core.util.ReUtil;
  7. import cn.hutool.core.util.StrUtil;
  8. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  9. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  10. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  11. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  12. import com.google.common.collect.ImmutableMap;
  13. import com.kcim.common.constants.Constant;
  14. import com.kcim.common.constants.NumberConstant;
  15. import com.kcim.common.enums.CalcTypeEnum;
  16. import com.kcim.common.enums.ErrorCodeEnum;
  17. import com.kcim.common.enums.ReportTypeEnum;
  18. import com.kcim.common.exception.CostException;
  19. import com.kcim.common.file.MinioConfig;
  20. import com.kcim.common.file.MinioFileUtil;
  21. import com.kcim.common.util.BeanUtil;
  22. import com.kcim.common.util.PageUtils;
  23. import com.kcim.common.util.UserContext;
  24. import com.kcim.common.util.excel.ExcelPoiUtil;
  25. import com.kcim.common.util.excel.entity.ColEntity;
  26. import com.kcim.common.util.excel.entity.TitleEntity;
  27. import com.kcim.dao.mapper.HospProfitAndLossMapper;
  28. import com.kcim.dao.model.*;
  29. import com.kcim.service.*;
  30. import com.kcim.vo.AllocationQueryReportVO;
  31. import com.kcim.vo.HospProfitAndLossVo;
  32. import com.kcim.vo.RelationVO;
  33. import lombok.extern.slf4j.Slf4j;
  34. import org.apache.commons.fileupload.FileItem;
  35. import org.apache.commons.fileupload.FileItemFactory;
  36. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  37. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  38. import org.springframework.stereotype.Service;
  39. import org.springframework.transaction.annotation.Propagation;
  40. import org.springframework.transaction.annotation.Transactional;
  41. import org.springframework.util.CollectionUtils;
  42. import org.springframework.util.StringUtils;
  43. import org.springframework.web.multipart.MultipartFile;
  44. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  45. import java.io.IOException;
  46. import java.io.InputStream;
  47. import java.io.OutputStream;
  48. import java.math.BigDecimal;
  49. import java.math.RoundingMode;
  50. import java.text.DecimalFormat;
  51. import java.util.*;
  52. import java.util.concurrent.ConcurrentHashMap;
  53. import java.util.concurrent.atomic.AtomicReference;
  54. import java.util.stream.Collectors;
  55. @Slf4j
  56. @Service("hospProfitAndLossService")
  57. public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossMapper, HospProfitAndLoss> implements HospProfitAndLossService {
  58. // @Value("${file.filelocal}")
  59. // private String hospProfitReportUrl;
  60. //
  61. // @Value("${file.serverUrl}")
  62. // private String serverUrl;
  63. private final ReportFormService reportFormService;
  64. private final IncomeCollectionService collectionService;
  65. private final AllocationQueryService allocationQueryService;
  66. private final AllocationService allocationService;
  67. private final ReportRelationService reportRelationService;
  68. private final CostShareLevelService shareLevelService;
  69. private final CostOtherPaymentsDataService otherPaymentsDataService;
  70. private final ResponsibilityService responsibilityService;
  71. private final CostAccountShareService accountShareService;
  72. private final FileRecordService fileRecordService;
  73. private final MinioConfig minioConfig;
  74. private final MinioFileUtil minioFileUtil;
  75. public HospProfitAndLossServiceImpl(ReportFormService reportFormService,
  76. IncomeCollectionService collectionService,
  77. AllocationQueryService allocationQueryService,
  78. AllocationService allocationService, ReportRelationService reportRelationService,
  79. CostShareLevelService shareLevelService,
  80. CostOtherPaymentsDataService otherPaymentsDataService,
  81. ResponsibilityService responsibilityService,
  82. CostAccountShareService accountShareService, FileRecordService fileRecordService, MinioConfig minioConfig, MinioFileUtil minioFileUtil) {
  83. this.reportFormService = reportFormService;
  84. this.collectionService = collectionService;
  85. this.allocationQueryService = allocationQueryService;
  86. this.allocationService = allocationService;
  87. this.reportRelationService = reportRelationService;
  88. this.shareLevelService = shareLevelService;
  89. this.otherPaymentsDataService = otherPaymentsDataService;
  90. this.responsibilityService = responsibilityService;
  91. this.accountShareService = accountShareService;
  92. this.fileRecordService = fileRecordService;
  93. this.minioConfig = minioConfig;
  94. this.minioFileUtil = minioFileUtil;
  95. }
  96. /**
  97. * 计算全院损益
  98. *
  99. * @param date yyyy-MM-dd 时间
  100. * @param hospId 医院id
  101. */
  102. @Override
  103. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
  104. public void calc(String date, Long hospId) {
  105. reportFormService.checkExistLoss(hospId);
  106. DateTime parse = DateUtil.parse(date);
  107. int year = DateUtil.year(parse);
  108. int month = DateUtil.month(parse) + 1;
  109. this.remove(new LambdaQueryWrapper<HospProfitAndLoss>().eq(HospProfitAndLoss::getDateYear, year).eq(HospProfitAndLoss::getDateMonth, month).eq(HospProfitAndLoss::getHospId, hospId));
  110. // 得到全院损益计算报表
  111. List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
  112. if (CollUtil.isEmpty(reportForms)) {
  113. throw new CostException("医院未设置全院损益计算报表");
  114. }
  115. // 得到这个月所有收入数据
  116. List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
  117. if (incomes.isEmpty()) {
  118. throw new CostException("医院未归集本月收入数据");
  119. }
  120. // 得到这个月的所有成本数据
  121. List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
  122. if (allocationQueries.isEmpty()) {
  123. throw new CostException("医院未分摊本月数据");
  124. }
  125. List<HospProfitAndLoss> list = new ArrayList<>();
  126. List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
  127. for (ReportForm parentForm : parentForms) {
  128. Long parentId = parentForm.getId();
  129. List<ReportForm> children = reportForms.stream().filter(i -> i.getParentId().equals(parentId)).collect(Collectors.toList());
  130. for (ReportForm child : children) {
  131. Integer calcType = child.getCalcType();
  132. if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
  133. // 按会计科目计算单的话
  134. calcByAccount(hospId, child, incomes, list, allocationQueries, month, year);
  135. } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
  136. // 分摊层级计算
  137. calcByShareLevel(hospId, child, list, year, month);
  138. } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
  139. // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
  140. calcByLitterCount(year, month, child, children, list, hospId);
  141. } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
  142. // 按公式 (要保证总合计放到最后呀)
  143. calcByFormula(year, month, child, children, list);
  144. } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
  145. // 责任中心
  146. calcByResponsibility(hospId, child, allocationQueries, list, year, month);
  147. } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
  148. // 不设置不计算
  149. } else {
  150. }
  151. }
  152. }
  153. // 处理医院其他收支
  154. List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
  155. if (!otherPaymentsDatas.isEmpty()) {
  156. otherPaymentsDatas.forEach(ele -> {
  157. HospProfitAndLoss loss = new HospProfitAndLoss();
  158. loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum(ele.getId().intValue())
  159. .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId);
  160. // if (ele.getPaymentsType() == 2) {
  161. // loss.setAmount(BigDecimal.ZERO.subtract(ele.getTotalAmount()));
  162. // }
  163. list.add(loss);
  164. });
  165. }
  166. this.saveBatch(list);
  167. }
  168. // 计算公式中钱
  169. private BigDecimal calcAmount(List<HospProfitAndLoss> list, String calcFormula, ReportForm reportForm) {
  170. // 得到所有的编号
  171. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  172. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  173. // 得到编号的map
  174. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  175. for (int j = 0; j < numList.size(); j++) {
  176. numMap.put(j, Integer.parseInt(numList.get(j)));
  177. }
  178. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  179. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  180. // 得到预算表达式 得到所有表达式的Map + - 相关的
  181. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  182. for (int k = 0; k < expressions.size(); k++) {
  183. expressionMap.put(k, expressions.get(k));
  184. }
  185. // 数字的索引和表达式的索引累加计算
  186. Set<Integer> numSet = numMap.keySet();
  187. List<Integer> nums = new ArrayList<>(numSet);
  188. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  189. totalAmount.set(BigDecimal.ZERO);
  190. for (int i = 0; i < nums.size(); i++) {
  191. // 编号
  192. Integer num = numMap.get(i);
  193. List<HospProfitAndLoss> losses = list.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  194. if (CollUtil.isEmpty(losses)) {
  195. continue;
  196. }
  197. // log.info("data={}", reportForm);
  198. // if (losses.size() != 0 && losses.size() != 1) {
  199. // throw new CostException("数据异常");
  200. // }
  201. HospProfitAndLoss loss = losses.get(0);
  202. BigDecimal amount = loss.getAmount();
  203. String str = expressionMap.get(i);
  204. if (str.equals("+")) {
  205. totalAmount.set(totalAmount.get().add(amount));
  206. } else {
  207. totalAmount.set(totalAmount.get().subtract(amount));
  208. }
  209. }
  210. return totalAmount.get();
  211. }
  212. /**
  213. * 按责任中心计算
  214. *
  215. * @param hospId 医院id
  216. * @param reportForm 报表
  217. * @param allocationQueries 分摊成本数据
  218. * @param list
  219. * @param year
  220. * @param month
  221. */
  222. private void calcByResponsibility(Long hospId, ReportForm reportForm, List<AllocationQuery> allocationQueries, List<HospProfitAndLoss> list, int year, int month) {
  223. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(reportForm.getId(), hospId);
  224. if (responsibilities.isEmpty()) {
  225. return;
  226. }
  227. List<String> accountCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  228. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  229. calcTotal.set(BigDecimal.ZERO);
  230. accountCodes.forEach(i -> {
  231. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  232. .reduce(BigDecimal.ZERO, BigDecimal::add);
  233. calcTotal.set(calcTotal.get().add(costAmount));
  234. });
  235. HospProfitAndLoss loss = new HospProfitAndLoss();
  236. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  237. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  238. list.add(loss);
  239. }
  240. /**
  241. * 按计算公式计算
  242. */
  243. private void calcByFormula(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list) {
  244. // 得到当前下按公式计算的
  245. List<ReportForm> calcFormulas = reportForms.stream().filter(i -> i.getCalcType() == CalcTypeEnum.CALC_FORMULA.getType()).collect(Collectors.toList());
  246. calcFormulas = calcFormulas.stream().filter(i -> i.getNum().equals(child.getNum())).collect(Collectors.toList());
  247. for (ReportForm i : calcFormulas) {
  248. String calcFormula = i.getCalcFormula();
  249. // TODO: 2021/8/27 校验公式合法性
  250. if (StrUtil.isBlank(calcFormula)) {
  251. throw new CostException("reportForm名称为" + i.getReportName() + "计算公式不正确");
  252. }
  253. BigDecimal bigDecimal = calcAmount(list, calcFormula, i);
  254. HospProfitAndLoss loss = new HospProfitAndLoss();
  255. loss.setDateYear(year).setDateMonth(month).setReportNum(i.getNum()).setReportName(i.getReportName())
  256. .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(i.getHospId());
  257. list.add(loss);
  258. }
  259. }
  260. /**
  261. * 按小计计算
  262. */
  263. private void calcByLitterCount(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list, Long hospId) {
  264. // 其他的
  265. List<ReportForm> calcList = reportForms.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
  266. List<HospProfitAndLoss> thisList = new ArrayList<>();
  267. list.forEach(i -> {
  268. calcList.forEach(j -> {
  269. if (i.getReportNum().equals(j.getNum())) {
  270. thisList.add(i);
  271. }
  272. });
  273. });
  274. if (thisList.isEmpty()) {
  275. return;
  276. }
  277. BigDecimal reduce = thisList.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  278. HospProfitAndLoss loss = new HospProfitAndLoss();
  279. loss.setDateYear(year).setDateMonth(month).setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
  280. // 小计只能有一个
  281. loss.setReportNum(child.getNum()).setReportName(child.getReportName());
  282. list.add(loss);
  283. }
  284. /**
  285. * 按分摊层级计算、
  286. *
  287. * @param hospId 医院id
  288. * @param reportForm 报表
  289. * @param list
  290. * @param year
  291. * @param month
  292. */
  293. private void calcByShareLevel(Long hospId, ReportForm reportForm, List<HospProfitAndLoss> list, int year, int month) {
  294. List<RelationVO> shareLevels = reportRelationService.getShareLevel(reportForm.getId(), hospId);
  295. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  296. if (CollUtil.isEmpty(shareLevelId)) {
  297. return;
  298. }
  299. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  300. if (costShareLevels.isEmpty()) {
  301. throw new CostException("医院分摊层级设置错误," + reportForm.getReportName());
  302. }
  303. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  304. List<AllocationQuery> allocations = allocationQueryService.getByDate(year, month, hospId, shareLevelId);
  305. if (allocations.isEmpty()) {
  306. throw new CostException("医院未分摊本月数据");
  307. }
  308. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  309. if (accountShares.isEmpty()) {
  310. return;
  311. }
  312. // allocations = allocations.stream().filter(i -> levelSorts.contains(i.getLevelSort())).collect(Collectors.toList());
  313. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  314. HospProfitAndLoss loss = new HospProfitAndLoss();
  315. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  316. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  317. list.add(loss);
  318. }
  319. /**
  320. * 计算按会计科目下的科目名称
  321. *
  322. * @param hospId 医院id
  323. * @param reportForm 报表
  324. * @param incomes 归集收入数据
  325. * @param list
  326. * @param allocationQueries 分摊成本数据
  327. * @param month
  328. * @param year
  329. */
  330. private void calcByAccount(Long hospId, ReportForm reportForm, List<IncomeCollection> incomes, List<HospProfitAndLoss> list, List<AllocationQuery> allocationQueries, int month, int year) {
  331. // check 这个医院是否有对应的损益标识
  332. reportFormService.checkExistLoss(hospId);
  333. // 报表项目关联的会计科目对象
  334. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(reportForm.getId(), hospId);
  335. if (accountRelations.isEmpty()) {
  336. return;
  337. }
  338. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  339. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  340. calcTotal.set(BigDecimal.ZERO);
  341. accountCodes.forEach(i -> {
  342. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  343. .reduce(BigDecimal.ZERO, BigDecimal::add);
  344. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  345. .reduce(BigDecimal.ZERO, BigDecimal::add);
  346. BigDecimal total = incomeAmount.add(costAmount);
  347. calcTotal.set(calcTotal.get().add(total));
  348. });
  349. HospProfitAndLoss loss = new HospProfitAndLoss();
  350. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  351. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  352. list.add(loss);
  353. }
  354. /**
  355. * 全院损益列表
  356. *
  357. * @param current 当前页
  358. * @param pageSize 每页展示数据大小
  359. * @param date 日期
  360. * @param hospId 医院id
  361. * @return PageUtils
  362. */
  363. @Override
  364. public PageUtils getHospProfits(Integer current, Integer pageSize, String date, Long hospId) {
  365. reportFormService.checkExistLoss(hospId);
  366. DateTime parse = DateUtil.parse(date);
  367. int year = DateUtil.year(parse);
  368. int month = DateUtil.month(parse) + 1;
  369. int startIndex = (current - 1) * pageSize;
  370. List<HospProfitAndLoss> list = baseMapper.getPageList(startIndex, pageSize, year, month, hospId);
  371. // 损益的时候计算下
  372. list.forEach(i -> {
  373. ReportForm one = reportFormService.getOne(
  374. new LambdaQueryWrapper<ReportForm>().select(ReportForm::getId)
  375. .eq(ReportForm::getNum, i.getReportNum())
  376. .eq(ReportForm::getHospId, hospId)
  377. .eq(ReportForm::getReportType, 3)
  378. .eq(ReportForm::getIsLoss, 1)
  379. .last(Constant.LIMIT)
  380. );
  381. if (Objects.nonNull(one)) {
  382. List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
  383. AtomicReference<BigDecimal> total = new AtomicReference<>();
  384. total.set(BigDecimal.ZERO);
  385. byMonth.forEach(j -> {
  386. if (j.getPaymentsType().equals(1)) {
  387. total.set(total.get().add(j.getTotalAmount()));
  388. } else {
  389. total.set(total.get().subtract(j.getTotalAmount()));
  390. }
  391. });
  392. i.setAmount(i.getAmount().add(total.get()));
  393. }
  394. });
  395. int totalCount = baseMapper.getPageCount(year, month, hospId);
  396. return new PageUtils(list, totalCount, pageSize, current);
  397. }
  398. /**
  399. * 导出全院损益计算
  400. *
  401. * @param date yyyy-MM-dd
  402. * @param hospId
  403. */
  404. @Override
  405. public void hospProfitReport(String date, Long hospId) {
  406. DateTime parse = DateUtil.parse(date);
  407. int year = DateUtil.year(parse);
  408. int month = DateUtil.month(parse) + 1;
  409. // 得到所有责任中心的子节点
  410. List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
  411. // List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
  412. List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
  413. // if (!byMonth.isEmpty()) {
  414. // Responsibility responsibility = new Responsibility("-1", "全院", -1L);
  415. // responsibilityList.add(responsibility);
  416. // }
  417. Map<String, Long> responseCodeParentIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
  418. Map<Long, Responsibility> responsibilityIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
  419. // 查询所有的全院损益数据 内存溢出问题
  420. List<HospProfitAndLoss> hospProfitAndLosses = getAllDataByDate(year, month, hospId);
  421. if (CollectionUtils.isEmpty(hospProfitAndLosses)) {
  422. throw new CostException(500, "未进行全院损益计算");
  423. }
  424. //判断是否有全院的数据 有单独取出另算
  425. List<HospProfitAndLoss> hospAllList = hospProfitAndLosses.stream().filter(f -> f.getResponsibilityCode().equals("-1")).collect(Collectors.toList());
  426. if (!CollectionUtils.isEmpty(hospAllList)) {
  427. hospProfitAndLosses.removeAll(hospAllList);
  428. }
  429. //多层级责任 中心 添加父类责任中心 方便excel分组
  430. for (HospProfitAndLoss hospProfitAndLoss : hospProfitAndLosses) {
  431. Long aLong = responseCodeParentIdMap.get(hospProfitAndLoss.getResponsibilityCode());
  432. if (aLong != null) {
  433. if (aLong.equals(NumberConstant.ZERO_L)) {
  434. // Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
  435. hospProfitAndLoss.setParentResponsibilityCode(hospProfitAndLoss.getResponsibilityCode());
  436. hospProfitAndLoss.setParentResponsibilityName(hospProfitAndLoss.getResponsibilityName());
  437. } else if (aLong.equals(-1L)) {
  438. hospProfitAndLoss.setParentResponsibilityCode("-1");
  439. hospProfitAndLoss.setParentResponsibilityName("全院");
  440. } else {
  441. Responsibility responsibility = responsibilityIdMap.get(aLong);
  442. if (Objects.nonNull(responsibility)) {
  443. hospProfitAndLoss.setParentResponsibilityCode(responsibility.getResponsibilityCode());
  444. hospProfitAndLoss.setParentResponsibilityName(responsibility.getResponsibilityName());
  445. }
  446. }
  447. }
  448. }
  449. //损益表设置
  450. List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
  451. .eq(ReportForm::getHospId, hospId)
  452. .eq(ReportForm::getReportType, NumberConstant.THREE));
  453. if (CollUtil.isEmpty(reportFormList)) {
  454. throw new CostException(500, "损益表未找到");
  455. }
  456. if (!byMonth.isEmpty()) {
  457. // 手动构造全院数据表头 生成全院其他收支
  458. //添加全院其他报表项目
  459. //最上层
  460. ReportForm parentReport = new ReportForm();
  461. parentReport.setId(-1L);
  462. parentReport.setReportType(NumberConstant.THREE);
  463. parentReport.setParentId(NumberConstant.ZERO_L);
  464. parentReport.setSort(0);
  465. parentReport.setReportName("全院其他收支");
  466. parentReport.setNum(-1);
  467. reportFormList.add(parentReport);
  468. //第二层按全院收支数据自动生成
  469. for (int i = 0; i < byMonth.size(); i++) {
  470. CostOtherPaymentsData data = byMonth.get(i);
  471. ReportForm reportForm = new ReportForm();
  472. // reportForm.setId(-1L -i - byMonth.size());
  473. reportForm.setId(-System.currentTimeMillis() - i);
  474. reportForm.setReportType(NumberConstant.THREE);
  475. reportForm.setParentId(-1L);
  476. reportForm.setSort(0);
  477. reportForm.setReportName(data.getPaymentsName());
  478. reportForm.setNum((int) (-data.getId()));
  479. reportFormList.add(reportForm);
  480. }
  481. }
  482. Map<Long, List<ReportForm>> collect = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getParentId));
  483. Map<String, List<ColEntity>> heads = new HashMap<>();// 最终导出的多个sheet的表头
  484. Map<String, List<Map<String, String>>> datas = new HashMap<>();// 最终导出的多个sheet的内容
  485. Map<String, Integer> types = new HashMap<>();
  486. Map<String, List<Integer>> mergeindexs = new HashMap<>();// 最终导出的每个sheet的需要纵向合并的单元格列号
  487. //第一层
  488. List<ReportForm> firstTitle = collect.get(NumberConstant.ZERO_L);
  489. List<TitleEntity> titleList = new ArrayList<>();
  490. titleList.add(new TitleEntity("0", null, "全院损益 \n" + "制表时间:" + DateUtil.now(), false, NumberConstant.ZERO));
  491. //添加默认三列责任中心 父类责任中心 子类责任中心 项目名称
  492. setDefaultColumn(titleList);
  493. for (ReportForm reportForm : firstTitle) {
  494. TitleEntity entity = new TitleEntity();
  495. entity.setId(String.valueOf(reportForm.getId()));
  496. entity.setPid(String.valueOf(reportForm.getParentId()));
  497. entity.setContent(reportForm.getReportName());
  498. entity.setFieldName(String.valueOf(reportForm.getNum()));
  499. entity.setWidth(20);
  500. entity.setSort(reportForm.getSort());
  501. boolean child = getChild(titleList, reportForm, collect);
  502. entity.setLast(child);
  503. titleList.add(entity);
  504. }
  505. titleList.sort(Comparator.comparing(TitleEntity::getSort));
  506. hospProfitAndLosses.sort(Comparator.comparing(HospProfitAndLoss::getParentResponsibilityCode));
  507. //行
  508. Map<String, List<HospProfitAndLoss>> lineMap = hospProfitAndLosses.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getParentResponsibilityCode));
  509. //列
  510. List<TitleEntity> titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList());
  511. List<Map<String, String>> rowList = new ArrayList<>();
  512. //行数据
  513. setRowList(lineMap, titleEntities, rowList);
  514. //添加 全院其他收支数据
  515. setHospRowList(hospAllList, titleEntities, rowList);
  516. try {
  517. ExcelPoiUtil excelTool = new ExcelPoiUtil("全院损益");
  518. Map<String, String> param = ImmutableMap.<String, String>builder().put("id", "id").put("pid", "pid")
  519. .put("content", "content").put("fieldName", "fieldName").put("width", "width").build();
  520. List<ColEntity> titleData = excelTool.colEntityTransformer(titleList, param, "0");
  521. Map<String, List<Integer>> autoRowHeights = new HashMap<>();
  522. heads.put("全院损益", titleData);// 每个sheet的表头,sheet名称为key
  523. datas.put("全院损益", rowList);// 每个sheet的内容,sheet名称为key
  524. types.put("全院损益", 0);// 每个sheet的样式类型,sheet名称为key
  525. mergeindexs.put("全院损益", Arrays.asList(0, 1));// 每个sheet的默认行高,sheet名称为key
  526. autoRowHeights.put("全院损益", Arrays.asList(1, 2, 3, 4, 5));
  527. // 多个sheet导出
  528. HSSFWorkbook workbook = excelTool.exportWorkbook(heads, datas, types, autoRowHeights, mergeindexs);
  529. // excelTool.save(workbook, "D:\\全院损益.xls");
  530. // // 得到上一层的title子节点
  531. //// ExcelWriter writer = ExcelUtil.getWriter();
  532. // String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
  533. // //todo:后面调整为上传到文件服务器,先启动确认环境
  534. // String fileName = "全院损益" + time + ".xlsx";
  535. // ExcelWriter writer = ExcelUtil.getWriter(fileName);
  536. //
  537. // List<String> secondTitleListCode = leafResp.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
  538. // writer.merge(leafResp.size() + 1, "全院损益计算导出 \n" + "制表时间:" + DateUtil.now());
  539. // // 得到两层结构
  540. // writer.setColumnWidth(-1, 20);
  541. // writer.passCurrentRow();
  542. // writer.merge(2, 2, 0, 1, "项目", true);
  543. // int oldSize = 2;
  544. // Map<Long, Object> map = new HashMap<>();
  545. // for (int i = 0; i < leafResp.size(); i++) {
  546. // Responsibility responsibility = leafResp.get(i);
  547. // String str = responsibility.getResponsibilityName();
  548. // writer.writeCellValue(i + 2, 2, str);
  549. // // 写父亲层级
  550. // Long parentId = responsibility.getParentId();
  551. // if (map.get(parentId) != null) {
  552. // // 如果parentId = 0
  553. // if (parentId != 0L) {
  554. // continue;
  555. // }
  556. // }
  557. // Responsibility byId = responsibilityService.getById(parentId);
  558. // String name = "";
  559. // if (byId != null) {
  560. // name = byId.getResponsibilityName();
  561. // }
  562. // int count = (int) leafResp.stream().filter(o -> o.getParentId().equals(parentId)).count();
  563. //
  564. // if (count == 1) {
  565. // writer.writeCellValue(oldSize, 1, name);
  566. // } else if (count == 0) {
  567. // writer.writeCellValue(oldSize, 1, "全院其他");
  568. // } else {
  569. // writer.merge(1, 1, oldSize, oldSize + count - 1, name, false);
  570. // }
  571. //
  572. // oldSize = oldSize + count;
  573. // map.put(parentId, oldSize);
  574. //
  575. // }
  576. // // 得到全院损益报表处理 树状结构(only 2层)
  577. // List<ReportFormVO> allHospList = reportFormService.getAllHospList(hospId);
  578. // if (allHospList.isEmpty()) {
  579. // throw new CostException("请先设置全院损益报表");
  580. // }
  581. //
  582. // if (!byMonth.isEmpty()) {
  583. // // 构造假数据 生成全院其他收支
  584. // ReportFormVO vo = new ReportFormVO(-1L, -1, "全院其他收支", 0L, new ArrayList<>());
  585. // for (CostOtherPaymentsData data : byMonth) {
  586. // ReportFormVO reportFormVO = new ReportFormVO(-2L, (int) (-data.getId()), data.getPaymentsName(), -1L, null);
  587. // vo.getChildren().add(reportFormVO);
  588. // }
  589. // allHospList.add(allHospList.size() - 1, vo);
  590. // }
  591. // // 查询所有的全院损益数据 内存溢出问题
  592. // List<HospProfitAndLoss> list = getAllDataByDate(year, month, hospId);
  593. // int lastRow = 3;
  594. // for (int i = 0; i < allHospList.size(); i++) {
  595. // ReportFormVO parentFormVO = allHospList.get(i);
  596. // List<ReportFormVO> children = parentFormVO.getChildren();
  597. // if (CollUtil.isEmpty(children)) {
  598. // continue;
  599. // }
  600. // int size = children.size();
  601. // // 当最后一个的时候写上全院其他收支
  602. // if (allHospList.size() == 1) {
  603. // writer.writeCellValue(0, lastRow, parentFormVO.getReportName());
  604. // } else {
  605. // writer.merge(lastRow, lastRow + size - 1, 0, 0, parentFormVO.getReportName(), true);
  606. // }
  607. //
  608. // // 具体的报表项目
  609. // for (int j = 0; j < size; j++) {
  610. // // todo 可以抽取出单独方法
  611. // ReportFormVO childFormVO = children.get(j);
  612. // // 第二列的数据
  613. // writer.writeCellValue(1, lastRow + j, childFormVO.getReportName());
  614. // // 单独计每个数据的责任中心对应的金额
  615. // for (int k = 0; k < secondTitleListCode.size(); k++) {
  616. //
  617. // String responsibilityCode = secondTitleListCode.get(k);
  618. // Integer num = childFormVO.getNum();
  619. // HospProfitAndLoss loss = list.stream().filter(o -> o.getReportNum().equals(num) && o.getResponsibilityCode().equals(responsibilityCode)).findAny()
  620. // .orElse(null);
  621. // BigDecimal bigDecimal = Objects.isNull(loss) ? BigDecimal.ZERO : loss.getAmount();
  622. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  623. // if (k == secondTitleListCode.size() - 1) {
  624. // bigDecimal = list.stream().filter(o -> o.getReportNum().equals(num)).map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  625. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  626. //
  627. // if (j == size - 1 && i == allHospList.size() - 1) {
  628. // // 计算 其他
  629. // BigDecimal another = BigDecimal.ZERO;
  630. // for (CostOtherPaymentsData costOtherPaymentsData : byMonth) {
  631. // if (costOtherPaymentsData.getPaymentsType() == 1) {
  632. // another = another.add(costOtherPaymentsData.getTotalAmount());
  633. // } else {
  634. // another = another.subtract(costOtherPaymentsData.getTotalAmount());
  635. // }
  636. // }
  637. // bigDecimal = bigDecimal.add(another);
  638. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  639. // }
  640. // }
  641. //
  642. //
  643. // }
  644. //
  645. // }
  646. // lastRow = lastRow + size;
  647. // }
  648. String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
  649. FileItemFactory factory = new DiskFileItemFactory(5242880, null);
  650. FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, "全院损益" + time + ".xls");
  651. String file = "";
  652. OutputStream outputStream = fileItem.getOutputStream();
  653. // writer.flush(outputStream,true);
  654. workbook.write(outputStream);
  655. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  656. //上传 excel
  657. file = uploadFile(multipartFile);
  658. //保存文件记录
  659. FileRecord fileRecord = new FileRecord();
  660. fileRecord.setFileName("全院损益" + time + ".xls")
  661. .setFileSource(1)
  662. .setFileType("全院损益")
  663. .setFileUrl(file)
  664. .setHospId(hospId)
  665. .setDateYear(year).setDateMonth(month)
  666. .setCreateTime(System.currentTimeMillis());
  667. fileRecordService.save(fileRecord);
  668. workbook.close();
  669. } catch (Exception e) {
  670. throw new RuntimeException(e);
  671. }
  672. }
  673. private static void setHospRowList(List<HospProfitAndLoss> hospAllList, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
  674. List<Map<String, String>> amountRowList = new ArrayList<>();
  675. for (Map<String, String> map : rowList) {
  676. String itemType = map.get("itemType");
  677. if (itemType.equals("金额")) {
  678. amountRowList.add(map);
  679. }
  680. }
  681. //相 同key 的数值 进行汇总
  682. // for (int i = 0; i < 2; i++) {
  683. Map<String, String> hospMap = new HashMap<>();
  684. for (TitleEntity titleEntity : titleEntities) {
  685. AtomicReference<BigDecimal> total = new AtomicReference<>(new BigDecimal("0.00"));
  686. for (Map<String, String> map : amountRowList) {
  687. String s = map.get(titleEntity.getFieldName());
  688. if (!titleEntity.getFieldName().equals("child") && !titleEntity.getFieldName().equals("parent") && !titleEntity.getFieldName().equals("itemType")) {
  689. // if(StringUtils.isEmpty(s)){
  690. // total.updateAndGet(v -> v.add(BigDecimal.ZERO));
  691. // }else {
  692. total.updateAndGet(v -> v.add(new BigDecimal(s)));
  693. // }
  694. }
  695. }
  696. if (titleEntity.getFieldName().equals("parent")) {
  697. hospMap.put("parent", "全院");
  698. } else if (titleEntity.getFieldName().equals("child")) {
  699. hospMap.put("child", "全院");
  700. } else if (titleEntity.getFieldName().equals("itemType")) {
  701. // if (i == 0) {
  702. hospMap.put("itemType", "金额");
  703. // } else {
  704. // hospMap.put("itemType", "占比");
  705. // }
  706. } else {
  707. // if (i == 0) {
  708. hospMap.put(titleEntity.getFieldName(), total.get().toString());
  709. if(!CollectionUtils.isEmpty(hospAllList)){
  710. for (HospProfitAndLoss data : hospAllList) {
  711. hospMap.put(data.getReportNum().toString(), data.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  712. }
  713. }
  714. // } else {
  715. // hospMap.put(titleEntity.getFieldName(), "");
  716. // }
  717. }
  718. }
  719. rowList.add(hospMap);
  720. // }
  721. }
  722. private static void setRowList(Map<String, List<HospProfitAndLoss>> lineMap, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
  723. DecimalFormat df = new DecimalFormat("0.00%");
  724. for (String parentCode : lineMap.keySet()) {
  725. List<HospProfitAndLoss> costDepartmentProfits1 = lineMap.get(parentCode);
  726. Map<String, List<HospProfitAndLoss>> listMap = costDepartmentProfits1.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getResponsibilityCode));
  727. for (String s : listMap.keySet()) {
  728. List<HospProfitAndLoss> costDepartmentProfits2 = listMap.get(s);
  729. Map<String, HospProfitAndLoss> map = costDepartmentProfits2.stream().collect(Collectors.toMap(profit -> String.valueOf(profit.getReportNum()), profit -> profit, (a, b) -> b));
  730. for (int i = 0; i < 2; i++) {
  731. Map<String, String> m = new HashMap<String, String>();
  732. for (TitleEntity titleEntity : titleEntities) {
  733. if (titleEntity.getId().equals("parentResponsibility")) {
  734. m.put("parent", costDepartmentProfits2.get(0).getParentResponsibilityName());
  735. } else if (titleEntity.getId().equals("childResponsibility")) {
  736. m.put("child", costDepartmentProfits2.get(0).getResponsibilityName());
  737. } else if (titleEntity.getId().equals("item")) {
  738. if (i == 0) {
  739. m.put("itemType", "金额");
  740. } else {
  741. m.put("itemType", "占比");
  742. }
  743. } else if (titleEntity.getId().contains("-")) {
  744. HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
  745. if (Objects.nonNull(profit)) {
  746. if (i == 0) {
  747. m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  748. } else {
  749. if (profit.getPercent() != null) {
  750. m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
  751. } else {
  752. m.put(titleEntity.getFieldName(), "");
  753. }
  754. }
  755. } else {
  756. m.put(titleEntity.getFieldName(), "0.00");
  757. }
  758. } else {
  759. HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
  760. if (Objects.nonNull(profit)) {
  761. if (i == 0) {
  762. m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  763. } else {
  764. if (profit.getPercent() != null) {
  765. m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
  766. } else {
  767. m.put(titleEntity.getFieldName(), "");
  768. }
  769. }
  770. }
  771. }
  772. }
  773. rowList.add(m);
  774. }
  775. }
  776. }
  777. }
  778. private void setDefaultColumn(List<TitleEntity> titleList) {
  779. TitleEntity parentResponsibility = new TitleEntity();
  780. parentResponsibility.setId("parentResponsibility");
  781. parentResponsibility.setPid("0");
  782. parentResponsibility.setContent("");
  783. parentResponsibility.setFieldName("parent");
  784. parentResponsibility.setWidth(15);
  785. parentResponsibility.setSort(NumberConstant.ZERO);
  786. parentResponsibility.setLast(true);
  787. titleList.add(parentResponsibility);
  788. TitleEntity childResponsibility = new TitleEntity();
  789. childResponsibility.setId("childResponsibility");
  790. childResponsibility.setPid("0");
  791. childResponsibility.setContent("");
  792. childResponsibility.setFieldName("child");
  793. childResponsibility.setWidth(15);
  794. childResponsibility.setSort(NumberConstant.ZERO);
  795. childResponsibility.setLast(true);
  796. titleList.add(childResponsibility);
  797. TitleEntity item = new TitleEntity();
  798. item.setId("item");
  799. item.setPid("0");
  800. item.setContent("");
  801. item.setFieldName("itemType");
  802. item.setWidth(10);
  803. item.setSort(NumberConstant.ZERO);
  804. item.setLast(true);
  805. titleList.add(item);
  806. }
  807. private boolean getChild(List<TitleEntity> titleList, ReportForm reportForm, Map<Long, List<ReportForm>> collect) {
  808. List<ReportForm> forms = collect.get(reportForm.getId());
  809. if (!CollectionUtils.isEmpty(forms)) {
  810. for (ReportForm form : forms) {
  811. TitleEntity entity = new TitleEntity();
  812. entity.setId(String.valueOf(form.getId()));
  813. entity.setPid(String.valueOf(form.getParentId()));
  814. entity.setContent(form.getReportName());
  815. entity.setFieldName(String.valueOf(form.getNum()));
  816. entity.setWidth(15);
  817. entity.setSort(form.getSort());
  818. boolean last = getChild(titleList, form, collect);
  819. entity.setLast(last);
  820. titleList.add(entity);
  821. }
  822. return false;
  823. } else {
  824. return true;
  825. }
  826. }
  827. public String uploadFile(MultipartFile file) {
  828. Long hospId = UserContext.getCurrentLoginHospId();
  829. String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + ".xls";
  830. DateTime date = DateUtil.date();
  831. int month = DateUtil.month(date) + 1;
  832. int year = DateUtil.year(date);
  833. int day = DateUtil.dayOfMonth(date);
  834. String fileUrl = "";
  835. try {
  836. // file.transferTo(new File(localFilePath));
  837. String format = DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN);
  838. String originalFilename = format + fileName;
  839. String dataDirectory = minioConfig.getBucketName();
  840. String uploadFileName = "hospReport" + "/" + hospId + "/" + year + "/" + month + "/" + day + "/" + originalFilename;
  841. InputStream inputStream = file.getInputStream();
  842. minioFileUtil.putObject(dataDirectory, uploadFileName, inputStream);
  843. fileUrl = minioFileUtil.getObjectUrl(dataDirectory, uploadFileName);
  844. } catch (IOException e) {
  845. log.error("【文件上传至服务器】失败,绝对路径:{}", e.getMessage());
  846. throw new CostException(ErrorCodeEnum.FILE_UPLOAD_ERROR);
  847. }
  848. return fileUrl;
  849. }
  850. @Override
  851. public PageUtils hospProfitReports(Integer current, Integer pageSize, Long hospId, String date) {
  852. DateTime parse = DateUtil.parse(date);
  853. int year = DateUtil.year(parse);
  854. int month = DateUtil.month(parse) + 1;
  855. Page<FileRecord> page = new Page<>(current, pageSize);
  856. Page<FileRecord> pageUtils = fileRecordService.page(page,
  857. new LambdaQueryWrapper<FileRecord>()
  858. .eq(FileRecord::getHospId, hospId)
  859. .eq(FileRecord::getFileType, "全院损益")
  860. .eq(FileRecord::getDateYear, year)
  861. .eq(FileRecord::getDateMonth, month)
  862. .orderByDesc(FileRecord::getCreateTime)
  863. );
  864. return new PageUtils(pageUtils);
  865. }
  866. private List<HospProfitAndLoss> getAllDataByDate(int year, int month, Long hospId) {
  867. return this.list(
  868. new LambdaQueryWrapper<HospProfitAndLoss>()
  869. .eq(HospProfitAndLoss::getHospId, hospId)
  870. .eq(HospProfitAndLoss::getDateMonth, month)
  871. .eq(HospProfitAndLoss::getDateYear, year)
  872. );
  873. }
  874. /**
  875. * @param date
  876. * @param hospId
  877. */
  878. @Override
  879. @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
  880. public void calcByResponsibility(String date, Long hospId) {
  881. List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
  882. DateTime parse = DateUtil.parse(date);
  883. int year = DateUtil.year(parse);
  884. int month = DateUtil.month(parse) + 1;
  885. this.remove(
  886. new LambdaQueryWrapper<HospProfitAndLoss>()
  887. .eq(HospProfitAndLoss::getDateYear, year)
  888. .eq(HospProfitAndLoss::getDateMonth, month)
  889. .eq(HospProfitAndLoss::getHospId, hospId)
  890. );
  891. // 得到全院损益计算报表
  892. List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
  893. if (CollUtil.isEmpty(reportForms)) {
  894. throw new CostException("医院未设置全院损益计算报表");
  895. }
  896. // 得到这个月所有收入数据
  897. List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
  898. if (incomes.isEmpty()) {
  899. throw new CostException("医院未归集本月收入数据");
  900. }
  901. Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
  902. // 得到这个月的所有成本数据
  903. List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
  904. if (allocationQueries.isEmpty()) {
  905. throw new CostException("医院未分摊本月数据");
  906. }
  907. List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueries, AllocationQueryReportVO.class);
  908. allocationQueryReportVOList.forEach(i -> {
  909. i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
  910. i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
  911. });
  912. // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
  913. List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>().lambda().eq(Allocation::getHospId, hospId)
  914. .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month));
  915. if (CollUtil.isEmpty(allocationList)) {
  916. throw new CostException(500, "分摊报表数据不存在");
  917. }
  918. // 查询最后一个层级的责任中心
  919. List<CostShareLevel> costShareLevelList = shareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
  920. .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort));
  921. if (CollUtil.isEmpty(costShareLevelList)) {
  922. throw new CostException(500, "分摊层级未设置");
  923. }
  924. List<HospProfitAndLossVo> listVo = new ArrayList<>();
  925. // List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
  926. int finalYear = year;
  927. int finalMonth = month;
  928. leafResp.forEach(i -> {
  929. reportForms.forEach(j -> {
  930. HospProfitAndLossVo hospProfitAndLossVo = new HospProfitAndLossVo();
  931. hospProfitAndLossVo.setDateYear(finalYear);
  932. hospProfitAndLossVo.setDateMonth(finalMonth);
  933. hospProfitAndLossVo.setReportNum(j.getNum());
  934. hospProfitAndLossVo.setReportName(j.getReportName());
  935. hospProfitAndLossVo.setResponsibilityCode(i.getResponsibilityCode());
  936. hospProfitAndLossVo.setResponsibilityName(i.getResponsibilityName());
  937. hospProfitAndLossVo.setCostType(NumberConstant.ZERO);
  938. hospProfitAndLossVo.setIncomeType(NumberConstant.ZERO);
  939. hospProfitAndLossVo.setHospId(hospId);
  940. hospProfitAndLossVo.setType(j.getCostType());
  941. hospProfitAndLossVo.setFraction(j.getFraction());
  942. hospProfitAndLossVo.setReportId(j.getId());
  943. hospProfitAndLossVo.setReportNum(j.getNum());
  944. hospProfitAndLossVo.setCalcType(j.getCalcType());
  945. hospProfitAndLossVo.setReportName(j.getReportName());
  946. hospProfitAndLossVo.setCalcFormula(j.getCalcFormula());
  947. hospProfitAndLossVo.setReportParentId(j.getParentId());
  948. listVo.add(hospProfitAndLossVo);
  949. });
  950. });
  951. Map<Long, List<HospProfitAndLossVo>> listMap = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getReportId));
  952. List<HospProfitAndLossVo> allList = BeanUtil.convertList(listVo, HospProfitAndLossVo.class);
  953. // 记录每一次计算的钱
  954. //所有小计 总计单独处理
  955. listVo.forEach(i -> {
  956. Integer calcType = i.getCalcType();
  957. if (NumberConstant.ONE.equals(calcType)) {
  958. // TODO 按照会计科目进行计算
  959. i.setAmount(setAccountReportData(i, incomes, allocationQueryReportVOList, reportRelationMap));
  960. } else if (NumberConstant.TWO.equals(calcType)) {
  961. // TODO 按照分摊层级进行计算
  962. i.setAmount(setShareLevelReportData(i, reportRelationMap, allocationList));
  963. } else if (NumberConstant.THREE.equals(calcType)) {
  964. // TODO 按照小计进行计算
  965. i.setAmount(setSubtotal(i, costShareLevelList, listMap, listVo, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
  966. } else if (NumberConstant.FOUR.equals(calcType)) {
  967. // TODO 按照计算公式进行计算
  968. i.setAmount(setCalculation(i, listVo, costShareLevelList, listMap, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
  969. } else if (NumberConstant.FIVE.equals(calcType)) {
  970. // TODO 按照责任中心进行计算
  971. i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList));
  972. } else {
  973. i.setAmount(new BigDecimal("0.0000"));
  974. }
  975. });
  976. //
  977. //
  978. //
  979. // listVo.forEach(i -> {
  980. // Integer calcType = i.getCalcType();
  981. // if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
  982. // // 按会计科目计算单的话
  983. // calcByAccountByResp(hospId, i);
  984. // } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
  985. // // 分摊层级计算
  986. // calcByShareLevelResp(hospId, i);
  987. // } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
  988. // // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
  989. // calcByLitterCountResp(i,listParentMap, listVo,hospId);
  990. // } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
  991. // // 按公式 (要保证总合计放到最后呀)
  992. // calcByFormulaResp(i,listVo);
  993. // } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
  994. // // 责任中心
  995. // calcByResponsibilityResp(hospId, i);
  996. // } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
  997. // // 不设置不计算
  998. // i.setAmount(new BigDecimal("0.0000"));
  999. // } else {
  1000. // i.setAmount(new BigDecimal("0.0000"));
  1001. // }
  1002. // });
  1003. // for (Responsibility responsibility : leafResp) {
  1004. // for (ReportForm parentForm : reportForms) {
  1005. // Long parentId = parentForm.getId();
  1006. // List<ReportForm> children = reportForms.stream().filter(i -> i.getParentId().equals(parentId)).collect(Collectors.toList());
  1007. // for (ReportForm child : children) {
  1008. // Integer calcType = child.getCalcType();
  1009. // if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
  1010. // // 按会计科目计算单的话
  1011. // calcByAccountByResp(hospId, child, list, month, year, responsibility);
  1012. // } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
  1013. // // 分摊层级计算
  1014. // calcByShareLevelResp(hospId, child, list, year, month, responsibility);
  1015. // } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
  1016. // // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
  1017. // calcByLitterCountResp(year, month, child, children, list, hospId, responsibility);
  1018. // } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
  1019. // // 按公式 (要保证总合计放到最后呀)
  1020. // calcByFormulaResp(year, month, child, list, responsibility);
  1021. // } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
  1022. // // 责任中心
  1023. // calcByResponsibilityResp(hospId, child, list, year, month, responsibility);
  1024. // } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
  1025. // // 不设置不计算
  1026. // } else {
  1027. //
  1028. // }
  1029. // }
  1030. // }
  1031. // }
  1032. //计算占比
  1033. if (CollectionUtils.isEmpty(listVo)) {
  1034. return;
  1035. }
  1036. //收入
  1037. List<HospProfitAndLossVo> profitIncomeList = listVo.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList());
  1038. List<HospProfitAndLossVo> profitIncome = costPercent(profitIncomeList);
  1039. //成本
  1040. List<HospProfitAndLossVo> profitCostList = listVo.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList());
  1041. List<HospProfitAndLossVo> profitCost = costPercent(profitCostList);
  1042. //不计算项目
  1043. List<HospProfitAndLossVo> noCompute = listVo.stream().filter(f -> f.getFraction().equals(NumberConstant.THREE)).collect(Collectors.toList());
  1044. noCompute.forEach(profitVO -> profitVO.setPercent(null));
  1045. List<HospProfitAndLossVo> listAllVo = new ArrayList<>();
  1046. if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
  1047. listAllVo.addAll(profitIncome);
  1048. listAllVo.addAll(profitCost);
  1049. listAllVo.addAll(noCompute);
  1050. } else if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(noCompute)) {
  1051. listAllVo.addAll(noCompute);
  1052. listAllVo.addAll(profitIncome);
  1053. } else if (!CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
  1054. listAllVo.addAll(noCompute);
  1055. listAllVo.addAll(profitCost);
  1056. } else if (!CollectionUtils.isEmpty(noCompute)) {
  1057. listAllVo.addAll(noCompute);
  1058. }
  1059. List<HospProfitAndLoss> list = BeanUtil.convertList(listAllVo, HospProfitAndLoss.class);
  1060. // 处理医院其他收支
  1061. List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
  1062. if (!otherPaymentsDatas.isEmpty()) {
  1063. otherPaymentsDatas.forEach(ele -> {
  1064. HospProfitAndLoss loss = new HospProfitAndLoss();
  1065. loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum((int) (-ele.getId()))
  1066. .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId)
  1067. .setResponsibilityName("全院").setResponsibilityCode("-1").setPercent(null)
  1068. ;
  1069. list.add(loss);
  1070. });
  1071. }
  1072. long l = System.currentTimeMillis();
  1073. list.forEach(i -> {
  1074. i.setCreateTime(l);
  1075. });
  1076. this.saveBatch(list);
  1077. }
  1078. /**
  1079. * 按照责任中心进行计算
  1080. * 原始责任中心是设置的责任中心 目标责任中心是报表的责任中心
  1081. * 查询分摊报表里面目标责任中心是当前责任中心 报表责任中心是当前设置的责任中心
  1082. */
  1083. public BigDecimal setResponsibilityCode(HospProfitAndLossVo costDepartmentProfitVO, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1084. // 获取当前报表对应的责任中心
  1085. List<ReportRelation> reportRelationList = reportRelationMap.get(costDepartmentProfitVO.getReportId());
  1086. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1087. if (CollUtil.isNotEmpty(reportRelationList)) {
  1088. // 获取对应的责任中心的Code集合 这个是设置的责任中心
  1089. List<String> responsibilityCodes = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
  1090. if (CollUtil.isNotEmpty(responsibilityCodes)) {
  1091. // 查询报表里面是当前分摊层级的数据
  1092. List<Allocation> allocations = allocationList.stream().filter(i -> i.getTargetResponsibilityCode().equals(costDepartmentProfitVO.getResponsibilityCode()) && responsibilityCodes.contains(i.getResponsibilityCode())).collect(Collectors.toList());
  1093. if (CollUtil.isNotEmpty(allocations)) {
  1094. BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1095. sum.set(reduce);
  1096. // allocations.forEach(m -> {
  1097. // sum.updateAndGet(v -> v.add(m.getAmount()));
  1098. // });
  1099. }
  1100. }
  1101. }
  1102. // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
  1103. return sum.get();
  1104. }
  1105. /***
  1106. * 按照计算方式进行计算
  1107. */
  1108. public BigDecimal setCalculation(HospProfitAndLossVo costDepartmentProfitVO, List<HospProfitAndLossVo> costDepartmentProfitVOList,
  1109. List<CostShareLevel> costShareLevelList, Map<Long, List<HospProfitAndLossVo>> listMap,
  1110. List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList,
  1111. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1112. // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2]
  1113. String calcFormula = costDepartmentProfitVO.getCalcFormula();
  1114. String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
  1115. String replace = calcFormula.replace("[", "").replace("]", "").replace("+", ",").replace("-", ",-");
  1116. List<Integer> calcFormulaList = Arrays.stream(replace.split(StrUtil.COMMA)).map(Integer::valueOf).collect(Collectors.toList());
  1117. // 查询这个编号集合的报表
  1118. AtomicReference<BigDecimal> bigDecimal = new AtomicReference<>(new BigDecimal("0.0000"));
  1119. calcFormulaList.forEach(calc -> {
  1120. Integer calcNum = Math.abs(calc);
  1121. List<Long> reportIdList = allList.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode) && calcNum.equals(i.getReportNum())).map(HospProfitAndLossVo::getReportId).collect(Collectors.toList());
  1122. if (CollUtil.isNotEmpty(reportIdList)) {
  1123. reportIdList.forEach(i -> {
  1124. List<HospProfitAndLossVo> profitVOS = listMap.get(i);
  1125. if (CollUtil.isEmpty(profitVOS)) {
  1126. throw new CostException(500, "报表未找到");
  1127. }
  1128. BigDecimal amount = getAmount(profitVOS, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
  1129. if (calc > 0) {
  1130. bigDecimal.updateAndGet(v -> v.add(amount));
  1131. } else {
  1132. bigDecimal.updateAndGet(v -> v.subtract(amount));
  1133. }
  1134. });
  1135. }
  1136. });
  1137. return bigDecimal.get();
  1138. }
  1139. /**
  1140. * 按照小计的计算方式
  1141. * 同一个目录下相同的其他金额的和
  1142. */
  1143. public BigDecimal setSubtotal(HospProfitAndLossVo costDepartmentProfitVO,
  1144. List<CostShareLevel> costShareLevelList,
  1145. Map<Long, List<HospProfitAndLossVo>> listMap,
  1146. List<HospProfitAndLossVo> profitVOS,
  1147. List<IncomeCollection> list,
  1148. List<AllocationQueryReportVO> allocationQueryReportVOList,
  1149. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1150. // 因为报表是按照报表项目的升序进行排序的 前面的报表是已经进行计算了的
  1151. // 查询当前报表的父层级id
  1152. Long reportParentId = costDepartmentProfitVO.getReportParentId();
  1153. String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
  1154. // 查询报表里面在当前父层级下的并且不是自己的报表项目
  1155. List<HospProfitAndLossVo> costDepartmentProfitVOS = allList.stream().filter(i -> i.getReportParentId().equals(reportParentId) && i.getResponsibilityCode().equals(responsibilityCode) && !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
  1156. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
  1157. // 遍历数据 之前的已经经过了计算
  1158. costDepartmentProfitVOS.forEach(i -> {
  1159. Long reportId = i.getReportId();
  1160. List<HospProfitAndLossVo> costDepartmentProfitVOS1 = listMap.get(reportId);
  1161. if (CollUtil.isEmpty(costDepartmentProfitVOS1)) {
  1162. throw new CostException(500, "报表未找到");
  1163. }
  1164. BigDecimal amount = getAmount(costDepartmentProfitVOS1, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
  1165. sum.set(amount.add(sum.get()));
  1166. ;
  1167. });
  1168. // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
  1169. return sum.get();
  1170. }
  1171. /**
  1172. * 判断是那种计算方式 调用方法进行计算
  1173. */
  1174. public BigDecimal getAmount(List<HospProfitAndLossVo> profitVOS,
  1175. List<CostShareLevel> costShareLevelList,
  1176. String responsibilityCode, List<IncomeCollection> list,
  1177. List<AllocationQueryReportVO> allocationQueryReportVOList,
  1178. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList,
  1179. Map<Long, List<HospProfitAndLossVo>> listMap, List<HospProfitAndLossVo> allList) {
  1180. BigDecimal bigDecimal = new BigDecimal("0.0000");
  1181. // 在对这个报表进行过滤
  1182. List<HospProfitAndLossVo> costDepartmentProfitVOS = profitVOS.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList());
  1183. // 都一个就是
  1184. HospProfitAndLossVo costDepartmentProfitVO = costDepartmentProfitVOS.get(0);
  1185. Integer calcType = costDepartmentProfitVO.getCalcType();
  1186. if (NumberConstant.ONE.equals(calcType)) {
  1187. // 调用计算的方法 按照会计科目
  1188. bigDecimal = setAccountReportData(costDepartmentProfitVO, list, allocationQueryReportVOList, reportRelationMap);
  1189. } else if (NumberConstant.TWO.equals(calcType)) {
  1190. // 按照分摊层级
  1191. bigDecimal = setShareLevelReportData(costDepartmentProfitVO, reportRelationMap, allocationList);
  1192. } else if (NumberConstant.THREE.equals(calcType)) {
  1193. // 小计
  1194. bigDecimal = setSubtotal(costDepartmentProfitVO, costShareLevelList, listMap, profitVOS, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
  1195. } else if (NumberConstant.FIVE.equals(calcType)) {
  1196. // 按照责任中心
  1197. bigDecimal = setResponsibilityCode(costDepartmentProfitVO, reportRelationMap, allocationList, allList);
  1198. } else if (NumberConstant.FOUR.equals(calcType)) {
  1199. bigDecimal = setCalculation(costDepartmentProfitVO, costDepartmentProfitVOS, costShareLevelList, listMap, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
  1200. }
  1201. return bigDecimal;
  1202. }
  1203. private BigDecimal setAccountReportData(HospProfitAndLossVo i, List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList, Map<Long, List<ReportRelation>> reportRelationMap) {
  1204. // 在报表关联里面查询当前报表关联的
  1205. Long reportId = i.getReportId();
  1206. List<ReportRelation> reportRelationList = reportRelationMap.get(reportId);
  1207. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1208. if (CollUtil.isNotEmpty(reportRelationList)) {
  1209. // 获取对应的会计科目信息 筛选会计科目的Code
  1210. List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
  1211. // 查找在归集数据里面当前责任中心对应的这些会计科目的金额
  1212. List<IncomeCollection> incomeCollectionList = list.stream().filter(income -> income.getResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList());
  1213. // 需要查询分摊后的表
  1214. List<AllocationQueryReportVO> reportVOList = allocationQueryReportVOList.stream().filter(m -> m.getTargetResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(m.getAccountingCode())).collect(Collectors.toList());
  1215. if (CollUtil.isNotEmpty(incomeCollectionList)) {
  1216. incomeCollectionList.forEach(m -> {
  1217. sum.updateAndGet(v -> v.add(m.getAmount()));
  1218. });
  1219. }
  1220. // 成本减
  1221. if (CollUtil.isNotEmpty(reportVOList)) {
  1222. reportVOList.forEach(m -> {
  1223. sum.updateAndGet(v -> v.add(m.getAmount()));
  1224. });
  1225. }
  1226. }
  1227. // i.setAmount(new BigDecimal(sum.toString()));
  1228. // numMap.put(i.getReportNum()+i.getResponsibilityCode(),new BigDecimal(sum.toString()));
  1229. return sum.get();
  1230. }
  1231. private BigDecimal setShareLevelReportData(HospProfitAndLossVo i, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList) {
  1232. List<ReportRelation> reportRelationList = reportRelationMap.get(i.getReportId());
  1233. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1234. if (CollUtil.isNotEmpty(reportRelationList)) {
  1235. // 找到对应的分摊层级的Id 但是分摊报表里面存的是分摊层级的序号
  1236. List<Long> shareLevelIds = reportRelationList.stream().map(ReportRelation::getRelationCode).map(Long::valueOf).collect(Collectors.toList());
  1237. // List<Integer> levelShortList = costShareLevelList.stream()
  1238. // .filter(m -> shareLevelIds.contains(m.getId()))
  1239. // .map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  1240. if (CollUtil.isNotEmpty(shareLevelIds)) {
  1241. // 查询报表里面是当前分摊层级的数据
  1242. List<Allocation> allocations = allocationList.stream().filter(m -> shareLevelIds.contains(m.getShareLevelId()) && m.getTargetResponsibilityCode().equals(i.getResponsibilityCode())).collect(Collectors.toList());
  1243. if (CollUtil.isNotEmpty(allocations)) {
  1244. // allocations.forEach(m -> {
  1245. // sum.updateAndGet(v -> v.add(m.getAmount()));
  1246. // });
  1247. BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1248. sum.set(reduce);
  1249. }
  1250. }
  1251. }
  1252. // i.setAmount(new BigDecimal(sum.toString()));
  1253. return sum.get();
  1254. }
  1255. private void calcByLitterCountResp(HospProfitAndLossVo lossVo, Map<Long, List<HospProfitAndLossVo>> listParentMap, List<HospProfitAndLossVo> listVo, Long hospId) {
  1256. //lossVo 当前 小计对象
  1257. //listParentMap 与小计同级别的对象
  1258. //listVo 存储计算过的对象
  1259. // 通地当前小计 找出 同级别需要合计的对象 再从计算过的对象取出数值合计
  1260. Long reportParentId = lossVo.getReportParentId();
  1261. List<HospProfitAndLossVo> hospProfitAndLossVos = listParentMap.get(reportParentId);
  1262. //去除小计本身
  1263. hospProfitAndLossVos.remove(lossVo);
  1264. List<Integer> reportNums = hospProfitAndLossVos.stream().map(HospProfitAndLossVo::getReportNum).collect(Collectors.toList());
  1265. List<HospProfitAndLossVo> collect = listVo.stream().filter(i -> reportNums.contains(i.getReportNum()) && i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
  1266. if (collect.isEmpty()) {
  1267. return;
  1268. }
  1269. BigDecimal reduce = collect.stream().map(HospProfitAndLossVo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1270. lossVo.setAmount(reduce);
  1271. }
  1272. private List<HospProfitAndLossVo> costPercent(List<HospProfitAndLossVo> profitIncomeList) {
  1273. List<HospProfitAndLossVo> list = new ArrayList<>();
  1274. Map<String, List<HospProfitAndLossVo>> responsibilityGroup = profitIncomeList.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getResponsibilityCode));
  1275. for (String s : responsibilityGroup.keySet()) {
  1276. List<HospProfitAndLossVo> costDepartmentProfitVOS = responsibilityGroup.get(s);
  1277. Map<Integer, List<HospProfitAndLossVo>> collect = costDepartmentProfitVOS.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getFraction));
  1278. //分母只有一个
  1279. List<HospProfitAndLossVo> denominatorList = collect.get(NumberConstant.TWO);
  1280. if (denominatorList.size() > 1) {
  1281. throw new CostException("收入项目分母大于一个,请查证后再计算科室损益");
  1282. }
  1283. BigDecimal denominator = denominatorList.get(0).getAmount();
  1284. //收入分子
  1285. List<HospProfitAndLossVo> numeratorList = collect.get(NumberConstant.ONE);
  1286. if (denominator.compareTo(BigDecimal.ZERO) == 0) {
  1287. for (HospProfitAndLossVo profitVO : numeratorList) {
  1288. profitVO.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  1289. }
  1290. denominatorList.get(0).setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  1291. } else {
  1292. for (HospProfitAndLossVo profitVO : numeratorList) {
  1293. profitVO.setPercent(profitVO.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
  1294. }
  1295. denominatorList.get(0).setPercent(BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP));
  1296. }
  1297. list.add(denominatorList.get(0));
  1298. list.addAll(numeratorList);
  1299. }
  1300. return list;
  1301. }
  1302. private void calcByResponsibilityResp(Long hospId, HospProfitAndLossVo lossVo) {
  1303. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(lossVo.getReportId(), hospId);
  1304. if (responsibilities.isEmpty()) {
  1305. return;
  1306. }
  1307. List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  1308. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  1309. calcTotal.set(BigDecimal.ZERO);
  1310. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  1311. responsibilityCodes.forEach(i -> {
  1312. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  1313. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1314. calcTotal.set(calcTotal.get().add(costAmount));
  1315. });
  1316. lossVo.setAmount(calcTotal.get());
  1317. }
  1318. private void calcByResponsibilityResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
  1319. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(child.getId(), hospId);
  1320. if (responsibilities.isEmpty()) {
  1321. return;
  1322. }
  1323. List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  1324. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  1325. calcTotal.set(BigDecimal.ZERO);
  1326. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  1327. responsibilityCodes.forEach(i -> {
  1328. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  1329. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1330. calcTotal.set(calcTotal.get().add(costAmount));
  1331. });
  1332. HospProfitAndLoss loss = new HospProfitAndLoss();
  1333. loss.setReportName(child.getReportName()).setReportNum(child.getNum()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  1334. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  1335. list.add(loss);
  1336. }
  1337. private void calcByFormulaResp(HospProfitAndLossVo lossVo, List<HospProfitAndLossVo> list) {
  1338. // 得到这个责任中心下所有的已经收集的数据
  1339. List<HospProfitAndLossVo> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
  1340. String calcFormula = lossVo.getCalcFormula();
  1341. // TODO: 2021/8/27 校验公式合法性
  1342. if (StrUtil.isBlank(calcFormula)) {
  1343. throw new CostException("reportForm名称为" + lossVo.getReportName() + "计算公式不正确");
  1344. }
  1345. BigDecimal bigDecimal = calcAmountRes(hadCalcLosses, calcFormula);
  1346. lossVo.setAmount(bigDecimal);
  1347. }
  1348. private void calcByFormulaResp(int year, int month, ReportForm child, List<HospProfitAndLoss> list, Responsibility responsibility) {
  1349. // 得到这个责任中心下所有的已经收集的数据
  1350. List<HospProfitAndLoss> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
  1351. String calcFormula = child.getCalcFormula();
  1352. // TODO: 2021/8/27 校验公式合法性
  1353. if (StrUtil.isBlank(calcFormula)) {
  1354. throw new CostException("reportForm名称为" + child.getReportName() + "计算公式不正确");
  1355. }
  1356. BigDecimal bigDecimal = calcAmountResp(hadCalcLosses, calcFormula);
  1357. HospProfitAndLoss loss = new HospProfitAndLoss();
  1358. loss.setDateYear(year).setDateMonth(month).setReportNum(child.getNum()).setReportName(child.getReportName())
  1359. .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(child.getHospId()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
  1360. list.add(loss);
  1361. }
  1362. private BigDecimal calcAmountRes(List<HospProfitAndLossVo> hadCalcLosses, String calcFormula) {
  1363. // 得到所有的编号
  1364. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  1365. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  1366. // 得到编号的map
  1367. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  1368. for (int j = 0; j < numList.size(); j++) {
  1369. numMap.put(j, Integer.parseInt(numList.get(j)));
  1370. }
  1371. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  1372. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  1373. // 得到预算表达式 得到所有表达式的Map + - 相关的
  1374. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  1375. for (int k = 0; k < expressions.size(); k++) {
  1376. expressionMap.put(k, expressions.get(k));
  1377. }
  1378. // 数字的索引和表达式的索引累加计算
  1379. Set<Integer> numSet = numMap.keySet();
  1380. List<Integer> nums = new ArrayList<>(numSet);
  1381. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  1382. totalAmount.set(BigDecimal.ZERO);
  1383. for (int i = 0; i < nums.size(); i++) {
  1384. // 编号
  1385. Integer num = numMap.get(i);
  1386. List<HospProfitAndLossVo> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  1387. if (CollUtil.isEmpty(losses)) {
  1388. continue;
  1389. }
  1390. HospProfitAndLossVo loss = losses.get(0);
  1391. BigDecimal amount = loss.getAmount();
  1392. String str = expressionMap.get(i);
  1393. if (str.equals("+")) {
  1394. totalAmount.set(totalAmount.get().add(amount));
  1395. } else {
  1396. totalAmount.set(totalAmount.get().subtract(amount));
  1397. }
  1398. }
  1399. return totalAmount.get();
  1400. }
  1401. private BigDecimal calcAmountResp(List<HospProfitAndLoss> hadCalcLosses, String calcFormula) {
  1402. // 得到所有的编号
  1403. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  1404. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  1405. // 得到编号的map
  1406. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  1407. for (int j = 0; j < numList.size(); j++) {
  1408. numMap.put(j, Integer.parseInt(numList.get(j)));
  1409. }
  1410. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  1411. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  1412. // 得到预算表达式 得到所有表达式的Map + - 相关的
  1413. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  1414. for (int k = 0; k < expressions.size(); k++) {
  1415. expressionMap.put(k, expressions.get(k));
  1416. }
  1417. // 数字的索引和表达式的索引累加计算
  1418. Set<Integer> numSet = numMap.keySet();
  1419. List<Integer> nums = new ArrayList<>(numSet);
  1420. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  1421. totalAmount.set(BigDecimal.ZERO);
  1422. for (int i = 0; i < nums.size(); i++) {
  1423. // 编号
  1424. Integer num = numMap.get(i);
  1425. List<HospProfitAndLoss> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  1426. if (CollUtil.isEmpty(losses)) {
  1427. continue;
  1428. }
  1429. HospProfitAndLoss loss = losses.get(0);
  1430. BigDecimal amount = loss.getAmount();
  1431. String str = expressionMap.get(i);
  1432. if (str.equals("+")) {
  1433. totalAmount.set(totalAmount.get().add(amount));
  1434. } else {
  1435. totalAmount.set(totalAmount.get().subtract(amount));
  1436. }
  1437. }
  1438. return totalAmount.get();
  1439. }
  1440. private void calcByLitterCountResp(int year, int month, ReportForm child, List<ReportForm> children,
  1441. List<HospProfitAndLoss> list, Long hospId, Responsibility responsibility) {
  1442. List<HospProfitAndLoss> thisRespCodeList = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
  1443. List<ReportForm> thisForEachList = children.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
  1444. List<HospProfitAndLoss> collect = thisRespCodeList.stream().filter(i -> thisForEachList.stream().map(ReportForm::getNum).collect(Collectors.toList()).contains(i.getReportNum())).collect(Collectors.toList());
  1445. if (collect.isEmpty()) {
  1446. return;
  1447. }
  1448. BigDecimal reduce = collect.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1449. HospProfitAndLoss loss = new HospProfitAndLoss();
  1450. loss.setDateYear(year).setDateMonth(month)
  1451. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
  1452. // 小计只能有一个
  1453. loss.setReportNum(child.getNum()).setReportName(child.getReportName())
  1454. .setResponsibilityCode(responsibility.getResponsibilityCode())
  1455. .setResponsibilityName(responsibility.getResponsibilityName());
  1456. list.add(loss);
  1457. }
  1458. private void calcByShareLevelResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
  1459. List<RelationVO> shareLevels = reportRelationService.getShareLevel(child.getId(), hospId);
  1460. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  1461. if (CollUtil.isEmpty(shareLevelId)) {
  1462. return;
  1463. }
  1464. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  1465. if (costShareLevels.isEmpty()) {
  1466. throw new CostException("医院分摊层级设置错误," + child.getReportName());
  1467. }
  1468. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  1469. List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(year, month, hospId, shareLevelId, responsibility.getResponsibilityCode());
  1470. if (allocations.isEmpty()) {
  1471. throw new CostException("医院未分摊本月数据");
  1472. }
  1473. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  1474. if (accountShares.isEmpty()) {
  1475. return;
  1476. }
  1477. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1478. HospProfitAndLoss loss = new HospProfitAndLoss();
  1479. loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  1480. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  1481. .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  1482. ;
  1483. list.add(loss);
  1484. }
  1485. private void calcByShareLevelResp(Long hospId, HospProfitAndLossVo lossVo) {
  1486. List<RelationVO> shareLevels = reportRelationService.getShareLevel(lossVo.getReportId(), hospId);
  1487. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  1488. if (CollUtil.isEmpty(shareLevelId)) {
  1489. return;
  1490. }
  1491. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  1492. if (costShareLevels.isEmpty()) {
  1493. throw new CostException("医院分摊层级设置错误," + lossVo.getReportName());
  1494. }
  1495. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  1496. List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, shareLevelId, lossVo.getResponsibilityCode());
  1497. if (allocations.isEmpty()) {
  1498. throw new CostException("医院未分摊本月数据");
  1499. }
  1500. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  1501. if (accountShares.isEmpty()) {
  1502. return;
  1503. }
  1504. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1505. lossVo.setAmount(reduce);
  1506. // HospProfitAndLoss loss = new HospProfitAndLoss();
  1507. // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  1508. // .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  1509. // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  1510. // ;
  1511. // list.add(loss);
  1512. }
  1513. private void calcByAccountByResp(Long hospId, HospProfitAndLossVo lossVo) {
  1514. // 报表项目关联的会计科目对象
  1515. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(lossVo.getReportId(), hospId);
  1516. if (accountRelations.isEmpty()) {
  1517. return;
  1518. }
  1519. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  1520. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  1521. calcTotal.set(BigDecimal.ZERO);
  1522. List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  1523. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  1524. accountCodes.forEach(i -> {
  1525. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  1526. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1527. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  1528. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1529. BigDecimal total = incomeAmount.add(costAmount);
  1530. calcTotal.set(calcTotal.get().add(total));
  1531. });
  1532. // HospProfitAndLoss loss = new HospProfitAndLoss();
  1533. lossVo.setAmount(calcTotal.get());
  1534. // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  1535. // .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  1536. // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
  1537. // list.add(loss);
  1538. }
  1539. private void calcByAccountByResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int month, int year, Responsibility responsibility) {
  1540. // 报表项目关联的会计科目对象
  1541. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(child.getId(), hospId);
  1542. if (accountRelations.isEmpty()) {
  1543. return;
  1544. }
  1545. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  1546. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  1547. calcTotal.set(BigDecimal.ZERO);
  1548. List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  1549. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  1550. accountCodes.forEach(i -> {
  1551. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  1552. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1553. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  1554. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1555. BigDecimal total = incomeAmount.add(costAmount);
  1556. calcTotal.set(calcTotal.get().add(total));
  1557. });
  1558. HospProfitAndLoss loss = new HospProfitAndLoss();
  1559. loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  1560. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  1561. .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  1562. ;
  1563. list.add(loss);
  1564. }
  1565. }