package com.kcim.service.impl; import cn.hutool.core.collection.CollUtil; 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.Constant; import com.kcim.common.constants.NumberConstant; import com.kcim.common.exception.CostException; import com.kcim.common.util.BeanUtil; import com.kcim.common.util.UserContext; import com.kcim.dao.mapper.AccountingMapper; import com.kcim.dao.model.Accounting; import com.kcim.dao.model.User; import com.kcim.dao.model.dto.AccountingEditDTO; import com.kcim.dao.model.dto.AccountingSaveDTO; import com.kcim.dao.repository.AccountingRepository; import com.kcim.service.AccountingService; import com.kcim.service.CenterService; import com.kcim.service.CostShareParamService; import com.kcim.vo.AccountVO; import com.kcim.vo.DictDataVo; import com.kcim.vo.SelectAccountingVO; import lombok.extern.slf4j.Slf4j; 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 java.util.*; import java.util.stream.Collectors; import static com.kcim.common.constants.Constant.ACCOUNTING_TYPE; @Slf4j @Service("accountingService") public class AccountingServiceImpl extends ServiceImpl implements AccountingService { private final CostShareParamService shareParamService; private final AccountingRepository accountingRepository; private final CenterService centerService; public AccountingServiceImpl(CostShareParamService shareParamService, AccountingRepository accountingRepository, CenterService centerService) { this.shareParamService = shareParamService; this.accountingRepository = accountingRepository; this.centerService = centerService; } /** * 获取会计科目列表按收入支出类型 * * @param accountType 会计科目类型1.收入,2.支出 * @param shareParamId 分摊id * @param filter * @return */ @Override public List getListByAccountType(Integer accountType, Integer shareParamId, Integer incomeGroutSetId, String filter) { // 1. 得到所有的会计科目 List allAccount = accountingRepository.getList(accountType); if (CollUtil.isEmpty(allAccount)) { return Collections.emptyList(); } // 所有的 // List all = list.stream().map(i -> BeanUtil.con(i, AccountVO.class)).collect(Collectors.toList()); List all = BeanUtil.convertList(allAccount, AccountVO.class); // 查询所有的已绑定的分摊参数 if (Objects.nonNull(shareParamId)) { List ids = shareParamService.selectIsSelect(shareParamId); if (CollUtil.isNotEmpty(ids)) { all.forEach(i -> { if (ids.contains(i.getId())) { i.setIsShareParamSelect(true); } }); } } if (!StringUtils.isEmpty(filter)) { List filterAccount = accountingRepository.getList(accountType, filter); if (CollectionUtils.isEmpty(filterAccount)) { return Collections.emptyList(); } List filterVo = BeanUtil.convertList(filterAccount, AccountVO.class); Map> collect = filterVo.stream().collect(Collectors.groupingBy(AccountVO::getParentId)); List filterParent = collect.get(NumberConstant.ZERO_L); collect.remove(NumberConstant.ZERO_L); List removeAccount = new ArrayList<>(); all.forEach(f -> { if (!CollectionUtils.isEmpty(collect.get(f.getId()))) { f.setChildren(getAccountTree(f, collect.get(f.getId()))); } else { removeAccount.add(f); } }); if (!CollectionUtils.isEmpty(removeAccount)) { all.removeAll(removeAccount); } if (!CollectionUtils.isEmpty(filterParent)) { if (CollectionUtils.isEmpty(all)) { all.addAll(filterParent); } else { //查询条件不为空 对比 最上层是否有 costItems 的父类 没有 加回去 有 不添加 Map filterMap = filterParent.stream().collect(Collectors.toMap(AccountVO::getId, item -> item, (a, b) -> b)); List filterAccountVo = all.stream().map(parent -> filterMap.get(parent.getId())).filter(Objects::nonNull).collect(Collectors.toList()); //去掉包含的 数据 filterParent.removeAll(filterAccountVo); //剩下数据加回去 if (!CollectionUtils.isEmpty(filterParent)) { all.addAll(filterParent); } } } return all; } else { return all.stream().filter(o -> o.getParentId() == 0) .peek(o -> o.setChildren(this.getAccountTree(o, all))) .collect(Collectors.toList()); } } /** * 递归处理 * * @param accountVO * @param list * @return */ private List getAccountTree(AccountVO accountVO, List list) { return list.stream().filter(o -> o.getParentId().equals(accountVO.getId())) .peek(o -> o.setChildren(this.getAccountTree(o, list))) .collect(Collectors.toList()); } /** * 保存会计科目 * * @param accountingSaveDTO */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void saveAccounting(AccountingSaveDTO accountingSaveDTO) { Long hospId = UserContext.getCurrentLoginHospId(); // 校验会计科目代码 this.checkAccountingCode(accountingSaveDTO.getAccountingCode(), hospId); // 新增逻辑 Long parentId = accountingSaveDTO.getId(); // 不是顶层的 String allParentIds = "0"; if (parentId != 0) { Accounting byId = this.getById(parentId); if (Objects.isNull(byId)) { throw new CostException(500, "上层级别会计科目已被移除"); } // 如果父子节点的会计科目类型不一致,退出 if (!byId.getAccountingType().equals(accountingSaveDTO.getAccountingType())) { throw new CostException(500, "会计科目类型要与上层一致"); } String oldParentIds = byId.getAllParentIds(); if ("0".equals(oldParentIds)) { allParentIds = parentId + ""; } else { allParentIds = oldParentIds + "-" + parentId; } } Accounting accounting = BeanUtil.convertObj(accountingSaveDTO, Accounting.class); accounting.setHospId(hospId); accounting.setParentId(parentId); accounting.setAllParentIds(allParentIds); accounting.setCreateTime(System.currentTimeMillis()); accounting.setId(null); // 如果是支出类型 if (accountingSaveDTO.getAccountingType().equals(NumberConstant.TWO)) { Integer isBaseCode = accountingSaveDTO.getIsBaseCost(); if (Objects.isNull(isBaseCode)) { throw new CostException(500, "支出类型需要选择是否固定支出成本"); } accounting.setIsBaseCost(isBaseCode); } this.save(accounting); } private void checkAccountingCode(String code, Long hospId) { List list = this.baseMapper.selectList( new QueryWrapper().lambda().select(Accounting::getId) .eq(Accounting::getAccountingCode, code) .eq(Accounting::getHospId, hospId) ); if (CollUtil.isNotEmpty(list)) { throw new CostException(500, "会计科目代码已存在,请重新生成"); } } /** * 选择会计科目列表 * * @return */ @Override public List selectAccounting() { Long hospId = UserContext.getCurrentLoginHospId(); List list = this.list( new LambdaQueryWrapper().select(Accounting::getId, Accounting::getAccountingName, Accounting::getParentId, Accounting::getAllParentIds) .eq(Accounting::getHospId, hospId) ); if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } // 所有的 List all = list.stream().map(i -> { SelectAccountingVO vo = new SelectAccountingVO(); vo.setValue(i.getId()); vo.setLabel(i.getAccountingName()); vo.setChildren(null); vo.setParentId(i.getParentId()); vo.setAllParentIds(i.getAllParentIds()); return vo; }).collect(Collectors.toList()); // 顶层的 List parents = all.stream().filter(i -> i.getParentId() == 0).collect(Collectors.toList()); List accountVOS = new ArrayList<>(); for (SelectAccountingVO parent : parents) { List accountTree = this.getSelectAccountTree(parent, all); accountVOS.addAll(accountTree); } return accountVOS; } private List getSelectAccountTree(SelectAccountingVO parent, List all) { List accountVOS = new ArrayList<>(); accountVOS.add(parent); for (SelectAccountingVO account : all) { // 如果是父子关系 if (parent.getValue().equals(account.getParentId())) { List child = parent.getChildren(); if (CollUtil.isEmpty(child)) { child = new ArrayList<>(); } child.add(account); parent.setChildren(child); // 处理子节点 this.getSelectAccountTree(account, all); } } return accountVOS; } /** * 编辑科目代码 * * @param accountingEditDTO */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void updateAccount(AccountingEditDTO accountingEditDTO) { // TODO: 2021/7/28 追踪溯源需求不满足 Long id = accountingEditDTO.getId(); Long hospId = UserContext.getCurrentLoginHospId(); // this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId()); Accounting one = this.baseMapper.selectOne( new QueryWrapper().lambda() .eq(Accounting::getAccountingCode, accountingEditDTO.getAccountingCode()) .eq(Accounting::getHospId, hospId) .last("limit 1") ); Accounting byId = this.getById(id); if (Objects.isNull(byId)) { throw new CostException(500, "当前选中会计科目已被移除"); } if (Objects.nonNull(one) && !byId.getAccountingCode().equals(one.getAccountingCode())) { throw new CostException(500, "会计科目代码已存在,请重新生成"); } // 直接修改 TODO 不修改会计科目Code byId.setAccountingCode(byId.getAccountingCode()); byId.setAccountingName(accountingEditDTO.getAccountingName()); byId.setCreateTime(System.currentTimeMillis()); byId.setControlType(accountingEditDTO.getControlType()); byId.setType(accountingEditDTO.getType()); byId.setTypeName(accountingEditDTO.getTypeName()); byId.setMedicalType(accountingEditDTO.getMedicalType()); if (accountingEditDTO.getAccountType().equals(NumberConstant.TWO)) { byId.setCostType(accountingEditDTO.getCostType()); } // byId.setAccountingType(accountingEditDTO.getAccountingType()); this.updateById(byId); // this.removeById(id); // Accounting accounting = BeanUtil.convertObj(byId, Accounting.class); // saveAccount(accountingEditDTO, user, byId, accounting); // List list = new ArrayList<>(); // this.getAndAllChild(Arrays.asList(id), user.getHospId(), list); // log.info("list:{}", list); // if (CollUtil.isEmpty(list)) { // return; // } // // 第一个子节点 // List childList = list.stream().filter(i -> i.getParentId().equals(id)).collect(Collectors.toList()); // if (CollUtil.isEmpty(childList)) { // throw new CostException(500, "数据异常"); // } // childList.forEach(i -> { // i.setParentId(accounting.getId()); // String allParentIds = setAllParentIds(byId); // i.setAllParentIds(allParentIds); // }); // this.updateBatchById(childList); // // } // private String setAllParentIds(Accounting byId) { // Integer parentId = byId.getParentId(); // // 不是顶层的 // String allParentIds = "0"; // if (parentId != 0) { // String oldParentIds = byId.getAllParentIds(); // if ("0".equals(oldParentIds)) { // allParentIds = parentId + ""; // } else { // allParentIds = oldParentIds + "-" + parentId; // } // } // return allParentIds; // } @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void saveAccount(AccountingEditDTO accountingEditDTO, User user, Accounting byId, Accounting accounting) { this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId()); accounting.setAccountingCode(accounting.getAccountingCode()); accounting.setCreateTime(System.currentTimeMillis()); // 新增逻辑 Long parentId = byId.getParentId(); // 不是顶层的 String allParentIds = "0"; if (parentId != 0) { String oldParentIds = byId.getAllParentIds(); if ("0".equals(oldParentIds)) { allParentIds = parentId + ""; } else { allParentIds = oldParentIds + "-" + parentId; } } accounting.setHospId(user.getHospId()); accounting.setParentId(parentId); accounting.setAllParentIds(allParentIds); accounting.setCreateTime(System.currentTimeMillis()); this.save(accounting); } /** * 得到自己还有所有的子节点 * * @param ids * @param accounts * @return */ private List getAndAllChild(List ids, Long hospId, List accounts) { List list = this.list( new LambdaQueryWrapper() .in(Accounting::getParentId, ids).eq(Accounting::getHospId, hospId) ); if (CollUtil.isEmpty(list)) { return accounts; } accounts.addAll(list); this.getAndAllChild(list.stream().map(Accounting::getId).collect(Collectors.toList()), hospId, accounts); return accounts; } /** * 删除 * * @param id */ @Override @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void deleteAccount(Long id) { List list = new ArrayList<>(); List andAllChild = this.getAndAllChild(Collections.singletonList(id), UserContext.getCurrentLoginHospId(), list); if (CollUtil.isEmpty(andAllChild)) { this.removeById(id); } List collect = andAllChild.stream().map(Accounting::getId).collect(Collectors.toList()); collect.add(id); this.removeByIds(collect); } /** * 通过code得到对应的会计科目对象 需要调用者自己判断空 * * @param accountCode 会计科目代码 * @return {@link Accounting} 可能为空 需要调用者自行判断 */ @Override public Accounting getByCode(String accountCode, Long hospId) { if (StrUtil.isEmpty(accountCode)) { throw new CostException("参数异常,accountCode 不能为空"); } Accounting one = this.getOne( new LambdaQueryWrapper() .eq(Accounting::getAccountingCode, accountCode) .eq(Accounting::getHospId, hospId) .last(Constant.LIMIT) ); return one; } @Override public Object getAccountTypeDict(Integer type) { DictDataVo dict = centerService.getDict(ACCOUNTING_TYPE); if(Objects.isNull(dict)){ throw new CostException("未维护会计科目类别字典"); } List dataVoList = dict.getDataVoList(); if(CollectionUtils.isEmpty(dataVoList)){ throw new CostException("未维护会计科目类别字典"); } if(type.equals(NumberConstant.ONE)){ //收入 return dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.ONE_S)).collect(Collectors.toList()); }else { //成本 return dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.TWO_S)).collect(Collectors.toList()); } } public List getAccountList(Long hospId, List accountList){ return this.list( new LambdaQueryWrapper().select(Accounting::getId,Accounting::getAccountingCode, Accounting::getAccountingName) .eq(Accounting::getHospId, hospId).in(Accounting::getAccountingCode,accountList) ); } }