package com.kcim.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; 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.service.impl.ServiceImpl; import com.kcim.common.constants.NumberConstant; import com.kcim.common.exception.CostException; import com.kcim.common.enums.DateStyleEnum; import com.kcim.dao.mapper.ShareParamValueMapper; import com.kcim.dao.model.*; import com.kcim.dao.model.dto.CopyShareParamValueDTO; import com.kcim.dao.model.dto.ShareParamValueEditDTO; import com.kcim.dao.model.dto.ShareParamValueSaveDTO; import com.kcim.dao.model.dto.ShareParamValueVO; import com.kcim.vo.IncomeErrorMessage; import com.kcim.common.constants.Constant; import com.kcim.common.util.*; import com.kcim.service.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; 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.web.multipart.MultipartFile; import java.math.BigDecimal; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static cn.hutool.core.date.DatePattern.PURE_DATE_PATTERN; @Slf4j @Service("shareParamValueService") public class ShareParamValueServiceImpl extends ServiceImpl implements ShareParamValueService { private final CostIncomeGroupServiceImpl costIncomeGroupService; private final CostShareParamService costShareParamService; private final CostIncomeFileService costIncomeFileService; private final ResponsibilityService responsibilityService; private final IncomeCollectionService incomeCollectionService; public ShareParamValueServiceImpl(CostIncomeGroupServiceImpl costIncomeGroupService, CostShareParamService costShareParamService, CostIncomeFileService costIncomeFileService, ResponsibilityService responsibilityService, IncomeCollectionService incomeCollectionService) { this.costIncomeGroupService = costIncomeGroupService; this.costShareParamService = costShareParamService; this.costIncomeFileService = costIncomeFileService; this.responsibilityService = responsibilityService; this.incomeCollectionService = incomeCollectionService; } /** * 添加分摊参数值 * * @param shareParamValueSaveDTO {@link ShareParamValueSaveDTO} * @param hospId 医院id */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void addData(ShareParamValueSaveDTO shareParamValueSaveDTO, Long hospId) { ShareParamValue paramValue = BeanUtil.convertObj(shareParamValueSaveDTO, ShareParamValue.class); DateTime dateTime = DateUtil.parse(shareParamValueSaveDTO.getDate(), PURE_DATE_PATTERN); // 校验是否唯一 Boolean flag = checkUniq(shareParamValueSaveDTO.getShareParamCode(), shareParamValueSaveDTO.getResponsibilityCode(), hospId, dateTime); if (flag) { throw new CostException("本月已存在对应责任中心和分摊参数中心,请直接修改"); } // 校验两个code是否存在 checkCodeIsExist(shareParamValueSaveDTO.getShareParamCode(), shareParamValueSaveDTO.getResponsibilityCode(), hospId); paramValue.setCreateTime(System.currentTimeMillis()) .setDateYear(DateUtil.year(dateTime)) .setDateMonth(DateUtil.month(dateTime) + 1) .setHospId(hospId) .setDataSourceType(0); this.save(paramValue); } /** * 校验两个code是否存在 * * @param shareParamCode 成本分摊参数code * @param responsibilityCode 责任中心代码 * @param hospId 医院id */ @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED) public void checkCodeIsExist(String shareParamCode, String responsibilityCode, Long hospId) { List shareParams = costShareParamService.list(new LambdaQueryWrapper().select(CostShareParam::getId) .eq(CostShareParam::getShareParamCode, shareParamCode).eq(CostShareParam::getHospId, hospId)); if (shareParams.isEmpty()) { throw new CostException("分摊参数code非法"); } List responsibilities = responsibilityService.list( new LambdaQueryWrapper().select(Responsibility::getId) .eq(Responsibility::getResponsibilityCode, responsibilityCode).eq(Responsibility::getHospId, hospId) ); if (responsibilities.isEmpty()) { throw new CostException("责任中心code非法"); } } /** * 校验是否已存在 * * @param shareParamCode 分摊参数代码 * @param responsibilityCode 责任中心代码 * @param hospId 医院id * @param date 时间 */ private Boolean checkUniq(String shareParamCode, String responsibilityCode, Long hospId, DateTime date) { List list = this.list( new LambdaQueryWrapper() .eq(ShareParamValue::getHospId, hospId) .eq(ShareParamValue::getShareParamCode, shareParamCode) .eq(ShareParamValue::getResponsibilityCode, responsibilityCode) .eq(ShareParamValue::getDateYear, DateUtil.year(date)) .eq(ShareParamValue::getDateMonth, DateUtil.month(date) + 1) ); return !list.isEmpty(); } /** * 分摊参数值列表 * * @param current 当前页 * @param pageSize 每页数据量大小 * @param date 日期 * @param shareParamCode 分摊参数代码 * @param responsibilityCode 责任中心代码 * @param hospId 医院id * @return {@link PageUtils} 分页对象 */ @Override public PageUtils selectList(Integer current, Integer pageSize, String date, String shareParamCode, String responsibilityCode, Long hospId) { Integer startIndex = (current - 1) * pageSize; if (startIndex < 0) { startIndex = 0; } List list = baseMapper.getValues(startIndex, pageSize, date, shareParamCode, responsibilityCode, hospId); int count = baseMapper.getValuesCount(startIndex, pageSize, date, shareParamCode, responsibilityCode, hospId); return new PageUtils(list, count, pageSize, current); } /** * 复制数据从某年月到某年月 * * @param copyShareParamValueDTO {@link CopyShareParamValueDTO} * @param hospId 医院id */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void copyData(CopyShareParamValueDTO copyShareParamValueDTO, Long hospId) { // TODO 复制数据 多个医院同时使用的情况下启用线程池处理 String fromDate = copyShareParamValueDTO.getFromDate(); String toDate = copyShareParamValueDTO.getToDate(); Integer dataSourceType = copyShareParamValueDTO.getDataSourceType(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .eq(ShareParamValue::getDateYear, DateUtil.year(DateUtil.parse(fromDate, PURE_DATE_PATTERN))) .eq(ShareParamValue::getDateMonth, DateUtil.month(DateUtil.parse(fromDate, PURE_DATE_PATTERN)) + 1); if (dataSourceType == 0) { wrapper.eq(ShareParamValue::getDataSourceType, 0); } else if (dataSourceType == 1) { wrapper.eq(ShareParamValue::getDataSourceType, 1); } else { wrapper.in(ShareParamValue::getDataSourceType, CollUtil.newArrayList(0, 1)); } // 拿到复制的数据 List list = this.list(wrapper); if (list.isEmpty()) { throw new CostException("复制日期" + fromDate + "数据不存在"); } DateTime toDateTime = DateUtil.parse(toDate, PURE_DATE_PATTERN); int year = DateUtil.year(toDateTime); int month = DateUtil.month(toDateTime) + 1; // 删除之前的数据 wrapper.clear(); this.remove( wrapper.eq(ShareParamValue::getDateYear, year) .eq(ShareParamValue::getDateMonth, month) .eq(ShareParamValue::getHospId, hospId) ); list.forEach(i -> { i.setId(null); i.setCreateTime(System.currentTimeMillis()); i.setHospId(hospId); i.setDateYear(year); i.setDateMonth(month); }); this.saveBatch(list); } /** * 编辑某条数据 * * @param shareParamValueEditDTO {@link ShareParamValueEditDTO} * @param hospId 医院id */ @Override @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED) public void editParamValue(ShareParamValueEditDTO shareParamValueEditDTO, Long hospId) { Long id = shareParamValueEditDTO.getId(); this.removeById(id); DateTime dateTime = DateUtil.parse(shareParamValueEditDTO.getDate(), PURE_DATE_PATTERN); Boolean flag = checkUniq(shareParamValueEditDTO.getShareParamCode(), shareParamValueEditDTO.getResponsibilityCode(), hospId, dateTime); if (flag) { throw new CostException("本月已存在对应责任中心和分摊参数中心,请直接修改"); } checkCodeIsExist(shareParamValueEditDTO.getShareParamCode(), shareParamValueEditDTO.getResponsibilityCode(), hospId); ShareParamValue shareParamValue = BeanUtil.convertObj(shareParamValueEditDTO, ShareParamValue.class); shareParamValue .setId(null) .setCreateTime(System.currentTimeMillis()) .setDateYear(DateUtil.year(DateUtil.parse(shareParamValueEditDTO.getDate(), PURE_DATE_PATTERN))) .setDateMonth(DateUtil.month(DateUtil.parse(shareParamValueEditDTO.getDate(), PURE_DATE_PATTERN)) + 1) .setHospId(hospId) .setDataSourceType(0); this.save(shareParamValue); } /** * 成本分摊参数导入 * * @param list * @param file * @param dateTime * @param fileType * @return */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public Result importShareParamGroup(List> list, MultipartFile file, String dateTime, Integer fileType) { // 先检验当前年月是否存在数据 int year = 0; int month = 0; Date date = DateUtils.StringToDate(dateTime, DateStyleEnum.YYYY_MM); if (StrUtil.isNotBlank(dateTime)) { year = DateUtil.year(date); month = DateUtil.month(date) + 1; } Long hospId = UserContext.getHospId(); // List groups = this.list(new QueryWrapper().lambda().eq(ShareParamValue::getHospId, hospId) // .eq(ShareParamValue::getDateYear, year).eq(ShareParamValue::getDateMonth, month)); // if (!CollectionUtils.isEmpty(groups)) { // throw new CostException(500, year + "年" + month + "月数据已存在"); // } list.remove(list.get(0)); Map departmentMap = costIncomeGroupService.getDepartmentByCodeNameMap(hospId); Map responsibilityMap = costIncomeGroupService.getResponsibilityIdResponsibilityMap(hospId); List responsibilityDepartmentList = costIncomeGroupService.getResponsibilityDepartments(hospId); if (CollectionUtils.isEmpty(responsibilityDepartmentList)) { throw new CostException(500, "没有科室责任中心对照数据"); } Map responsibilityDepMap = costIncomeGroupService.getDepartmentIdResponsibilityIdMap(responsibilityDepartmentList); Map shareParamMap = costShareParamService.list(new QueryWrapper().lambda().eq(CostShareParam::getHospId, hospId)).stream().collect(Collectors.toMap(k -> k.getShareParamCode() + k.getShareParamName(), synOe -> synOe)); // 要保存的数据 List shareParamValues = new LinkedList<>(); // List costShareParamGroupList = new LinkedList<>(); List departmentCodes = list.get(0); List departmentNames = list.get(1); List incomeErrorMessageList = new ArrayList<>(); //检验数据是否准确 list包含了科室Code行与Name行 所以要从list的第三行开始 checkShareParamGroupData(list, year, month, incomeErrorMessageList, departmentMap, responsibilityMap, responsibilityDepMap, shareParamMap, shareParamValues, departmentCodes, departmentNames); // 文件上传 String uploadFile = costIncomeGroupService.uploadFile(file); // 上传记录保存 if (StrUtil.isBlank(uploadFile)) { throw new CostException(500, "文件上传异常"); } // 记录文件上传记录 CostIncomeFile costIncomeFile = costIncomeFileService.saveCostIncomeFile(list, file, hospId, incomeErrorMessageList, uploadFile, fileType, year, month); Long id = costIncomeFile.getId(); shareParamValues.forEach(i -> { // 设置文件Id i.setFileId(id); i.setDataSourceType(1); }); if (!CollectionUtils.isEmpty(incomeErrorMessageList)) { return Result.build(200, "数据未成功导入", null); } // 保存数据的唯一性 Map> map = shareParamValues.stream().collect(Collectors.groupingBy(k -> k.getShareParamCode().trim() + "code" + k.getResponsibilityCode().trim() + k.getDateYear().toString().trim() + "code" + k.getDateMonth().toString().trim() )); LinkedList realList = new LinkedList<>(); // Set strings = map.keySet(); map.forEach((k, v) -> { if (CollUtil.isNotEmpty(v)) { BigDecimal reduce = v.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add); ShareParamValue shareParamValue = v.get(0); shareParamValue.setValueNum(reduce); realList.add(shareParamValue); } }); // for (String str : strings) { // List shareParamValuesList = map.get(str); // if (CollUtil.isNotEmpty(shareParamValuesList)) { // BigDecimal reduce = shareParamValuesList.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add); // ShareParamValue shareParamValue = shareParamValuesList.get(0); // shareParamValue.setValueNum(reduce); // realList.add(shareParamValue); // } // } this.saveBatch(realList); return Result.build(200, "数据导入成功", null); // if (CollectionUtils.isEmpty(incomeErrorMessageList)) { // } else { // return Result.build(200, "数据未成功导入", null); // } } private void checkShareParamGroupData(List> list, int year, int month, List incomeErrorMessageList, Map departmentMap, Map responsibilityMap, Map responsibilityDepMap, Map shareParamMap, List shareParamValues, List departmentCodes, List departmentNames) { // Pattern pattern = Pattern.compile("^\\d+(\\.\\d+)?$"); for (int i = 2; i < list.size(); i++) { int row = i + 1; List data = list.get(i); // 检验成本分摊参数是否正确 ShareParamValue shareParamValueRequest = new ShareParamValue(); String shareParamCode = data.get(0).toString().trim(); String shareParamName = data.get(1).toString().trim(); CostShareParam costShareParam = shareParamMap.get(shareParamCode + shareParamName); if (Objects.nonNull(costShareParam)) { shareParamValueRequest.setShareParamCode(shareParamCode); } else { IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage(); incomeErrorMessage.setTotal(i); incomeErrorMessage.setErrMessage("成本分摊代码:" + shareParamCode + " 名称" + shareParamName + "不存在"); if (incomeErrorMessageList != null) { incomeErrorMessageList.add(incomeErrorMessage); } } for (int j = 2; j < departmentCodes.size(); j++) { int column = j + 1; if (data.size() > j) { if (Objects.isNull(data.get(j))) { data.set(j, NumberConstant.ZERO); // } else if (data.get(j).toString().contains("-") ) {//!StringUtils.isNumeric(data.get(j).toString()) || !pattern.matcher(data.get(j).toString()).matches() // IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage(); // incomeErrorMessage.setTotal(row); // incomeErrorMessage.setErrMessage("第" + row + "行 第" + column + "列数据不符合规范"); // incomeErrorMessageList.add(incomeErrorMessage); } else { data.set(j, Double.parseDouble(data.get(j).toString())); } } else { data.add(NumberConstant.ZERO); } } if (CollectionUtils.isEmpty(incomeErrorMessageList)) { // 检验数据是否全为0 int zeroStatus = 0; for (int j = 2; j < data.size(); j++) { if (!NumberConstant.ZERO.equals(data.get(j))) { zeroStatus = 1; break; } } if (NumberConstant.ONE.equals(zeroStatus)) { for (int j = 2; j < data.size(); j++) { ShareParamValue shareParamValue = BeanUtil.convertObj(shareParamValueRequest, ShareParamValue.class); // 检验科室信息是否准确 String departmentCode = departmentCodes.get(j).toString(); String departmentName = departmentNames.get(j).toString(); Department department = departmentMap.get(departmentCode + departmentName); if (Objects.nonNull(department)) { // 检测责任中心是否存在 Long id = department.getId(); Long responsibilityId = responsibilityDepMap.get(id); if (Objects.nonNull(responsibilityId)) { Responsibility responsibility = responsibilityMap.get(responsibilityId); if (Objects.nonNull(responsibility)) { shareParamValue.setResponsibilityCode(responsibility.getResponsibilityCode()); } else { IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage(); incomeErrorMessage.setTotal(j); incomeErrorMessage.setErrMessage("第" + j + "列科室信息对应的责任中心不存在"); if (incomeErrorMessageList != null) { incomeErrorMessageList.add(incomeErrorMessage); } } } else { IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage(); incomeErrorMessage.setTotal(j); incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在对应的责任中心"); if (incomeErrorMessageList != null) { incomeErrorMessageList.add(incomeErrorMessage); } } } else { IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage(); incomeErrorMessage.setTotal(j); incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在"); if (incomeErrorMessageList != null) { incomeErrorMessageList.add(incomeErrorMessage); } } shareParamValue.setValueNum(BigDecimal.valueOf(Double.parseDouble(("0".equals(data.get(j).toString()) || StrUtil.isBlank(data.get(j).toString())) ? "0.00" : data.get(j).toString()))); shareParamValue.setHospId(UserContext.getHospId()); shareParamValue.setCreateTime(System.currentTimeMillis()); shareParamValue.setDateYear(year); shareParamValue.setDateMonth(month); shareParamValues.add(shareParamValue); } } } } } /** * 计算数值 * * @param date 日期 yyyyMM * @param hospId 医院id */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class) public void calcData(String date, Long hospId) { DateTime parse = DateUtil.parse(date, PURE_DATE_PATTERN); int year = DateUtil.year(parse); int month = DateUtil.month(parse) + 1; // 拿到这些年月的数据 List list = this.list( new LambdaQueryWrapper() .eq(ShareParamValue::getDateYear, year).eq(ShareParamValue::getDateMonth, month).eq(ShareParamValue::getHospId, hospId) ); if (list.isEmpty()) { throw new CostException(500, parse + "数据未录入"); } // 得到这些会计科目代码 List accountCodes = new ArrayList<>(); list.forEach(i -> { String shareParamCode = i.getShareParamCode(); CostShareParam one = costShareParamService.getOne( new LambdaQueryWrapper() .eq(CostShareParam::getHospId, hospId) .eq(CostShareParam::getShareParamCode, shareParamCode) .last(Constant.LIMIT) ); if (Objects.isNull(one)) { return; } String accountingCodes = one.getAccountingCodes(); if (StrUtil.isBlank(accountingCodes)) { return; } String[] split = StringUtils.split(accountingCodes, StrUtil.COMMA); ArrayList accountCodeList = CollUtil.newArrayList(split); accountCodes.addAll(accountCodeList); List calcList = new ArrayList<>(); accountCodeList.forEach(j -> { calcList.add(i.getResponsibilityCode() + "cost" + j); }); i.setCalcList(calcList); }); log.info("list={}", accountCodes); List incomeCollections = incomeCollectionService.list( new LambdaQueryWrapper() .eq(IncomeCollection::getYear, year) .eq(IncomeCollection::getMonth, month) .eq(IncomeCollection::getHospId, hospId) .in(IncomeCollection::getAccountingCode, accountCodes.stream().distinct().collect(Collectors.toList())) ); if (incomeCollections.isEmpty()) { List collections = incomeCollectionService.list( new LambdaQueryWrapper() .eq(IncomeCollection::getYear, year) .eq(IncomeCollection::getMonth, month) .eq(IncomeCollection::getHospId, hospId)); if (collections.isEmpty()) { throw new CostException("本月未归集数据,请先归集数据"); } return ; } Map> collectMap = incomeCollections.stream() .collect(Collectors.groupingBy(i -> i.getResponsibilityCode() + "cost" + i.getAccountingCode())); // Set strings = collectMap.keySet(); Map map = new ConcurrentHashMap<>(); collectMap.forEach((k,v)->{ if (CollUtil.isNotEmpty(v)) { // BigDecimal reduce = v.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); map.put(k, v.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add)); } }); // strings.forEach(str -> { // List collections = collectMap.get(str); // if (CollUtil.isNotEmpty(collections)) { // BigDecimal reduce = collections.stream().map(IncomeCollection::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); // map.put(str, reduce); // } // }); list.forEach(i -> { map.forEach((k,v)->{ if (CollUtil.isNotEmpty(i.getCalcList()) && i.getCalcList().contains(k)) { i.setValueNum(v); } }); }); this.updateBatchById(list); } /** * 得到这个月导入的成本分摊参数值列表 聚合过 * * @param year 年 * @param month 月 * @param hospId 医院id * @return 某月成本分摊参数值 */ @Override public List getListByYearAndMonth(Integer year, Integer month, Long hospId) { return baseMapper.getListByYearAndMonth(year, month, hospId); } /** * 成本分摊参数值批量删除 * * @param asList id集合 */ @Override @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class) public void deleteByIds(List asList) { this.removeByIds(asList); } @Override public void removeShareParam(String computeDate) { int year = 0; int month = 0; Date date = DateUtils.StringToDate(computeDate, DateStyleEnum.YYYY_MM); if (StrUtil.isNotBlank(computeDate)) { year = DateUtil.year(date); month = DateUtil.month(date) + 1; } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ShareParamValue::getHospId,UserContext.getHospId()); queryWrapper.eq(ShareParamValue::getDateYear,year); queryWrapper.eq(ShareParamValue::getDateMonth,month); List list = this.list(queryWrapper); if(!CollectionUtils.isEmpty(list)){ List collect = list.stream().map(ShareParamValue::getId).collect(Collectors.toList()); this.removeByIds(collect); } } }