HospProfitAndLossServiceImpl.java 132 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546
  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.*;
  14. import com.kcim.common.enums.*;
  15. import com.kcim.common.exception.CostException;
  16. import com.kcim.common.file.MinioConfig;
  17. import com.kcim.common.file.MinioFileUtil;
  18. import com.kcim.common.util.*;
  19. import com.kcim.common.util.excel.ExcelPoiUtil;
  20. import com.kcim.common.util.excel.entity.ColEntity;
  21. import com.kcim.common.util.excel.entity.TitleEntity;
  22. import com.kcim.dao.mapper.HospProfitAndLossMapper;
  23. import com.kcim.dao.model.*;
  24. import com.kcim.service.*;
  25. import com.kcim.vo.*;
  26. import com.kcim.web.reponse.BatchCostProfitResponse;
  27. import lombok.extern.slf4j.Slf4j;
  28. import org.apache.commons.fileupload.FileItem;
  29. import org.apache.commons.fileupload.FileItemFactory;
  30. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  31. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  32. import org.jetbrains.annotations.NotNull;
  33. import org.springframework.stereotype.Service;
  34. import org.springframework.transaction.annotation.Propagation;
  35. import org.springframework.transaction.annotation.Transactional;
  36. import org.springframework.util.CollectionUtils;
  37. import org.springframework.util.ObjectUtils;
  38. import org.springframework.util.StringUtils;
  39. import org.springframework.web.multipart.MultipartFile;
  40. import org.springframework.web.multipart.commons.CommonsMultipartFile;
  41. import java.io.IOException;
  42. import java.io.InputStream;
  43. import java.io.OutputStream;
  44. import java.math.BigDecimal;
  45. import java.math.RoundingMode;
  46. import java.text.DecimalFormat;
  47. import java.util.*;
  48. import java.util.concurrent.ConcurrentHashMap;
  49. import java.util.concurrent.atomic.AtomicReference;
  50. import java.util.function.UnaryOperator;
  51. import java.util.stream.Collectors;
  52. @Slf4j
  53. @Service("hospProfitAndLossService")
  54. public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossMapper, HospProfitAndLoss> implements HospProfitAndLossService {
  55. // @Value("${file.filelocal}")
  56. // private String hospProfitReportUrl;
  57. //
  58. // @Value("${file.serverUrl}")
  59. // private String serverUrl;
  60. private final ReportFormService reportFormService;
  61. private final IncomeCollectionService collectionService;
  62. private final AllocationQueryService allocationQueryService;
  63. private final AllocationService allocationService;
  64. private final ReportRelationService reportRelationService;
  65. private final CostShareLevelService shareLevelService;
  66. private final CostOtherPaymentsDataService otherPaymentsDataService;
  67. private final ResponsibilityService responsibilityService;
  68. private final CostAccountShareService accountShareService;
  69. private final FileRecordService fileRecordService;
  70. private final SqlService sqlService;
  71. private final CenterService centerService;
  72. private final MinioConfig minioConfig;
  73. private final MinioFileUtil minioFileUtil;
  74. public HospProfitAndLossServiceImpl(ReportFormService reportFormService,
  75. IncomeCollectionService collectionService,
  76. AllocationQueryService allocationQueryService,
  77. AllocationService allocationService, ReportRelationService reportRelationService,
  78. CostShareLevelService shareLevelService,
  79. CostOtherPaymentsDataService otherPaymentsDataService,
  80. ResponsibilityService responsibilityService,
  81. CostAccountShareService accountShareService,
  82. FileRecordService fileRecordService,
  83. MinioConfig minioConfig,
  84. MinioFileUtil minioFileUtil,
  85. SqlService sqlService,
  86. CenterService centerService
  87. ) {
  88. this.reportFormService = reportFormService;
  89. this.collectionService = collectionService;
  90. this.allocationQueryService = allocationQueryService;
  91. this.allocationService = allocationService;
  92. this.reportRelationService = reportRelationService;
  93. this.shareLevelService = shareLevelService;
  94. this.otherPaymentsDataService = otherPaymentsDataService;
  95. this.responsibilityService = responsibilityService;
  96. this.accountShareService = accountShareService;
  97. this.fileRecordService = fileRecordService;
  98. this.minioConfig = minioConfig;
  99. this.minioFileUtil = minioFileUtil;
  100. this.sqlService=sqlService;
  101. this.centerService=centerService;
  102. }
  103. /**
  104. * 计算全院损益
  105. *
  106. * @param date yyyy-MM-dd 时间
  107. * @param hospId 医院id
  108. */
  109. @Override
  110. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
  111. public void calc(String date, Long hospId) {
  112. reportFormService.checkExistLoss(hospId);
  113. DateTime parse = DateUtil.parse(date);
  114. int year = DateUtil.year(parse);
  115. int month = DateUtil.month(parse) + 1;
  116. this.remove(new LambdaQueryWrapper<HospProfitAndLoss>().eq(HospProfitAndLoss::getDateYear, year).eq(HospProfitAndLoss::getDateMonth, month).eq(HospProfitAndLoss::getHospId, hospId));
  117. // 得到全院损益计算报表
  118. List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
  119. if (CollUtil.isEmpty(reportForms)) {
  120. throw new CostException("医院未设置全院损益计算报表");
  121. }
  122. // 得到这个月所有收入数据
  123. List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
  124. if (incomes.isEmpty()) {
  125. throw new CostException("医院未归集本月收入数据");
  126. }
  127. // 得到这个月的所有成本数据
  128. List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
  129. if (allocationQueries.isEmpty()) {
  130. throw new CostException("医院未分摊本月数据");
  131. }
  132. List<HospProfitAndLoss> list = new ArrayList<>();
  133. List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
  134. for (ReportForm parentForm : parentForms) {
  135. Long parentId = parentForm.getId();
  136. List<ReportForm> children = reportForms.stream().filter(i -> i.getParentId().equals(parentId)).collect(Collectors.toList());
  137. for (ReportForm child : children) {
  138. Integer calcType = child.getCalcType();
  139. if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
  140. // 按会计科目计算单的话
  141. calcByAccount(hospId, child, incomes, list, allocationQueries, month, year);
  142. } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
  143. // 分摊层级计算
  144. calcByShareLevel(hospId, child, list, year, month);
  145. } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
  146. // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
  147. calcByLitterCount(year, month, child, children, list, hospId);
  148. } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
  149. // 按公式 (要保证总合计放到最后呀)
  150. calcByFormula(year, month, child, children, list);
  151. } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
  152. // 责任中心
  153. calcByResponsibility(hospId, child, allocationQueries, list, year, month);
  154. } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
  155. // 不设置不计算
  156. } else {
  157. }
  158. }
  159. }
  160. // 处理医院其他收支
  161. List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
  162. if (!otherPaymentsDatas.isEmpty()) {
  163. otherPaymentsDatas.forEach(ele -> {
  164. HospProfitAndLoss loss = new HospProfitAndLoss();
  165. loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum(ele.getId().intValue())
  166. .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId);
  167. // if (ele.getPaymentsType() == 2) {
  168. // loss.setAmount(BigDecimal.ZERO.subtract(ele.getTotalAmount()));
  169. // }
  170. list.add(loss);
  171. });
  172. }
  173. this.saveBatch(list);
  174. }
  175. /**
  176. * 计算全院损益
  177. * @param date yyyy-MM-dd 时间
  178. * @param hospId 医院id
  179. * @param reportType 报表类型
  180. */
  181. @Override
  182. public void calcHospProfit(String date, Long hospId, Integer reportType){
  183. //需要用代码计算全院损益时
  184. if(IsNeedCalc(reportType)){
  185. //计算全院损益
  186. calcHospProfitAction(date,hospId,reportType);
  187. //计算同环比
  188. handleSpecificMonthsCalculation(hospId, date, reportType);
  189. }
  190. execHospProfitSql(date,reportType);
  191. }
  192. @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
  193. public void calcHospProfitAction(String date, Long hospId, Integer reportType) {
  194. List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
  195. DateTime parse = DateUtil.parse(date);
  196. int year = DateUtil.year(parse);
  197. int month = DateUtil.month(parse) + 1;
  198. this.remove(
  199. new LambdaQueryWrapper<HospProfitAndLoss>()
  200. .eq(HospProfitAndLoss::getDateYear, year)
  201. .eq(HospProfitAndLoss::getDateMonth, month)
  202. .eq(HospProfitAndLoss::getHospId, hospId)
  203. .eq(HospProfitAndLoss::getReportType, reportType)
  204. );
  205. // 得到全院损益计算报表
  206. List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, reportType);
  207. if (CollUtil.isEmpty(reportForms)) {
  208. throw new CostException("医院未设置全院损益计算报表");
  209. }
  210. reportFormService.checkExistLoss(hospId,reportType);
  211. // 得到这个月所有收入数据
  212. List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
  213. if (incomes.isEmpty()) {
  214. throw new CostException("医院未归集本月收入数据");
  215. }
  216. Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
  217. // 得到这个月的所有成本数据
  218. List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
  219. if (allocationQueries.isEmpty()) {
  220. throw new CostException("医院未分摊本月数据");
  221. }
  222. List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueries, AllocationQueryReportVO.class);
  223. allocationQueryReportVOList.forEach(i -> {
  224. i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
  225. i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
  226. });
  227. // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
  228. List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>().lambda().eq(Allocation::getHospId, hospId)
  229. .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month));
  230. if (CollUtil.isEmpty(allocationList)) {
  231. throw new CostException(500, "分摊报表数据不存在");
  232. }
  233. // 查询最后一个层级的责任中心
  234. List<CostShareLevel> costShareLevelList = shareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
  235. .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort));
  236. if (CollUtil.isEmpty(costShareLevelList)) {
  237. throw new CostException(500, "分摊层级未设置");
  238. }
  239. List<HospProfitAndLossVo> listVo = new ArrayList<>();
  240. // List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
  241. int finalYear = year;
  242. int finalMonth = month;
  243. leafResp.forEach(i -> {
  244. reportForms.forEach(j -> {
  245. HospProfitAndLossVo hospProfitAndLossVo = new HospProfitAndLossVo();
  246. hospProfitAndLossVo.setDateYear(finalYear);
  247. hospProfitAndLossVo.setDateMonth(finalMonth);
  248. hospProfitAndLossVo.setReportNum(j.getNum());
  249. hospProfitAndLossVo.setReportName(j.getReportName());
  250. hospProfitAndLossVo.setResponsibilityCode(i.getResponsibilityCode());
  251. hospProfitAndLossVo.setResponsibilityName(i.getResponsibilityName());
  252. hospProfitAndLossVo.setCostType(NumberConstant.ZERO);
  253. hospProfitAndLossVo.setIncomeType(NumberConstant.ZERO);
  254. hospProfitAndLossVo.setHospId(hospId);
  255. hospProfitAndLossVo.setType(j.getCostType());
  256. hospProfitAndLossVo.setFraction(j.getFraction());
  257. hospProfitAndLossVo.setReportId(j.getId());
  258. hospProfitAndLossVo.setReportNum(j.getNum());
  259. hospProfitAndLossVo.setCalcType(j.getCalcType());
  260. hospProfitAndLossVo.setReportName(j.getReportName());
  261. hospProfitAndLossVo.setCalcFormula(j.getCalcFormula());
  262. hospProfitAndLossVo.setReportParentId(j.getParentId());
  263. listVo.add(hospProfitAndLossVo);
  264. });
  265. });
  266. Map<Long, List<HospProfitAndLossVo>> listMap = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getReportId));
  267. List<HospProfitAndLossVo> allList = BeanUtil.convertList(listVo, HospProfitAndLossVo.class);
  268. // 记录每一次计算的钱
  269. //所有小计 总计单独处理
  270. listVo.forEach(i -> {
  271. Integer calcType = i.getCalcType();
  272. if (NumberConstant.ONE.equals(calcType)) {
  273. // TODO 按照会计科目进行计算
  274. i.setAmount(setAccountReportData(i, incomes, allocationQueryReportVOList, reportRelationMap));
  275. } else if (NumberConstant.TWO.equals(calcType)) {
  276. // TODO 按照分摊层级进行计算
  277. i.setAmount(setShareLevelReportData(i, reportRelationMap, allocationList));
  278. } else if (NumberConstant.THREE.equals(calcType)) {
  279. // TODO 按照小计进行计算
  280. i.setAmount(setSubtotal(i, costShareLevelList, listMap, listVo, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
  281. } else if (NumberConstant.FOUR.equals(calcType)) {
  282. // TODO 按照计算公式进行计算
  283. // i.setAmount(setCalculation(i, listVo, costShareLevelList, listMap, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
  284. } else if (NumberConstant.FIVE.equals(calcType)) {
  285. // TODO 按照责任中心进行计算
  286. i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList));
  287. } else {
  288. i.setAmount(new BigDecimal("0.000000"));
  289. }
  290. });
  291. //计算占比
  292. if (CollectionUtils.isEmpty(listVo)) {
  293. return;
  294. }
  295. List<HospProfitAndLossVo> listSum = new ArrayList<>();
  296. //把所有数据按报表项目汇总
  297. for (ReportForm j : reportForms) {
  298. HospProfitAndLossVo hospProfitAndLossVo = new HospProfitAndLossVo();
  299. hospProfitAndLossVo.setDateYear(finalYear);
  300. hospProfitAndLossVo.setDateMonth(finalMonth);
  301. hospProfitAndLossVo.setReportNum(j.getNum());
  302. hospProfitAndLossVo.setReportName(j.getReportName());
  303. hospProfitAndLossVo.setCostType(NumberConstant.ZERO);
  304. hospProfitAndLossVo.setIncomeType(NumberConstant.ZERO);
  305. hospProfitAndLossVo.setHospId(hospId);
  306. hospProfitAndLossVo.setType(j.getCostType());
  307. hospProfitAndLossVo.setFraction(j.getFraction());
  308. hospProfitAndLossVo.setReportId(j.getId());
  309. hospProfitAndLossVo.setReportNum(j.getNum());
  310. hospProfitAndLossVo.setCalcType(j.getCalcType());
  311. hospProfitAndLossVo.setReportName(j.getReportName());
  312. hospProfitAndLossVo.setCalcFormula(j.getCalcFormula());
  313. hospProfitAndLossVo.setReportParentId(j.getParentId());
  314. listSum.add(hospProfitAndLossVo);
  315. }
  316. Map<Integer, List<HospProfitAndLossVo>> reportNumGroup = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getReportNum));
  317. Map<Integer, BigDecimal> reportNumSumMap = new HashMap<>();
  318. reportNumGroup.forEach((reportNum, hospProfitAndLossList) -> {
  319. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000000"));
  320. for (HospProfitAndLossVo hospProfitAndLoss : hospProfitAndLossList) {
  321. if (hospProfitAndLoss.getAmount() != null) {
  322. sum.updateAndGet(f -> f.add(hospProfitAndLoss.getAmount()));
  323. }
  324. }
  325. reportNumSumMap.put(reportNum, sum.get());
  326. });
  327. for (HospProfitAndLossVo costProfitVo : listSum) {
  328. BigDecimal bigDecimal = reportNumSumMap.get(costProfitVo.getReportNum());
  329. if (bigDecimal != null) {
  330. costProfitVo.setAmount(bigDecimal);
  331. } else {
  332. costProfitVo.setAmount(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP));
  333. }
  334. }
  335. //单独计算计算公式数据
  336. setCalculationAmount(listSum);
  337. //收入
  338. List<HospProfitAndLossVo> profitIncomeList = listSum.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList());
  339. List<HospProfitAndLossVo> profitIncome = costPercent(profitIncomeList);
  340. //成本
  341. List<HospProfitAndLossVo> profitCostList = listSum.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList());
  342. List<HospProfitAndLossVo> profitCost = costPercent(profitCostList);
  343. //不计算项目
  344. List<HospProfitAndLossVo> noCompute = listSum.stream().filter(f -> f.getFraction().equals(NumberConstant.THREE)).collect(Collectors.toList());
  345. noCompute.forEach(profitVO -> profitVO.setPercent(null));
  346. List<HospProfitAndLossVo> listAllVo = new ArrayList<>();
  347. if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
  348. listAllVo.addAll(profitIncome);
  349. listAllVo.addAll(profitCost);
  350. listAllVo.addAll(noCompute);
  351. } else if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(noCompute)) {
  352. listAllVo.addAll(noCompute);
  353. listAllVo.addAll(profitIncome);
  354. } else if (!CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
  355. listAllVo.addAll(noCompute);
  356. listAllVo.addAll(profitCost);
  357. } else if (!CollectionUtils.isEmpty(noCompute)) {
  358. listAllVo.addAll(noCompute);
  359. }
  360. List<HospProfitAndLoss> list = BeanUtil.convertList(listAllVo, HospProfitAndLoss.class);
  361. // 处理医院其他收支
  362. List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
  363. if (!otherPaymentsDatas.isEmpty()) {
  364. Optional<ReportForm> firstLossReport = reportForms.stream().filter(f -> NumberConstant.ONE.equals(f.getIsLoss())).findFirst();
  365. if(!firstLossReport.isPresent()){
  366. throw new CostException("全院损益报表配置有误,未设置损益项目");
  367. }
  368. Optional<HospProfitAndLoss> firstHospProfitAndLoss = list.stream().filter(f -> firstLossReport.get().getNum().equals(f.getReportNum())).findFirst();
  369. if(!firstHospProfitAndLoss.isPresent()){
  370. throw new CostException("全院损益报表配置有误,未找到配置的损益项目");
  371. }
  372. for (CostOtherPaymentsData ele : otherPaymentsDatas) {
  373. HospProfitAndLoss loss = new HospProfitAndLoss();
  374. loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum((int) (-ele.getId()))
  375. .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId)
  376. .setResponsibilityName("全院").setResponsibilityCode("-1").setPercent(null).setOriginType(NumberConstant.ONE);
  377. if( NumberConstant.ONE.equals(ele.getPaymentsType()) ) {
  378. //全院损益项目加上收入
  379. firstHospProfitAndLoss.get().setAmount(firstHospProfitAndLoss.get().getAmount().add(ele.getTotalAmount()));
  380. }else{
  381. //全院损益项目减去支出
  382. firstHospProfitAndLoss.get().setAmount(firstHospProfitAndLoss.get().getAmount().subtract(ele.getTotalAmount()));
  383. }
  384. list.add(loss);
  385. }
  386. }
  387. long l = System.currentTimeMillis();
  388. list.forEach(i -> {
  389. i.setCreateTime(l);
  390. i.setReportType(reportType);
  391. });
  392. this.saveBatch(list);
  393. }
  394. /**
  395. * 是否需要代码计算
  396. * @return
  397. */
  398. public boolean IsNeedCalc(Integer reportType) {
  399. String parameterValue = centerService.getParameterValue(ParameterConstant.SQL_CALC_REPORT_TYPE);
  400. if(StringUtils.isEmpty(parameterValue)){
  401. return true;
  402. }
  403. //不需计算的报表类型列表
  404. List<String> nonCalcReportTypeList = Arrays.stream(parameterValue.split(SplitConstant.SEPARATOR_VERTICALLINE)).collect(Collectors.toList());
  405. return !nonCalcReportTypeList.contains(String.valueOf(reportType));
  406. }
  407. /**
  408. * 处理指定月份及关联月份的计算(当前月、下个月、明年同月)
  409. *
  410. * @param hospId 院区ID
  411. * @param computeDate 日期字符串,格式:YYYY-MM
  412. * @param shareType 报表类型
  413. */
  414. public void handleSpecificMonthsCalculation(Long hospId, String computeDate, Integer shareType) {
  415. // 解析输入的年月
  416. Integer currentYear = ComputeDateUtils.getComputeYear(computeDate);
  417. Integer currentMonth = ComputeDateUtils.getComputeMonth(computeDate);
  418. // 计算需要处理的期间信息
  419. List<PeriodInfoVO> periods = calculateAllRelatedPeriods(currentYear, currentMonth);
  420. // 获取所有相关的期间数据
  421. Map<String, List<HospProfitAndLoss>> allDataMap = loadAllPeriodData(hospId, shareType, periods);
  422. // 对每个期间执行计算
  423. for (PeriodInfoVO period : periods) {
  424. String currentKey = buildPeriodKey(period.getYear(), period.getMonth());
  425. if (allDataMap.containsKey(currentKey) && !CollectionUtils.isEmpty(allDataMap.get(currentKey))) {
  426. List<HospProfitAndLoss> currentRecords = allDataMap.get(currentKey);
  427. List<HospProfitAndLoss> prevRecords = getPeriodData(allDataMap, period.getPrevYear(), period.getPrevMonth());
  428. List<HospProfitAndLoss> lastYearRecords = getPeriodData(allDataMap, period.getLastYear(), period.getLastMonth());
  429. // 执行批量计算
  430. calculatePeriodComparisonWithPreloadedData(currentRecords, prevRecords, lastYearRecords);
  431. }
  432. }
  433. }
  434. /**
  435. * 构建所有需要处理的期间信息
  436. */
  437. private List<PeriodInfoVO> calculateAllRelatedPeriods(int baseYear, int baseMonth) {
  438. List<PeriodInfoVO> result = new ArrayList<>();
  439. // 添加当前期间
  440. result.add(calculatePeriodInfo(baseYear, baseMonth));
  441. // 下个月
  442. int nextMonth = baseMonth + 1;
  443. int nextMonthYear = baseYear;
  444. if (baseMonth == 12) {
  445. nextMonth = 1;
  446. nextMonthYear += 1;
  447. }
  448. result.add(calculatePeriodInfo(nextMonthYear, nextMonth));
  449. // 明年同月
  450. result.add(calculatePeriodInfo(baseYear + 1, baseMonth));
  451. return result;
  452. }
  453. /**
  454. * 构建单个期间的信息(当前月、上月、去年同期)
  455. */
  456. private PeriodInfoVO calculatePeriodInfo(int year, int month) {
  457. PeriodInfoVO info = new PeriodInfoVO();
  458. info.setYear( year);
  459. info.setMonth( month);
  460. // 上期
  461. if (month == 1) {
  462. info.setPrevYear(year - 1);
  463. info.setPrevMonth(12);
  464. } else {
  465. info.setPrevYear( year);
  466. info.setPrevMonth(month - 1);
  467. }
  468. // 同期
  469. info.setLastYear(year - 1);
  470. info.setLastMonth( month);
  471. return info;
  472. }
  473. /**
  474. * 加载所有相关期间的数据(去重处理)
  475. */
  476. private Map<String, List<HospProfitAndLoss>> loadAllPeriodData(Long hospId, Integer shareType, List<PeriodInfoVO> periods) {
  477. Set<String> allPeriodKeys = new HashSet<>();
  478. // 收集所有需要查询的年月组合
  479. for (PeriodInfoVO period : periods) {
  480. allPeriodKeys.add(buildPeriodKey(period.getYear(), period.getMonth()));
  481. allPeriodKeys.add(buildPeriodKey(period.getPrevYear(), period.getPrevMonth()));
  482. allPeriodKeys.add(buildPeriodKey(period.getLastYear(), period.getLastMonth()));
  483. }
  484. // 去重后查询
  485. Map<String, List<HospProfitAndLoss>> result = new HashMap<>();
  486. Set<String> processedKeys = new HashSet<>(); // 已处理的键集合
  487. for (String key : allPeriodKeys) {
  488. if (!processedKeys.contains(key)) {
  489. int[] ym = parsePeriodKey(key);
  490. List<HospProfitAndLoss> records = getPeriodRecords(hospId, shareType, ym[0], ym[1]);
  491. result.put(key, records);
  492. processedKeys.add(key); // 标记为已处理
  493. }
  494. }
  495. return result;
  496. }
  497. /**
  498. * 获取指定期间的数据
  499. *
  500. * @param hospId 院区ID
  501. * @param shareType 报表类型
  502. * @param year 年份
  503. * @param month 月份
  504. * @return 符合条件的数据列表
  505. */
  506. private List<HospProfitAndLoss> getPeriodRecords(Long hospId, Integer shareType, int year, int month) {
  507. return this.list(new QueryWrapper<HospProfitAndLoss>().lambda()
  508. .eq(HospProfitAndLoss::getHospId, hospId)
  509. .eq(HospProfitAndLoss::getReportType, shareType)
  510. .eq(HospProfitAndLoss::getDateYear, year)
  511. .eq(HospProfitAndLoss::getDateMonth, month)
  512. .eq(HospProfitAndLoss::getDeleteTime, 0));
  513. }
  514. /**
  515. * 根据年月获取对应的数据(从内存中查找)
  516. */
  517. private List<HospProfitAndLoss> getPeriodData(Map<String, List<HospProfitAndLoss>> dataMap, int year, int month) {
  518. String key = buildPeriodKey(year, month);
  519. return dataMap.getOrDefault(key, Collections.emptyList());
  520. }
  521. /**
  522. * 批量计算同环比及同期金额(使用预加载数据)
  523. */
  524. public void calculatePeriodComparisonWithPreloadedData(
  525. List<HospProfitAndLoss> currentRecords,
  526. List<HospProfitAndLoss> prevRecords,
  527. List<HospProfitAndLoss> lastYearRecords) {
  528. if (CollectionUtils.isEmpty(currentRecords)) {
  529. return;
  530. }
  531. // 创建报表编号到记录的映射
  532. Map<String, HospProfitAndLoss> prevMap = new HashMap<>();
  533. for (HospProfitAndLoss record : prevRecords) {
  534. String key = buildRecordKey(record);
  535. prevMap.put(key, record);
  536. }
  537. Map<String, HospProfitAndLoss> lastYearMap = new HashMap<>();
  538. for (HospProfitAndLoss record : lastYearRecords) {
  539. String key = buildRecordKey(record);
  540. lastYearMap.put(key, record);
  541. }
  542. // 批量更新数据
  543. for (HospProfitAndLoss record : currentRecords) {
  544. String key = buildRecordKey(record);
  545. HospProfitAndLoss prevRecord = prevMap.get(key);
  546. HospProfitAndLoss lastYearRecord = lastYearMap.get(key);
  547. // 设置上期和同期金额
  548. record.setPrevPeriodAmount(prevRecord != null ? prevRecord.getAmount() : BigDecimal.ZERO);
  549. record.setSamePeriodAmount(lastYearRecord != null ? lastYearRecord.getAmount() : BigDecimal.ZERO);
  550. // 计算环比和同比
  551. record.setMomRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getPrevPeriodAmount()));
  552. record.setYoyRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getSamePeriodAmount()));
  553. }
  554. // 批量更新数据库
  555. this.updateBatchById(currentRecords);
  556. }
  557. /**
  558. * 构建期间键(用于存储和检索数据)
  559. */
  560. private String buildPeriodKey(int year, int month) {
  561. return year + "_" + month;
  562. }
  563. /**
  564. * 解析期间键为年月数组
  565. */
  566. private int[] parsePeriodKey(String key) {
  567. String[] parts = key.split("_");
  568. return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])};
  569. }
  570. /**
  571. * 构建记录的唯一标识键(责任码 + 报表编号)
  572. */
  573. private String buildRecordKey(HospProfitAndLoss record) {
  574. return String.valueOf(record.getReportNum());
  575. }
  576. /**
  577. * 安全地计算百分比:避免除零错误
  578. */
  579. private BigDecimal calculateProfitRate(BigDecimal current, BigDecimal base) {
  580. if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
  581. return BigDecimal.ZERO;
  582. }
  583. BigDecimal bigDecimal = current.divide(base, 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP);
  584. return bigDecimal;
  585. }
  586. /**
  587. * 执行全院损益后续脚本
  588. * @param date
  589. * @param reportType
  590. */
  591. public void execHospProfitSql(String date,Integer reportType){
  592. Map<String,String> sqlParameter = new HashMap<>();
  593. sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, DateUtils.StringToString(date, DateStyleEnum.YYYY_MM));
  594. sqlParameter.put(SQLParameter.REPORT_TYPE_CODE,String.valueOf(reportType));
  595. sqlService.autoExecuteSql(CustomSqlTypeEnum.HOSP_PROFIT_CALC.getCode(),sqlParameter);
  596. }
  597. // 计算公式中钱
  598. private BigDecimal calcAmount(List<HospProfitAndLoss> list, String calcFormula, ReportForm reportForm) {
  599. // 得到所有的编号
  600. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  601. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  602. // 得到编号的map
  603. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  604. for (int j = 0; j < numList.size(); j++) {
  605. numMap.put(j, Integer.parseInt(numList.get(j)));
  606. }
  607. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  608. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  609. // 得到预算表达式 得到所有表达式的Map + - 相关的
  610. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  611. for (int k = 0; k < expressions.size(); k++) {
  612. expressionMap.put(k, expressions.get(k));
  613. }
  614. // 数字的索引和表达式的索引累加计算
  615. Set<Integer> numSet = numMap.keySet();
  616. List<Integer> nums = new ArrayList<>(numSet);
  617. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  618. totalAmount.set(BigDecimal.ZERO);
  619. for (int i = 0; i < nums.size(); i++) {
  620. // 编号
  621. Integer num = numMap.get(i);
  622. List<HospProfitAndLoss> losses = list.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  623. if (CollUtil.isEmpty(losses)) {
  624. continue;
  625. }
  626. // log.info("data={}", reportForm);
  627. // if (losses.size() != 0 && losses.size() != 1) {
  628. // throw new CostException("数据异常");
  629. // }
  630. HospProfitAndLoss loss = losses.get(0);
  631. BigDecimal amount = loss.getAmount();
  632. String str = expressionMap.get(i);
  633. if (str.equals("+")) {
  634. totalAmount.set(totalAmount.get().add(amount));
  635. } else {
  636. totalAmount.set(totalAmount.get().subtract(amount));
  637. }
  638. }
  639. return totalAmount.get();
  640. }
  641. /**
  642. * 按责任中心计算
  643. *
  644. * @param hospId 医院id
  645. * @param reportForm 报表
  646. * @param allocationQueries 分摊成本数据
  647. * @param list
  648. * @param year
  649. * @param month
  650. */
  651. private void calcByResponsibility(Long hospId, ReportForm reportForm, List<AllocationQuery> allocationQueries, List<HospProfitAndLoss> list, int year, int month) {
  652. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(reportForm.getId(), hospId);
  653. if (responsibilities.isEmpty()) {
  654. return;
  655. }
  656. List<String> accountCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  657. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  658. calcTotal.set(BigDecimal.ZERO);
  659. accountCodes.forEach(i -> {
  660. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  661. .reduce(BigDecimal.ZERO, BigDecimal::add);
  662. calcTotal.set(calcTotal.get().add(costAmount));
  663. });
  664. HospProfitAndLoss loss = new HospProfitAndLoss();
  665. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  666. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  667. list.add(loss);
  668. }
  669. /**
  670. * 按计算公式计算
  671. */
  672. private void calcByFormula(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list) {
  673. // 得到当前下按公式计算的
  674. List<ReportForm> calcFormulas = reportForms.stream().filter(i -> i.getCalcType() == CalcTypeEnum.CALC_FORMULA.getType()).collect(Collectors.toList());
  675. calcFormulas = calcFormulas.stream().filter(i -> i.getNum().equals(child.getNum())).collect(Collectors.toList());
  676. for (ReportForm i : calcFormulas) {
  677. String calcFormula = i.getCalcFormula();
  678. // TODO: 2021/8/27 校验公式合法性
  679. if (StrUtil.isBlank(calcFormula)) {
  680. throw new CostException("reportForm名称为" + i.getReportName() + "计算公式不正确");
  681. }
  682. BigDecimal bigDecimal = calcAmount(list, calcFormula, i);
  683. HospProfitAndLoss loss = new HospProfitAndLoss();
  684. loss.setDateYear(year).setDateMonth(month).setReportNum(i.getNum()).setReportName(i.getReportName())
  685. .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(i.getHospId());
  686. list.add(loss);
  687. }
  688. }
  689. /**
  690. * 按小计计算
  691. */
  692. private void calcByLitterCount(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list, Long hospId) {
  693. // 其他的
  694. List<ReportForm> calcList = reportForms.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
  695. List<HospProfitAndLoss> thisList = new ArrayList<>();
  696. list.forEach(i -> {
  697. calcList.forEach(j -> {
  698. if (i.getReportNum().equals(j.getNum())) {
  699. thisList.add(i);
  700. }
  701. });
  702. });
  703. if (thisList.isEmpty()) {
  704. return;
  705. }
  706. BigDecimal reduce = thisList.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  707. HospProfitAndLoss loss = new HospProfitAndLoss();
  708. loss.setDateYear(year).setDateMonth(month).setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
  709. // 小计只能有一个
  710. loss.setReportNum(child.getNum()).setReportName(child.getReportName());
  711. list.add(loss);
  712. }
  713. /**
  714. * 按分摊层级计算、
  715. *
  716. * @param hospId 医院id
  717. * @param reportForm 报表
  718. * @param list
  719. * @param year
  720. * @param month
  721. */
  722. private void calcByShareLevel(Long hospId, ReportForm reportForm, List<HospProfitAndLoss> list, int year, int month) {
  723. List<RelationVO> shareLevels = reportRelationService.getShareLevel(reportForm.getId(), hospId);
  724. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  725. if (CollUtil.isEmpty(shareLevelId)) {
  726. return;
  727. }
  728. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  729. if (costShareLevels.isEmpty()) {
  730. throw new CostException("医院分摊层级设置错误," + reportForm.getReportName());
  731. }
  732. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  733. List<AllocationQuery> allocations = allocationQueryService.getByDate(year, month, hospId, shareLevelId);
  734. if (allocations.isEmpty()) {
  735. throw new CostException("医院未分摊本月数据");
  736. }
  737. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  738. if (accountShares.isEmpty()) {
  739. return;
  740. }
  741. // allocations = allocations.stream().filter(i -> levelSorts.contains(i.getLevelSort())).collect(Collectors.toList());
  742. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  743. HospProfitAndLoss loss = new HospProfitAndLoss();
  744. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  745. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  746. list.add(loss);
  747. }
  748. /**
  749. * 计算按会计科目下的科目名称
  750. *
  751. * @param hospId 医院id
  752. * @param reportForm 报表
  753. * @param incomes 归集收入数据
  754. * @param list
  755. * @param allocationQueries 分摊成本数据
  756. * @param month
  757. * @param year
  758. */
  759. private void calcByAccount(Long hospId, ReportForm reportForm, List<IncomeCollection> incomes, List<HospProfitAndLoss> list, List<AllocationQuery> allocationQueries, int month, int year) {
  760. // check 这个医院是否有对应的损益标识
  761. reportFormService.checkExistLoss(hospId);
  762. // 报表项目关联的会计科目对象
  763. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(reportForm.getId(), hospId);
  764. if (accountRelations.isEmpty()) {
  765. return;
  766. }
  767. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  768. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  769. calcTotal.set(BigDecimal.ZERO);
  770. accountCodes.forEach(i -> {
  771. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  772. .reduce(BigDecimal.ZERO, BigDecimal::add);
  773. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  774. .reduce(BigDecimal.ZERO, BigDecimal::add);
  775. BigDecimal total = incomeAmount.add(costAmount);
  776. calcTotal.set(calcTotal.get().add(total));
  777. });
  778. HospProfitAndLoss loss = new HospProfitAndLoss();
  779. loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
  780. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  781. list.add(loss);
  782. }
  783. /**
  784. * 全院损益列表
  785. *
  786. * @param current 当前页
  787. * @param pageSize 每页展示数据大小
  788. * @param date 日期
  789. * @param hospId 医院id
  790. * @return PageUtils
  791. */
  792. @Override
  793. public PageUtils getHospProfits(Integer current, Integer pageSize, String date, Long hospId) {
  794. reportFormService.checkExistLoss(hospId);
  795. DateTime parse = DateUtil.parse(date);
  796. int year = DateUtil.year(parse);
  797. int month = DateUtil.month(parse) + 1;
  798. int startIndex = (current - 1) * pageSize;
  799. List<HospProfitAndLoss> list = baseMapper.getPageList(startIndex, pageSize, year, month, hospId);
  800. // 损益的时候计算下
  801. list.forEach(i -> {
  802. ReportForm one = reportFormService.getOne(
  803. new LambdaQueryWrapper<ReportForm>().select(ReportForm::getId)
  804. .eq(ReportForm::getNum, i.getReportNum())
  805. .eq(ReportForm::getHospId, hospId)
  806. .eq(ReportForm::getReportType, 3)
  807. .eq(ReportForm::getIsLoss, 1)
  808. .last(Constant.LIMIT)
  809. );
  810. if (Objects.nonNull(one)) {
  811. List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
  812. AtomicReference<BigDecimal> total = new AtomicReference<>();
  813. total.set(BigDecimal.ZERO);
  814. byMonth.forEach(j -> {
  815. if (j.getPaymentsType().equals(1)) {
  816. total.set(total.get().add(j.getTotalAmount()));
  817. } else {
  818. total.set(total.get().subtract(j.getTotalAmount()));
  819. }
  820. });
  821. i.setAmount(i.getAmount().add(total.get()));
  822. }
  823. });
  824. int totalCount = baseMapper.getPageCount(year, month, hospId);
  825. return new PageUtils(list, totalCount, pageSize, current);
  826. }
  827. /**
  828. * 导出全院损益计算
  829. *
  830. * @param date yyyy-MM-dd
  831. * @param hospId
  832. */
  833. @Override
  834. public void hospProfitReport(String date, Long hospId) {
  835. DateTime parse = DateUtil.parse(date);
  836. int year = DateUtil.year(parse);
  837. int month = DateUtil.month(parse) + 1;
  838. // 得到所有责任中心的子节点
  839. List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
  840. // List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
  841. List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
  842. // if (!byMonth.isEmpty()) {
  843. // Responsibility responsibility = new Responsibility("-1", "全院", -1L);
  844. // responsibilityList.add(responsibility);
  845. // }
  846. Map<String, Long> responseCodeParentIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
  847. Map<Long, Responsibility> responsibilityIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
  848. // 查询所有的全院损益数据 内存溢出问题
  849. List<HospProfitAndLoss> hospProfitAndLosses = getAllDataByDate(year, month, hospId,NumberConstant.THREE);
  850. if (CollectionUtils.isEmpty(hospProfitAndLosses)) {
  851. throw new CostException(500, "未进行全院损益计算");
  852. }
  853. //判断是否有全院的数据 有单独取出另算
  854. List<HospProfitAndLoss> hospAllList = hospProfitAndLosses.stream().filter(f -> f.getResponsibilityCode().equals("-1")).collect(Collectors.toList());
  855. if (!CollectionUtils.isEmpty(hospAllList)) {
  856. hospProfitAndLosses.removeAll(hospAllList);
  857. }
  858. //多层级责任 中心 添加父类责任中心 方便excel分组
  859. for (HospProfitAndLoss hospProfitAndLoss : hospProfitAndLosses) {
  860. Long aLong = responseCodeParentIdMap.get(hospProfitAndLoss.getResponsibilityCode());
  861. if (aLong != null) {
  862. if (aLong.equals(NumberConstant.ZERO_L)) {
  863. // Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
  864. hospProfitAndLoss.setParentResponsibilityCode(hospProfitAndLoss.getResponsibilityCode());
  865. hospProfitAndLoss.setParentResponsibilityName(hospProfitAndLoss.getResponsibilityName());
  866. } else if (aLong.equals(-1L)) {
  867. hospProfitAndLoss.setParentResponsibilityCode("-1");
  868. hospProfitAndLoss.setParentResponsibilityName("全院");
  869. } else {
  870. Responsibility responsibility = responsibilityIdMap.get(aLong);
  871. if (Objects.nonNull(responsibility)) {
  872. hospProfitAndLoss.setParentResponsibilityCode(responsibility.getResponsibilityCode());
  873. hospProfitAndLoss.setParentResponsibilityName(responsibility.getResponsibilityName());
  874. }
  875. }
  876. }
  877. }
  878. //损益表设置
  879. List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
  880. .eq(ReportForm::getHospId, hospId)
  881. .eq(ReportForm::getReportType, NumberConstant.THREE));
  882. if (CollUtil.isEmpty(reportFormList)) {
  883. throw new CostException(500, "损益表未找到");
  884. }
  885. if (!byMonth.isEmpty()) {
  886. // 手动构造全院数据表头 生成全院其他收支
  887. //添加全院其他报表项目
  888. //最上层
  889. ReportForm parentReport = new ReportForm();
  890. parentReport.setId(-1L);
  891. parentReport.setReportType(NumberConstant.THREE);
  892. parentReport.setParentId(NumberConstant.ZERO_L);
  893. parentReport.setSort(0);
  894. parentReport.setReportName("全院其他收支");
  895. parentReport.setNum(-1);
  896. reportFormList.add(parentReport);
  897. //第二层按全院收支数据自动生成
  898. for (int i = 0; i < byMonth.size(); i++) {
  899. CostOtherPaymentsData data = byMonth.get(i);
  900. ReportForm reportForm = new ReportForm();
  901. // reportForm.setId(-1L -i - byMonth.size());
  902. reportForm.setId(-System.currentTimeMillis() - i);
  903. reportForm.setReportType(NumberConstant.THREE);
  904. reportForm.setParentId(-1L);
  905. reportForm.setSort(0);
  906. reportForm.setReportName(data.getPaymentsName());
  907. reportForm.setNum((int) (-data.getId()));
  908. reportFormList.add(reportForm);
  909. }
  910. }
  911. Map<Long, List<ReportForm>> collect = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getParentId));
  912. Map<String, List<ColEntity>> heads = new HashMap<>();// 最终导出的多个sheet的表头
  913. Map<String, List<Map<String, String>>> datas = new HashMap<>();// 最终导出的多个sheet的内容
  914. Map<String, Integer> types = new HashMap<>();
  915. Map<String, List<Integer>> mergeindexs = new HashMap<>();// 最终导出的每个sheet的需要纵向合并的单元格列号
  916. //第一层
  917. List<ReportForm> firstTitle = collect.get(NumberConstant.ZERO_L);
  918. List<TitleEntity> titleList = new ArrayList<>();
  919. titleList.add(new TitleEntity("0", null, "全院损益 \n" + "制表时间:" + DateUtil.now(), false, NumberConstant.ZERO));
  920. //添加默认三列责任中心 父类责任中心 子类责任中心 项目名称
  921. setDefaultColumn(titleList);
  922. for (ReportForm reportForm : firstTitle) {
  923. TitleEntity entity = new TitleEntity();
  924. entity.setId(String.valueOf(reportForm.getId()));
  925. entity.setPid(String.valueOf(reportForm.getParentId()));
  926. entity.setContent(reportForm.getReportName());
  927. entity.setFieldName(String.valueOf(reportForm.getNum()));
  928. entity.setWidth(20);
  929. entity.setSort(reportForm.getSort());
  930. boolean child = getChild(titleList, reportForm, collect);
  931. entity.setLast(child);
  932. titleList.add(entity);
  933. }
  934. titleList.sort(Comparator.comparing(TitleEntity::getSort));
  935. hospProfitAndLosses.sort(Comparator.comparing(HospProfitAndLoss::getParentResponsibilityCode));
  936. //行
  937. Map<String, List<HospProfitAndLoss>> lineMap = hospProfitAndLosses.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getParentResponsibilityCode));
  938. //列
  939. List<TitleEntity> titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList());
  940. List<Map<String, String>> rowList = new ArrayList<>();
  941. //行数据
  942. setRowList(lineMap, titleEntities, rowList);
  943. //添加 全院其他收支数据
  944. setHospRowList(hospAllList, titleEntities, rowList);
  945. try {
  946. ExcelPoiUtil excelTool = new ExcelPoiUtil();
  947. excelTool.setTitle("全院损益");
  948. Map<String, String> param = ImmutableMap.<String, String>builder().put("id", "id").put("pid", "pid")
  949. .put("content", "content").put("fieldName", "fieldName").put("width", "width").build();
  950. List<ColEntity> titleData = excelTool.colEntityTransformer(titleList, param, "0");
  951. Map<String, List<Integer>> autoRowHeights = new HashMap<>();
  952. heads.put("全院损益", titleData);// 每个sheet的表头,sheet名称为key
  953. datas.put("全院损益", rowList);// 每个sheet的内容,sheet名称为key
  954. types.put("全院损益", 0);// 每个sheet的样式类型,sheet名称为key
  955. mergeindexs.put("全院损益", Arrays.asList(0, 1));// 每个sheet的默认行高,sheet名称为key
  956. autoRowHeights.put("全院损益", Arrays.asList(1, 2, 3, 4, 5));
  957. // 多个sheet导出
  958. HSSFWorkbook workbook = excelTool.exportWorkbook(heads, datas, types, autoRowHeights, mergeindexs);
  959. // excelTool.save(workbook, "D:\\全院损益.xls");
  960. // // 得到上一层的title子节点
  961. //// ExcelWriter writer = ExcelUtil.getWriter();
  962. // String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
  963. // //todo:后面调整为上传到文件服务器,先启动确认环境
  964. // String fileName = "全院损益" + time + ".xlsx";
  965. // ExcelWriter writer = ExcelUtil.getWriter(fileName);
  966. //
  967. // List<String> secondTitleListCode = leafResp.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
  968. // writer.merge(leafResp.size() + 1, "全院损益计算导出 \n" + "制表时间:" + DateUtil.now());
  969. // // 得到两层结构
  970. // writer.setColumnWidth(-1, 20);
  971. // writer.passCurrentRow();
  972. // writer.merge(2, 2, 0, 1, "项目", true);
  973. // int oldSize = 2;
  974. // Map<Long, Object> map = new HashMap<>();
  975. // for (int i = 0; i < leafResp.size(); i++) {
  976. // Responsibility responsibility = leafResp.get(i);
  977. // String str = responsibility.getResponsibilityName();
  978. // writer.writeCellValue(i + 2, 2, str);
  979. // // 写父亲层级
  980. // Long parentId = responsibility.getParentId();
  981. // if (map.get(parentId) != null) {
  982. // // 如果parentId = 0
  983. // if (parentId != 0L) {
  984. // continue;
  985. // }
  986. // }
  987. // Responsibility byId = responsibilityService.getById(parentId);
  988. // String name = "";
  989. // if (byId != null) {
  990. // name = byId.getResponsibilityName();
  991. // }
  992. // int count = (int) leafResp.stream().filter(o -> o.getParentId().equals(parentId)).count();
  993. //
  994. // if (count == 1) {
  995. // writer.writeCellValue(oldSize, 1, name);
  996. // } else if (count == 0) {
  997. // writer.writeCellValue(oldSize, 1, "全院其他");
  998. // } else {
  999. // writer.merge(1, 1, oldSize, oldSize + count - 1, name, false);
  1000. // }
  1001. //
  1002. // oldSize = oldSize + count;
  1003. // map.put(parentId, oldSize);
  1004. //
  1005. // }
  1006. // // 得到全院损益报表处理 树状结构(only 2层)
  1007. // List<ReportFormVO> allHospList = reportFormService.getAllHospList(hospId);
  1008. // if (allHospList.isEmpty()) {
  1009. // throw new CostException("请先设置全院损益报表");
  1010. // }
  1011. //
  1012. // if (!byMonth.isEmpty()) {
  1013. // // 构造假数据 生成全院其他收支
  1014. // ReportFormVO vo = new ReportFormVO(-1L, -1, "全院其他收支", 0L, new ArrayList<>());
  1015. // for (CostOtherPaymentsData data : byMonth) {
  1016. // ReportFormVO reportFormVO = new ReportFormVO(-2L, (int) (-data.getId()), data.getPaymentsName(), -1L, null);
  1017. // vo.getChildren().add(reportFormVO);
  1018. // }
  1019. // allHospList.add(allHospList.size() - 1, vo);
  1020. // }
  1021. // // 查询所有的全院损益数据 内存溢出问题
  1022. // List<HospProfitAndLoss> list = getAllDataByDate(year, month, hospId);
  1023. // int lastRow = 3;
  1024. // for (int i = 0; i < allHospList.size(); i++) {
  1025. // ReportFormVO parentFormVO = allHospList.get(i);
  1026. // List<ReportFormVO> children = parentFormVO.getChildren();
  1027. // if (CollUtil.isEmpty(children)) {
  1028. // continue;
  1029. // }
  1030. // int size = children.size();
  1031. // // 当最后一个的时候写上全院其他收支
  1032. // if (allHospList.size() == 1) {
  1033. // writer.writeCellValue(0, lastRow, parentFormVO.getReportName());
  1034. // } else {
  1035. // writer.merge(lastRow, lastRow + size - 1, 0, 0, parentFormVO.getReportName(), true);
  1036. // }
  1037. //
  1038. // // 具体的报表项目
  1039. // for (int j = 0; j < size; j++) {
  1040. // // todo 可以抽取出单独方法
  1041. // ReportFormVO childFormVO = children.get(j);
  1042. // // 第二列的数据
  1043. // writer.writeCellValue(1, lastRow + j, childFormVO.getReportName());
  1044. // // 单独计每个数据的责任中心对应的金额
  1045. // for (int k = 0; k < secondTitleListCode.size(); k++) {
  1046. //
  1047. // String responsibilityCode = secondTitleListCode.get(k);
  1048. // Integer num = childFormVO.getNum();
  1049. // HospProfitAndLoss loss = list.stream().filter(o -> o.getReportNum().equals(num) && o.getResponsibilityCode().equals(responsibilityCode)).findAny()
  1050. // .orElse(null);
  1051. // BigDecimal bigDecimal = Objects.isNull(loss) ? BigDecimal.ZERO : loss.getAmount();
  1052. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  1053. // if (k == secondTitleListCode.size() - 1) {
  1054. // bigDecimal = list.stream().filter(o -> o.getReportNum().equals(num)).map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1055. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  1056. //
  1057. // if (j == size - 1 && i == allHospList.size() - 1) {
  1058. // // 计算 其他
  1059. // BigDecimal another = BigDecimal.ZERO;
  1060. // for (CostOtherPaymentsData costOtherPaymentsData : byMonth) {
  1061. // if (costOtherPaymentsData.getPaymentsType() == 1) {
  1062. // another = another.add(costOtherPaymentsData.getTotalAmount());
  1063. // } else {
  1064. // another = another.subtract(costOtherPaymentsData.getTotalAmount());
  1065. // }
  1066. // }
  1067. // bigDecimal = bigDecimal.add(another);
  1068. // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
  1069. // }
  1070. // }
  1071. //
  1072. //
  1073. // }
  1074. //
  1075. // }
  1076. // lastRow = lastRow + size;
  1077. // }
  1078. String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
  1079. FileItemFactory factory = new DiskFileItemFactory(5242880, null);
  1080. FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, "全院损益" + time + ".xls");
  1081. String file = "";
  1082. OutputStream outputStream = fileItem.getOutputStream();
  1083. // writer.flush(outputStream,true);
  1084. workbook.write(outputStream);
  1085. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  1086. //上传 excel
  1087. file = uploadFile(multipartFile);
  1088. //保存文件记录
  1089. FileRecord fileRecord = new FileRecord();
  1090. fileRecord.setFileName("全院损益" + time + ".xls")
  1091. .setFileSource(1)
  1092. .setFileType("全院损益")
  1093. .setFileUrl(file)
  1094. .setHospId(hospId)
  1095. .setDateYear(year).setDateMonth(month)
  1096. .setCreateTime(System.currentTimeMillis());
  1097. fileRecordService.save(fileRecord);
  1098. workbook.close();
  1099. } catch (Exception e) {
  1100. throw new RuntimeException(e);
  1101. }
  1102. }
  1103. private static void setHospRowList(List<HospProfitAndLoss> hospAllList, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
  1104. List<Map<String, String>> amountRowList = new ArrayList<>();
  1105. for (Map<String, String> map : rowList) {
  1106. String itemType = map.get("itemType");
  1107. if (itemType.equals("金额")) {
  1108. amountRowList.add(map);
  1109. }
  1110. }
  1111. //相 同key 的数值 进行汇总
  1112. // for (int i = 0; i < 2; i++) {
  1113. Map<String, String> hospMap = new HashMap<>();
  1114. for (TitleEntity titleEntity : titleEntities) {
  1115. AtomicReference<BigDecimal> total = new AtomicReference<>(new BigDecimal("0.00"));
  1116. for (Map<String, String> map : amountRowList) {
  1117. String s = map.get(titleEntity.getFieldName());
  1118. if (!titleEntity.getFieldName().equals("child") && !titleEntity.getFieldName().equals("parent") && !titleEntity.getFieldName().equals("itemType")) {
  1119. // if(StringUtils.isEmpty(s)){
  1120. // total.updateAndGet(v -> v.add(BigDecimal.ZERO));
  1121. // }else {
  1122. total.updateAndGet(v -> v.add(new BigDecimal(s)));
  1123. // }
  1124. }
  1125. }
  1126. if (titleEntity.getFieldName().equals("parent")) {
  1127. hospMap.put("parent", "全院");
  1128. } else if (titleEntity.getFieldName().equals("child")) {
  1129. hospMap.put("child", "全院");
  1130. } else if (titleEntity.getFieldName().equals("itemType")) {
  1131. // if (i == 0) {
  1132. hospMap.put("itemType", "金额");
  1133. // } else {
  1134. // hospMap.put("itemType", "占比");
  1135. // }
  1136. } else {
  1137. // if (i == 0) {
  1138. hospMap.put(titleEntity.getFieldName(), total.get().toString());
  1139. if (!CollectionUtils.isEmpty(hospAllList)) {
  1140. for (HospProfitAndLoss data : hospAllList) {
  1141. hospMap.put(data.getReportNum().toString(), data.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  1142. }
  1143. }
  1144. // } else {
  1145. // hospMap.put(titleEntity.getFieldName(), "");
  1146. // }
  1147. }
  1148. }
  1149. rowList.add(hospMap);
  1150. // }
  1151. }
  1152. private static void setRowList(Map<String, List<HospProfitAndLoss>> lineMap, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
  1153. DecimalFormat df = new DecimalFormat("0.00%");
  1154. for (String parentCode : lineMap.keySet()) {
  1155. List<HospProfitAndLoss> costDepartmentProfits1 = lineMap.get(parentCode);
  1156. Map<String, List<HospProfitAndLoss>> listMap = costDepartmentProfits1.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getResponsibilityCode));
  1157. for (String s : listMap.keySet()) {
  1158. List<HospProfitAndLoss> costDepartmentProfits2 = listMap.get(s);
  1159. Map<String, HospProfitAndLoss> map = costDepartmentProfits2.stream().collect(Collectors.toMap(profit -> String.valueOf(profit.getReportNum()), profit -> profit, (a, b) -> b));
  1160. for (int i = 0; i < 2; i++) {
  1161. Map<String, String> m = new HashMap<String, String>();
  1162. for (TitleEntity titleEntity : titleEntities) {
  1163. if (titleEntity.getId().equals("parentResponsibility")) {
  1164. m.put("parent", costDepartmentProfits2.get(0).getParentResponsibilityName());
  1165. } else if (titleEntity.getId().equals("childResponsibility")) {
  1166. m.put("child", costDepartmentProfits2.get(0).getResponsibilityName());
  1167. } else if (titleEntity.getId().equals("item")) {
  1168. if (i == 0) {
  1169. m.put("itemType", "金额");
  1170. } else {
  1171. m.put("itemType", "占比");
  1172. }
  1173. } else if (titleEntity.getId().contains("-")) {
  1174. HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
  1175. if (Objects.nonNull(profit)) {
  1176. if (i == 0) {
  1177. m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  1178. } else {
  1179. if (profit.getPercent() != null) {
  1180. m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
  1181. } else {
  1182. m.put(titleEntity.getFieldName(), "");
  1183. }
  1184. }
  1185. } else {
  1186. m.put(titleEntity.getFieldName(), "0.00");
  1187. }
  1188. } else {
  1189. HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
  1190. if (Objects.nonNull(profit)) {
  1191. if (i == 0) {
  1192. m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
  1193. } else {
  1194. if (profit.getPercent() != null) {
  1195. m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
  1196. } else {
  1197. m.put(titleEntity.getFieldName(), "");
  1198. }
  1199. }
  1200. }
  1201. }
  1202. }
  1203. rowList.add(m);
  1204. }
  1205. }
  1206. }
  1207. }
  1208. private void setDefaultColumn(List<TitleEntity> titleList) {
  1209. TitleEntity parentResponsibility = new TitleEntity();
  1210. parentResponsibility.setId("parentResponsibility");
  1211. parentResponsibility.setPid("0");
  1212. parentResponsibility.setContent("");
  1213. parentResponsibility.setFieldName("parent");
  1214. parentResponsibility.setWidth(15);
  1215. parentResponsibility.setSort(NumberConstant.ZERO);
  1216. parentResponsibility.setLast(true);
  1217. titleList.add(parentResponsibility);
  1218. TitleEntity childResponsibility = new TitleEntity();
  1219. childResponsibility.setId("childResponsibility");
  1220. childResponsibility.setPid("0");
  1221. childResponsibility.setContent("");
  1222. childResponsibility.setFieldName("child");
  1223. childResponsibility.setWidth(15);
  1224. childResponsibility.setSort(NumberConstant.ZERO);
  1225. childResponsibility.setLast(true);
  1226. titleList.add(childResponsibility);
  1227. TitleEntity item = new TitleEntity();
  1228. item.setId("item");
  1229. item.setPid("0");
  1230. item.setContent("");
  1231. item.setFieldName("itemType");
  1232. item.setWidth(10);
  1233. item.setSort(NumberConstant.ZERO);
  1234. item.setLast(true);
  1235. titleList.add(item);
  1236. }
  1237. private boolean getChild(List<TitleEntity> titleList, ReportForm reportForm, Map<Long, List<ReportForm>> collect) {
  1238. List<ReportForm> forms = collect.get(reportForm.getId());
  1239. if (!CollectionUtils.isEmpty(forms)) {
  1240. for (ReportForm form : forms) {
  1241. TitleEntity entity = new TitleEntity();
  1242. entity.setId(String.valueOf(form.getId()));
  1243. entity.setPid(String.valueOf(form.getParentId()));
  1244. entity.setContent(form.getReportName());
  1245. entity.setFieldName(String.valueOf(form.getNum()));
  1246. entity.setWidth(15);
  1247. entity.setSort(form.getSort());
  1248. boolean last = getChild(titleList, form, collect);
  1249. entity.setLast(last);
  1250. titleList.add(entity);
  1251. }
  1252. return false;
  1253. } else {
  1254. return true;
  1255. }
  1256. }
  1257. public String uploadFile(MultipartFile file) {
  1258. Long hospId = UserContext.getCurrentLoginHospId();
  1259. String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + ".xls";
  1260. DateTime date = DateUtil.date();
  1261. int month = DateUtil.month(date) + 1;
  1262. int year = DateUtil.year(date);
  1263. int day = DateUtil.dayOfMonth(date);
  1264. String fileUrl = "";
  1265. try {
  1266. // file.transferTo(new File(localFilePath));
  1267. String format = DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN);
  1268. String originalFilename = format + fileName;
  1269. String dataDirectory = minioConfig.getBucketName();
  1270. String uploadFileName = "hospReport" + "/" + hospId + "/" + year + "/" + month + "/" + day + "/" + originalFilename;
  1271. InputStream inputStream = file.getInputStream();
  1272. minioFileUtil.putObject(dataDirectory, uploadFileName, inputStream);
  1273. fileUrl = minioFileUtil.getObjectUrl(dataDirectory, uploadFileName);
  1274. } catch (IOException e) {
  1275. log.error("【文件上传至服务器】失败,绝对路径:{}", e.getMessage());
  1276. throw new CostException(ErrorCodeEnum.FILE_UPLOAD_ERROR);
  1277. }
  1278. return fileUrl;
  1279. }
  1280. @Override
  1281. public PageUtils hospProfitReports(Integer current, Integer pageSize, Long hospId, String date) {
  1282. DateTime parse = DateUtil.parse(date);
  1283. int year = DateUtil.year(parse);
  1284. int month = DateUtil.month(parse) + 1;
  1285. Page<FileRecord> page = new Page<>(current, pageSize);
  1286. Page<FileRecord> pageUtils = fileRecordService.page(page,
  1287. new LambdaQueryWrapper<FileRecord>()
  1288. .eq(FileRecord::getHospId, hospId)
  1289. .eq(FileRecord::getFileType, "全院损益")
  1290. .eq(FileRecord::getDateYear, year)
  1291. .eq(FileRecord::getDateMonth, month)
  1292. .orderByDesc(FileRecord::getCreateTime)
  1293. );
  1294. return new PageUtils(pageUtils);
  1295. }
  1296. @Override
  1297. public Object getHospProfitResponsibilities(String responsibilityName) {
  1298. List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
  1299. .eq(Responsibility::getHospId, UserContext.getHospId())
  1300. .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null))
  1301. .like(StrUtil.isNotBlank(responsibilityName), Responsibility::getResponsibilityName, responsibilityName));
  1302. List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
  1303. .eq(Responsibility::getHospId, UserContext.getHospId()));
  1304. Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
  1305. List<Responsibility> addList = new ArrayList<>();
  1306. for (Responsibility responsibility : responsibilityList) {
  1307. Responsibility responsibility1 = map.get(responsibility.getParentId());
  1308. if (Objects.nonNull(responsibility1)) {
  1309. addList.add(responsibility1);
  1310. if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
  1311. getResponsibilityParent(responsibility1, map, addList);
  1312. }
  1313. }
  1314. }
  1315. if (!CollectionUtils.isEmpty(addList)) {
  1316. //去重
  1317. List<Responsibility> collect = addList.stream().distinct().collect(Collectors.toList());
  1318. responsibilityList.addAll(collect);
  1319. }
  1320. Map<Long, List<Responsibility>> collect = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
  1321. List<Responsibility> responsibilities = collect.get(NumberConstant.ZERO_L);
  1322. collect.remove(NumberConstant.ZERO_L);
  1323. for (Responsibility responsibility : responsibilities) {
  1324. List<Responsibility> responsibilities1 = collect.get(responsibility.getId());
  1325. if (!CollectionUtils.isEmpty(responsibilities1)) {
  1326. responsibility.setChildren(setResponsibilityChildren(responsibilities1, collect));
  1327. }
  1328. }
  1329. responsibilitySort(responsibilities);
  1330. return responsibilities;
  1331. }
  1332. @Override
  1333. public Object getHospProfitList(String computeDate, Long hospId, String reportType) {
  1334. DateTime parse = DateUtil.parse(computeDate);
  1335. int year = DateUtil.year(parse);
  1336. int month = DateUtil.month(parse) + 1;
  1337. //查询全院损益报表配置
  1338. Integer integerReportType = Integer.valueOf(reportType);
  1339. // Integer year = ComputeDateUtils.getComputeYear(computeDate);
  1340. // Integer month = ComputeDateUtils.getComputeMonth(computeDate);
  1341. // 查询所有的全院损益数据 内存溢出问题
  1342. List<HospProfitAndLoss> hospProfitAndLosses = getAllDataByDate(year, month, hospId,integerReportType);
  1343. if (CollectionUtils.isEmpty(hospProfitAndLosses)) {
  1344. throw new CostException(500, "未进行全院损益计算");
  1345. }
  1346. //判断是否有全院的数据 有单独取出另算
  1347. List<HospProfitAndLoss> hospAllList = hospProfitAndLosses.stream().filter(f -> f.getResponsibilityCode().equals("-1")).collect(Collectors.toList());
  1348. if (!CollectionUtils.isEmpty(hospAllList)) {
  1349. hospProfitAndLosses.removeAll(hospAllList);
  1350. }
  1351. List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
  1352. .eq(ReportForm::getHospId, hospId)
  1353. .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE));
  1354. if (CollUtil.isEmpty(reportFormList)) {
  1355. throw new CostException(500, "未找到全院损益表配置");
  1356. }
  1357. List<HospProfitVO> costProfitVos = BeanUtil.convertList(reportFormList, HospProfitVO.class);
  1358. //把所有数据按报表项目汇总
  1359. Map<Integer, List<HospProfitAndLoss>> reportNumGroup = hospProfitAndLosses.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getReportNum));
  1360. Map<Integer, BigDecimal> reportNumSumMap = new HashMap<>();
  1361. reportNumGroup.forEach((reportNum, hospProfitAndLossList) -> {
  1362. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000000"));
  1363. hospProfitAndLossList.stream().<UnaryOperator<BigDecimal>>map(hospProfitAndLoss -> f -> f.add(hospProfitAndLoss.getAmount())).forEach(sum::updateAndGet);
  1364. reportNumSumMap.put(reportNum, sum.get());
  1365. });
  1366. for (HospProfitVO costProfitVo : costProfitVos) {
  1367. BigDecimal bigDecimal = reportNumSumMap.get(costProfitVo.getNum());
  1368. if (bigDecimal != null) {
  1369. costProfitVo.setAmount(bigDecimal);
  1370. } else {
  1371. costProfitVo.setAmount(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP));
  1372. }
  1373. }
  1374. //判断有无其他全院数据 有组装进去
  1375. if (!CollectionUtils.isEmpty(hospAllList)) {
  1376. //全院其他收支
  1377. HospProfitVO hospProfitVO = new HospProfitVO();
  1378. hospProfitVO.setId(-1L);
  1379. hospProfitVO.setNum(-1);
  1380. hospProfitVO.setParentId(0L);
  1381. hospProfitVO.setReportName("全院其他收支");
  1382. hospProfitVO.setSort(costProfitVos.size());
  1383. hospProfitVO.setReportType(integerReportType);
  1384. hospProfitVO.setFraction(3);
  1385. costProfitVos.add(hospProfitVO);
  1386. for (int i = 0, hospAllListSize = hospAllList.size(); i < hospAllListSize; i++) {
  1387. costProfitVos.add(getHospProfitVO(hospAllList, i,integerReportType));
  1388. }
  1389. }
  1390. //取出所有成本项目
  1391. List<HospProfitVO> costFractionList = costProfitVos.stream().filter(f -> f.getCostType() != null && f.getCostType().equals(NumberConstant.TWO) && f.getFraction().equals(NumberConstant.TWO)).collect(Collectors.toList());
  1392. if (CollectionUtils.isEmpty(costFractionList)) {
  1393. throw new CostException("全院损益未配置成本占比计算分母");
  1394. } else {
  1395. if (costFractionList.size() > 1) {
  1396. throw new CostException("全院损益成本占比计算分母有且只能有一个");
  1397. }
  1398. }
  1399. List<HospProfitVO> inComeFractionList = costProfitVos.stream().filter(f -> f.getCostType() != null && f.getCostType().equals(NumberConstant.ONE) && f.getFraction().equals(NumberConstant.TWO)).collect(Collectors.toList());
  1400. if (CollectionUtils.isEmpty(inComeFractionList)) {
  1401. throw new CostException("全院损益未配置收入占比计算分母");
  1402. } else {
  1403. if (inComeFractionList.size() > 1) {
  1404. throw new CostException("全院损益收入占比计算分母有且只能有一个");
  1405. }
  1406. }
  1407. HospProfitVO inComeFraction = inComeFractionList.get(0);
  1408. HospProfitVO costFraction = costFractionList.get(0);
  1409. for (HospProfitVO costProfitVo : costProfitVos) {
  1410. if (costProfitVo.getCostType() != null) {
  1411. if (costProfitVo.getCostType().equals(NumberConstant.ONE) && costProfitVo.getFraction().equals(NumberConstant.ONE)) {
  1412. //收入
  1413. BigDecimal denominator = inComeFraction.getAmount();
  1414. //收入分子
  1415. if (denominator.compareTo(BigDecimal.ZERO) == 0) {
  1416. costProfitVo.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  1417. } else {
  1418. costProfitVo.setPercent(costProfitVo.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
  1419. }
  1420. } else if (costProfitVo.getCostType().equals(NumberConstant.TWO) && costProfitVo.getFraction().equals(NumberConstant.ONE)) {
  1421. //成本
  1422. BigDecimal denominator = costFraction.getAmount();
  1423. if (denominator.compareTo(BigDecimal.ZERO) == 0) {
  1424. costProfitVo.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  1425. } else {
  1426. costProfitVo.setPercent(costProfitVo.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
  1427. }
  1428. }
  1429. }
  1430. }
  1431. Map<Long, List<HospProfitVO>> collect = costProfitVos.stream().collect(Collectors.groupingBy(HospProfitVO::getParentId));
  1432. List<HospProfitVO> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
  1433. collect.remove(NumberConstant.ZERO_L);
  1434. for (HospProfitVO costProfitVo : costProfitParentVos) {
  1435. List<HospProfitVO> costProfitVo1 = collect.get(costProfitVo.getId());
  1436. if (!CollectionUtils.isEmpty(costProfitVo1)) {
  1437. costProfitVo.setChild(setChildren(costProfitVo1, collect));
  1438. }
  1439. }
  1440. if (!CollectionUtils.isEmpty(costProfitParentVos)) {
  1441. costProfitParentVos.sort(Comparator.comparing(HospProfitVO::getSort, Comparator.nullsLast(Integer::compareTo)));
  1442. }
  1443. return costProfitParentVos;
  1444. }
  1445. @Override
  1446. public Object getBatchHospProfitList(String beginComputeDate, String endComputeDate, Long hospId, Integer reportType) {
  1447. List<HospProfitAndLoss> hospProfitAndLossByDateRange = getHospProfitAndLossByDateRange(beginComputeDate, endComputeDate,reportType);
  1448. if (CollectionUtils.isEmpty(hospProfitAndLossByDateRange)) {
  1449. throw new CostException(500, "未进行全院损益计算");
  1450. }
  1451. //获取全院损益表配置信息
  1452. List<ReportForm> reportFormList=getReportFormList(hospId,reportType);
  1453. if (CollectionUtils.isEmpty(reportFormList)) {
  1454. throw new CostException(500, "未找到全院损益表配置");
  1455. }
  1456. //按年-月进行分组
  1457. Map<String, List<HospProfitAndLoss>> groupedByYearMonth = hospProfitAndLossByDateRange.stream()
  1458. .collect(Collectors.groupingBy(
  1459. item -> item.getDateYear() + "-" + (item.getDateMonth() < 10 ? "0" + item.getDateMonth() : item.getDateMonth())
  1460. ));
  1461. List<BatchCostProfitResponse> responses = new ArrayList<>();
  1462. List<CostProfitVo> allCostProfitVo=new ArrayList<>();
  1463. //按年-月处理科室损益数据
  1464. for (Map.Entry<String, List<HospProfitAndLoss>> entry : groupedByYearMonth.entrySet()){
  1465. List<HospProfitAndLoss> hospProfitAndLossList = entry.getValue();
  1466. //转换成成本损益数据
  1467. List<CostProfitVo> costProfitVos = convertToCostProfitVoList(hospProfitAndLossList, reportFormList);
  1468. //记录所有月份的损益数据
  1469. allCostProfitVo.addAll(costProfitVos);
  1470. //生成出参样式
  1471. BatchCostProfitResponse response = new BatchCostProfitResponse();
  1472. //第13月为审计月份
  1473. if(hospProfitAndLossList.get(0).getDateMonth()==13){
  1474. response.setComputeDate(String.format("%s-%s", hospProfitAndLossList.get(0).getDateYear(), "12A"));
  1475. response.setAuditMonth(true);
  1476. response.setMonthlyAccumulation(false);
  1477. }else {
  1478. response.setComputeDate(entry.getKey());
  1479. response.setAuditMonth(false);
  1480. response.setMonthlyAccumulation(false);
  1481. }
  1482. response.setProfitVoList(costProfitVos);
  1483. response.setAllowDrillDown(false);
  1484. responses.add(response);
  1485. }
  1486. responses.sort(Comparator.comparing(BatchCostProfitResponse::getComputeDate));
  1487. //起止年月不同时代表有多月份需要处理月累计
  1488. if(!beginComputeDate.equals(endComputeDate)){
  1489. //获取月度汇总数据
  1490. List<CostProfitVo> costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo);
  1491. if(!CollectionUtils.isEmpty(costProfitVos)){
  1492. BatchCostProfitResponse response = new BatchCostProfitResponse();
  1493. response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate));
  1494. response.setProfitVoList(costProfitVos);
  1495. response.setAllowDrillDown(false);
  1496. response.setMonthlyAccumulation(true);
  1497. response.setAuditMonth(false);
  1498. responses.add(NumberConstant.ZERO,response);
  1499. }
  1500. }
  1501. return responses;
  1502. }
  1503. /**
  1504. * 生成多月份汇总的科室损益数据
  1505. *
  1506. * @param allCostProfitVo 原始数据列表
  1507. * @return 汇总后的科室损益数据
  1508. */
  1509. private List<CostProfitVo> generateSummaryForMultipleMonths(List<CostProfitVo> allCostProfitVo){
  1510. // 参数校验
  1511. if (CollectionUtils.isEmpty(allCostProfitVo)) {
  1512. return Collections.emptyList();
  1513. }
  1514. //排除掉13月的数据
  1515. List<CostProfitVo> activeCostProfitVo = allCostProfitVo.stream().filter(profitVo -> profitVo.getMonth() != 13).collect(Collectors.toList());
  1516. if (CollectionUtils.isEmpty(activeCostProfitVo)) {
  1517. return Collections.emptyList();
  1518. }
  1519. List<CostProfitVo> profitVoList=new ArrayList<>() ;
  1520. Map<Long, List<CostProfitVo>> reportGroup = allCostProfitVo.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
  1521. reportGroup.forEach((reportId, profitVos) -> {
  1522. CostProfitVo costProfitVo = BeanUtil.convertObj(profitVos.get(NumberConstant.ZERO), CostProfitVo.class);
  1523. BigDecimal totalAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getAmount()).orElse(BigDecimal.ZERO))
  1524. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1525. BigDecimal totalBudgetAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getBudgetAmount()).orElse(BigDecimal.ZERO))
  1526. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1527. BigDecimal totalPrevPeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getPrevPeriodAmount()).orElse(BigDecimal.ZERO))
  1528. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1529. BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO))
  1530. .reduce(BigDecimal.ZERO, BigDecimal::add);
  1531. costProfitVo.setAmount(totalAmount);
  1532. costProfitVo.setBudgetAmount(totalBudgetAmount);
  1533. costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount);
  1534. costProfitVo.setSamePeriodAmount(totalSamePeriodAmount);
  1535. costProfitVo.setCompletionRate(calculateProfitRate(costProfitVo.getAmount(), costProfitVo.getBudgetAmount()));
  1536. costProfitVo.setMomRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getPrevPeriodAmount()), costProfitVo.getPrevPeriodAmount()));
  1537. costProfitVo.setYoyRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getSamePeriodAmount()), costProfitVo.getSamePeriodAmount()));
  1538. profitVoList.add(costProfitVo);
  1539. });
  1540. //转成树状结构
  1541. List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(profitVoList);
  1542. return costProfitVoTree;
  1543. }
  1544. /**
  1545. * 转换为多层级样式全院损益数据
  1546. * @param hospProfitAndLossList
  1547. * @param reportFormList
  1548. * @return
  1549. */
  1550. public List<CostProfitVo> convertToCostProfitVoList(List<HospProfitAndLoss> hospProfitAndLossList,List<ReportForm> reportFormList ){
  1551. //全院其他收支项目
  1552. List<HospProfitAndLoss> otherHospProfitAndLoss = hospProfitAndLossList.stream().filter(i -> NumberConstant.ONE.equals(i.getOriginType())).collect(Collectors.toList());
  1553. //按报表项目编号map
  1554. Map<Integer, HospProfitAndLoss> hospProfitAndLossMap = hospProfitAndLossList.stream().collect(Collectors.toMap(HospProfitAndLoss::getReportNum, b -> b));
  1555. //报表项目转换成多层级损益对象
  1556. List<CostProfitVo> costProfitVos =reportFormList.stream().map(reportForm -> reportFormToProfitVo(reportForm)).collect(Collectors.toList());
  1557. //组装全院损益及报表项目信息
  1558. for (CostProfitVo profitVo : costProfitVos) {
  1559. //处理年月数据
  1560. profitVo.setYear(hospProfitAndLossList.get(0).getDateYear());
  1561. profitVo.setMonth(hospProfitAndLossList.get(0).getDateMonth());
  1562. //添加损益数据
  1563. HospProfitAndLoss hospProfitAndLoss = hospProfitAndLossMap.get(profitVo.getReportNum());
  1564. //组装全院损益及报表项目金额信息
  1565. combineReportAndProfitAmount(profitVo,hospProfitAndLoss);
  1566. }
  1567. //有全院其他收支时添加全院其他收支
  1568. if(!CollectionUtils.isEmpty(otherHospProfitAndLoss)){
  1569. //找到配置的损益项目
  1570. Optional<ReportForm> firstLossReport = reportFormList.stream().filter(i -> NumberConstant.ONE.equals(i.getIsLoss())).findFirst();
  1571. if(!firstLossReport.isPresent()){
  1572. throw new CostException(500, "全院损益报表配置有误,未设置损益项目");
  1573. }
  1574. //生成一个虚拟的全院其他收支
  1575. CostProfitVo otherProfit = getOtherProfit(reportFormList);
  1576. //处理年月数据
  1577. otherProfit.setYear(otherHospProfitAndLoss.get(NumberConstant.ZERO).getDateYear());
  1578. otherProfit.setMonth(otherHospProfitAndLoss.get(NumberConstant.ZERO).getDateMonth());
  1579. costProfitVos.add(otherProfit);
  1580. ReportForm reportForm = firstLossReport.get();
  1581. for (int i = 0; i < otherHospProfitAndLoss.size(); i++) {
  1582. HospProfitAndLoss hospProfitAndLoss = otherHospProfitAndLoss.get(i);
  1583. CostProfitVo costProfitVo =reportFormToProfitVo(reportForm);
  1584. //组装全院损益及报表项目金额信息
  1585. combineReportAndProfitAmount(costProfitVo,hospProfitAndLoss);
  1586. //处理年月数据
  1587. costProfitVo.setYear(hospProfitAndLoss.getDateYear());
  1588. costProfitVo.setMonth(hospProfitAndLoss.getDateMonth());
  1589. //全院其他收支项目放在虚拟的全院其他收支下
  1590. costProfitVo.setSort(i);
  1591. costProfitVo.setReportNum(hospProfitAndLoss.getReportNum());
  1592. costProfitVo.setReportId(hospProfitAndLoss.getReportNum().longValue());
  1593. costProfitVo.setReportParentId(otherProfit.getReportId());
  1594. costProfitVos.add(costProfitVo);
  1595. }
  1596. }
  1597. //转成树状结构的损益数据
  1598. List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(costProfitVos);
  1599. return costProfitVoTree;
  1600. }
  1601. /**
  1602. * 生成一个虚拟的全院其他收支
  1603. * @param reportFormList
  1604. * @return
  1605. */
  1606. public CostProfitVo getOtherProfit(List<ReportForm> reportFormList) {
  1607. //全院其他收支
  1608. CostProfitVo hospProfitVO = reportFormToProfitVo(reportFormList.get(NumberConstant.ZERO));
  1609. hospProfitVO.setId(-1L);
  1610. hospProfitVO.setReportId(-1L);
  1611. hospProfitVO.setReportNum(-1);
  1612. hospProfitVO.setReportParentId(0L);
  1613. hospProfitVO.setReportName("全院其他收支");
  1614. hospProfitVO.setSort(reportFormList.size());
  1615. return hospProfitVO;
  1616. }
  1617. /**
  1618. * 报表项目转换成多层级损益对象
  1619. * @param reportForm
  1620. * @return
  1621. */
  1622. public CostProfitVo reportFormToProfitVo(ReportForm reportForm){
  1623. CostProfitVo profitVo = new CostProfitVo();
  1624. profitVo.setReportId(reportForm.getId());
  1625. profitVo.setReportName(reportForm.getReportName());
  1626. profitVo.setReportParentId(reportForm.getParentId());
  1627. profitVo.setReportNum(reportForm.getNum());
  1628. profitVo.setCalcType(reportForm.getCalcType());
  1629. profitVo.setCalcFormula(reportForm.getCalcFormula());
  1630. profitVo.setCostType(reportForm.getCostType());
  1631. profitVo.setShareType(reportForm.getReportType());
  1632. profitVo.setSort(reportForm.getSort());
  1633. profitVo.setDescription(reportForm.getDescription());
  1634. profitVo.setDataType(reportForm.getDataType());
  1635. profitVo.setDecimalPlace(reportForm.getDecimalPlace());
  1636. profitVo.setPermil(reportForm.getPermil());
  1637. return profitVo;
  1638. }
  1639. /**
  1640. * 组装全院损益及报表项目的金额信息
  1641. * @param profitVo
  1642. * @param hospProfitAndLoss
  1643. */
  1644. public void combineReportAndProfitAmount(CostProfitVo profitVo, HospProfitAndLoss hospProfitAndLoss) {
  1645. if (ObjectUtils.isEmpty(hospProfitAndLoss)) {
  1646. profitVo.setAmount(BigDecimal.ZERO);
  1647. profitVo.setSamePeriodAmount(BigDecimal.ZERO);
  1648. profitVo.setPrevPeriodAmount(BigDecimal.ZERO);
  1649. profitVo.setBudgetAmount(BigDecimal.ZERO);
  1650. profitVo.setYoyRate(BigDecimal.ZERO);
  1651. profitVo.setMomRate(BigDecimal.ZERO);
  1652. profitVo.setCompletionRate(BigDecimal.ZERO);
  1653. } else {
  1654. profitVo.setAmount(hospProfitAndLoss.getAmount());
  1655. profitVo.setSamePeriodAmount(hospProfitAndLoss.getSamePeriodAmount());
  1656. profitVo.setPrevPeriodAmount(hospProfitAndLoss.getPrevPeriodAmount());
  1657. profitVo.setBudgetAmount(hospProfitAndLoss.getBudgetAmount());
  1658. profitVo.setYoyRate(hospProfitAndLoss.getYoyRate());
  1659. profitVo.setMomRate(hospProfitAndLoss.getMomRate());
  1660. profitVo.setCompletionRate(hospProfitAndLoss.getCompletionRate());
  1661. }
  1662. }
  1663. /**
  1664. * 转成树状结构的损益数据
  1665. * @param costProfitVos
  1666. * @return
  1667. */
  1668. public List<CostProfitVo> converToCostProfitVoTree(List<CostProfitVo> costProfitVos){
  1669. // 参数校验
  1670. if (CollectionUtils.isEmpty(costProfitVos)) {
  1671. return Collections.emptyList();
  1672. }
  1673. Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
  1674. List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
  1675. collect.remove(NumberConstant.ZERO_L);
  1676. for (CostProfitVo costProfitVo : costProfitParentVos) {
  1677. List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
  1678. if (!CollectionUtils.isEmpty(costProfitVo1)) {
  1679. costProfitVo.setChildren(setChildrenProfitVo(costProfitVo1, collect));
  1680. }
  1681. }
  1682. if (!CollectionUtils.isEmpty(costProfitParentVos)) {
  1683. costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
  1684. }
  1685. return costProfitParentVos;
  1686. }
  1687. private List<CostProfitVo> setChildrenProfitVo(List<CostProfitVo> child, Map<Long, List<CostProfitVo>> collect) {
  1688. for (CostProfitVo costProfitVo : child) {
  1689. if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getReportId()))) {
  1690. costProfitVo.setChildren(setChildrenProfitVo(collect.get(costProfitVo.getReportId()), collect));
  1691. }
  1692. }
  1693. if (!CollectionUtils.isEmpty(child)) {
  1694. child.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
  1695. }
  1696. return child;
  1697. }
  1698. /**
  1699. * 获取全院损益表配置信息
  1700. * @param hospId
  1701. * @param reportType
  1702. * @return
  1703. */
  1704. public List<ReportForm> getReportFormList(Long hospId,Integer reportType ) {
  1705. List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
  1706. .eq(ReportForm::getHospId, hospId)
  1707. .eq(ReportForm::getReportType, reportType)
  1708. .eq(ReportForm::getDeleteTime , NumberConstant.ZERO)
  1709. .eq(ReportForm::getHide, NumberConstant.ONE));
  1710. return reportFormList;
  1711. }
  1712. /**
  1713. * 获取指定年月区间的全院损益数据
  1714. * @param beginComputeDate
  1715. * @param endComputeDate
  1716. * @return
  1717. */
  1718. public List<HospProfitAndLoss> getHospProfitAndLossByDateRange(String beginComputeDate, String endComputeDate, Integer reportType) {
  1719. // 解析开始和结束时间
  1720. int startYear = Integer.parseInt(beginComputeDate.split("-")[0]);
  1721. int startMonth = Integer.parseInt(beginComputeDate.split("-")[1]);
  1722. int endYear = Integer.parseInt(endComputeDate.split("-")[0]);
  1723. int endMonth = Integer.parseInt(endComputeDate.split("-")[1]);
  1724. if( startYear * 100 + startMonth> endYear * 100 + endMonth){
  1725. throw new CostException("开始时间不能大于结束时间");
  1726. }
  1727. //如果截止月份是12月要自动添加第13月的数据
  1728. if(endMonth==12)
  1729. {
  1730. endMonth=13;
  1731. }
  1732. List<HospProfitAndLoss> list = this.list(new QueryWrapper<HospProfitAndLoss>().lambda()
  1733. .eq(HospProfitAndLoss::getDeleteTime, NumberConstant.ZERO)
  1734. .eq(HospProfitAndLoss::getHospId, UserContext.getHospId())
  1735. .eq(HospProfitAndLoss::getReportType, reportType)
  1736. .apply("(date_year * 100 + date_month) >= {0}", startYear * 100 + startMonth)
  1737. .apply("(date_year * 100 + date_month) <= {0}", endYear * 100 + endMonth));
  1738. return list;
  1739. }
  1740. private static @NotNull HospProfitVO getHospProfitVO(List<HospProfitAndLoss> hospAllList, int i,int reportType) {
  1741. HospProfitAndLoss hospProfitAndLoss = hospAllList.get(i);
  1742. HospProfitVO hospProfitVO1 = new HospProfitVO();
  1743. hospProfitVO1.setId(Long.valueOf(hospProfitAndLoss.getReportNum()));
  1744. hospProfitVO1.setNum(hospProfitAndLoss.getReportNum());
  1745. hospProfitVO1.setParentId(-1L);
  1746. hospProfitVO1.setReportName(hospProfitAndLoss.getReportName());
  1747. hospProfitVO1.setSort(i);
  1748. hospProfitVO1.setReportType(reportType);
  1749. hospProfitVO1.setAmount(hospProfitAndLoss.getAmount());
  1750. hospProfitVO1.setFraction(3);
  1751. return hospProfitVO1;
  1752. }
  1753. private List<HospProfitAndLoss> getAllDataByDate(int year, int month, Long hospId,int reportType) {
  1754. return this.list(
  1755. new LambdaQueryWrapper<HospProfitAndLoss>()
  1756. .eq(HospProfitAndLoss::getHospId, hospId)
  1757. .eq(HospProfitAndLoss::getDateMonth, month)
  1758. .eq(HospProfitAndLoss::getDateYear, year)
  1759. .eq(HospProfitAndLoss::getReportType, reportType)
  1760. );
  1761. }
  1762. /**
  1763. * @param date
  1764. * @param hospId
  1765. */
  1766. @Override
  1767. public void calcByResponsibility(String date, Long hospId) {
  1768. calcHospProfit(date,hospId,ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
  1769. }
  1770. private void setCalculationAmount(List<HospProfitAndLossVo> listVo) {
  1771. Map<Integer, List<HospProfitAndLossVo>> collect = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getCalcType));
  1772. //取出所有计算公式数据
  1773. List<HospProfitAndLossVo> costDepartmentProfitVOS = collect.get(NumberConstant.FOUR);
  1774. costDepartmentProfitVOS.sort(Comparator.comparing(HospProfitAndLossVo::getReportNum, Comparator.nullsLast(Integer::compareTo)));
  1775. for (HospProfitAndLossVo profitVO : costDepartmentProfitVOS) {
  1776. // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2]
  1777. String formula = profitVO.getCalcFormula();
  1778. //找出公式当中所有代码
  1779. String replace = formula.replace("[", "")
  1780. .replace("]", "")
  1781. .replace("-", ",")
  1782. .replace("+", ",")
  1783. .replace("*", ",")
  1784. .replace("/", ",");
  1785. ArrayList<String> codeList = CollUtil.newArrayList(replace.split(","));
  1786. Map<Integer, String> codeMap = new ConcurrentHashMap<>();
  1787. for (int j = 0; j < codeList.size(); j++) {
  1788. codeMap.put(j, codeList.get(j));
  1789. }
  1790. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "")
  1791. .replace("]", "").trim(), 0)
  1792. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  1793. // 得到预算表达式 得到所有表达式的Map + - 相关的
  1794. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  1795. for (int k = 0; k < expressions.size(); k++) {
  1796. expressionMap.put(k, expressions.get(k));
  1797. }
  1798. // 数字的索引和表达式的索引累加计算
  1799. Set<Integer> codeSet = codeMap.keySet();
  1800. List<Integer> codes = new ArrayList<>(codeSet);
  1801. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(new BigDecimal("0.000000"));
  1802. for (int i = 0; i < codes.size(); i++) {
  1803. // 编号
  1804. String code = codeMap.get(i);
  1805. BigDecimal amount = null;
  1806. for (HospProfitAndLossVo costDepartmentProfitVO : listVo) {
  1807. if (costDepartmentProfitVO.getReportNum().equals(Integer.valueOf(code))) {
  1808. amount = costDepartmentProfitVO.getAmount();
  1809. }
  1810. }
  1811. if (amount == null) {
  1812. continue;
  1813. }
  1814. // BigDecimal amount = new BigDecimal(o.toString());
  1815. String str = expressionMap.get(i);
  1816. if (str.equals("+")) {
  1817. totalAmount.set(totalAmount.get().add(amount));
  1818. } else if (str.contains("-")) {
  1819. totalAmount.set(totalAmount.get().subtract(amount));
  1820. } else if (str.contains("*")) {
  1821. totalAmount.set(totalAmount.get().multiply(amount));
  1822. } else if (str.contains("/")) {
  1823. if (amount.compareTo(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP)) == 0) {
  1824. totalAmount.set(BigDecimal.ZERO);
  1825. break;
  1826. } else {
  1827. totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP));
  1828. }
  1829. }
  1830. }
  1831. profitVO.setAmount(totalAmount.get());
  1832. }
  1833. }
  1834. /**
  1835. * 按照责任中心进行计算
  1836. * 原始责任中心是设置的责任中心 目标责任中心是报表的责任中心
  1837. * 查询分摊报表里面目标责任中心是当前责任中心 报表责任中心是当前设置的责任中心
  1838. */
  1839. public BigDecimal setResponsibilityCode(HospProfitAndLossVo costDepartmentProfitVO, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1840. // 获取当前报表对应的责任中心
  1841. List<ReportRelation> reportRelationList = reportRelationMap.get(costDepartmentProfitVO.getReportId());
  1842. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1843. if (CollUtil.isNotEmpty(reportRelationList)) {
  1844. // 获取对应的责任中心的Code集合 这个是设置的责任中心
  1845. List<String> responsibilityCodes = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
  1846. if (CollUtil.isNotEmpty(responsibilityCodes)) {
  1847. // 查询报表里面是当前分摊层级的数据
  1848. List<Allocation> allocations = allocationList.stream().filter(i -> i.getTargetResponsibilityCode().equals(costDepartmentProfitVO.getResponsibilityCode()) && responsibilityCodes.contains(i.getResponsibilityCode())).collect(Collectors.toList());
  1849. if (CollUtil.isNotEmpty(allocations)) {
  1850. BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  1851. sum.set(reduce);
  1852. // allocations.forEach(m -> {
  1853. // sum.updateAndGet(v -> v.add(m.getAmount()));
  1854. // });
  1855. }
  1856. }
  1857. }
  1858. // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
  1859. return sum.get();
  1860. }
  1861. /***
  1862. * 按照计算方式进行计算
  1863. */
  1864. public BigDecimal setCalculation(HospProfitAndLossVo costDepartmentProfitVO, List<HospProfitAndLossVo> costDepartmentProfitVOList,
  1865. List<CostShareLevel> costShareLevelList, Map<Long, List<HospProfitAndLossVo>> listMap,
  1866. List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList,
  1867. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1868. // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2]
  1869. String calcFormula = costDepartmentProfitVO.getCalcFormula();
  1870. String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
  1871. String replace = calcFormula.replace("[", "").replace("]", "").replace("+", ",").replace("-", ",-");
  1872. List<Integer> calcFormulaList = Arrays.stream(replace.split(StrUtil.COMMA)).map(Integer::valueOf).collect(Collectors.toList());
  1873. // 查询这个编号集合的报表
  1874. AtomicReference<BigDecimal> bigDecimal = new AtomicReference<>(new BigDecimal("0.0000"));
  1875. calcFormulaList.forEach(calc -> {
  1876. Integer calcNum = Math.abs(calc);
  1877. List<Long> reportIdList = allList.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode) && calcNum.equals(i.getReportNum())).map(HospProfitAndLossVo::getReportId).collect(Collectors.toList());
  1878. if (CollUtil.isNotEmpty(reportIdList)) {
  1879. reportIdList.forEach(i -> {
  1880. List<HospProfitAndLossVo> profitVOS = listMap.get(i);
  1881. if (CollUtil.isEmpty(profitVOS)) {
  1882. throw new CostException(500, "报表未找到");
  1883. }
  1884. BigDecimal amount = getAmount(profitVOS, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
  1885. if (calc > 0) {
  1886. bigDecimal.updateAndGet(v -> v.add(amount));
  1887. } else {
  1888. bigDecimal.updateAndGet(v -> v.subtract(amount));
  1889. }
  1890. });
  1891. }
  1892. });
  1893. return bigDecimal.get();
  1894. }
  1895. /**
  1896. * 按照小计的计算方式
  1897. * 同一个目录下相同的其他金额的和
  1898. */
  1899. public BigDecimal setSubtotal(HospProfitAndLossVo costDepartmentProfitVO,
  1900. List<CostShareLevel> costShareLevelList,
  1901. Map<Long, List<HospProfitAndLossVo>> listMap,
  1902. List<HospProfitAndLossVo> profitVOS,
  1903. List<IncomeCollection> list,
  1904. List<AllocationQueryReportVO> allocationQueryReportVOList,
  1905. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
  1906. // 因为报表是按照报表项目的升序进行排序的 前面的报表是已经进行计算了的
  1907. // 查询当前报表的父层级id
  1908. Long reportParentId = costDepartmentProfitVO.getReportParentId();
  1909. String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
  1910. // 查询报表里面在当前父层级下的并且不是自己的报表项目
  1911. List<HospProfitAndLossVo> costDepartmentProfitVOS = allList.stream().filter(i -> i.getReportParentId().equals(reportParentId) && i.getResponsibilityCode().equals(responsibilityCode) && !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
  1912. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
  1913. // 遍历数据 之前的已经经过了计算
  1914. costDepartmentProfitVOS.forEach(i -> {
  1915. Long reportId = i.getReportId();
  1916. List<HospProfitAndLossVo> costDepartmentProfitVOS1 = listMap.get(reportId);
  1917. if (CollUtil.isEmpty(costDepartmentProfitVOS1)) {
  1918. throw new CostException(500, "报表未找到");
  1919. }
  1920. BigDecimal amount = getAmount(costDepartmentProfitVOS1, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
  1921. sum.set(amount.add(sum.get()));
  1922. ;
  1923. });
  1924. // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
  1925. return sum.get();
  1926. }
  1927. /**
  1928. * 判断是那种计算方式 调用方法进行计算
  1929. */
  1930. public BigDecimal getAmount(List<HospProfitAndLossVo> profitVOS,
  1931. List<CostShareLevel> costShareLevelList,
  1932. String responsibilityCode, List<IncomeCollection> list,
  1933. List<AllocationQueryReportVO> allocationQueryReportVOList,
  1934. Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList,
  1935. Map<Long, List<HospProfitAndLossVo>> listMap, List<HospProfitAndLossVo> allList) {
  1936. BigDecimal bigDecimal = new BigDecimal("0.0000");
  1937. // 在对这个报表进行过滤
  1938. List<HospProfitAndLossVo> costDepartmentProfitVOS = profitVOS.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList());
  1939. // 都一个就是
  1940. HospProfitAndLossVo costDepartmentProfitVO = costDepartmentProfitVOS.get(0);
  1941. Integer calcType = costDepartmentProfitVO.getCalcType();
  1942. if (NumberConstant.ONE.equals(calcType)) {
  1943. // 调用计算的方法 按照会计科目
  1944. bigDecimal = setAccountReportData(costDepartmentProfitVO, list, allocationQueryReportVOList, reportRelationMap);
  1945. } else if (NumberConstant.TWO.equals(calcType)) {
  1946. // 按照分摊层级
  1947. bigDecimal = setShareLevelReportData(costDepartmentProfitVO, reportRelationMap, allocationList);
  1948. } else if (NumberConstant.THREE.equals(calcType)) {
  1949. // 小计
  1950. bigDecimal = setSubtotal(costDepartmentProfitVO, costShareLevelList, listMap, profitVOS, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
  1951. } else if (NumberConstant.FIVE.equals(calcType)) {
  1952. // 按照责任中心
  1953. bigDecimal = setResponsibilityCode(costDepartmentProfitVO, reportRelationMap, allocationList, allList);
  1954. } else if (NumberConstant.FOUR.equals(calcType)) {
  1955. bigDecimal = setCalculation(costDepartmentProfitVO, costDepartmentProfitVOS, costShareLevelList, listMap, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
  1956. }
  1957. return bigDecimal;
  1958. }
  1959. private BigDecimal setAccountReportData(HospProfitAndLossVo i, List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList, Map<Long, List<ReportRelation>> reportRelationMap) {
  1960. // 在报表关联里面查询当前报表关联的
  1961. Long reportId = i.getReportId();
  1962. List<ReportRelation> reportRelationList = reportRelationMap.get(reportId);
  1963. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1964. if (CollUtil.isNotEmpty(reportRelationList)) {
  1965. // 获取对应的会计科目信息 筛选会计科目的Code
  1966. List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
  1967. // 查找在归集数据里面当前责任中心对应的这些会计科目的金额
  1968. List<IncomeCollection> incomeCollectionList = list.stream().filter(income -> income.getResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList());
  1969. // 需要查询分摊后的表
  1970. List<AllocationQueryReportVO> reportVOList = allocationQueryReportVOList.stream().filter(m -> m.getTargetResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(m.getAccountingCode())).collect(Collectors.toList());
  1971. if (CollUtil.isNotEmpty(incomeCollectionList)) {
  1972. incomeCollectionList.forEach(m -> {
  1973. sum.updateAndGet(v -> v.add(m.getAmount()));
  1974. });
  1975. }
  1976. // 成本减
  1977. if (CollUtil.isNotEmpty(reportVOList)) {
  1978. reportVOList.forEach(m -> {
  1979. sum.updateAndGet(v -> v.add(m.getAmount()));
  1980. });
  1981. }
  1982. }
  1983. // i.setAmount(new BigDecimal(sum.toString()));
  1984. // numMap.put(i.getReportNum()+i.getResponsibilityCode(),new BigDecimal(sum.toString()));
  1985. return sum.get();
  1986. }
  1987. private BigDecimal setShareLevelReportData(HospProfitAndLossVo i, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList) {
  1988. List<ReportRelation> reportRelationList = reportRelationMap.get(i.getReportId());
  1989. AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
  1990. if (CollUtil.isNotEmpty(reportRelationList)) {
  1991. // 找到对应的分摊层级的Id 但是分摊报表里面存的是分摊层级的序号
  1992. List<Long> shareLevelIds = reportRelationList.stream().map(ReportRelation::getRelationCode).map(Long::valueOf).collect(Collectors.toList());
  1993. // List<Integer> levelShortList = costShareLevelList.stream()
  1994. // .filter(m -> shareLevelIds.contains(m.getId()))
  1995. // .map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  1996. if (CollUtil.isNotEmpty(shareLevelIds)) {
  1997. // 查询报表里面是当前分摊层级的数据
  1998. List<Allocation> allocations = allocationList.stream().filter(m -> shareLevelIds.contains(m.getShareLevelId()) && m.getTargetResponsibilityCode().equals(i.getResponsibilityCode())).collect(Collectors.toList());
  1999. if (CollUtil.isNotEmpty(allocations)) {
  2000. // allocations.forEach(m -> {
  2001. // sum.updateAndGet(v -> v.add(m.getAmount()));
  2002. // });
  2003. BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  2004. sum.set(reduce);
  2005. }
  2006. }
  2007. }
  2008. // i.setAmount(new BigDecimal(sum.toString()));
  2009. return sum.get();
  2010. }
  2011. private void calcByLitterCountResp(HospProfitAndLossVo lossVo, Map<Long, List<HospProfitAndLossVo>> listParentMap, List<HospProfitAndLossVo> listVo, Long hospId) {
  2012. //lossVo 当前 小计对象
  2013. //listParentMap 与小计同级别的对象
  2014. //listVo 存储计算过的对象
  2015. // 通地当前小计 找出 同级别需要合计的对象 再从计算过的对象取出数值合计
  2016. Long reportParentId = lossVo.getReportParentId();
  2017. List<HospProfitAndLossVo> hospProfitAndLossVos = listParentMap.get(reportParentId);
  2018. //去除小计本身
  2019. hospProfitAndLossVos.remove(lossVo);
  2020. List<Integer> reportNums = hospProfitAndLossVos.stream().map(HospProfitAndLossVo::getReportNum).collect(Collectors.toList());
  2021. List<HospProfitAndLossVo> collect = listVo.stream().filter(i -> reportNums.contains(i.getReportNum()) && i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
  2022. if (collect.isEmpty()) {
  2023. return;
  2024. }
  2025. BigDecimal reduce = collect.stream().map(HospProfitAndLossVo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  2026. lossVo.setAmount(reduce);
  2027. }
  2028. private List<HospProfitAndLossVo> costPercent(List<HospProfitAndLossVo> profitIncomeList) {
  2029. List<HospProfitAndLossVo> list = new ArrayList<>();
  2030. Map<Integer, List<HospProfitAndLossVo>> collect = profitIncomeList.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getFraction));
  2031. //分母只有一个
  2032. List<HospProfitAndLossVo> denominatorList = collect.get(NumberConstant.TWO);
  2033. if (denominatorList.size() > 1) {
  2034. throw new CostException("收入项目分母大于一个,请查证后再计算科室损益");
  2035. }
  2036. BigDecimal denominator = denominatorList.get(0).getAmount();
  2037. //收入分子
  2038. List<HospProfitAndLossVo> numeratorList = collect.get(NumberConstant.ONE);
  2039. if (denominator.compareTo(BigDecimal.ZERO) == 0) {
  2040. for (HospProfitAndLossVo profitVO : numeratorList) {
  2041. profitVO.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  2042. }
  2043. denominatorList.get(0).setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
  2044. } else {
  2045. for (HospProfitAndLossVo profitVO : numeratorList) {
  2046. profitVO.setPercent(profitVO.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
  2047. }
  2048. denominatorList.get(0).setPercent(BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP));
  2049. }
  2050. list.add(denominatorList.get(0));
  2051. list.addAll(numeratorList);
  2052. return list;
  2053. }
  2054. private void calcByResponsibilityResp(Long hospId, HospProfitAndLossVo lossVo) {
  2055. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(lossVo.getReportId(), hospId);
  2056. if (responsibilities.isEmpty()) {
  2057. return;
  2058. }
  2059. List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  2060. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  2061. calcTotal.set(BigDecimal.ZERO);
  2062. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  2063. responsibilityCodes.forEach(i -> {
  2064. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  2065. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2066. calcTotal.set(calcTotal.get().add(costAmount));
  2067. });
  2068. lossVo.setAmount(calcTotal.get());
  2069. }
  2070. private void calcByResponsibilityResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
  2071. List<RelationVO> responsibilities = reportRelationService.getResponsibilities(child.getId(), hospId);
  2072. if (responsibilities.isEmpty()) {
  2073. return;
  2074. }
  2075. List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
  2076. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  2077. calcTotal.set(BigDecimal.ZERO);
  2078. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  2079. responsibilityCodes.forEach(i -> {
  2080. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
  2081. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2082. calcTotal.set(calcTotal.get().add(costAmount));
  2083. });
  2084. HospProfitAndLoss loss = new HospProfitAndLoss();
  2085. loss.setReportName(child.getReportName()).setReportNum(child.getNum()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  2086. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
  2087. list.add(loss);
  2088. }
  2089. private void calcByFormulaResp(HospProfitAndLossVo lossVo, List<HospProfitAndLossVo> list) {
  2090. // 得到这个责任中心下所有的已经收集的数据
  2091. List<HospProfitAndLossVo> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
  2092. String calcFormula = lossVo.getCalcFormula();
  2093. // TODO: 2021/8/27 校验公式合法性
  2094. if (StrUtil.isBlank(calcFormula)) {
  2095. throw new CostException("reportForm名称为" + lossVo.getReportName() + "计算公式不正确");
  2096. }
  2097. BigDecimal bigDecimal = calcAmountRes(hadCalcLosses, calcFormula);
  2098. lossVo.setAmount(bigDecimal);
  2099. }
  2100. private void calcByFormulaResp(int year, int month, ReportForm child, List<HospProfitAndLoss> list, Responsibility responsibility) {
  2101. // 得到这个责任中心下所有的已经收集的数据
  2102. List<HospProfitAndLoss> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
  2103. String calcFormula = child.getCalcFormula();
  2104. // TODO: 2021/8/27 校验公式合法性
  2105. if (StrUtil.isBlank(calcFormula)) {
  2106. throw new CostException("reportForm名称为" + child.getReportName() + "计算公式不正确");
  2107. }
  2108. BigDecimal bigDecimal = calcAmountResp(hadCalcLosses, calcFormula);
  2109. HospProfitAndLoss loss = new HospProfitAndLoss();
  2110. loss.setDateYear(year).setDateMonth(month).setReportNum(child.getNum()).setReportName(child.getReportName())
  2111. .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(child.getHospId()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
  2112. list.add(loss);
  2113. }
  2114. private BigDecimal calcAmountRes(List<HospProfitAndLossVo> hadCalcLosses, String calcFormula) {
  2115. // 得到所有的编号
  2116. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  2117. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  2118. // 得到编号的map
  2119. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  2120. for (int j = 0; j < numList.size(); j++) {
  2121. numMap.put(j, Integer.parseInt(numList.get(j)));
  2122. }
  2123. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  2124. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  2125. // 得到预算表达式 得到所有表达式的Map + - 相关的
  2126. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  2127. for (int k = 0; k < expressions.size(); k++) {
  2128. expressionMap.put(k, expressions.get(k));
  2129. }
  2130. // 数字的索引和表达式的索引累加计算
  2131. Set<Integer> numSet = numMap.keySet();
  2132. List<Integer> nums = new ArrayList<>(numSet);
  2133. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  2134. totalAmount.set(BigDecimal.ZERO);
  2135. for (int i = 0; i < nums.size(); i++) {
  2136. // 编号
  2137. Integer num = numMap.get(i);
  2138. List<HospProfitAndLossVo> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  2139. if (CollUtil.isEmpty(losses)) {
  2140. continue;
  2141. }
  2142. HospProfitAndLossVo loss = losses.get(0);
  2143. BigDecimal amount = loss.getAmount();
  2144. String str = expressionMap.get(i);
  2145. if (str.equals("+")) {
  2146. totalAmount.set(totalAmount.get().add(amount));
  2147. } else {
  2148. totalAmount.set(totalAmount.get().subtract(amount));
  2149. }
  2150. }
  2151. return totalAmount.get();
  2152. }
  2153. private BigDecimal calcAmountResp(List<HospProfitAndLoss> hadCalcLosses, String calcFormula) {
  2154. // 得到所有的编号
  2155. String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
  2156. ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
  2157. // 得到编号的map
  2158. Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
  2159. for (int j = 0; j < numList.size(); j++) {
  2160. numMap.put(j, Integer.parseInt(numList.get(j)));
  2161. }
  2162. List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
  2163. .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
  2164. // 得到预算表达式 得到所有表达式的Map + - 相关的
  2165. Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
  2166. for (int k = 0; k < expressions.size(); k++) {
  2167. expressionMap.put(k, expressions.get(k));
  2168. }
  2169. // 数字的索引和表达式的索引累加计算
  2170. Set<Integer> numSet = numMap.keySet();
  2171. List<Integer> nums = new ArrayList<>(numSet);
  2172. AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
  2173. totalAmount.set(BigDecimal.ZERO);
  2174. for (int i = 0; i < nums.size(); i++) {
  2175. // 编号
  2176. Integer num = numMap.get(i);
  2177. List<HospProfitAndLoss> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
  2178. if (CollUtil.isEmpty(losses)) {
  2179. continue;
  2180. }
  2181. HospProfitAndLoss loss = losses.get(0);
  2182. BigDecimal amount = loss.getAmount();
  2183. String str = expressionMap.get(i);
  2184. if (str.equals("+")) {
  2185. totalAmount.set(totalAmount.get().add(amount));
  2186. } else {
  2187. totalAmount.set(totalAmount.get().subtract(amount));
  2188. }
  2189. }
  2190. return totalAmount.get();
  2191. }
  2192. private void calcByLitterCountResp(int year, int month, ReportForm child, List<ReportForm> children,
  2193. List<HospProfitAndLoss> list, Long hospId, Responsibility responsibility) {
  2194. List<HospProfitAndLoss> thisRespCodeList = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
  2195. List<ReportForm> thisForEachList = children.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
  2196. List<HospProfitAndLoss> collect = thisRespCodeList.stream().filter(i -> thisForEachList.stream().map(ReportForm::getNum).collect(Collectors.toList()).contains(i.getReportNum())).collect(Collectors.toList());
  2197. if (collect.isEmpty()) {
  2198. return;
  2199. }
  2200. BigDecimal reduce = collect.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  2201. HospProfitAndLoss loss = new HospProfitAndLoss();
  2202. loss.setDateYear(year).setDateMonth(month)
  2203. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
  2204. // 小计只能有一个
  2205. loss.setReportNum(child.getNum()).setReportName(child.getReportName())
  2206. .setResponsibilityCode(responsibility.getResponsibilityCode())
  2207. .setResponsibilityName(responsibility.getResponsibilityName());
  2208. list.add(loss);
  2209. }
  2210. private void calcByShareLevelResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
  2211. List<RelationVO> shareLevels = reportRelationService.getShareLevel(child.getId(), hospId);
  2212. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  2213. if (CollUtil.isEmpty(shareLevelId)) {
  2214. return;
  2215. }
  2216. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  2217. if (costShareLevels.isEmpty()) {
  2218. throw new CostException("医院分摊层级设置错误," + child.getReportName());
  2219. }
  2220. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  2221. List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(year, month, hospId, shareLevelId, responsibility.getResponsibilityCode());
  2222. if (allocations.isEmpty()) {
  2223. throw new CostException("医院未分摊本月数据");
  2224. }
  2225. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  2226. if (accountShares.isEmpty()) {
  2227. return;
  2228. }
  2229. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  2230. HospProfitAndLoss loss = new HospProfitAndLoss();
  2231. loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  2232. .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  2233. .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  2234. ;
  2235. list.add(loss);
  2236. }
  2237. private void calcByShareLevelResp(Long hospId, HospProfitAndLossVo lossVo) {
  2238. List<RelationVO> shareLevels = reportRelationService.getShareLevel(lossVo.getReportId(), hospId);
  2239. List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
  2240. if (CollUtil.isEmpty(shareLevelId)) {
  2241. return;
  2242. }
  2243. List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
  2244. if (costShareLevels.isEmpty()) {
  2245. throw new CostException("医院分摊层级设置错误," + lossVo.getReportName());
  2246. }
  2247. List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
  2248. List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, shareLevelId, lossVo.getResponsibilityCode());
  2249. if (allocations.isEmpty()) {
  2250. throw new CostException("医院未分摊本月数据");
  2251. }
  2252. List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
  2253. if (accountShares.isEmpty()) {
  2254. return;
  2255. }
  2256. BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  2257. lossVo.setAmount(reduce);
  2258. // HospProfitAndLoss loss = new HospProfitAndLoss();
  2259. // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  2260. // .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  2261. // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  2262. // ;
  2263. // list.add(loss);
  2264. }
  2265. private void calcByAccountByResp(Long hospId, HospProfitAndLossVo lossVo) {
  2266. // 报表项目关联的会计科目对象
  2267. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(lossVo.getReportId(), hospId);
  2268. if (accountRelations.isEmpty()) {
  2269. return;
  2270. }
  2271. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  2272. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  2273. calcTotal.set(BigDecimal.ZERO);
  2274. List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  2275. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
  2276. accountCodes.forEach(i -> {
  2277. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  2278. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2279. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  2280. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2281. BigDecimal total = incomeAmount.add(costAmount);
  2282. calcTotal.set(calcTotal.get().add(total));
  2283. });
  2284. // HospProfitAndLoss loss = new HospProfitAndLoss();
  2285. lossVo.setAmount(calcTotal.get());
  2286. // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  2287. // .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  2288. // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
  2289. // list.add(loss);
  2290. }
  2291. private void calcByAccountByResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int month, int year, Responsibility responsibility) {
  2292. // 报表项目关联的会计科目对象
  2293. List<RelationVO> accountRelations = reportRelationService.getAccountRelation(child.getId(), hospId);
  2294. if (accountRelations.isEmpty()) {
  2295. return;
  2296. }
  2297. List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
  2298. AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
  2299. calcTotal.set(BigDecimal.ZERO);
  2300. List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  2301. List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
  2302. accountCodes.forEach(i -> {
  2303. BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
  2304. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2305. BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
  2306. .reduce(BigDecimal.ZERO, BigDecimal::add);
  2307. BigDecimal total = incomeAmount.add(costAmount);
  2308. calcTotal.set(calcTotal.get().add(total));
  2309. });
  2310. HospProfitAndLoss loss = new HospProfitAndLoss();
  2311. loss.setReportName(child.getReportName()).setReportNum(child.getNum())
  2312. .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
  2313. .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
  2314. ;
  2315. list.add(loss);
  2316. }
  2317. private void responsibilitySort(List<Responsibility> responsibilityList) {
  2318. for (Responsibility responsibility : responsibilityList) {
  2319. if (!CollectionUtils.isEmpty(responsibility.getChildren())) {
  2320. responsibilitySort(responsibility.getChildren());
  2321. }
  2322. }
  2323. responsibilityList.sort(Comparator.comparing(Responsibility::getSort, Comparator.nullsLast(Integer::compareTo)));
  2324. }
  2325. private List<Responsibility> setResponsibilityChildren(List<Responsibility> child, Map<Long, List<Responsibility>> collect) {
  2326. for (Responsibility responsibility : child) {
  2327. if (!CollectionUtils.isEmpty(collect.get(responsibility.getId()))) {
  2328. responsibility.setChildren(setResponsibilityChildren(collect.get(responsibility.getId()), collect));
  2329. }
  2330. }
  2331. return child;
  2332. }
  2333. private void getResponsibilityParent(Responsibility responsibility, Map<Long, Responsibility> collect, List<Responsibility> addList) {
  2334. Responsibility responsibility1 = collect.get(responsibility.getParentId());
  2335. if (Objects.nonNull(responsibility1)) {
  2336. addList.add(responsibility1);
  2337. if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
  2338. getResponsibilityParent(responsibility1, collect, addList);
  2339. }
  2340. }
  2341. }
  2342. private List<HospProfitVO> setChildren(List<HospProfitVO> child, Map<Long, List<HospProfitVO>> collect) {
  2343. for (HospProfitVO costProfitVo : child) {
  2344. if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getId()))) {
  2345. costProfitVo.setChild(setChildren(collect.get(costProfitVo.getId()), collect));
  2346. }
  2347. }
  2348. if (!CollectionUtils.isEmpty(child)) {
  2349. child.sort(Comparator.comparing(HospProfitVO::getSort, Comparator.nullsLast(Integer::compareTo)));
  2350. }
  2351. return child;
  2352. }
  2353. }