1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690 |
- 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.Constant;
- import com.kcim.common.constants.NumberConstant;
- import com.kcim.common.enums.CalcTypeEnum;
- import com.kcim.common.enums.ErrorCodeEnum;
- import com.kcim.common.enums.ReportTypeEnum;
- import com.kcim.common.exception.CostException;
- import com.kcim.common.file.MinioConfig;
- import com.kcim.common.file.MinioFileUtil;
- import com.kcim.common.util.BeanUtil;
- import com.kcim.common.util.PageUtils;
- import com.kcim.common.util.UserContext;
- 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.AllocationQueryReportVO;
- import com.kcim.vo.HospProfitAndLossVo;
- import com.kcim.vo.RelationVO;
- 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.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.util.CollectionUtils;
- 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.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 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) {
- 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;
- }
- /**
- * 计算全院损益
- *
- * @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);
- }
- // 计算公式中钱
- 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);
- 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("全院损益");
- 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);
- }
- private List<HospProfitAndLoss> getAllDataByDate(int year, int month, Long hospId) {
- return this.list(
- new LambdaQueryWrapper<HospProfitAndLoss>()
- .eq(HospProfitAndLoss::getHospId, hospId)
- .eq(HospProfitAndLoss::getDateMonth, month)
- .eq(HospProfitAndLoss::getDateYear, year)
- );
- }
- /**
- * @param date
- * @param hospId
- */
- @Override
- @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
- public void calcByResponsibility(String date, Long hospId) {
- 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)
- );
- // 得到全院损益计算报表
- 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("医院未归集本月收入数据");
- }
- 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.0000"));
- }
- });
- //
- //
- //
- // listVo.forEach(i -> {
- // Integer calcType = i.getCalcType();
- // if (calcType == CalcTypeEnum.BY_ACCOUNT.getType()) {
- // // 按会计科目计算单的话
- // calcByAccountByResp(hospId, i);
- // } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
- // // 分摊层级计算
- // calcByShareLevelResp(hospId, i);
- // } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
- // // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
- // calcByLitterCountResp(i,listParentMap, listVo,hospId);
- // } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
- // // 按公式 (要保证总合计放到最后呀)
- // calcByFormulaResp(i,listVo);
- // } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
- // // 责任中心
- // calcByResponsibilityResp(hospId, i);
- // } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
- // // 不设置不计算
- // i.setAmount(new BigDecimal("0.0000"));
- // } else {
- // i.setAmount(new BigDecimal("0.0000"));
- // }
- // });
- // for (Responsibility responsibility : leafResp) {
- // for (ReportForm parentForm : reportForms) {
- // 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()) {
- // // 按会计科目计算单的话
- // calcByAccountByResp(hospId, child, list, month, year, responsibility);
- // } else if (calcType == CalcTypeEnum.BY_SHARE_LEVEL.getType()) {
- // // 分摊层级计算
- // calcByShareLevelResp(hospId, child, list, year, month, responsibility);
- // } else if (calcType == CalcTypeEnum.LITTER_COUNT.getType()) {
- // // 处理小计 todo 默认认为 小计都是在同一个下面最后一个
- // calcByLitterCountResp(year, month, child, children, list, hospId, responsibility);
- // } else if (calcType == CalcTypeEnum.CALC_FORMULA.getType()) {
- // // 按公式 (要保证总合计放到最后呀)
- // calcByFormulaResp(year, month, child, list, responsibility);
- // } else if (calcType == CalcTypeEnum.BY_RESPONSIBILITY.getType()) {
- // // 责任中心
- // calcByResponsibilityResp(hospId, child, list, year, month, responsibility);
- // } else if (calcType == CalcTypeEnum.NO_CONFIG.getType()) {
- // // 不设置不计算
- // } else {
- //
- // }
- // }
- // }
- // }
- //计算占比
- if (CollectionUtils.isEmpty(listVo)) {
- return;
- }
- //收入
- List<HospProfitAndLossVo> profitIncomeList = listVo.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList());
- List<HospProfitAndLossVo> profitIncome = costPercent(profitIncomeList);
- //成本
- List<HospProfitAndLossVo> profitCostList = listVo.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList());
- List<HospProfitAndLossVo> profitCost = costPercent(profitCostList);
- //不计算项目
- List<HospProfitAndLossVo> noCompute = listVo.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()) {
- otherPaymentsDatas.forEach(ele -> {
- 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)
- ;
- list.add(loss);
- });
- }
- long l = System.currentTimeMillis();
- list.forEach(i -> {
- i.setCreateTime(l);
- });
- this.saveBatch(list);
- }
- /**
- * 按照责任中心进行计算
- * 原始责任中心是设置的责任中心 目标责任中心是报表的责任中心
- * 查询分摊报表里面目标责任中心是当前责任中心 报表责任中心是当前设置的责任中心
- */
- 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<String, List<HospProfitAndLossVo>> responsibilityGroup = profitIncomeList.stream().collect(Collectors.groupingBy(HospProfitAndLossVo::getResponsibilityCode));
- for (String s : responsibilityGroup.keySet()) {
- List<HospProfitAndLossVo> costDepartmentProfitVOS = responsibilityGroup.get(s);
- Map<Integer, List<HospProfitAndLossVo>> collect = costDepartmentProfitVOS.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);
- }
- }
|