123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- package com.imed.costaccount.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.util.StrUtil;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.imed.costaccount.common.exception.CostException;
- import com.imed.costaccount.common.util.BeanUtil;
- import com.imed.costaccount.common.util.JacksonUtil;
- import com.imed.costaccount.common.util.PageUtils;
- import com.imed.costaccount.common.util.RedisLock;
- import com.imed.costaccount.mapper.CostIncomeGroupMapper;
- import com.imed.costaccount.mapper.IncomeCollectionMapper;
- import com.imed.costaccount.model.*;
- import com.imed.costaccount.model.dto.CollectDTO;
- import com.imed.costaccount.model.vo.*;
- import com.imed.costaccount.service.CostIncomeGroupSetService;
- import com.imed.costaccount.service.IncomeCollectionService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import java.math.BigDecimal;
- import java.util.*;
- import java.util.stream.Collectors;
- import static com.imed.costaccount.common.constants.Constant.LIMIT;
- @Slf4j
- @Service("incomeCollectionService")
- public class IncomeCollectionServiceImpl
- extends ServiceImpl<IncomeCollectionMapper, IncomeCollection>
- implements IncomeCollectionService {
- private final RedisLock redisLock;
- private final CostIncomeGroupMapper incomeGroupMapper;
- private final CostIncomeGroupSetService incomeGroupSetService;
- public IncomeCollectionServiceImpl(RedisLock redisLock, CostIncomeGroupMapper incomeGroupMapper, CostIncomeGroupSetService incomeGroupSetService) {
- this.redisLock = redisLock;
- this.incomeGroupMapper = incomeGroupMapper;
- this.incomeGroupSetService = incomeGroupSetService;
- }
- /**
- * 获取收入归集分页列表
- *
- * @param current 当前页
- * @param pageSize 页码数据大小
- * @param date 日期 yyyyMM
- * @param hospId 医院id
- * @return {@link PageUtils} 分页对象
- */
- @Override
- public PageUtils getCollections(Integer current, Integer pageSize, String date, Long hospId) {
- current = current - 1;
- Integer startIndex = current * pageSize;
- List<CollectionVO> list = incomeGroupMapper.getCollections(startIndex, pageSize, date, hospId);
- int count = incomeGroupMapper.getCollectionCount(date, hospId);
- // 设置是否归集字段
- list.forEach(i -> {
- i.setIsCollection(true);
- IncomeCollection one = this.getOne(
- new LambdaQueryWrapper<IncomeCollection>().select(IncomeCollection::getId)
- .eq(IncomeCollection::getYear, i.getYear())
- .eq(IncomeCollection::getMonth, i.getMonth())
- .last(LIMIT)
- );
- if (Objects.isNull(one)) {
- i.setIsCollection(false);
- }
- });
- return new PageUtils(list, count, pageSize, current + 1);
- }
- /**
- * 按年月归集数据
- *
- * @param year 年 数字类型
- * @param month 月 数字
- * @param hospId 医院id
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
- public void collect(Integer year, Integer month, Long hospId) {
- // todo 可能几十万次数据 需要分段异步多线程处理,
- // 1个小时
- String key = "collect" + hospId;
- String timestamp = DateUtil.offsetMillisecond(DateUtil.date(), 60 * 60).getTime() + "";
- boolean lock = redisLock.lock(key, timestamp);
- try {
- if (lock) {
- List<CostIncomeGroup> costIncomeGroups = incomeGroupMapper.selectList(
- new LambdaQueryWrapper<CostIncomeGroup>()
- .eq(CostIncomeGroup::getDateYear, year)
- .eq(CostIncomeGroup::getDateMonth, month)
- .eq(CostIncomeGroup::getHospId, hospId)
- );
- if (costIncomeGroups.isEmpty()) {
- String format = StrUtil.format("{}年{}月数据不存在,请先导入数据", year, month);
- throw new CostException(format);
- }
- // 删掉已归集的数据
- this.remove(
- new LambdaQueryWrapper<IncomeCollection>().eq(IncomeCollection::getYear, year).eq(IncomeCollection::getMonth, month).eq(IncomeCollection::getHospId, hospId)
- );
- // 根据会计科目和成本项目归纳所有数据
- Map<String, List<CostIncomeGroup>> collectMap = costIncomeGroups.stream()
- .collect(Collectors.groupingBy(i -> i.getOpenDepartmentCode() + "cost" + i.getStartDepartmentCode() + "cost" + i.getProductCode()));
- // 遍历map 组装成List保存
- List<IncomeCollection> list = new LinkedList<>();
- Set<Map.Entry<String, List<CostIncomeGroup>>> entries = collectMap.entrySet();
- entries.stream().map(Map.Entry::getValue).flatMap(Collection::stream).forEach(costIncomeGroup -> {
- //TODO 统计总金额
- IncomeCollection incomeCollection = new IncomeCollection();
- incomeCollection.setYear(year);
- incomeCollection.setMonth(month);
- incomeCollection.setAccountingCode(costIncomeGroup.getAccountCode());
- incomeCollection.setAccountingName(costIncomeGroup.getAccountName());
- incomeCollection.setProductName(costIncomeGroup.getProductName());
- incomeCollection.setProductCode(costIncomeGroup.getProductCode());
- incomeCollection.setHospId(hospId);
- // todo 来源id暂时不确定
- incomeCollection.setFileId(costIncomeGroup.getFileId());
- incomeCollection.setCreateTime(System.currentTimeMillis());
- String afterIncomeGroupStr = costIncomeGroup.getAfterIncomeGroup();
- AfterIncomeGroup afterIncomegroup = JacksonUtil.str2Obj(afterIncomeGroupStr, AfterIncomeGroup.class);
- if (Objects.isNull(afterIncomegroup)) {
- throw new CostException("未能正确归集对应的....");
- }
- // 转换一下其他的
- if (afterIncomegroup.getOpenDepartmentStatus() == 1 && afterIncomegroup.getStartDepartmentStatus() == 1) {
- // 排除会计科目
- List<CostIncomeGroupSet> sets = incomeGroupSetService.list(
- new LambdaQueryWrapper<CostIncomeGroupSet>()
- .eq(CostIncomeGroupSet::getOpenDepartmentStatus, 1).eq(CostIncomeGroupSet::getStartDepartmentStatus, 1).eq(CostIncomeGroupSet::getHospId, hospId)
- );
- if (!sets.isEmpty()) {
- for (CostIncomeGroupSet set : sets) {
- String accountCode = set.getAccountCode();
- if (StrUtil.isBlank(accountCode)) {
- continue;
- }
- String[] split = accountCode.split(StrUtil.COMMA);
- boolean contains = CollUtil.newArrayList(split).contains(costIncomeGroup.getAccountCode());
- if (contains) {
- // 钱全给执行科室
- incomeCollection.setAmount(new BigDecimal("0.0000"));
- incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode());
- incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName());
- incomeCollection.setResponsibilityCode(afterIncomegroup.getOpenResponsibilityCode());
- incomeCollection.setResponsibilityName(afterIncomegroup.getOpenResponsibilityName());
- list.add(incomeCollection);
- // 执行科室数据
- IncomeCollection startCollect = BeanUtil.convertObj(incomeCollection, IncomeCollection.class);
- startCollect.setAmount(costIncomeGroup.getAmount());
- startCollect.setDepartmentCode(afterIncomegroup.getStartDepartmentCode());
- startCollect.setDepartmentName(afterIncomegroup.getStartDepartmentName());
- startCollect.setResponsibilityCode(afterIncomegroup.getStartResponsibilityCode());
- startCollect.setResponsibilityName(afterIncomegroup.getStartResponsibilityName());
- log.info("start:{}", startCollect);
- log.info("open:{}", incomeCollection);
- list.add(startCollect);
- } else {
- if (afterIncomegroup.getDirectStatus() == 2) {
- afterIncomegroup.setDirectStatus(0);
- }
- incomeCollection.setIsDirectIncome(afterIncomegroup.getDirectStatus());
- String responsibilityCode = afterIncomegroup.getResponsibilityCode();
- if (StrUtil.isNotBlank(responsibilityCode)) {
- incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName() + "|" + afterIncomegroup.getStartDepartmentName());
- incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode() + "|" + afterIncomegroup.getStartDepartmentCode());
- incomeCollection.setResponsibilityCode(responsibilityCode);
- incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
- incomeCollection.setAmount(afterIncomegroup.getOtherResponsibilityDecimal());
- list.add(incomeCollection);
- } else {
- // 开单中心的数据
- incomeCollection.setAmount(afterIncomegroup.getOpenDepartmentDecimal());
- incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode());
- incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName());
- incomeCollection.setResponsibilityCode(afterIncomegroup.getOpenResponsibilityCode());
- incomeCollection.setResponsibilityName(afterIncomegroup.getOpenResponsibilityName());
- list.add(incomeCollection);
- // 执行科室数据
- IncomeCollection startCollect = BeanUtil.convertObj(incomeCollection, IncomeCollection.class);
- startCollect.setAmount(afterIncomegroup.getStartDepartmentDecimal());
- startCollect.setDepartmentCode(afterIncomegroup.getStartDepartmentCode());
- startCollect.setDepartmentName(afterIncomegroup.getStartDepartmentName());
- startCollect.setResponsibilityCode(afterIncomegroup.getStartResponsibilityCode());
- startCollect.setResponsibilityName(afterIncomegroup.getStartResponsibilityName());
- log.info("start:{}", startCollect);
- log.info("open:{}", incomeCollection);
- list.add(startCollect);
- }
- }
- }
- }
- return;
- }
- if (afterIncomegroup.getDirectStatus() == 2) {
- afterIncomegroup.setDirectStatus(0);
- }
- incomeCollection.setIsDirectIncome(afterIncomegroup.getDirectStatus());
- String responsibilityCode = afterIncomegroup.getResponsibilityCode();
- if (StrUtil.isNotBlank(responsibilityCode)) {
- incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName() + "|" + afterIncomegroup.getStartDepartmentName());
- incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode() + "|" + afterIncomegroup.getStartDepartmentCode());
- incomeCollection.setResponsibilityCode(responsibilityCode);
- incomeCollection.setResponsibilityName(afterIncomegroup.getResponsibilityName());
- incomeCollection.setAmount(afterIncomegroup.getOtherResponsibilityDecimal());
- list.add(incomeCollection);
- } else {
- // 开单中心的数据
- incomeCollection.setAmount(afterIncomegroup.getOpenDepartmentDecimal());
- incomeCollection.setDepartmentCode(afterIncomegroup.getOpenDepartmentCode());
- incomeCollection.setDepartmentName(afterIncomegroup.getOpenDepartmentName());
- incomeCollection.setResponsibilityCode(afterIncomegroup.getOpenResponsibilityCode());
- incomeCollection.setResponsibilityName(afterIncomegroup.getOpenResponsibilityName());
- list.add(incomeCollection);
- // 执行科室数据
- IncomeCollection startCollect = BeanUtil.convertObj(incomeCollection, IncomeCollection.class);
- startCollect.setAmount(afterIncomegroup.getStartDepartmentDecimal());
- startCollect.setDepartmentCode(afterIncomegroup.getStartDepartmentCode());
- startCollect.setDepartmentName(afterIncomegroup.getStartDepartmentName());
- startCollect.setResponsibilityCode(afterIncomegroup.getStartResponsibilityCode());
- startCollect.setResponsibilityName(afterIncomegroup.getStartResponsibilityName());
- log.info("start:{}", startCollect);
- log.info("open:{}", incomeCollection);
- list.add(startCollect);
- }
- });
- // TODO: 2021/8/10 几十万条数据如何处理 待测试处理
- Map<String, List<IncomeCollection>> collect = list.stream().collect(Collectors.groupingBy(i -> i.getDepartmentCode() + "cost" + i.getResponsibilityCode() + "cost" + i.getAccountingCode() + "cost" + i.getProductCode()));
- List<IncomeCollection> realList = new LinkedList<>();
- Set<String> strings = collect.keySet();
- for (String str : strings) {
- List<IncomeCollection> incomeCollections = collect.get(str);
- if (CollUtil.isNotEmpty(incomeCollections)) {
- BigDecimal reduce = incomeCollections.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- IncomeCollection incomeCollection = incomeCollections.get(0);
- incomeCollection.setAmount(reduce);
- realList.add(incomeCollection);
- }
- }
- this.saveBatch(realList);
- } else {
- throw new CostException("已有人在操作,请稍后重试");
- }
- } finally {
- redisLock.release(key, timestamp);
- }
- }
- /**
- * 按年月撤销归集
- *
- * @param year 年 数字类型
- * @param month 月 数字
- * @param hospId 医院id
- */
- @Override
- @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
- public void cancelCollect(Integer year, Integer month, Long hospId) {
- LambdaQueryWrapper<IncomeCollection> wrapper = new LambdaQueryWrapper<IncomeCollection>()
- .eq(IncomeCollection::getYear, year)
- .eq(IncomeCollection::getMonth, month)
- .eq(IncomeCollection::getHospId, hospId);
- this.remove(wrapper);
- }
- /**
- * 归集后数据分页列表
- *
- * @param collectDTO {@link CollectDTO} 查询相关参数
- * @return {@link PageUtils}
- */
- @Override
- public PageUtils collectList(CollectDTO collectDTO) {
- // 分页数据初始化
- Integer current = collectDTO.getCurrent();
- current = (Objects.isNull(current) || current == 0) ? 0 : current - 1;
- Integer pageSize = collectDTO.getPageSize();
- pageSize = Objects.isNull(pageSize) ? 10 : pageSize;
- collectDTO.setCurrent(current * pageSize);
- collectDTO.setPageSize(pageSize);
- // 查询需要的数据 DB
- List<CollectedVO> list = baseMapper.getCollectList(collectDTO);
- int count = baseMapper.getCollectListCount(collectDTO);
- BigDecimal totalAmount = baseMapper.getTotalAmount(collectDTO);
- return new PageUtils(list, count, pageSize, current + 1, totalAmount);
- }
- /**
- * 数据报表
- *
- * @param collectDTO
- * @return
- */
- @Override
- public CollectDataFormVO collectDataForm(CollectDTO collectDTO) {
- Long hospId = collectDTO.getHospId();
- String date = collectDTO.getDate();
- // 1. 得到所有的标题栏 责任中心代码
- List<CodeAndNameVO> responsibilities = this.baseMapper.getResponsibility(hospId, collectDTO.getResponsibilityCode(), date).stream().distinct().collect(Collectors.toList());
- if (responsibilities.isEmpty()) {
- return new CollectDataFormVO();
- }
- List<String> responsibilityCodes = responsibilities.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
- responsibilities.add(0, new CodeAndNameVO("#", "#"));
- responsibilities.add(responsibilities.size(), new CodeAndNameVO("合计", "合计"));
- List<String> titleData = responsibilities.stream().map(CodeAndNameVO::getName).collect(Collectors.toList());
- Map<Integer, String> titleMap = new HashMap<>();
- for (int i = 0; i < titleData.size(); i++) {
- titleMap.put(i + 1, titleData.get(i));
- }
- // 所有的数据格式
- List<CodeAndNameVO> realData = this.baseMapper.getAccount(hospId, date);
- if (realData.isEmpty()) {
- return new CollectDataFormVO();
- }
- // realData [#,123,123,"合计"]
- List<Map<Integer, Object>> realDatas = new ArrayList<>();
- List<CodeAndNameVO> accounts = realData.stream().distinct().collect(Collectors.toList());
- for (CodeAndNameVO account : accounts) {
- Map<Integer, Object> map = new HashMap<>();
- for (int i = 0; i < responsibilities.size(); i++) {
- if (i == 0) {
- map.put(i + 1, account.getName());
- continue;
- } else if (i == responsibilities.size() - 1) {
- // TODO: 2021/8/12 合计
- BigDecimal amount = this.baseMapper.getCountAccountAndResponsibilities(hospId, date, account.getCode(), responsibilityCodes);
- map.put(i + 1, amount);
- continue;
- }
- List<IncomeCollection> list = this.list(
- new LambdaQueryWrapper<IncomeCollection>().select(IncomeCollection::getAmount)
- .eq(IncomeCollection::getHospId, hospId)
- .eq(IncomeCollection::getYear, date.substring(0, 4))
- .eq(IncomeCollection::getMonth, date.substring(4))
- .eq(IncomeCollection::getAccountingCode, account.getCode())
- .eq(IncomeCollection::getResponsibilityCode, responsibilities.get(i).getCode())
- );
- if (list.isEmpty()) {
- map.put(i + 1, new BigDecimal("0.0000"));
- } else {
- BigDecimal reduce = list.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
- map.put(i + 1, reduce);
- }
- }
- realDatas.add(map);
- }
- //
- // 合计栏计算
- // 长度一致的
- List<String> accountingCodes = realData.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
- Map<Integer, Object> map = new HashMap<>();
- for (int i = 0; i < responsibilities.size(); i++) {
- if (i == 0) {
- map.put(i + 1, "合计");
- continue;
- } else if (i == responsibilities.size() - 1) {
- // 统计问题
- BigDecimal bigDecimal = this.baseMapper.getCountByResponsibilitiesAndAccounts(responsibilityCodes, accountingCodes, hospId, date);
- map.put(i + 1, bigDecimal);
- continue;
- }
- BigDecimal bigDecimal = this.baseMapper.getCountByResponseAndAccounts(responsibilities.get(i).getCode(), accountingCodes, hospId, date);
- map.put(i + 1, bigDecimal);
- }
- return new CollectDataFormVO(titleMap, realDatas, map);
- }
- }
|