12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546 |
- package com.kcim.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DatePattern;
- import cn.hutool.core.date.DateTime;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.util.ReUtil;
- import cn.hutool.core.util.StrUtil;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.google.common.collect.ImmutableMap;
- import com.kcim.common.constants.*;
- import com.kcim.common.enums.*;
- import com.kcim.common.exception.CostException;
- import com.kcim.common.file.MinioConfig;
- import com.kcim.common.file.MinioFileUtil;
- import com.kcim.common.util.*;
- import com.kcim.common.util.excel.ExcelPoiUtil;
- import com.kcim.common.util.excel.entity.ColEntity;
- import com.kcim.common.util.excel.entity.TitleEntity;
- import com.kcim.dao.mapper.HospProfitAndLossMapper;
- import com.kcim.dao.model.*;
- import com.kcim.service.*;
- import com.kcim.vo.*;
- import com.kcim.web.reponse.BatchCostProfitResponse;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.fileupload.FileItem;
- import org.apache.commons.fileupload.FileItemFactory;
- import org.apache.commons.fileupload.disk.DiskFileItemFactory;
- import org.apache.poi.hssf.usermodel.HSSFWorkbook;
- import org.jetbrains.annotations.NotNull;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.CollectionUtils;
- import org.springframework.util.ObjectUtils;
- import org.springframework.util.StringUtils;
- import org.springframework.web.multipart.MultipartFile;
- import org.springframework.web.multipart.commons.CommonsMultipartFile;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.text.DecimalFormat;
- import java.util.*;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.atomic.AtomicReference;
- import java.util.function.UnaryOperator;
- import java.util.stream.Collectors;
- @Slf4j
- @Service("hospProfitAndLossService")
- public class HospProfitAndLossServiceImpl extends ServiceImpl<HospProfitAndLossMapper, HospProfitAndLoss> implements HospProfitAndLossService {
- // @Value("${file.filelocal}")
- // private String hospProfitReportUrl;
- //
- // @Value("${file.serverUrl}")
- // private String serverUrl;
- private final ReportFormService reportFormService;
- private final IncomeCollectionService collectionService;
- private final AllocationQueryService allocationQueryService;
- private final AllocationService allocationService;
- private final ReportRelationService reportRelationService;
- private final CostShareLevelService shareLevelService;
- private final CostOtherPaymentsDataService otherPaymentsDataService;
- private final ResponsibilityService responsibilityService;
- private final CostAccountShareService accountShareService;
- private final FileRecordService fileRecordService;
- private final SqlService sqlService;
- private final CenterService centerService;
- private final MinioConfig minioConfig;
- private final MinioFileUtil minioFileUtil;
- public HospProfitAndLossServiceImpl(ReportFormService reportFormService,
- IncomeCollectionService collectionService,
- AllocationQueryService allocationQueryService,
- AllocationService allocationService, ReportRelationService reportRelationService,
- CostShareLevelService shareLevelService,
- CostOtherPaymentsDataService otherPaymentsDataService,
- ResponsibilityService responsibilityService,
- CostAccountShareService accountShareService,
- FileRecordService fileRecordService,
- MinioConfig minioConfig,
- MinioFileUtil minioFileUtil,
- SqlService sqlService,
- CenterService centerService
- ) {
- this.reportFormService = reportFormService;
- this.collectionService = collectionService;
- this.allocationQueryService = allocationQueryService;
- this.allocationService = allocationService;
- this.reportRelationService = reportRelationService;
- this.shareLevelService = shareLevelService;
- this.otherPaymentsDataService = otherPaymentsDataService;
- this.responsibilityService = responsibilityService;
- this.accountShareService = accountShareService;
- this.fileRecordService = fileRecordService;
- this.minioConfig = minioConfig;
- this.minioFileUtil = minioFileUtil;
- this.sqlService=sqlService;
- this.centerService=centerService;
- }
- /**
- * 计算全院损益
- *
- * @param date yyyy-MM-dd 时间
- * @param hospId 医院id
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
- public void calc(String date, Long hospId) {
- reportFormService.checkExistLoss(hospId);
- DateTime parse = DateUtil.parse(date);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- this.remove(new LambdaQueryWrapper<HospProfitAndLoss>().eq(HospProfitAndLoss::getDateYear, year).eq(HospProfitAndLoss::getDateMonth, month).eq(HospProfitAndLoss::getHospId, hospId));
- // 得到全院损益计算报表
- List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
- if (CollUtil.isEmpty(reportForms)) {
- throw new CostException("医院未设置全院损益计算报表");
- }
- // 得到这个月所有收入数据
- List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
- if (incomes.isEmpty()) {
- throw new CostException("医院未归集本月收入数据");
- }
- // 得到这个月的所有成本数据
- List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
- if (allocationQueries.isEmpty()) {
- throw new CostException("医院未分摊本月数据");
- }
- List<HospProfitAndLoss> list = new ArrayList<>();
- List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
- for (ReportForm parentForm : parentForms) {
- Long parentId = parentForm.getId();
- List<ReportForm> children = reportForms.stream().filter(i -> i.getParentId().equals(parentId)).collect(Collectors.toList());
- for (ReportForm child : children) {
- Integer calcType = child.getCalcType();
- if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
- // 按会计科目计算单的话
- calcByAccount(hospId, child, incomes, list, allocationQueries, month, year);
- } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
- // 分摊层级计算
- calcByShareLevel(hospId, child, list, year, month);
- } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
- // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
- calcByLitterCount(year, month, child, children, list, hospId);
- } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
- // 按公式 (要保证总合计放到最后呀)
- calcByFormula(year, month, child, children, list);
- } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
- // 责任中心
- calcByResponsibility(hospId, child, allocationQueries, list, year, month);
- } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
- // 不设置不计算
- } else {
- }
- }
- }
- // 处理医院其他收支
- List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
- if (!otherPaymentsDatas.isEmpty()) {
- otherPaymentsDatas.forEach(ele -> {
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum(ele.getId().intValue())
- .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId);
- // if (ele.getPaymentsType() == 2) {
- // loss.setAmount(BigDecimal.ZERO.subtract(ele.getTotalAmount()));
- // }
- list.add(loss);
- });
- }
- this.saveBatch(list);
- }
- /**
- * 计算全院损益
- * @param date yyyy-MM-dd 时间
- * @param hospId 医院id
- * @param reportType 报表类型
- */
- @Override
- public void calcHospProfit(String date, Long hospId, Integer reportType){
- //需要用代码计算全院损益时
- if(IsNeedCalc(reportType)){
- //计算全院损益
- calcHospProfitAction(date,hospId,reportType);
- //计算同环比
- handleSpecificMonthsCalculation(hospId, date, reportType);
- }
- execHospProfitSql(date,reportType);
- }
- @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
- public void calcHospProfitAction(String date, Long hospId, Integer reportType) {
- List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
- DateTime parse = DateUtil.parse(date);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- this.remove(
- new LambdaQueryWrapper<HospProfitAndLoss>()
- .eq(HospProfitAndLoss::getDateYear, year)
- .eq(HospProfitAndLoss::getDateMonth, month)
- .eq(HospProfitAndLoss::getHospId, hospId)
- .eq(HospProfitAndLoss::getReportType, reportType)
- );
- // 得到全院损益计算报表
- List<ReportForm> reportForms = reportFormService.getListByReportType(hospId, reportType);
- if (CollUtil.isEmpty(reportForms)) {
- throw new CostException("医院未设置全院损益计算报表");
- }
- reportFormService.checkExistLoss(hospId,reportType);
- // 得到这个月所有收入数据
- List<IncomeCollection> incomes = collectionService.getCollectionsByDate(year, month, hospId);
- if (incomes.isEmpty()) {
- throw new CostException("医院未归集本月收入数据");
- }
- Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
- // 得到这个月的所有成本数据
- List<AllocationQuery> allocationQueries = allocationQueryService.getAllByDate(hospId, year, month);
- if (allocationQueries.isEmpty()) {
- throw new CostException("医院未分摊本月数据");
- }
- List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueries, AllocationQueryReportVO.class);
- allocationQueryReportVOList.forEach(i -> {
- i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
- i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
- });
- // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
- List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>().lambda().eq(Allocation::getHospId, hospId)
- .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month));
- if (CollUtil.isEmpty(allocationList)) {
- throw new CostException(500, "分摊报表数据不存在");
- }
- // 查询最后一个层级的责任中心
- List<CostShareLevel> costShareLevelList = shareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
- .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort));
- if (CollUtil.isEmpty(costShareLevelList)) {
- throw new CostException(500, "分摊层级未设置");
- }
- List<HospProfitAndLossVo> listVo = new ArrayList<>();
- // List<ReportForm> parentForms = reportForms.stream().filter(i -> i.getParentId().equals(0L)).collect(Collectors.toList());
- int finalYear = year;
- int finalMonth = month;
- leafResp.forEach(i -> {
- reportForms.forEach(j -> {
- HospProfitAndLossVo hospProfitAndLossVo = new HospProfitAndLossVo();
- hospProfitAndLossVo.setDateYear(finalYear);
- hospProfitAndLossVo.setDateMonth(finalMonth);
- hospProfitAndLossVo.setReportNum(j.getNum());
- hospProfitAndLossVo.setReportName(j.getReportName());
- hospProfitAndLossVo.setResponsibilityCode(i.getResponsibilityCode());
- hospProfitAndLossVo.setResponsibilityName(i.getResponsibilityName());
- hospProfitAndLossVo.setCostType(NumberConstant.ZERO);
- hospProfitAndLossVo.setIncomeType(NumberConstant.ZERO);
- hospProfitAndLossVo.setHospId(hospId);
- hospProfitAndLossVo.setType(j.getCostType());
- hospProfitAndLossVo.setFraction(j.getFraction());
- hospProfitAndLossVo.setReportId(j.getId());
- hospProfitAndLossVo.setReportNum(j.getNum());
- hospProfitAndLossVo.setCalcType(j.getCalcType());
- hospProfitAndLossVo.setReportName(j.getReportName());
- hospProfitAndLossVo.setCalcFormula(j.getCalcFormula());
- hospProfitAndLossVo.setReportParentId(j.getParentId());
- listVo.add(hospProfitAndLossVo);
- });
- });
- Map<Long, List<HospProfitAndLossVo>> listMap = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getReportId));
- List<HospProfitAndLossVo> allList = BeanUtil.convertList(listVo, HospProfitAndLossVo.class);
- // 记录每一次计算的钱
- //所有小计 总计单独处理
- listVo.forEach(i -> {
- Integer calcType = i.getCalcType();
- if (NumberConstant.ONE.equals(calcType)) {
- // TODO 按照会计科目进行计算
- i.setAmount(setAccountReportData(i, incomes, allocationQueryReportVOList, reportRelationMap));
- } else if (NumberConstant.TWO.equals(calcType)) {
- // TODO 按照分摊层级进行计算
- i.setAmount(setShareLevelReportData(i, reportRelationMap, allocationList));
- } else if (NumberConstant.THREE.equals(calcType)) {
- // TODO 按照小计进行计算
- i.setAmount(setSubtotal(i, costShareLevelList, listMap, listVo, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
- } else if (NumberConstant.FOUR.equals(calcType)) {
- // TODO 按照计算公式进行计算
- // i.setAmount(setCalculation(i, listVo, costShareLevelList, listMap, incomes, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
- } else if (NumberConstant.FIVE.equals(calcType)) {
- // TODO 按照责任中心进行计算
- i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList));
- } else {
- i.setAmount(new BigDecimal("0.000000"));
- }
- });
- //计算占比
- if (CollectionUtils.isEmpty(listVo)) {
- return;
- }
- List<HospProfitAndLossVo> listSum = new ArrayList<>();
- //把所有数据按报表项目汇总
- for (ReportForm j : reportForms) {
- HospProfitAndLossVo hospProfitAndLossVo = new HospProfitAndLossVo();
- hospProfitAndLossVo.setDateYear(finalYear);
- hospProfitAndLossVo.setDateMonth(finalMonth);
- hospProfitAndLossVo.setReportNum(j.getNum());
- hospProfitAndLossVo.setReportName(j.getReportName());
- hospProfitAndLossVo.setCostType(NumberConstant.ZERO);
- hospProfitAndLossVo.setIncomeType(NumberConstant.ZERO);
- hospProfitAndLossVo.setHospId(hospId);
- hospProfitAndLossVo.setType(j.getCostType());
- hospProfitAndLossVo.setFraction(j.getFraction());
- hospProfitAndLossVo.setReportId(j.getId());
- hospProfitAndLossVo.setReportNum(j.getNum());
- hospProfitAndLossVo.setCalcType(j.getCalcType());
- hospProfitAndLossVo.setReportName(j.getReportName());
- hospProfitAndLossVo.setCalcFormula(j.getCalcFormula());
- hospProfitAndLossVo.setReportParentId(j.getParentId());
- listSum.add(hospProfitAndLossVo);
- }
- Map<Integer, List<HospProfitAndLossVo>> reportNumGroup = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getReportNum));
- Map<Integer, BigDecimal> reportNumSumMap = new HashMap<>();
- reportNumGroup.forEach((reportNum, hospProfitAndLossList) -> {
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000000"));
- for (HospProfitAndLossVo hospProfitAndLoss : hospProfitAndLossList) {
- if (hospProfitAndLoss.getAmount() != null) {
- sum.updateAndGet(f -> f.add(hospProfitAndLoss.getAmount()));
- }
- }
- reportNumSumMap.put(reportNum, sum.get());
- });
- for (HospProfitAndLossVo costProfitVo : listSum) {
- BigDecimal bigDecimal = reportNumSumMap.get(costProfitVo.getReportNum());
- if (bigDecimal != null) {
- costProfitVo.setAmount(bigDecimal);
- } else {
- costProfitVo.setAmount(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP));
- }
- }
- //单独计算计算公式数据
- setCalculationAmount(listSum);
- //收入
- List<HospProfitAndLossVo> profitIncomeList = listSum.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList());
- List<HospProfitAndLossVo> profitIncome = costPercent(profitIncomeList);
- //成本
- List<HospProfitAndLossVo> profitCostList = listSum.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList());
- List<HospProfitAndLossVo> profitCost = costPercent(profitCostList);
- //不计算项目
- List<HospProfitAndLossVo> noCompute = listSum.stream().filter(f -> f.getFraction().equals(NumberConstant.THREE)).collect(Collectors.toList());
- noCompute.forEach(profitVO -> profitVO.setPercent(null));
- List<HospProfitAndLossVo> listAllVo = new ArrayList<>();
- if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
- listAllVo.addAll(profitIncome);
- listAllVo.addAll(profitCost);
- listAllVo.addAll(noCompute);
- } else if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(noCompute)) {
- listAllVo.addAll(noCompute);
- listAllVo.addAll(profitIncome);
- } else if (!CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
- listAllVo.addAll(noCompute);
- listAllVo.addAll(profitCost);
- } else if (!CollectionUtils.isEmpty(noCompute)) {
- listAllVo.addAll(noCompute);
- }
- List<HospProfitAndLoss> list = BeanUtil.convertList(listAllVo, HospProfitAndLoss.class);
- // 处理医院其他收支
- List<CostOtherPaymentsData> otherPaymentsDatas = otherPaymentsDataService.getByMonth(year, month, hospId);
- if (!otherPaymentsDatas.isEmpty()) {
- Optional<ReportForm> firstLossReport = reportForms.stream().filter(f -> NumberConstant.ONE.equals(f.getIsLoss())).findFirst();
- if(!firstLossReport.isPresent()){
- throw new CostException("全院损益报表配置有误,未设置损益项目");
- }
- Optional<HospProfitAndLoss> firstHospProfitAndLoss = list.stream().filter(f -> firstLossReport.get().getNum().equals(f.getReportNum())).findFirst();
- if(!firstHospProfitAndLoss.isPresent()){
- throw new CostException("全院损益报表配置有误,未找到配置的损益项目");
- }
- for (CostOtherPaymentsData ele : otherPaymentsDatas) {
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month).setReportName(ele.getPaymentsName()).setReportNum((int) (-ele.getId()))
- .setCreateTime(System.currentTimeMillis()).setAmount(ele.getTotalAmount()).setHospId(hospId)
- .setResponsibilityName("全院").setResponsibilityCode("-1").setPercent(null).setOriginType(NumberConstant.ONE);
- if( NumberConstant.ONE.equals(ele.getPaymentsType()) ) {
- //全院损益项目加上收入
- firstHospProfitAndLoss.get().setAmount(firstHospProfitAndLoss.get().getAmount().add(ele.getTotalAmount()));
- }else{
- //全院损益项目减去支出
- firstHospProfitAndLoss.get().setAmount(firstHospProfitAndLoss.get().getAmount().subtract(ele.getTotalAmount()));
- }
- list.add(loss);
- }
- }
- long l = System.currentTimeMillis();
- list.forEach(i -> {
- i.setCreateTime(l);
- i.setReportType(reportType);
- });
- this.saveBatch(list);
- }
- /**
- * 是否需要代码计算
- * @return
- */
- public boolean IsNeedCalc(Integer reportType) {
- String parameterValue = centerService.getParameterValue(ParameterConstant.SQL_CALC_REPORT_TYPE);
- if(StringUtils.isEmpty(parameterValue)){
- return true;
- }
- //不需计算的报表类型列表
- List<String> nonCalcReportTypeList = Arrays.stream(parameterValue.split(SplitConstant.SEPARATOR_VERTICALLINE)).collect(Collectors.toList());
- return !nonCalcReportTypeList.contains(String.valueOf(reportType));
- }
- /**
- * 处理指定月份及关联月份的计算(当前月、下个月、明年同月)
- *
- * @param hospId 院区ID
- * @param computeDate 日期字符串,格式:YYYY-MM
- * @param shareType 报表类型
- */
- public void handleSpecificMonthsCalculation(Long hospId, String computeDate, Integer shareType) {
- // 解析输入的年月
- Integer currentYear = ComputeDateUtils.getComputeYear(computeDate);
- Integer currentMonth = ComputeDateUtils.getComputeMonth(computeDate);
- // 计算需要处理的期间信息
- List<PeriodInfoVO> periods = calculateAllRelatedPeriods(currentYear, currentMonth);
- // 获取所有相关的期间数据
- Map<String, List<HospProfitAndLoss>> allDataMap = loadAllPeriodData(hospId, shareType, periods);
- // 对每个期间执行计算
- for (PeriodInfoVO period : periods) {
- String currentKey = buildPeriodKey(period.getYear(), period.getMonth());
- if (allDataMap.containsKey(currentKey) && !CollectionUtils.isEmpty(allDataMap.get(currentKey))) {
- List<HospProfitAndLoss> currentRecords = allDataMap.get(currentKey);
- List<HospProfitAndLoss> prevRecords = getPeriodData(allDataMap, period.getPrevYear(), period.getPrevMonth());
- List<HospProfitAndLoss> lastYearRecords = getPeriodData(allDataMap, period.getLastYear(), period.getLastMonth());
- // 执行批量计算
- calculatePeriodComparisonWithPreloadedData(currentRecords, prevRecords, lastYearRecords);
- }
- }
- }
- /**
- * 构建所有需要处理的期间信息
- */
- private List<PeriodInfoVO> calculateAllRelatedPeriods(int baseYear, int baseMonth) {
- List<PeriodInfoVO> result = new ArrayList<>();
- // 添加当前期间
- result.add(calculatePeriodInfo(baseYear, baseMonth));
- // 下个月
- int nextMonth = baseMonth + 1;
- int nextMonthYear = baseYear;
- if (baseMonth == 12) {
- nextMonth = 1;
- nextMonthYear += 1;
- }
- result.add(calculatePeriodInfo(nextMonthYear, nextMonth));
- // 明年同月
- result.add(calculatePeriodInfo(baseYear + 1, baseMonth));
- return result;
- }
- /**
- * 构建单个期间的信息(当前月、上月、去年同期)
- */
- private PeriodInfoVO calculatePeriodInfo(int year, int month) {
- PeriodInfoVO info = new PeriodInfoVO();
- info.setYear( year);
- info.setMonth( month);
- // 上期
- if (month == 1) {
- info.setPrevYear(year - 1);
- info.setPrevMonth(12);
- } else {
- info.setPrevYear( year);
- info.setPrevMonth(month - 1);
- }
- // 同期
- info.setLastYear(year - 1);
- info.setLastMonth( month);
- return info;
- }
- /**
- * 加载所有相关期间的数据(去重处理)
- */
- private Map<String, List<HospProfitAndLoss>> loadAllPeriodData(Long hospId, Integer shareType, List<PeriodInfoVO> periods) {
- Set<String> allPeriodKeys = new HashSet<>();
- // 收集所有需要查询的年月组合
- for (PeriodInfoVO period : periods) {
- allPeriodKeys.add(buildPeriodKey(period.getYear(), period.getMonth()));
- allPeriodKeys.add(buildPeriodKey(period.getPrevYear(), period.getPrevMonth()));
- allPeriodKeys.add(buildPeriodKey(period.getLastYear(), period.getLastMonth()));
- }
- // 去重后查询
- Map<String, List<HospProfitAndLoss>> result = new HashMap<>();
- Set<String> processedKeys = new HashSet<>(); // 已处理的键集合
- for (String key : allPeriodKeys) {
- if (!processedKeys.contains(key)) {
- int[] ym = parsePeriodKey(key);
- List<HospProfitAndLoss> records = getPeriodRecords(hospId, shareType, ym[0], ym[1]);
- result.put(key, records);
- processedKeys.add(key); // 标记为已处理
- }
- }
- return result;
- }
- /**
- * 获取指定期间的数据
- *
- * @param hospId 院区ID
- * @param shareType 报表类型
- * @param year 年份
- * @param month 月份
- * @return 符合条件的数据列表
- */
- private List<HospProfitAndLoss> getPeriodRecords(Long hospId, Integer shareType, int year, int month) {
- return this.list(new QueryWrapper<HospProfitAndLoss>().lambda()
- .eq(HospProfitAndLoss::getHospId, hospId)
- .eq(HospProfitAndLoss::getReportType, shareType)
- .eq(HospProfitAndLoss::getDateYear, year)
- .eq(HospProfitAndLoss::getDateMonth, month)
- .eq(HospProfitAndLoss::getDeleteTime, 0));
- }
- /**
- * 根据年月获取对应的数据(从内存中查找)
- */
- private List<HospProfitAndLoss> getPeriodData(Map<String, List<HospProfitAndLoss>> dataMap, int year, int month) {
- String key = buildPeriodKey(year, month);
- return dataMap.getOrDefault(key, Collections.emptyList());
- }
- /**
- * 批量计算同环比及同期金额(使用预加载数据)
- */
- public void calculatePeriodComparisonWithPreloadedData(
- List<HospProfitAndLoss> currentRecords,
- List<HospProfitAndLoss> prevRecords,
- List<HospProfitAndLoss> lastYearRecords) {
- if (CollectionUtils.isEmpty(currentRecords)) {
- return;
- }
- // 创建报表编号到记录的映射
- Map<String, HospProfitAndLoss> prevMap = new HashMap<>();
- for (HospProfitAndLoss record : prevRecords) {
- String key = buildRecordKey(record);
- prevMap.put(key, record);
- }
- Map<String, HospProfitAndLoss> lastYearMap = new HashMap<>();
- for (HospProfitAndLoss record : lastYearRecords) {
- String key = buildRecordKey(record);
- lastYearMap.put(key, record);
- }
- // 批量更新数据
- for (HospProfitAndLoss record : currentRecords) {
- String key = buildRecordKey(record);
- HospProfitAndLoss prevRecord = prevMap.get(key);
- HospProfitAndLoss lastYearRecord = lastYearMap.get(key);
- // 设置上期和同期金额
- record.setPrevPeriodAmount(prevRecord != null ? prevRecord.getAmount() : BigDecimal.ZERO);
- record.setSamePeriodAmount(lastYearRecord != null ? lastYearRecord.getAmount() : BigDecimal.ZERO);
- // 计算环比和同比
- record.setMomRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getPrevPeriodAmount()));
- record.setYoyRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getSamePeriodAmount()));
- }
- // 批量更新数据库
- this.updateBatchById(currentRecords);
- }
- /**
- * 构建期间键(用于存储和检索数据)
- */
- private String buildPeriodKey(int year, int month) {
- return year + "_" + month;
- }
- /**
- * 解析期间键为年月数组
- */
- private int[] parsePeriodKey(String key) {
- String[] parts = key.split("_");
- return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])};
- }
- /**
- * 构建记录的唯一标识键(责任码 + 报表编号)
- */
- private String buildRecordKey(HospProfitAndLoss record) {
- return String.valueOf(record.getReportNum());
- }
- /**
- * 安全地计算百分比:避免除零错误
- */
- private BigDecimal calculateProfitRate(BigDecimal current, BigDecimal base) {
- if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
- return BigDecimal.ZERO;
- }
- BigDecimal bigDecimal = current.divide(base, 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP);
- return bigDecimal;
- }
- /**
- * 执行全院损益后续脚本
- * @param date
- * @param reportType
- */
- public void execHospProfitSql(String date,Integer reportType){
- Map<String,String> sqlParameter = new HashMap<>();
- sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, DateUtils.StringToString(date, DateStyleEnum.YYYY_MM));
- sqlParameter.put(SQLParameter.REPORT_TYPE_CODE,String.valueOf(reportType));
- sqlService.autoExecuteSql(CustomSqlTypeEnum.HOSP_PROFIT_CALC.getCode(),sqlParameter);
- }
- // 计算公式中钱
- private BigDecimal calcAmount(List<HospProfitAndLoss> list, String calcFormula, ReportForm reportForm) {
- // 得到所有的编号
- String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
- ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
- // 得到编号的map
- Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
- for (int j = 0; j < numList.size(); j++) {
- numMap.put(j, Integer.parseInt(numList.get(j)));
- }
- List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
- .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
- // 得到预算表达式 得到所有表达式的Map + - 相关的
- Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
- for (int k = 0; k < expressions.size(); k++) {
- expressionMap.put(k, expressions.get(k));
- }
- // 数字的索引和表达式的索引累加计算
- Set<Integer> numSet = numMap.keySet();
- List<Integer> nums = new ArrayList<>(numSet);
- AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
- totalAmount.set(BigDecimal.ZERO);
- for (int i = 0; i < nums.size(); i++) {
- // 编号
- Integer num = numMap.get(i);
- List<HospProfitAndLoss> losses = list.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
- if (CollUtil.isEmpty(losses)) {
- continue;
- }
- // log.info("data={}", reportForm);
- // if (losses.size() != 0 && losses.size() != 1) {
- // throw new CostException("数据异常");
- // }
- HospProfitAndLoss loss = losses.get(0);
- BigDecimal amount = loss.getAmount();
- String str = expressionMap.get(i);
- if (str.equals("+")) {
- totalAmount.set(totalAmount.get().add(amount));
- } else {
- totalAmount.set(totalAmount.get().subtract(amount));
- }
- }
- return totalAmount.get();
- }
- /**
- * 按责任中心计算
- *
- * @param hospId 医院id
- * @param reportForm 报表
- * @param allocationQueries 分摊成本数据
- * @param list
- * @param year
- * @param month
- */
- private void calcByResponsibility(Long hospId, ReportForm reportForm, List<AllocationQuery> allocationQueries, List<HospProfitAndLoss> list, int year, int month) {
- List<RelationVO> responsibilities = reportRelationService.getResponsibilities(reportForm.getId(), hospId);
- if (responsibilities.isEmpty()) {
- return;
- }
- List<String> accountCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- accountCodes.forEach(i -> {
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- calcTotal.set(calcTotal.get().add(costAmount));
- });
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
- .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
- list.add(loss);
- }
- /**
- * 按计算公式计算
- */
- private void calcByFormula(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list) {
- // 得到当前下按公式计算的
- List<ReportForm> calcFormulas = reportForms.stream().filter(i -> i.getCalcType() == CalcTypeEnum.CALC_FORMULA.getType()).collect(Collectors.toList());
- calcFormulas = calcFormulas.stream().filter(i -> i.getNum().equals(child.getNum())).collect(Collectors.toList());
- for (ReportForm i : calcFormulas) {
- String calcFormula = i.getCalcFormula();
- // TODO: 2021/8/27 校验公式合法性
- if (StrUtil.isBlank(calcFormula)) {
- throw new CostException("reportForm名称为" + i.getReportName() + "计算公式不正确");
- }
- BigDecimal bigDecimal = calcAmount(list, calcFormula, i);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month).setReportNum(i.getNum()).setReportName(i.getReportName())
- .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(i.getHospId());
- list.add(loss);
- }
- }
- /**
- * 按小计计算
- */
- private void calcByLitterCount(Integer year, Integer month, ReportForm child, List<ReportForm> reportForms, List<HospProfitAndLoss> list, Long hospId) {
- // 其他的
- List<ReportForm> calcList = reportForms.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
- List<HospProfitAndLoss> thisList = new ArrayList<>();
- list.forEach(i -> {
- calcList.forEach(j -> {
- if (i.getReportNum().equals(j.getNum())) {
- thisList.add(i);
- }
- });
- });
- if (thisList.isEmpty()) {
- return;
- }
- BigDecimal reduce = thisList.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month).setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
- // 小计只能有一个
- loss.setReportNum(child.getNum()).setReportName(child.getReportName());
- list.add(loss);
- }
- /**
- * 按分摊层级计算、
- *
- * @param hospId 医院id
- * @param reportForm 报表
- * @param list
- * @param year
- * @param month
- */
- private void calcByShareLevel(Long hospId, ReportForm reportForm, List<HospProfitAndLoss> list, int year, int month) {
- List<RelationVO> shareLevels = reportRelationService.getShareLevel(reportForm.getId(), hospId);
- List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
- if (CollUtil.isEmpty(shareLevelId)) {
- return;
- }
- List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
- if (costShareLevels.isEmpty()) {
- throw new CostException("医院分摊层级设置错误," + reportForm.getReportName());
- }
- List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
- List<AllocationQuery> allocations = allocationQueryService.getByDate(year, month, hospId, shareLevelId);
- if (allocations.isEmpty()) {
- throw new CostException("医院未分摊本月数据");
- }
- List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
- if (accountShares.isEmpty()) {
- return;
- }
- // allocations = allocations.stream().filter(i -> levelSorts.contains(i.getLevelSort())).collect(Collectors.toList());
- BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
- .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
- list.add(loss);
- }
- /**
- * 计算按会计科目下的科目名称
- *
- * @param hospId 医院id
- * @param reportForm 报表
- * @param incomes 归集收入数据
- * @param list
- * @param allocationQueries 分摊成本数据
- * @param month
- * @param year
- */
- private void calcByAccount(Long hospId, ReportForm reportForm, List<IncomeCollection> incomes, List<HospProfitAndLoss> list, List<AllocationQuery> allocationQueries, int month, int year) {
- // check 这个医院是否有对应的损益标识
- reportFormService.checkExistLoss(hospId);
- // 报表项目关联的会计科目对象
- List<RelationVO> accountRelations = reportRelationService.getAccountRelation(reportForm.getId(), hospId);
- if (accountRelations.isEmpty()) {
- return;
- }
- List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- accountCodes.forEach(i -> {
- BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal total = incomeAmount.add(costAmount);
- calcTotal.set(calcTotal.get().add(total));
- });
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(reportForm.getReportName()).setReportNum(reportForm.getNum())
- .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
- list.add(loss);
- }
- /**
- * 全院损益列表
- *
- * @param current 当前页
- * @param pageSize 每页展示数据大小
- * @param date 日期
- * @param hospId 医院id
- * @return PageUtils
- */
- @Override
- public PageUtils getHospProfits(Integer current, Integer pageSize, String date, Long hospId) {
- reportFormService.checkExistLoss(hospId);
- DateTime parse = DateUtil.parse(date);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- int startIndex = (current - 1) * pageSize;
- List<HospProfitAndLoss> list = baseMapper.getPageList(startIndex, pageSize, year, month, hospId);
- // 损益的时候计算下
- list.forEach(i -> {
- ReportForm one = reportFormService.getOne(
- new LambdaQueryWrapper<ReportForm>().select(ReportForm::getId)
- .eq(ReportForm::getNum, i.getReportNum())
- .eq(ReportForm::getHospId, hospId)
- .eq(ReportForm::getReportType, 3)
- .eq(ReportForm::getIsLoss, 1)
- .last(Constant.LIMIT)
- );
- if (Objects.nonNull(one)) {
- List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
- AtomicReference<BigDecimal> total = new AtomicReference<>();
- total.set(BigDecimal.ZERO);
- byMonth.forEach(j -> {
- if (j.getPaymentsType().equals(1)) {
- total.set(total.get().add(j.getTotalAmount()));
- } else {
- total.set(total.get().subtract(j.getTotalAmount()));
- }
- });
- i.setAmount(i.getAmount().add(total.get()));
- }
- });
- int totalCount = baseMapper.getPageCount(year, month, hospId);
- return new PageUtils(list, totalCount, pageSize, current);
- }
- /**
- * 导出全院损益计算
- *
- * @param date yyyy-MM-dd
- * @param hospId
- */
- @Override
- public void hospProfitReport(String date, Long hospId) {
- DateTime parse = DateUtil.parse(date);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- // 得到所有责任中心的子节点
- List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
- // List<Responsibility> leafResp = responsibilityService.getLeafResp(hospId);
- List<CostOtherPaymentsData> byMonth = otherPaymentsDataService.getByMonth(year, month, hospId);
- // if (!byMonth.isEmpty()) {
- // Responsibility responsibility = new Responsibility("-1", "全院", -1L);
- // responsibilityList.add(responsibility);
- // }
- Map<String, Long> responseCodeParentIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
- Map<Long, Responsibility> responsibilityIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
- // 查询所有的全院损益数据 内存溢出问题
- List<HospProfitAndLoss> hospProfitAndLosses = getAllDataByDate(year, month, hospId,NumberConstant.THREE);
- if (CollectionUtils.isEmpty(hospProfitAndLosses)) {
- throw new CostException(500, "未进行全院损益计算");
- }
- //判断是否有全院的数据 有单独取出另算
- List<HospProfitAndLoss> hospAllList = hospProfitAndLosses.stream().filter(f -> f.getResponsibilityCode().equals("-1")).collect(Collectors.toList());
- if (!CollectionUtils.isEmpty(hospAllList)) {
- hospProfitAndLosses.removeAll(hospAllList);
- }
- //多层级责任 中心 添加父类责任中心 方便excel分组
- for (HospProfitAndLoss hospProfitAndLoss : hospProfitAndLosses) {
- Long aLong = responseCodeParentIdMap.get(hospProfitAndLoss.getResponsibilityCode());
- if (aLong != null) {
- if (aLong.equals(NumberConstant.ZERO_L)) {
- // Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
- hospProfitAndLoss.setParentResponsibilityCode(hospProfitAndLoss.getResponsibilityCode());
- hospProfitAndLoss.setParentResponsibilityName(hospProfitAndLoss.getResponsibilityName());
- } else if (aLong.equals(-1L)) {
- hospProfitAndLoss.setParentResponsibilityCode("-1");
- hospProfitAndLoss.setParentResponsibilityName("全院");
- } else {
- Responsibility responsibility = responsibilityIdMap.get(aLong);
- if (Objects.nonNull(responsibility)) {
- hospProfitAndLoss.setParentResponsibilityCode(responsibility.getResponsibilityCode());
- hospProfitAndLoss.setParentResponsibilityName(responsibility.getResponsibilityName());
- }
- }
- }
- }
- //损益表设置
- List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
- .eq(ReportForm::getHospId, hospId)
- .eq(ReportForm::getReportType, NumberConstant.THREE));
- if (CollUtil.isEmpty(reportFormList)) {
- throw new CostException(500, "损益表未找到");
- }
- if (!byMonth.isEmpty()) {
- // 手动构造全院数据表头 生成全院其他收支
- //添加全院其他报表项目
- //最上层
- ReportForm parentReport = new ReportForm();
- parentReport.setId(-1L);
- parentReport.setReportType(NumberConstant.THREE);
- parentReport.setParentId(NumberConstant.ZERO_L);
- parentReport.setSort(0);
- parentReport.setReportName("全院其他收支");
- parentReport.setNum(-1);
- reportFormList.add(parentReport);
- //第二层按全院收支数据自动生成
- for (int i = 0; i < byMonth.size(); i++) {
- CostOtherPaymentsData data = byMonth.get(i);
- ReportForm reportForm = new ReportForm();
- // reportForm.setId(-1L -i - byMonth.size());
- reportForm.setId(-System.currentTimeMillis() - i);
- reportForm.setReportType(NumberConstant.THREE);
- reportForm.setParentId(-1L);
- reportForm.setSort(0);
- reportForm.setReportName(data.getPaymentsName());
- reportForm.setNum((int) (-data.getId()));
- reportFormList.add(reportForm);
- }
- }
- Map<Long, List<ReportForm>> collect = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getParentId));
- Map<String, List<ColEntity>> heads = new HashMap<>();// 最终导出的多个sheet的表头
- Map<String, List<Map<String, String>>> datas = new HashMap<>();// 最终导出的多个sheet的内容
- Map<String, Integer> types = new HashMap<>();
- Map<String, List<Integer>> mergeindexs = new HashMap<>();// 最终导出的每个sheet的需要纵向合并的单元格列号
- //第一层
- List<ReportForm> firstTitle = collect.get(NumberConstant.ZERO_L);
- List<TitleEntity> titleList = new ArrayList<>();
- titleList.add(new TitleEntity("0", null, "全院损益 \n" + "制表时间:" + DateUtil.now(), false, NumberConstant.ZERO));
- //添加默认三列责任中心 父类责任中心 子类责任中心 项目名称
- setDefaultColumn(titleList);
- for (ReportForm reportForm : firstTitle) {
- TitleEntity entity = new TitleEntity();
- entity.setId(String.valueOf(reportForm.getId()));
- entity.setPid(String.valueOf(reportForm.getParentId()));
- entity.setContent(reportForm.getReportName());
- entity.setFieldName(String.valueOf(reportForm.getNum()));
- entity.setWidth(20);
- entity.setSort(reportForm.getSort());
- boolean child = getChild(titleList, reportForm, collect);
- entity.setLast(child);
- titleList.add(entity);
- }
- titleList.sort(Comparator.comparing(TitleEntity::getSort));
- hospProfitAndLosses.sort(Comparator.comparing(HospProfitAndLoss::getParentResponsibilityCode));
- //行
- Map<String, List<HospProfitAndLoss>> lineMap = hospProfitAndLosses.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getParentResponsibilityCode));
- //列
- List<TitleEntity> titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList());
- List<Map<String, String>> rowList = new ArrayList<>();
- //行数据
- setRowList(lineMap, titleEntities, rowList);
- //添加 全院其他收支数据
- setHospRowList(hospAllList, titleEntities, rowList);
- try {
- ExcelPoiUtil excelTool = new ExcelPoiUtil();
- excelTool.setTitle("全院损益");
- Map<String, String> param = ImmutableMap.<String, String>builder().put("id", "id").put("pid", "pid")
- .put("content", "content").put("fieldName", "fieldName").put("width", "width").build();
- List<ColEntity> titleData = excelTool.colEntityTransformer(titleList, param, "0");
- Map<String, List<Integer>> autoRowHeights = new HashMap<>();
- heads.put("全院损益", titleData);// 每个sheet的表头,sheet名称为key
- datas.put("全院损益", rowList);// 每个sheet的内容,sheet名称为key
- types.put("全院损益", 0);// 每个sheet的样式类型,sheet名称为key
- mergeindexs.put("全院损益", Arrays.asList(0, 1));// 每个sheet的默认行高,sheet名称为key
- autoRowHeights.put("全院损益", Arrays.asList(1, 2, 3, 4, 5));
- // 多个sheet导出
- HSSFWorkbook workbook = excelTool.exportWorkbook(heads, datas, types, autoRowHeights, mergeindexs);
- // excelTool.save(workbook, "D:\\全院损益.xls");
- // // 得到上一层的title子节点
- //// ExcelWriter writer = ExcelUtil.getWriter();
- // String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
- // //todo:后面调整为上传到文件服务器,先启动确认环境
- // String fileName = "全院损益" + time + ".xlsx";
- // ExcelWriter writer = ExcelUtil.getWriter(fileName);
- //
- // List<String> secondTitleListCode = leafResp.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
- // writer.merge(leafResp.size() + 1, "全院损益计算导出 \n" + "制表时间:" + DateUtil.now());
- // // 得到两层结构
- // writer.setColumnWidth(-1, 20);
- // writer.passCurrentRow();
- // writer.merge(2, 2, 0, 1, "项目", true);
- // int oldSize = 2;
- // Map<Long, Object> map = new HashMap<>();
- // for (int i = 0; i < leafResp.size(); i++) {
- // Responsibility responsibility = leafResp.get(i);
- // String str = responsibility.getResponsibilityName();
- // writer.writeCellValue(i + 2, 2, str);
- // // 写父亲层级
- // Long parentId = responsibility.getParentId();
- // if (map.get(parentId) != null) {
- // // 如果parentId = 0
- // if (parentId != 0L) {
- // continue;
- // }
- // }
- // Responsibility byId = responsibilityService.getById(parentId);
- // String name = "";
- // if (byId != null) {
- // name = byId.getResponsibilityName();
- // }
- // int count = (int) leafResp.stream().filter(o -> o.getParentId().equals(parentId)).count();
- //
- // if (count == 1) {
- // writer.writeCellValue(oldSize, 1, name);
- // } else if (count == 0) {
- // writer.writeCellValue(oldSize, 1, "全院其他");
- // } else {
- // writer.merge(1, 1, oldSize, oldSize + count - 1, name, false);
- // }
- //
- // oldSize = oldSize + count;
- // map.put(parentId, oldSize);
- //
- // }
- // // 得到全院损益报表处理 树状结构(only 2层)
- // List<ReportFormVO> allHospList = reportFormService.getAllHospList(hospId);
- // if (allHospList.isEmpty()) {
- // throw new CostException("请先设置全院损益报表");
- // }
- //
- // if (!byMonth.isEmpty()) {
- // // 构造假数据 生成全院其他收支
- // ReportFormVO vo = new ReportFormVO(-1L, -1, "全院其他收支", 0L, new ArrayList<>());
- // for (CostOtherPaymentsData data : byMonth) {
- // ReportFormVO reportFormVO = new ReportFormVO(-2L, (int) (-data.getId()), data.getPaymentsName(), -1L, null);
- // vo.getChildren().add(reportFormVO);
- // }
- // allHospList.add(allHospList.size() - 1, vo);
- // }
- // // 查询所有的全院损益数据 内存溢出问题
- // List<HospProfitAndLoss> list = getAllDataByDate(year, month, hospId);
- // int lastRow = 3;
- // for (int i = 0; i < allHospList.size(); i++) {
- // ReportFormVO parentFormVO = allHospList.get(i);
- // List<ReportFormVO> children = parentFormVO.getChildren();
- // if (CollUtil.isEmpty(children)) {
- // continue;
- // }
- // int size = children.size();
- // // 当最后一个的时候写上全院其他收支
- // if (allHospList.size() == 1) {
- // writer.writeCellValue(0, lastRow, parentFormVO.getReportName());
- // } else {
- // writer.merge(lastRow, lastRow + size - 1, 0, 0, parentFormVO.getReportName(), true);
- // }
- //
- // // 具体的报表项目
- // for (int j = 0; j < size; j++) {
- // // todo 可以抽取出单独方法
- // ReportFormVO childFormVO = children.get(j);
- // // 第二列的数据
- // writer.writeCellValue(1, lastRow + j, childFormVO.getReportName());
- // // 单独计每个数据的责任中心对应的金额
- // for (int k = 0; k < secondTitleListCode.size(); k++) {
- //
- // String responsibilityCode = secondTitleListCode.get(k);
- // Integer num = childFormVO.getNum();
- // HospProfitAndLoss loss = list.stream().filter(o -> o.getReportNum().equals(num) && o.getResponsibilityCode().equals(responsibilityCode)).findAny()
- // .orElse(null);
- // BigDecimal bigDecimal = Objects.isNull(loss) ? BigDecimal.ZERO : loss.getAmount();
- // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
- // if (k == secondTitleListCode.size() - 1) {
- // bigDecimal = list.stream().filter(o -> o.getReportNum().equals(num)).map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
- //
- // if (j == size - 1 && i == allHospList.size() - 1) {
- // // 计算 其他
- // BigDecimal another = BigDecimal.ZERO;
- // for (CostOtherPaymentsData costOtherPaymentsData : byMonth) {
- // if (costOtherPaymentsData.getPaymentsType() == 1) {
- // another = another.add(costOtherPaymentsData.getTotalAmount());
- // } else {
- // another = another.subtract(costOtherPaymentsData.getTotalAmount());
- // }
- // }
- // bigDecimal = bigDecimal.add(another);
- // writer.writeCellValue(k + 2, lastRow + j, bigDecimal);
- // }
- // }
- //
- //
- // }
- //
- // }
- // lastRow = lastRow + size;
- // }
- String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
- FileItemFactory factory = new DiskFileItemFactory(5242880, null);
- FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, "全院损益" + time + ".xls");
- String file = "";
- OutputStream outputStream = fileItem.getOutputStream();
- // writer.flush(outputStream,true);
- workbook.write(outputStream);
- MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
- //上传 excel
- file = uploadFile(multipartFile);
- //保存文件记录
- FileRecord fileRecord = new FileRecord();
- fileRecord.setFileName("全院损益" + time + ".xls")
- .setFileSource(1)
- .setFileType("全院损益")
- .setFileUrl(file)
- .setHospId(hospId)
- .setDateYear(year).setDateMonth(month)
- .setCreateTime(System.currentTimeMillis());
- fileRecordService.save(fileRecord);
- workbook.close();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- private static void setHospRowList(List<HospProfitAndLoss> hospAllList, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
- List<Map<String, String>> amountRowList = new ArrayList<>();
- for (Map<String, String> map : rowList) {
- String itemType = map.get("itemType");
- if (itemType.equals("金额")) {
- amountRowList.add(map);
- }
- }
- //相 同key 的数值 进行汇总
- // for (int i = 0; i < 2; i++) {
- Map<String, String> hospMap = new HashMap<>();
- for (TitleEntity titleEntity : titleEntities) {
- AtomicReference<BigDecimal> total = new AtomicReference<>(new BigDecimal("0.00"));
- for (Map<String, String> map : amountRowList) {
- String s = map.get(titleEntity.getFieldName());
- if (!titleEntity.getFieldName().equals("child") && !titleEntity.getFieldName().equals("parent") && !titleEntity.getFieldName().equals("itemType")) {
- // if(StringUtils.isEmpty(s)){
- // total.updateAndGet(v -> v.add(BigDecimal.ZERO));
- // }else {
- total.updateAndGet(v -> v.add(new BigDecimal(s)));
- // }
- }
- }
- if (titleEntity.getFieldName().equals("parent")) {
- hospMap.put("parent", "全院");
- } else if (titleEntity.getFieldName().equals("child")) {
- hospMap.put("child", "全院");
- } else if (titleEntity.getFieldName().equals("itemType")) {
- // if (i == 0) {
- hospMap.put("itemType", "金额");
- // } else {
- // hospMap.put("itemType", "占比");
- // }
- } else {
- // if (i == 0) {
- hospMap.put(titleEntity.getFieldName(), total.get().toString());
- if (!CollectionUtils.isEmpty(hospAllList)) {
- for (HospProfitAndLoss data : hospAllList) {
- hospMap.put(data.getReportNum().toString(), data.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
- }
- }
- // } else {
- // hospMap.put(titleEntity.getFieldName(), "");
- // }
- }
- }
- rowList.add(hospMap);
- // }
- }
- private static void setRowList(Map<String, List<HospProfitAndLoss>> lineMap, List<TitleEntity> titleEntities, List<Map<String, String>> rowList) {
- DecimalFormat df = new DecimalFormat("0.00%");
- for (String parentCode : lineMap.keySet()) {
- List<HospProfitAndLoss> costDepartmentProfits1 = lineMap.get(parentCode);
- Map<String, List<HospProfitAndLoss>> listMap = costDepartmentProfits1.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getResponsibilityCode));
- for (String s : listMap.keySet()) {
- List<HospProfitAndLoss> costDepartmentProfits2 = listMap.get(s);
- Map<String, HospProfitAndLoss> map = costDepartmentProfits2.stream().collect(Collectors.toMap(profit -> String.valueOf(profit.getReportNum()), profit -> profit, (a, b) -> b));
- for (int i = 0; i < 2; i++) {
- Map<String, String> m = new HashMap<String, String>();
- for (TitleEntity titleEntity : titleEntities) {
- if (titleEntity.getId().equals("parentResponsibility")) {
- m.put("parent", costDepartmentProfits2.get(0).getParentResponsibilityName());
- } else if (titleEntity.getId().equals("childResponsibility")) {
- m.put("child", costDepartmentProfits2.get(0).getResponsibilityName());
- } else if (titleEntity.getId().equals("item")) {
- if (i == 0) {
- m.put("itemType", "金额");
- } else {
- m.put("itemType", "占比");
- }
- } else if (titleEntity.getId().contains("-")) {
- HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
- if (Objects.nonNull(profit)) {
- if (i == 0) {
- m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
- } else {
- if (profit.getPercent() != null) {
- m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
- } else {
- m.put(titleEntity.getFieldName(), "");
- }
- }
- } else {
- m.put(titleEntity.getFieldName(), "0.00");
- }
- } else {
- HospProfitAndLoss profit = map.get(titleEntity.getFieldName());
- if (Objects.nonNull(profit)) {
- if (i == 0) {
- m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
- } else {
- if (profit.getPercent() != null) {
- m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
- } else {
- m.put(titleEntity.getFieldName(), "");
- }
- }
- }
- }
- }
- rowList.add(m);
- }
- }
- }
- }
- private void setDefaultColumn(List<TitleEntity> titleList) {
- TitleEntity parentResponsibility = new TitleEntity();
- parentResponsibility.setId("parentResponsibility");
- parentResponsibility.setPid("0");
- parentResponsibility.setContent("");
- parentResponsibility.setFieldName("parent");
- parentResponsibility.setWidth(15);
- parentResponsibility.setSort(NumberConstant.ZERO);
- parentResponsibility.setLast(true);
- titleList.add(parentResponsibility);
- TitleEntity childResponsibility = new TitleEntity();
- childResponsibility.setId("childResponsibility");
- childResponsibility.setPid("0");
- childResponsibility.setContent("");
- childResponsibility.setFieldName("child");
- childResponsibility.setWidth(15);
- childResponsibility.setSort(NumberConstant.ZERO);
- childResponsibility.setLast(true);
- titleList.add(childResponsibility);
- TitleEntity item = new TitleEntity();
- item.setId("item");
- item.setPid("0");
- item.setContent("");
- item.setFieldName("itemType");
- item.setWidth(10);
- item.setSort(NumberConstant.ZERO);
- item.setLast(true);
- titleList.add(item);
- }
- private boolean getChild(List<TitleEntity> titleList, ReportForm reportForm, Map<Long, List<ReportForm>> collect) {
- List<ReportForm> forms = collect.get(reportForm.getId());
- if (!CollectionUtils.isEmpty(forms)) {
- for (ReportForm form : forms) {
- TitleEntity entity = new TitleEntity();
- entity.setId(String.valueOf(form.getId()));
- entity.setPid(String.valueOf(form.getParentId()));
- entity.setContent(form.getReportName());
- entity.setFieldName(String.valueOf(form.getNum()));
- entity.setWidth(15);
- entity.setSort(form.getSort());
- boolean last = getChild(titleList, form, collect);
- entity.setLast(last);
- titleList.add(entity);
- }
- return false;
- } else {
- return true;
- }
- }
- public String uploadFile(MultipartFile file) {
- Long hospId = UserContext.getCurrentLoginHospId();
- String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + ".xls";
- DateTime date = DateUtil.date();
- int month = DateUtil.month(date) + 1;
- int year = DateUtil.year(date);
- int day = DateUtil.dayOfMonth(date);
- String fileUrl = "";
- try {
- // file.transferTo(new File(localFilePath));
- String format = DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN);
- String originalFilename = format + fileName;
- String dataDirectory = minioConfig.getBucketName();
- String uploadFileName = "hospReport" + "/" + hospId + "/" + year + "/" + month + "/" + day + "/" + originalFilename;
- InputStream inputStream = file.getInputStream();
- minioFileUtil.putObject(dataDirectory, uploadFileName, inputStream);
- fileUrl = minioFileUtil.getObjectUrl(dataDirectory, uploadFileName);
- } catch (IOException e) {
- log.error("【文件上传至服务器】失败,绝对路径:{}", e.getMessage());
- throw new CostException(ErrorCodeEnum.FILE_UPLOAD_ERROR);
- }
- return fileUrl;
- }
- @Override
- public PageUtils hospProfitReports(Integer current, Integer pageSize, Long hospId, String date) {
- DateTime parse = DateUtil.parse(date);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- Page<FileRecord> page = new Page<>(current, pageSize);
- Page<FileRecord> pageUtils = fileRecordService.page(page,
- new LambdaQueryWrapper<FileRecord>()
- .eq(FileRecord::getHospId, hospId)
- .eq(FileRecord::getFileType, "全院损益")
- .eq(FileRecord::getDateYear, year)
- .eq(FileRecord::getDateMonth, month)
- .orderByDesc(FileRecord::getCreateTime)
- );
- return new PageUtils(pageUtils);
- }
- @Override
- public Object getHospProfitResponsibilities(String responsibilityName) {
- List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
- .eq(Responsibility::getHospId, UserContext.getHospId())
- .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null))
- .like(StrUtil.isNotBlank(responsibilityName), Responsibility::getResponsibilityName, responsibilityName));
- List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
- .eq(Responsibility::getHospId, UserContext.getHospId()));
- Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
- List<Responsibility> addList = new ArrayList<>();
- for (Responsibility responsibility : responsibilityList) {
- Responsibility responsibility1 = map.get(responsibility.getParentId());
- if (Objects.nonNull(responsibility1)) {
- addList.add(responsibility1);
- if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
- getResponsibilityParent(responsibility1, map, addList);
- }
- }
- }
- if (!CollectionUtils.isEmpty(addList)) {
- //去重
- List<Responsibility> collect = addList.stream().distinct().collect(Collectors.toList());
- responsibilityList.addAll(collect);
- }
- Map<Long, List<Responsibility>> collect = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
- List<Responsibility> responsibilities = collect.get(NumberConstant.ZERO_L);
- collect.remove(NumberConstant.ZERO_L);
- for (Responsibility responsibility : responsibilities) {
- List<Responsibility> responsibilities1 = collect.get(responsibility.getId());
- if (!CollectionUtils.isEmpty(responsibilities1)) {
- responsibility.setChildren(setResponsibilityChildren(responsibilities1, collect));
- }
- }
- responsibilitySort(responsibilities);
- return responsibilities;
- }
- @Override
- public Object getHospProfitList(String computeDate, Long hospId, String reportType) {
- DateTime parse = DateUtil.parse(computeDate);
- int year = DateUtil.year(parse);
- int month = DateUtil.month(parse) + 1;
- //查询全院损益报表配置
- Integer integerReportType = Integer.valueOf(reportType);
- // Integer year = ComputeDateUtils.getComputeYear(computeDate);
- // Integer month = ComputeDateUtils.getComputeMonth(computeDate);
- // 查询所有的全院损益数据 内存溢出问题
- List<HospProfitAndLoss> hospProfitAndLosses = getAllDataByDate(year, month, hospId,integerReportType);
- if (CollectionUtils.isEmpty(hospProfitAndLosses)) {
- throw new CostException(500, "未进行全院损益计算");
- }
- //判断是否有全院的数据 有单独取出另算
- List<HospProfitAndLoss> hospAllList = hospProfitAndLosses.stream().filter(f -> f.getResponsibilityCode().equals("-1")).collect(Collectors.toList());
- if (!CollectionUtils.isEmpty(hospAllList)) {
- hospProfitAndLosses.removeAll(hospAllList);
- }
- List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
- .eq(ReportForm::getHospId, hospId)
- .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE));
- if (CollUtil.isEmpty(reportFormList)) {
- throw new CostException(500, "未找到全院损益表配置");
- }
- List<HospProfitVO> costProfitVos = BeanUtil.convertList(reportFormList, HospProfitVO.class);
- //把所有数据按报表项目汇总
- Map<Integer, List<HospProfitAndLoss>> reportNumGroup = hospProfitAndLosses.stream().collect(Collectors.groupingBy(HospProfitAndLoss::getReportNum));
- Map<Integer, BigDecimal> reportNumSumMap = new HashMap<>();
- reportNumGroup.forEach((reportNum, hospProfitAndLossList) -> {
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000000"));
- hospProfitAndLossList.stream().<UnaryOperator<BigDecimal>>map(hospProfitAndLoss -> f -> f.add(hospProfitAndLoss.getAmount())).forEach(sum::updateAndGet);
- reportNumSumMap.put(reportNum, sum.get());
- });
- for (HospProfitVO costProfitVo : costProfitVos) {
- BigDecimal bigDecimal = reportNumSumMap.get(costProfitVo.getNum());
- if (bigDecimal != null) {
- costProfitVo.setAmount(bigDecimal);
- } else {
- costProfitVo.setAmount(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP));
- }
- }
- //判断有无其他全院数据 有组装进去
- if (!CollectionUtils.isEmpty(hospAllList)) {
- //全院其他收支
- HospProfitVO hospProfitVO = new HospProfitVO();
- hospProfitVO.setId(-1L);
- hospProfitVO.setNum(-1);
- hospProfitVO.setParentId(0L);
- hospProfitVO.setReportName("全院其他收支");
- hospProfitVO.setSort(costProfitVos.size());
- hospProfitVO.setReportType(integerReportType);
- hospProfitVO.setFraction(3);
- costProfitVos.add(hospProfitVO);
- for (int i = 0, hospAllListSize = hospAllList.size(); i < hospAllListSize; i++) {
- costProfitVos.add(getHospProfitVO(hospAllList, i,integerReportType));
- }
- }
- //取出所有成本项目
- List<HospProfitVO> costFractionList = costProfitVos.stream().filter(f -> f.getCostType() != null && f.getCostType().equals(NumberConstant.TWO) && f.getFraction().equals(NumberConstant.TWO)).collect(Collectors.toList());
- if (CollectionUtils.isEmpty(costFractionList)) {
- throw new CostException("全院损益未配置成本占比计算分母");
- } else {
- if (costFractionList.size() > 1) {
- throw new CostException("全院损益成本占比计算分母有且只能有一个");
- }
- }
- List<HospProfitVO> inComeFractionList = costProfitVos.stream().filter(f -> f.getCostType() != null && f.getCostType().equals(NumberConstant.ONE) && f.getFraction().equals(NumberConstant.TWO)).collect(Collectors.toList());
- if (CollectionUtils.isEmpty(inComeFractionList)) {
- throw new CostException("全院损益未配置收入占比计算分母");
- } else {
- if (inComeFractionList.size() > 1) {
- throw new CostException("全院损益收入占比计算分母有且只能有一个");
- }
- }
- HospProfitVO inComeFraction = inComeFractionList.get(0);
- HospProfitVO costFraction = costFractionList.get(0);
- for (HospProfitVO costProfitVo : costProfitVos) {
- if (costProfitVo.getCostType() != null) {
- if (costProfitVo.getCostType().equals(NumberConstant.ONE) && costProfitVo.getFraction().equals(NumberConstant.ONE)) {
- //收入
- BigDecimal denominator = inComeFraction.getAmount();
- //收入分子
- if (denominator.compareTo(BigDecimal.ZERO) == 0) {
- costProfitVo.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
- } else {
- costProfitVo.setPercent(costProfitVo.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
- }
- } else if (costProfitVo.getCostType().equals(NumberConstant.TWO) && costProfitVo.getFraction().equals(NumberConstant.ONE)) {
- //成本
- BigDecimal denominator = costFraction.getAmount();
- if (denominator.compareTo(BigDecimal.ZERO) == 0) {
- costProfitVo.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
- } else {
- costProfitVo.setPercent(costProfitVo.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
- }
- }
- }
- }
- Map<Long, List<HospProfitVO>> collect = costProfitVos.stream().collect(Collectors.groupingBy(HospProfitVO::getParentId));
- List<HospProfitVO> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
- collect.remove(NumberConstant.ZERO_L);
- for (HospProfitVO costProfitVo : costProfitParentVos) {
- List<HospProfitVO> costProfitVo1 = collect.get(costProfitVo.getId());
- if (!CollectionUtils.isEmpty(costProfitVo1)) {
- costProfitVo.setChild(setChildren(costProfitVo1, collect));
- }
- }
- if (!CollectionUtils.isEmpty(costProfitParentVos)) {
- costProfitParentVos.sort(Comparator.comparing(HospProfitVO::getSort, Comparator.nullsLast(Integer::compareTo)));
- }
- return costProfitParentVos;
- }
- @Override
- public Object getBatchHospProfitList(String beginComputeDate, String endComputeDate, Long hospId, Integer reportType) {
- List<HospProfitAndLoss> hospProfitAndLossByDateRange = getHospProfitAndLossByDateRange(beginComputeDate, endComputeDate,reportType);
- if (CollectionUtils.isEmpty(hospProfitAndLossByDateRange)) {
- throw new CostException(500, "未进行全院损益计算");
- }
- //获取全院损益表配置信息
- List<ReportForm> reportFormList=getReportFormList(hospId,reportType);
- if (CollectionUtils.isEmpty(reportFormList)) {
- throw new CostException(500, "未找到全院损益表配置");
- }
- //按年-月进行分组
- Map<String, List<HospProfitAndLoss>> groupedByYearMonth = hospProfitAndLossByDateRange.stream()
- .collect(Collectors.groupingBy(
- item -> item.getDateYear() + "-" + (item.getDateMonth() < 10 ? "0" + item.getDateMonth() : item.getDateMonth())
- ));
- List<BatchCostProfitResponse> responses = new ArrayList<>();
- List<CostProfitVo> allCostProfitVo=new ArrayList<>();
- //按年-月处理科室损益数据
- for (Map.Entry<String, List<HospProfitAndLoss>> entry : groupedByYearMonth.entrySet()){
- List<HospProfitAndLoss> hospProfitAndLossList = entry.getValue();
- //转换成成本损益数据
- List<CostProfitVo> costProfitVos = convertToCostProfitVoList(hospProfitAndLossList, reportFormList);
- //记录所有月份的损益数据
- allCostProfitVo.addAll(costProfitVos);
- //生成出参样式
- BatchCostProfitResponse response = new BatchCostProfitResponse();
- //第13月为审计月份
- if(hospProfitAndLossList.get(0).getDateMonth()==13){
- response.setComputeDate(String.format("%s-%s", hospProfitAndLossList.get(0).getDateYear(), "12A"));
- response.setAuditMonth(true);
- response.setMonthlyAccumulation(false);
- }else {
- response.setComputeDate(entry.getKey());
- response.setAuditMonth(false);
- response.setMonthlyAccumulation(false);
- }
- response.setProfitVoList(costProfitVos);
- response.setAllowDrillDown(false);
- responses.add(response);
- }
- responses.sort(Comparator.comparing(BatchCostProfitResponse::getComputeDate));
- //起止年月不同时代表有多月份需要处理月累计
- if(!beginComputeDate.equals(endComputeDate)){
- //获取月度汇总数据
- List<CostProfitVo> costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo);
- if(!CollectionUtils.isEmpty(costProfitVos)){
- BatchCostProfitResponse response = new BatchCostProfitResponse();
- response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate));
- response.setProfitVoList(costProfitVos);
- response.setAllowDrillDown(false);
- response.setMonthlyAccumulation(true);
- response.setAuditMonth(false);
- responses.add(NumberConstant.ZERO,response);
- }
- }
- return responses;
- }
- /**
- * 生成多月份汇总的科室损益数据
- *
- * @param allCostProfitVo 原始数据列表
- * @return 汇总后的科室损益数据
- */
- private List<CostProfitVo> generateSummaryForMultipleMonths(List<CostProfitVo> allCostProfitVo){
- // 参数校验
- if (CollectionUtils.isEmpty(allCostProfitVo)) {
- return Collections.emptyList();
- }
- //排除掉13月的数据
- List<CostProfitVo> activeCostProfitVo = allCostProfitVo.stream().filter(profitVo -> profitVo.getMonth() != 13).collect(Collectors.toList());
- if (CollectionUtils.isEmpty(activeCostProfitVo)) {
- return Collections.emptyList();
- }
- List<CostProfitVo> profitVoList=new ArrayList<>() ;
- Map<Long, List<CostProfitVo>> reportGroup = allCostProfitVo.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
- reportGroup.forEach((reportId, profitVos) -> {
- CostProfitVo costProfitVo = BeanUtil.convertObj(profitVos.get(NumberConstant.ZERO), CostProfitVo.class);
- BigDecimal totalAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getAmount()).orElse(BigDecimal.ZERO))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal totalBudgetAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getBudgetAmount()).orElse(BigDecimal.ZERO))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal totalPrevPeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getPrevPeriodAmount()).orElse(BigDecimal.ZERO))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO))
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- costProfitVo.setAmount(totalAmount);
- costProfitVo.setBudgetAmount(totalBudgetAmount);
- costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount);
- costProfitVo.setSamePeriodAmount(totalSamePeriodAmount);
- costProfitVo.setCompletionRate(calculateProfitRate(costProfitVo.getAmount(), costProfitVo.getBudgetAmount()));
- costProfitVo.setMomRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getPrevPeriodAmount()), costProfitVo.getPrevPeriodAmount()));
- costProfitVo.setYoyRate(calculateProfitRate(costProfitVo.getAmount().subtract(costProfitVo.getSamePeriodAmount()), costProfitVo.getSamePeriodAmount()));
- profitVoList.add(costProfitVo);
- });
- //转成树状结构
- List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(profitVoList);
- return costProfitVoTree;
- }
- /**
- * 转换为多层级样式全院损益数据
- * @param hospProfitAndLossList
- * @param reportFormList
- * @return
- */
- public List<CostProfitVo> convertToCostProfitVoList(List<HospProfitAndLoss> hospProfitAndLossList,List<ReportForm> reportFormList ){
- //全院其他收支项目
- List<HospProfitAndLoss> otherHospProfitAndLoss = hospProfitAndLossList.stream().filter(i -> NumberConstant.ONE.equals(i.getOriginType())).collect(Collectors.toList());
- //按报表项目编号map
- Map<Integer, HospProfitAndLoss> hospProfitAndLossMap = hospProfitAndLossList.stream().collect(Collectors.toMap(HospProfitAndLoss::getReportNum, b -> b));
- //报表项目转换成多层级损益对象
- List<CostProfitVo> costProfitVos =reportFormList.stream().map(reportForm -> reportFormToProfitVo(reportForm)).collect(Collectors.toList());
- //组装全院损益及报表项目信息
- for (CostProfitVo profitVo : costProfitVos) {
- //处理年月数据
- profitVo.setYear(hospProfitAndLossList.get(0).getDateYear());
- profitVo.setMonth(hospProfitAndLossList.get(0).getDateMonth());
- //添加损益数据
- HospProfitAndLoss hospProfitAndLoss = hospProfitAndLossMap.get(profitVo.getReportNum());
- //组装全院损益及报表项目金额信息
- combineReportAndProfitAmount(profitVo,hospProfitAndLoss);
- }
- //有全院其他收支时添加全院其他收支
- if(!CollectionUtils.isEmpty(otherHospProfitAndLoss)){
- //找到配置的损益项目
- Optional<ReportForm> firstLossReport = reportFormList.stream().filter(i -> NumberConstant.ONE.equals(i.getIsLoss())).findFirst();
- if(!firstLossReport.isPresent()){
- throw new CostException(500, "全院损益报表配置有误,未设置损益项目");
- }
- //生成一个虚拟的全院其他收支
- CostProfitVo otherProfit = getOtherProfit(reportFormList);
- //处理年月数据
- otherProfit.setYear(otherHospProfitAndLoss.get(NumberConstant.ZERO).getDateYear());
- otherProfit.setMonth(otherHospProfitAndLoss.get(NumberConstant.ZERO).getDateMonth());
- costProfitVos.add(otherProfit);
- ReportForm reportForm = firstLossReport.get();
- for (int i = 0; i < otherHospProfitAndLoss.size(); i++) {
- HospProfitAndLoss hospProfitAndLoss = otherHospProfitAndLoss.get(i);
- CostProfitVo costProfitVo =reportFormToProfitVo(reportForm);
- //组装全院损益及报表项目金额信息
- combineReportAndProfitAmount(costProfitVo,hospProfitAndLoss);
- //处理年月数据
- costProfitVo.setYear(hospProfitAndLoss.getDateYear());
- costProfitVo.setMonth(hospProfitAndLoss.getDateMonth());
- //全院其他收支项目放在虚拟的全院其他收支下
- costProfitVo.setSort(i);
- costProfitVo.setReportNum(hospProfitAndLoss.getReportNum());
- costProfitVo.setReportId(hospProfitAndLoss.getReportNum().longValue());
- costProfitVo.setReportParentId(otherProfit.getReportId());
- costProfitVos.add(costProfitVo);
- }
- }
- //转成树状结构的损益数据
- List<CostProfitVo> costProfitVoTree = converToCostProfitVoTree(costProfitVos);
- return costProfitVoTree;
- }
- /**
- * 生成一个虚拟的全院其他收支
- * @param reportFormList
- * @return
- */
- public CostProfitVo getOtherProfit(List<ReportForm> reportFormList) {
- //全院其他收支
- CostProfitVo hospProfitVO = reportFormToProfitVo(reportFormList.get(NumberConstant.ZERO));
- hospProfitVO.setId(-1L);
- hospProfitVO.setReportId(-1L);
- hospProfitVO.setReportNum(-1);
- hospProfitVO.setReportParentId(0L);
- hospProfitVO.setReportName("全院其他收支");
- hospProfitVO.setSort(reportFormList.size());
- return hospProfitVO;
- }
- /**
- * 报表项目转换成多层级损益对象
- * @param reportForm
- * @return
- */
- public CostProfitVo reportFormToProfitVo(ReportForm reportForm){
- CostProfitVo profitVo = new CostProfitVo();
- profitVo.setReportId(reportForm.getId());
- profitVo.setReportName(reportForm.getReportName());
- profitVo.setReportParentId(reportForm.getParentId());
- profitVo.setReportNum(reportForm.getNum());
- profitVo.setCalcType(reportForm.getCalcType());
- profitVo.setCalcFormula(reportForm.getCalcFormula());
- profitVo.setCostType(reportForm.getCostType());
- profitVo.setShareType(reportForm.getReportType());
- profitVo.setSort(reportForm.getSort());
- profitVo.setDescription(reportForm.getDescription());
- profitVo.setDataType(reportForm.getDataType());
- profitVo.setDecimalPlace(reportForm.getDecimalPlace());
- profitVo.setPermil(reportForm.getPermil());
- return profitVo;
- }
- /**
- * 组装全院损益及报表项目的金额信息
- * @param profitVo
- * @param hospProfitAndLoss
- */
- public void combineReportAndProfitAmount(CostProfitVo profitVo, HospProfitAndLoss hospProfitAndLoss) {
- if (ObjectUtils.isEmpty(hospProfitAndLoss)) {
- profitVo.setAmount(BigDecimal.ZERO);
- profitVo.setSamePeriodAmount(BigDecimal.ZERO);
- profitVo.setPrevPeriodAmount(BigDecimal.ZERO);
- profitVo.setBudgetAmount(BigDecimal.ZERO);
- profitVo.setYoyRate(BigDecimal.ZERO);
- profitVo.setMomRate(BigDecimal.ZERO);
- profitVo.setCompletionRate(BigDecimal.ZERO);
- } else {
- profitVo.setAmount(hospProfitAndLoss.getAmount());
- profitVo.setSamePeriodAmount(hospProfitAndLoss.getSamePeriodAmount());
- profitVo.setPrevPeriodAmount(hospProfitAndLoss.getPrevPeriodAmount());
- profitVo.setBudgetAmount(hospProfitAndLoss.getBudgetAmount());
- profitVo.setYoyRate(hospProfitAndLoss.getYoyRate());
- profitVo.setMomRate(hospProfitAndLoss.getMomRate());
- profitVo.setCompletionRate(hospProfitAndLoss.getCompletionRate());
- }
- }
- /**
- * 转成树状结构的损益数据
- * @param costProfitVos
- * @return
- */
- public List<CostProfitVo> converToCostProfitVoTree(List<CostProfitVo> costProfitVos){
- // 参数校验
- if (CollectionUtils.isEmpty(costProfitVos)) {
- return Collections.emptyList();
- }
- Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
- List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
- collect.remove(NumberConstant.ZERO_L);
- for (CostProfitVo costProfitVo : costProfitParentVos) {
- List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
- if (!CollectionUtils.isEmpty(costProfitVo1)) {
- costProfitVo.setChildren(setChildrenProfitVo(costProfitVo1, collect));
- }
- }
- if (!CollectionUtils.isEmpty(costProfitParentVos)) {
- costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
- }
- return costProfitParentVos;
- }
- private List<CostProfitVo> setChildrenProfitVo(List<CostProfitVo> child, Map<Long, List<CostProfitVo>> collect) {
- for (CostProfitVo costProfitVo : child) {
- if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getReportId()))) {
- costProfitVo.setChildren(setChildrenProfitVo(collect.get(costProfitVo.getReportId()), collect));
- }
- }
- if (!CollectionUtils.isEmpty(child)) {
- child.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
- }
- return child;
- }
- /**
- * 获取全院损益表配置信息
- * @param hospId
- * @param reportType
- * @return
- */
- public List<ReportForm> getReportFormList(Long hospId,Integer reportType ) {
- List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
- .eq(ReportForm::getHospId, hospId)
- .eq(ReportForm::getReportType, reportType)
- .eq(ReportForm::getDeleteTime , NumberConstant.ZERO)
- .eq(ReportForm::getHide, NumberConstant.ONE));
- return reportFormList;
- }
- /**
- * 获取指定年月区间的全院损益数据
- * @param beginComputeDate
- * @param endComputeDate
- * @return
- */
- public List<HospProfitAndLoss> getHospProfitAndLossByDateRange(String beginComputeDate, String endComputeDate, Integer reportType) {
- // 解析开始和结束时间
- int startYear = Integer.parseInt(beginComputeDate.split("-")[0]);
- int startMonth = Integer.parseInt(beginComputeDate.split("-")[1]);
- int endYear = Integer.parseInt(endComputeDate.split("-")[0]);
- int endMonth = Integer.parseInt(endComputeDate.split("-")[1]);
- if( startYear * 100 + startMonth> endYear * 100 + endMonth){
- throw new CostException("开始时间不能大于结束时间");
- }
- //如果截止月份是12月要自动添加第13月的数据
- if(endMonth==12)
- {
- endMonth=13;
- }
- List<HospProfitAndLoss> list = this.list(new QueryWrapper<HospProfitAndLoss>().lambda()
- .eq(HospProfitAndLoss::getDeleteTime, NumberConstant.ZERO)
- .eq(HospProfitAndLoss::getHospId, UserContext.getHospId())
- .eq(HospProfitAndLoss::getReportType, reportType)
- .apply("(date_year * 100 + date_month) >= {0}", startYear * 100 + startMonth)
- .apply("(date_year * 100 + date_month) <= {0}", endYear * 100 + endMonth));
- return list;
- }
- private static @NotNull HospProfitVO getHospProfitVO(List<HospProfitAndLoss> hospAllList, int i,int reportType) {
- HospProfitAndLoss hospProfitAndLoss = hospAllList.get(i);
- HospProfitVO hospProfitVO1 = new HospProfitVO();
- hospProfitVO1.setId(Long.valueOf(hospProfitAndLoss.getReportNum()));
- hospProfitVO1.setNum(hospProfitAndLoss.getReportNum());
- hospProfitVO1.setParentId(-1L);
- hospProfitVO1.setReportName(hospProfitAndLoss.getReportName());
- hospProfitVO1.setSort(i);
- hospProfitVO1.setReportType(reportType);
- hospProfitVO1.setAmount(hospProfitAndLoss.getAmount());
- hospProfitVO1.setFraction(3);
- return hospProfitVO1;
- }
- private List<HospProfitAndLoss> getAllDataByDate(int year, int month, Long hospId,int reportType) {
- return this.list(
- new LambdaQueryWrapper<HospProfitAndLoss>()
- .eq(HospProfitAndLoss::getHospId, hospId)
- .eq(HospProfitAndLoss::getDateMonth, month)
- .eq(HospProfitAndLoss::getDateYear, year)
- .eq(HospProfitAndLoss::getReportType, reportType)
- );
- }
- /**
- * @param date
- * @param hospId
- */
- @Override
- public void calcByResponsibility(String date, Long hospId) {
- calcHospProfit(date,hospId,ReportTypeEnum.HOSP_PROFIT_LOSS.getType());
- }
- private void setCalculationAmount(List<HospProfitAndLossVo> listVo) {
- Map<Integer, List<HospProfitAndLossVo>> collect = listVo.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getCalcType));
- //取出所有计算公式数据
- List<HospProfitAndLossVo> costDepartmentProfitVOS = collect.get(NumberConstant.FOUR);
- costDepartmentProfitVOS.sort(Comparator.comparing(HospProfitAndLossVo::getReportNum, Comparator.nullsLast(Integer::compareTo)));
- for (HospProfitAndLossVo profitVO : costDepartmentProfitVOS) {
- // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2]
- String formula = profitVO.getCalcFormula();
- //找出公式当中所有代码
- String replace = formula.replace("[", "")
- .replace("]", "")
- .replace("-", ",")
- .replace("+", ",")
- .replace("*", ",")
- .replace("/", ",");
- ArrayList<String> codeList = CollUtil.newArrayList(replace.split(","));
- Map<Integer, String> codeMap = new ConcurrentHashMap<>();
- for (int j = 0; j < codeList.size(); j++) {
- codeMap.put(j, codeList.get(j));
- }
- List<String> expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "")
- .replace("]", "").trim(), 0)
- .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
- // 得到预算表达式 得到所有表达式的Map + - 相关的
- Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
- for (int k = 0; k < expressions.size(); k++) {
- expressionMap.put(k, expressions.get(k));
- }
- // 数字的索引和表达式的索引累加计算
- Set<Integer> codeSet = codeMap.keySet();
- List<Integer> codes = new ArrayList<>(codeSet);
- AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(new BigDecimal("0.000000"));
- for (int i = 0; i < codes.size(); i++) {
- // 编号
- String code = codeMap.get(i);
- BigDecimal amount = null;
- for (HospProfitAndLossVo costDepartmentProfitVO : listVo) {
- if (costDepartmentProfitVO.getReportNum().equals(Integer.valueOf(code))) {
- amount = costDepartmentProfitVO.getAmount();
- }
- }
- if (amount == null) {
- continue;
- }
- // BigDecimal amount = new BigDecimal(o.toString());
- String str = expressionMap.get(i);
- if (str.equals("+")) {
- totalAmount.set(totalAmount.get().add(amount));
- } else if (str.contains("-")) {
- totalAmount.set(totalAmount.get().subtract(amount));
- } else if (str.contains("*")) {
- totalAmount.set(totalAmount.get().multiply(amount));
- } else if (str.contains("/")) {
- if (amount.compareTo(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP)) == 0) {
- totalAmount.set(BigDecimal.ZERO);
- break;
- } else {
- totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP));
- }
- }
- }
- profitVO.setAmount(totalAmount.get());
- }
- }
- /**
- * 按照责任中心进行计算
- * 原始责任中心是设置的责任中心 目标责任中心是报表的责任中心
- * 查询分摊报表里面目标责任中心是当前责任中心 报表责任中心是当前设置的责任中心
- */
- public BigDecimal setResponsibilityCode(HospProfitAndLossVo costDepartmentProfitVO, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
- // 获取当前报表对应的责任中心
- List<ReportRelation> reportRelationList = reportRelationMap.get(costDepartmentProfitVO.getReportId());
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
- if (CollUtil.isNotEmpty(reportRelationList)) {
- // 获取对应的责任中心的Code集合 这个是设置的责任中心
- List<String> responsibilityCodes = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(responsibilityCodes)) {
- // 查询报表里面是当前分摊层级的数据
- List<Allocation> allocations = allocationList.stream().filter(i -> i.getTargetResponsibilityCode().equals(costDepartmentProfitVO.getResponsibilityCode()) && responsibilityCodes.contains(i.getResponsibilityCode())).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(allocations)) {
- BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- sum.set(reduce);
- // allocations.forEach(m -> {
- // sum.updateAndGet(v -> v.add(m.getAmount()));
- // });
- }
- }
- }
- // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
- return sum.get();
- }
- /***
- * 按照计算方式进行计算
- */
- public BigDecimal setCalculation(HospProfitAndLossVo costDepartmentProfitVO, List<HospProfitAndLossVo> costDepartmentProfitVOList,
- List<CostShareLevel> costShareLevelList, Map<Long, List<HospProfitAndLossVo>> listMap,
- List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList,
- Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
- // 获取当前报表的计算方式 [1]+[2]类型/ [1]-[2]
- String calcFormula = costDepartmentProfitVO.getCalcFormula();
- String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
- String replace = calcFormula.replace("[", "").replace("]", "").replace("+", ",").replace("-", ",-");
- List<Integer> calcFormulaList = Arrays.stream(replace.split(StrUtil.COMMA)).map(Integer::valueOf).collect(Collectors.toList());
- // 查询这个编号集合的报表
- AtomicReference<BigDecimal> bigDecimal = new AtomicReference<>(new BigDecimal("0.0000"));
- calcFormulaList.forEach(calc -> {
- Integer calcNum = Math.abs(calc);
- List<Long> reportIdList = allList.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode) && calcNum.equals(i.getReportNum())).map(HospProfitAndLossVo::getReportId).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(reportIdList)) {
- reportIdList.forEach(i -> {
- List<HospProfitAndLossVo> profitVOS = listMap.get(i);
- if (CollUtil.isEmpty(profitVOS)) {
- throw new CostException(500, "报表未找到");
- }
- BigDecimal amount = getAmount(profitVOS, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
- if (calc > 0) {
- bigDecimal.updateAndGet(v -> v.add(amount));
- } else {
- bigDecimal.updateAndGet(v -> v.subtract(amount));
- }
- });
- }
- });
- return bigDecimal.get();
- }
- /**
- * 按照小计的计算方式
- * 同一个目录下相同的其他金额的和
- */
- public BigDecimal setSubtotal(HospProfitAndLossVo costDepartmentProfitVO,
- List<CostShareLevel> costShareLevelList,
- Map<Long, List<HospProfitAndLossVo>> listMap,
- List<HospProfitAndLossVo> profitVOS,
- List<IncomeCollection> list,
- List<AllocationQueryReportVO> allocationQueryReportVOList,
- Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<HospProfitAndLossVo> allList) {
- // 因为报表是按照报表项目的升序进行排序的 前面的报表是已经进行计算了的
- // 查询当前报表的父层级id
- Long reportParentId = costDepartmentProfitVO.getReportParentId();
- String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
- // 查询报表里面在当前父层级下的并且不是自己的报表项目
- List<HospProfitAndLossVo> costDepartmentProfitVOS = allList.stream().filter(i -> i.getReportParentId().equals(reportParentId) && i.getResponsibilityCode().equals(responsibilityCode) && !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
- // 遍历数据 之前的已经经过了计算
- costDepartmentProfitVOS.forEach(i -> {
- Long reportId = i.getReportId();
- List<HospProfitAndLossVo> costDepartmentProfitVOS1 = listMap.get(reportId);
- if (CollUtil.isEmpty(costDepartmentProfitVOS1)) {
- throw new CostException(500, "报表未找到");
- }
- BigDecimal amount = getAmount(costDepartmentProfitVOS1, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
- sum.set(amount.add(sum.get()));
- ;
- });
- // costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
- return sum.get();
- }
- /**
- * 判断是那种计算方式 调用方法进行计算
- */
- public BigDecimal getAmount(List<HospProfitAndLossVo> profitVOS,
- List<CostShareLevel> costShareLevelList,
- String responsibilityCode, List<IncomeCollection> list,
- List<AllocationQueryReportVO> allocationQueryReportVOList,
- Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList,
- Map<Long, List<HospProfitAndLossVo>> listMap, List<HospProfitAndLossVo> allList) {
- BigDecimal bigDecimal = new BigDecimal("0.0000");
- // 在对这个报表进行过滤
- List<HospProfitAndLossVo> costDepartmentProfitVOS = profitVOS.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList());
- // 都一个就是
- HospProfitAndLossVo costDepartmentProfitVO = costDepartmentProfitVOS.get(0);
- Integer calcType = costDepartmentProfitVO.getCalcType();
- if (NumberConstant.ONE.equals(calcType)) {
- // 调用计算的方法 按照会计科目
- bigDecimal = setAccountReportData(costDepartmentProfitVO, list, allocationQueryReportVOList, reportRelationMap);
- } else if (NumberConstant.TWO.equals(calcType)) {
- // 按照分摊层级
- bigDecimal = setShareLevelReportData(costDepartmentProfitVO, reportRelationMap, allocationList);
- } else if (NumberConstant.THREE.equals(calcType)) {
- // 小计
- bigDecimal = setSubtotal(costDepartmentProfitVO, costShareLevelList, listMap, profitVOS, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
- } else if (NumberConstant.FIVE.equals(calcType)) {
- // 按照责任中心
- bigDecimal = setResponsibilityCode(costDepartmentProfitVO, reportRelationMap, allocationList, allList);
- } else if (NumberConstant.FOUR.equals(calcType)) {
- bigDecimal = setCalculation(costDepartmentProfitVO, costDepartmentProfitVOS, costShareLevelList, listMap, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
- }
- return bigDecimal;
- }
- private BigDecimal setAccountReportData(HospProfitAndLossVo i, List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList, Map<Long, List<ReportRelation>> reportRelationMap) {
- // 在报表关联里面查询当前报表关联的
- Long reportId = i.getReportId();
- List<ReportRelation> reportRelationList = reportRelationMap.get(reportId);
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
- if (CollUtil.isNotEmpty(reportRelationList)) {
- // 获取对应的会计科目信息 筛选会计科目的Code
- List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
- // 查找在归集数据里面当前责任中心对应的这些会计科目的金额
- List<IncomeCollection> incomeCollectionList = list.stream().filter(income -> income.getResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList());
- // 需要查询分摊后的表
- List<AllocationQueryReportVO> reportVOList = allocationQueryReportVOList.stream().filter(m -> m.getTargetResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(m.getAccountingCode())).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(incomeCollectionList)) {
- incomeCollectionList.forEach(m -> {
- sum.updateAndGet(v -> v.add(m.getAmount()));
- });
- }
- // 成本减
- if (CollUtil.isNotEmpty(reportVOList)) {
- reportVOList.forEach(m -> {
- sum.updateAndGet(v -> v.add(m.getAmount()));
- });
- }
- }
- // i.setAmount(new BigDecimal(sum.toString()));
- // numMap.put(i.getReportNum()+i.getResponsibilityCode(),new BigDecimal(sum.toString()));
- return sum.get();
- }
- private BigDecimal setShareLevelReportData(HospProfitAndLossVo i, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList) {
- List<ReportRelation> reportRelationList = reportRelationMap.get(i.getReportId());
- AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
- if (CollUtil.isNotEmpty(reportRelationList)) {
- // 找到对应的分摊层级的Id 但是分摊报表里面存的是分摊层级的序号
- List<Long> shareLevelIds = reportRelationList.stream().map(ReportRelation::getRelationCode).map(Long::valueOf).collect(Collectors.toList());
- // List<Integer> levelShortList = costShareLevelList.stream()
- // .filter(m -> shareLevelIds.contains(m.getId()))
- // .map(CostShareLevel::getLeverSort).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(shareLevelIds)) {
- // 查询报表里面是当前分摊层级的数据
- List<Allocation> allocations = allocationList.stream().filter(m -> shareLevelIds.contains(m.getShareLevelId()) && m.getTargetResponsibilityCode().equals(i.getResponsibilityCode())).collect(Collectors.toList());
- if (CollUtil.isNotEmpty(allocations)) {
- // allocations.forEach(m -> {
- // sum.updateAndGet(v -> v.add(m.getAmount()));
- // });
- BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- sum.set(reduce);
- }
- }
- }
- // i.setAmount(new BigDecimal(sum.toString()));
- return sum.get();
- }
- private void calcByLitterCountResp(HospProfitAndLossVo lossVo, Map<Long, List<HospProfitAndLossVo>> listParentMap, List<HospProfitAndLossVo> listVo, Long hospId) {
- //lossVo 当前 小计对象
- //listParentMap 与小计同级别的对象
- //listVo 存储计算过的对象
- // 通地当前小计 找出 同级别需要合计的对象 再从计算过的对象取出数值合计
- Long reportParentId = lossVo.getReportParentId();
- List<HospProfitAndLossVo> hospProfitAndLossVos = listParentMap.get(reportParentId);
- //去除小计本身
- hospProfitAndLossVos.remove(lossVo);
- List<Integer> reportNums = hospProfitAndLossVos.stream().map(HospProfitAndLossVo::getReportNum).collect(Collectors.toList());
- List<HospProfitAndLossVo> collect = listVo.stream().filter(i -> reportNums.contains(i.getReportNum()) && i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
- if (collect.isEmpty()) {
- return;
- }
- BigDecimal reduce = collect.stream().map(HospProfitAndLossVo::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- lossVo.setAmount(reduce);
- }
- private List<HospProfitAndLossVo> costPercent(List<HospProfitAndLossVo> profitIncomeList) {
- List<HospProfitAndLossVo> list = new ArrayList<>();
- Map<Integer, List<HospProfitAndLossVo>> collect = profitIncomeList.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getFraction));
- //分母只有一个
- List<HospProfitAndLossVo> denominatorList = collect.get(NumberConstant.TWO);
- if (denominatorList.size() > 1) {
- throw new CostException("收入项目分母大于一个,请查证后再计算科室损益");
- }
- BigDecimal denominator = denominatorList.get(0).getAmount();
- //收入分子
- List<HospProfitAndLossVo> numeratorList = collect.get(NumberConstant.ONE);
- if (denominator.compareTo(BigDecimal.ZERO) == 0) {
- for (HospProfitAndLossVo profitVO : numeratorList) {
- profitVO.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
- }
- denominatorList.get(0).setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
- } else {
- for (HospProfitAndLossVo profitVO : numeratorList) {
- profitVO.setPercent(profitVO.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
- }
- denominatorList.get(0).setPercent(BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP));
- }
- list.add(denominatorList.get(0));
- list.addAll(numeratorList);
- return list;
- }
- private void calcByResponsibilityResp(Long hospId, HospProfitAndLossVo lossVo) {
- List<RelationVO> responsibilities = reportRelationService.getResponsibilities(lossVo.getReportId(), hospId);
- if (responsibilities.isEmpty()) {
- return;
- }
- List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
- responsibilityCodes.forEach(i -> {
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- calcTotal.set(calcTotal.get().add(costAmount));
- });
- lossVo.setAmount(calcTotal.get());
- }
- private void calcByResponsibilityResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
- List<RelationVO> responsibilities = reportRelationService.getResponsibilities(child.getId(), hospId);
- if (responsibilities.isEmpty()) {
- return;
- }
- List<String> responsibilityCodes = responsibilities.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
- responsibilityCodes.forEach(i -> {
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getResponsibilityCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- calcTotal.set(calcTotal.get().add(costAmount));
- });
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(child.getReportName()).setReportNum(child.getNum()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
- .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month);
- list.add(loss);
- }
- private void calcByFormulaResp(HospProfitAndLossVo lossVo, List<HospProfitAndLossVo> list) {
- // 得到这个责任中心下所有的已经收集的数据
- List<HospProfitAndLossVo> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(lossVo.getResponsibilityCode())).collect(Collectors.toList());
- String calcFormula = lossVo.getCalcFormula();
- // TODO: 2021/8/27 校验公式合法性
- if (StrUtil.isBlank(calcFormula)) {
- throw new CostException("reportForm名称为" + lossVo.getReportName() + "计算公式不正确");
- }
- BigDecimal bigDecimal = calcAmountRes(hadCalcLosses, calcFormula);
- lossVo.setAmount(bigDecimal);
- }
- private void calcByFormulaResp(int year, int month, ReportForm child, List<HospProfitAndLoss> list, Responsibility responsibility) {
- // 得到这个责任中心下所有的已经收集的数据
- List<HospProfitAndLoss> hadCalcLosses = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
- String calcFormula = child.getCalcFormula();
- // TODO: 2021/8/27 校验公式合法性
- if (StrUtil.isBlank(calcFormula)) {
- throw new CostException("reportForm名称为" + child.getReportName() + "计算公式不正确");
- }
- BigDecimal bigDecimal = calcAmountResp(hadCalcLosses, calcFormula);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month).setReportNum(child.getNum()).setReportName(child.getReportName())
- .setAmount(bigDecimal).setCreateTime(System.currentTimeMillis()).setHospId(child.getHospId()).setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
- list.add(loss);
- }
- private BigDecimal calcAmountRes(List<HospProfitAndLossVo> hadCalcLosses, String calcFormula) {
- // 得到所有的编号
- String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
- ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
- // 得到编号的map
- Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
- for (int j = 0; j < numList.size(); j++) {
- numMap.put(j, Integer.parseInt(numList.get(j)));
- }
- List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
- .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
- // 得到预算表达式 得到所有表达式的Map + - 相关的
- Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
- for (int k = 0; k < expressions.size(); k++) {
- expressionMap.put(k, expressions.get(k));
- }
- // 数字的索引和表达式的索引累加计算
- Set<Integer> numSet = numMap.keySet();
- List<Integer> nums = new ArrayList<>(numSet);
- AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
- totalAmount.set(BigDecimal.ZERO);
- for (int i = 0; i < nums.size(); i++) {
- // 编号
- Integer num = numMap.get(i);
- List<HospProfitAndLossVo> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
- if (CollUtil.isEmpty(losses)) {
- continue;
- }
- HospProfitAndLossVo loss = losses.get(0);
- BigDecimal amount = loss.getAmount();
- String str = expressionMap.get(i);
- if (str.equals("+")) {
- totalAmount.set(totalAmount.get().add(amount));
- } else {
- totalAmount.set(totalAmount.get().subtract(amount));
- }
- }
- return totalAmount.get();
- }
- private BigDecimal calcAmountResp(List<HospProfitAndLoss> hadCalcLosses, String calcFormula) {
- // 得到所有的编号
- String replace = calcFormula.replace("[", "").replace("]", "").replace("-", ",").replace("+", ",");
- ArrayList<String> numList = CollUtil.newArrayList(replace.split(","));
- // 得到编号的map
- Map<Integer, Integer> numMap = new ConcurrentHashMap<>();
- for (int j = 0; j < numList.size(); j++) {
- numMap.put(j, Integer.parseInt(numList.get(j)));
- }
- List<String> expressions = ReUtil.findAll("[^0-9]", "+" + calcFormula.replace("[", "").replace("]", "").trim(), 0)
- .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
- // 得到预算表达式 得到所有表达式的Map + - 相关的
- Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
- for (int k = 0; k < expressions.size(); k++) {
- expressionMap.put(k, expressions.get(k));
- }
- // 数字的索引和表达式的索引累加计算
- Set<Integer> numSet = numMap.keySet();
- List<Integer> nums = new ArrayList<>(numSet);
- AtomicReference<BigDecimal> totalAmount = new AtomicReference<>();
- totalAmount.set(BigDecimal.ZERO);
- for (int i = 0; i < nums.size(); i++) {
- // 编号
- Integer num = numMap.get(i);
- List<HospProfitAndLoss> losses = hadCalcLosses.stream().filter(item -> item.getReportNum().equals(num)).collect(Collectors.toList());
- if (CollUtil.isEmpty(losses)) {
- continue;
- }
- HospProfitAndLoss loss = losses.get(0);
- BigDecimal amount = loss.getAmount();
- String str = expressionMap.get(i);
- if (str.equals("+")) {
- totalAmount.set(totalAmount.get().add(amount));
- } else {
- totalAmount.set(totalAmount.get().subtract(amount));
- }
- }
- return totalAmount.get();
- }
- private void calcByLitterCountResp(int year, int month, ReportForm child, List<ReportForm> children,
- List<HospProfitAndLoss> list, Long hospId, Responsibility responsibility) {
- List<HospProfitAndLoss> thisRespCodeList = list.stream().filter(i -> i.getResponsibilityCode().equals(responsibility.getResponsibilityCode())).collect(Collectors.toList());
- List<ReportForm> thisForEachList = children.stream().filter(i -> !i.getCalcType().equals(CalcTypeEnum.LITTER_COUNT.getType())).collect(Collectors.toList());
- List<HospProfitAndLoss> collect = thisRespCodeList.stream().filter(i -> thisForEachList.stream().map(ReportForm::getNum).collect(Collectors.toList()).contains(i.getReportNum())).collect(Collectors.toList());
- if (collect.isEmpty()) {
- return;
- }
- BigDecimal reduce = collect.stream().map(HospProfitAndLoss::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setDateYear(year).setDateMonth(month)
- .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId);
- // 小计只能有一个
- loss.setReportNum(child.getNum()).setReportName(child.getReportName())
- .setResponsibilityCode(responsibility.getResponsibilityCode())
- .setResponsibilityName(responsibility.getResponsibilityName());
- list.add(loss);
- }
- private void calcByShareLevelResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int year, int month, Responsibility responsibility) {
- List<RelationVO> shareLevels = reportRelationService.getShareLevel(child.getId(), hospId);
- List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
- if (CollUtil.isEmpty(shareLevelId)) {
- return;
- }
- List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
- if (costShareLevels.isEmpty()) {
- throw new CostException("医院分摊层级设置错误," + child.getReportName());
- }
- List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
- List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(year, month, hospId, shareLevelId, responsibility.getResponsibilityCode());
- if (allocations.isEmpty()) {
- throw new CostException("医院未分摊本月数据");
- }
- List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
- if (accountShares.isEmpty()) {
- return;
- }
- BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(child.getReportName()).setReportNum(child.getNum())
- .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
- .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
- ;
- list.add(loss);
- }
- private void calcByShareLevelResp(Long hospId, HospProfitAndLossVo lossVo) {
- List<RelationVO> shareLevels = reportRelationService.getShareLevel(lossVo.getReportId(), hospId);
- List<Long> shareLevelId = shareLevels.stream().map(RelationVO::getCode).map(Long::valueOf).sorted(Long::compareTo).collect(Collectors.toList());
- if (CollUtil.isEmpty(shareLevelId)) {
- return;
- }
- List<CostShareLevel> costShareLevels = shareLevelService.listByIds(shareLevelId);
- if (costShareLevels.isEmpty()) {
- throw new CostException("医院分摊层级设置错误," + lossVo.getReportName());
- }
- List<Integer> levelSorts = costShareLevels.stream().map(CostShareLevel::getLeverSort).collect(Collectors.toList());
- List<AllocationQuery> allocations = allocationQueryService.getByDateRespn(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, shareLevelId, lossVo.getResponsibilityCode());
- if (allocations.isEmpty()) {
- throw new CostException("医院未分摊本月数据");
- }
- List<CostAccountShare> accountShares = accountShareService.getByShareLevelSort(levelSorts, hospId);
- if (accountShares.isEmpty()) {
- return;
- }
- BigDecimal reduce = allocations.stream().map(AllocationQuery::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- lossVo.setAmount(reduce);
- // HospProfitAndLoss loss = new HospProfitAndLoss();
- // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
- // .setAmount(reduce).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
- // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
- // ;
- // list.add(loss);
- }
- private void calcByAccountByResp(Long hospId, HospProfitAndLossVo lossVo) {
- // 报表项目关联的会计科目对象
- List<RelationVO> accountRelations = reportRelationService.getAccountRelation(lossVo.getReportId(), hospId);
- if (accountRelations.isEmpty()) {
- return;
- }
- List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
- List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(lossVo.getDateYear(), lossVo.getDateMonth(), hospId, lossVo.getResponsibilityCode());
- accountCodes.forEach(i -> {
- BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal total = incomeAmount.add(costAmount);
- calcTotal.set(calcTotal.get().add(total));
- });
- // HospProfitAndLoss loss = new HospProfitAndLoss();
- lossVo.setAmount(calcTotal.get());
- // loss.setReportName(child.getReportName()).setReportNum(child.getNum())
- // .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
- // .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName());
- // list.add(loss);
- }
- private void calcByAccountByResp(Long hospId, ReportForm child, List<HospProfitAndLoss> list, int month, int year, Responsibility responsibility) {
- // 报表项目关联的会计科目对象
- List<RelationVO> accountRelations = reportRelationService.getAccountRelation(child.getId(), hospId);
- if (accountRelations.isEmpty()) {
- return;
- }
- List<String> accountCodes = accountRelations.stream().map(RelationVO::getCode).collect(Collectors.toList());
- AtomicReference<BigDecimal> calcTotal = new AtomicReference<>();
- calcTotal.set(BigDecimal.ZERO);
- List<IncomeCollection> incomes = collectionService.getCollectionsByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
- List<AllocationQuery> allocationQueries = allocationQueryService.getByDateAndResp(year, month, hospId, responsibility.getResponsibilityCode());
- accountCodes.forEach(i -> {
- BigDecimal incomeAmount = incomes.stream().filter(j -> i.equals(j.getAccountingCode())).map(IncomeCollection::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal costAmount = allocationQueries.stream().filter(j -> i.equals(j.getAccountingCode())).map(AllocationQuery::getAmount)
- .reduce(BigDecimal.ZERO, BigDecimal::add);
- BigDecimal total = incomeAmount.add(costAmount);
- calcTotal.set(calcTotal.get().add(total));
- });
- HospProfitAndLoss loss = new HospProfitAndLoss();
- loss.setReportName(child.getReportName()).setReportNum(child.getNum())
- .setAmount(calcTotal.get()).setCreateTime(System.currentTimeMillis()).setHospId(hospId).setDateYear(year).setDateMonth(month)
- .setResponsibilityCode(responsibility.getResponsibilityCode()).setResponsibilityName(responsibility.getResponsibilityName())
- ;
- list.add(loss);
- }
- private void responsibilitySort(List<Responsibility> responsibilityList) {
- for (Responsibility responsibility : responsibilityList) {
- if (!CollectionUtils.isEmpty(responsibility.getChildren())) {
- responsibilitySort(responsibility.getChildren());
- }
- }
- responsibilityList.sort(Comparator.comparing(Responsibility::getSort, Comparator.nullsLast(Integer::compareTo)));
- }
- private List<Responsibility> setResponsibilityChildren(List<Responsibility> child, Map<Long, List<Responsibility>> collect) {
- for (Responsibility responsibility : child) {
- if (!CollectionUtils.isEmpty(collect.get(responsibility.getId()))) {
- responsibility.setChildren(setResponsibilityChildren(collect.get(responsibility.getId()), collect));
- }
- }
- return child;
- }
- private void getResponsibilityParent(Responsibility responsibility, Map<Long, Responsibility> collect, List<Responsibility> addList) {
- Responsibility responsibility1 = collect.get(responsibility.getParentId());
- if (Objects.nonNull(responsibility1)) {
- addList.add(responsibility1);
- if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
- getResponsibilityParent(responsibility1, collect, addList);
- }
- }
- }
- private List<HospProfitVO> setChildren(List<HospProfitVO> child, Map<Long, List<HospProfitVO>> collect) {
- for (HospProfitVO costProfitVo : child) {
- if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getId()))) {
- costProfitVo.setChild(setChildren(collect.get(costProfitVo.getId()), collect));
- }
- }
- if (!CollectionUtils.isEmpty(child)) {
- child.sort(Comparator.comparing(HospProfitVO::getSort, Comparator.nullsLast(Integer::compareTo)));
- }
- return child;
- }
- }
|