AccountingServiceImpl.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. package com.kcim.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.util.StrUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7. import com.kcim.common.constants.Constant;
  8. import com.kcim.common.constants.NumberConstant;
  9. import com.kcim.common.exception.CostException;
  10. import com.kcim.common.util.BeanUtil;
  11. import com.kcim.common.util.UserContext;
  12. import com.kcim.dao.mapper.AccountingMapper;
  13. import com.kcim.dao.model.Accounting;
  14. import com.kcim.dao.model.User;
  15. import com.kcim.dao.model.dto.AccountingEditDTO;
  16. import com.kcim.dao.model.dto.AccountingSaveDTO;
  17. import com.kcim.dao.repository.AccountingRepository;
  18. import com.kcim.service.AccountingService;
  19. import com.kcim.service.CenterService;
  20. import com.kcim.service.CostShareParamService;
  21. import com.kcim.vo.AccountVO;
  22. import com.kcim.vo.DictDataVo;
  23. import com.kcim.vo.SelectAccountingVO;
  24. import lombok.extern.slf4j.Slf4j;
  25. import org.springframework.stereotype.Service;
  26. import org.springframework.transaction.annotation.Propagation;
  27. import org.springframework.transaction.annotation.Transactional;
  28. import org.springframework.util.CollectionUtils;
  29. import org.springframework.util.StringUtils;
  30. import java.util.*;
  31. import java.util.stream.Collectors;
  32. import static com.kcim.common.constants.Constant.ACCOUNTING_TYPE;
  33. @Slf4j
  34. @Service("accountingService")
  35. public class AccountingServiceImpl extends ServiceImpl<AccountingMapper, Accounting> implements AccountingService {
  36. private final CostShareParamService shareParamService;
  37. private final AccountingRepository accountingRepository;
  38. private final CenterService centerService;
  39. public AccountingServiceImpl(CostShareParamService shareParamService, AccountingRepository accountingRepository, CenterService centerService) {
  40. this.shareParamService = shareParamService;
  41. this.accountingRepository = accountingRepository;
  42. this.centerService = centerService;
  43. }
  44. /**
  45. * 获取会计科目列表按收入支出类型
  46. *
  47. * @param accountType 会计科目类型1.收入,2.支出
  48. * @param shareParamId 分摊id
  49. * @param filter
  50. * @return
  51. */
  52. @Override
  53. public List<AccountVO> getListByAccountType(Integer accountType, Integer shareParamId, Integer incomeGroutSetId, String filter) {
  54. // 1. 得到所有的会计科目
  55. List<Accounting> allAccount = accountingRepository.getList(accountType);
  56. if (CollUtil.isEmpty(allAccount)) {
  57. return Collections.emptyList();
  58. }
  59. // 所有的
  60. // List<AccountVO> all = list.stream().map(i -> BeanUtil.con(i, AccountVO.class)).collect(Collectors.toList());
  61. List<AccountVO> all = BeanUtil.convertList(allAccount, AccountVO.class);
  62. // 查询所有的已绑定的分摊参数
  63. if (Objects.nonNull(shareParamId)) {
  64. List<Long> ids = shareParamService.selectIsSelect(shareParamId);
  65. if (CollUtil.isNotEmpty(ids)) {
  66. all.forEach(i -> {
  67. if (ids.contains(i.getId())) {
  68. i.setIsShareParamSelect(true);
  69. }
  70. });
  71. }
  72. }
  73. if (!StringUtils.isEmpty(filter)) {
  74. List<Accounting> filterAccount = accountingRepository.getList(accountType, filter);
  75. if (CollectionUtils.isEmpty(filterAccount)) {
  76. return Collections.emptyList();
  77. }
  78. List<AccountVO> filterVo = BeanUtil.convertList(filterAccount, AccountVO.class);
  79. Map<Long, List<AccountVO>> collect = filterVo.stream().collect(Collectors.groupingBy(AccountVO::getParentId));
  80. List<AccountVO> filterParent = collect.get(NumberConstant.ZERO_L);
  81. collect.remove(NumberConstant.ZERO_L);
  82. List<AccountVO> removeAccount = new ArrayList<>();
  83. all.forEach(f -> {
  84. if (!CollectionUtils.isEmpty(collect.get(f.getId()))) {
  85. f.setChildren(getAccountTree(f, collect.get(f.getId())));
  86. } else {
  87. removeAccount.add(f);
  88. }
  89. });
  90. if (!CollectionUtils.isEmpty(removeAccount)) {
  91. all.removeAll(removeAccount);
  92. }
  93. if (!CollectionUtils.isEmpty(filterParent)) {
  94. if (CollectionUtils.isEmpty(all)) {
  95. all.addAll(filterParent);
  96. } else {
  97. //查询条件不为空 对比 最上层是否有 costItems 的父类 没有 加回去 有 不添加
  98. Map<Long, AccountVO> filterMap = filterParent.stream().collect(Collectors.toMap(AccountVO::getId, item -> item, (a, b) -> b));
  99. List<AccountVO> filterAccountVo = all.stream().map(parent -> filterMap.get(parent.getId())).filter(Objects::nonNull).collect(Collectors.toList());
  100. //去掉包含的 数据
  101. filterParent.removeAll(filterAccountVo);
  102. //剩下数据加回去
  103. if (!CollectionUtils.isEmpty(filterParent)) {
  104. all.addAll(filterParent);
  105. }
  106. }
  107. }
  108. return all;
  109. } else {
  110. return all.stream().filter(o -> o.getParentId() == 0)
  111. .peek(o -> o.setChildren(this.getAccountTree(o, all)))
  112. .collect(Collectors.toList());
  113. }
  114. }
  115. /**
  116. * 递归处理
  117. *
  118. * @param accountVO
  119. * @param list
  120. * @return
  121. */
  122. private List<AccountVO> getAccountTree(AccountVO accountVO, List<AccountVO> list) {
  123. return list.stream().filter(o -> o.getParentId().equals(accountVO.getId()))
  124. .peek(o -> o.setChildren(this.getAccountTree(o, list)))
  125. .collect(Collectors.toList());
  126. }
  127. /**
  128. * 保存会计科目
  129. *
  130. * @param accountingSaveDTO
  131. */
  132. @Override
  133. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  134. public void saveAccounting(AccountingSaveDTO accountingSaveDTO) {
  135. Long hospId = UserContext.getCurrentLoginHospId();
  136. // 校验会计科目代码
  137. this.checkAccountingCode(accountingSaveDTO.getAccountingCode(), hospId);
  138. // 新增逻辑
  139. Long parentId = accountingSaveDTO.getId();
  140. // 不是顶层的
  141. String allParentIds = "0";
  142. if (parentId != 0) {
  143. Accounting byId = this.getById(parentId);
  144. if (Objects.isNull(byId)) {
  145. throw new CostException(500, "上层级别会计科目已被移除");
  146. }
  147. // 如果父子节点的会计科目类型不一致,退出
  148. if (!byId.getAccountingType().equals(accountingSaveDTO.getAccountingType())) {
  149. throw new CostException(500, "会计科目类型要与上层一致");
  150. }
  151. String oldParentIds = byId.getAllParentIds();
  152. if ("0".equals(oldParentIds)) {
  153. allParentIds = parentId + "";
  154. } else {
  155. allParentIds = oldParentIds + "-" + parentId;
  156. }
  157. }
  158. Accounting accounting = BeanUtil.convertObj(accountingSaveDTO, Accounting.class);
  159. accounting.setHospId(hospId);
  160. accounting.setParentId(parentId);
  161. accounting.setAllParentIds(allParentIds);
  162. accounting.setCreateTime(System.currentTimeMillis());
  163. accounting.setId(null);
  164. // 如果是支出类型
  165. if (accountingSaveDTO.getAccountingType().equals(NumberConstant.TWO)) {
  166. Integer isBaseCode = accountingSaveDTO.getIsBaseCost();
  167. if (Objects.isNull(isBaseCode)) {
  168. throw new CostException(500, "支出类型需要选择是否固定支出成本");
  169. }
  170. accounting.setIsBaseCost(isBaseCode);
  171. }
  172. this.save(accounting);
  173. }
  174. private void checkAccountingCode(String code, Long hospId) {
  175. List<Accounting> list = this.baseMapper.selectList(
  176. new QueryWrapper<Accounting>().lambda().select(Accounting::getId)
  177. .eq(Accounting::getAccountingCode, code)
  178. .eq(Accounting::getHospId, hospId)
  179. );
  180. if (CollUtil.isNotEmpty(list)) {
  181. throw new CostException(500, "会计科目代码已存在,请重新生成");
  182. }
  183. }
  184. /**
  185. * 选择会计科目列表
  186. *
  187. * @return
  188. */
  189. @Override
  190. public List<SelectAccountingVO> selectAccounting() {
  191. Long hospId = UserContext.getCurrentLoginHospId();
  192. List<Accounting> list = this.list(
  193. new LambdaQueryWrapper<Accounting>().select(Accounting::getId, Accounting::getAccountingName, Accounting::getParentId, Accounting::getAllParentIds)
  194. .eq(Accounting::getHospId, hospId)
  195. );
  196. if (CollUtil.isEmpty(list)) {
  197. return Collections.emptyList();
  198. }
  199. // 所有的
  200. List<SelectAccountingVO> all = list.stream().map(i -> {
  201. SelectAccountingVO vo = new SelectAccountingVO();
  202. vo.setValue(i.getId());
  203. vo.setLabel(i.getAccountingName());
  204. vo.setChildren(null);
  205. vo.setParentId(i.getParentId());
  206. vo.setAllParentIds(i.getAllParentIds());
  207. return vo;
  208. }).collect(Collectors.toList());
  209. // 顶层的
  210. List<SelectAccountingVO> parents = all.stream().filter(i -> i.getParentId() == 0).collect(Collectors.toList());
  211. List<SelectAccountingVO> accountVOS = new ArrayList<>();
  212. for (SelectAccountingVO parent : parents) {
  213. List<SelectAccountingVO> accountTree = this.getSelectAccountTree(parent, all);
  214. accountVOS.addAll(accountTree);
  215. }
  216. return accountVOS;
  217. }
  218. private List<SelectAccountingVO> getSelectAccountTree(SelectAccountingVO parent, List<SelectAccountingVO> all) {
  219. List<SelectAccountingVO> accountVOS = new ArrayList<>();
  220. accountVOS.add(parent);
  221. for (SelectAccountingVO account : all) {
  222. // 如果是父子关系
  223. if (parent.getValue().equals(account.getParentId())) {
  224. List<SelectAccountingVO> child = parent.getChildren();
  225. if (CollUtil.isEmpty(child)) {
  226. child = new ArrayList<>();
  227. }
  228. child.add(account);
  229. parent.setChildren(child);
  230. // 处理子节点
  231. this.getSelectAccountTree(account, all);
  232. }
  233. }
  234. return accountVOS;
  235. }
  236. /**
  237. * 编辑科目代码
  238. *
  239. * @param accountingEditDTO
  240. */
  241. @Override
  242. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  243. public void updateAccount(AccountingEditDTO accountingEditDTO) {
  244. // TODO: 2021/7/28 追踪溯源需求不满足
  245. Long id = accountingEditDTO.getId();
  246. Long hospId = UserContext.getCurrentLoginHospId();
  247. // this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId());
  248. Accounting one = this.baseMapper.selectOne(
  249. new QueryWrapper<Accounting>().lambda()
  250. .eq(Accounting::getAccountingCode, accountingEditDTO.getAccountingCode())
  251. .eq(Accounting::getHospId, hospId)
  252. .last("limit 1")
  253. );
  254. Accounting byId = this.getById(id);
  255. if (Objects.isNull(byId)) {
  256. throw new CostException(500, "当前选中会计科目已被移除");
  257. }
  258. if (Objects.nonNull(one) && !byId.getAccountingCode().equals(one.getAccountingCode())) {
  259. throw new CostException(500, "会计科目代码已存在,请重新生成");
  260. }
  261. // 直接修改 TODO 不修改会计科目Code
  262. byId.setAccountingCode(byId.getAccountingCode());
  263. byId.setAccountingName(accountingEditDTO.getAccountingName());
  264. byId.setCreateTime(System.currentTimeMillis());
  265. byId.setControlType(accountingEditDTO.getControlType());
  266. byId.setType(accountingEditDTO.getType());
  267. byId.setTypeName(accountingEditDTO.getTypeName());
  268. byId.setMedicalType(accountingEditDTO.getMedicalType());
  269. if (accountingEditDTO.getAccountType().equals(NumberConstant.TWO)) {
  270. byId.setCostType(accountingEditDTO.getCostType());
  271. }
  272. // byId.setAccountingType(accountingEditDTO.getAccountingType());
  273. this.updateById(byId);
  274. // this.removeById(id);
  275. // Accounting accounting = BeanUtil.convertObj(byId, Accounting.class);
  276. // saveAccount(accountingEditDTO, user, byId, accounting);
  277. // List<Accounting> list = new ArrayList<>();
  278. // this.getAndAllChild(Arrays.asList(id), user.getHospId(), list);
  279. // log.info("list:{}", list);
  280. // if (CollUtil.isEmpty(list)) {
  281. // return;
  282. // }
  283. // // 第一个子节点
  284. // List<Accounting> childList = list.stream().filter(i -> i.getParentId().equals(id)).collect(Collectors.toList());
  285. // if (CollUtil.isEmpty(childList)) {
  286. // throw new CostException(500, "数据异常");
  287. // }
  288. // childList.forEach(i -> {
  289. // i.setParentId(accounting.getId());
  290. // String allParentIds = setAllParentIds(byId);
  291. // i.setAllParentIds(allParentIds);
  292. // });
  293. // this.updateBatchById(childList);
  294. //
  295. //
  296. }
  297. // private String setAllParentIds(Accounting byId) {
  298. // Integer parentId = byId.getParentId();
  299. // // 不是顶层的
  300. // String allParentIds = "0";
  301. // if (parentId != 0) {
  302. // String oldParentIds = byId.getAllParentIds();
  303. // if ("0".equals(oldParentIds)) {
  304. // allParentIds = parentId + "";
  305. // } else {
  306. // allParentIds = oldParentIds + "-" + parentId;
  307. // }
  308. // }
  309. // return allParentIds;
  310. // }
  311. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  312. public void saveAccount(AccountingEditDTO accountingEditDTO, User user, Accounting byId, Accounting accounting) {
  313. this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId());
  314. accounting.setAccountingCode(accounting.getAccountingCode());
  315. accounting.setCreateTime(System.currentTimeMillis());
  316. // 新增逻辑
  317. Long parentId = byId.getParentId();
  318. // 不是顶层的
  319. String allParentIds = "0";
  320. if (parentId != 0) {
  321. String oldParentIds = byId.getAllParentIds();
  322. if ("0".equals(oldParentIds)) {
  323. allParentIds = parentId + "";
  324. } else {
  325. allParentIds = oldParentIds + "-" + parentId;
  326. }
  327. }
  328. accounting.setHospId(user.getHospId());
  329. accounting.setParentId(parentId);
  330. accounting.setAllParentIds(allParentIds);
  331. accounting.setCreateTime(System.currentTimeMillis());
  332. this.save(accounting);
  333. }
  334. /**
  335. * 得到自己还有所有的子节点
  336. *
  337. * @param ids
  338. * @param accounts
  339. * @return
  340. */
  341. private List<Accounting> getAndAllChild(List<Long> ids, Long hospId, List<Accounting> accounts) {
  342. List<Accounting> list = this.list(
  343. new LambdaQueryWrapper<Accounting>()
  344. .in(Accounting::getParentId, ids).eq(Accounting::getHospId, hospId)
  345. );
  346. if (CollUtil.isEmpty(list)) {
  347. return accounts;
  348. }
  349. accounts.addAll(list);
  350. this.getAndAllChild(list.stream().map(Accounting::getId).collect(Collectors.toList()), hospId, accounts);
  351. return accounts;
  352. }
  353. /**
  354. * 删除
  355. *
  356. * @param id
  357. */
  358. @Override
  359. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  360. public void deleteAccount(Long id) {
  361. List<Accounting> list = new ArrayList<>();
  362. List<Accounting> andAllChild = this.getAndAllChild(Collections.singletonList(id), UserContext.getCurrentLoginHospId(), list);
  363. if (CollUtil.isEmpty(andAllChild)) {
  364. this.removeById(id);
  365. }
  366. List<Long> collect = andAllChild.stream().map(Accounting::getId).collect(Collectors.toList());
  367. collect.add(id);
  368. this.removeByIds(collect);
  369. }
  370. /**
  371. * 通过code得到对应的会计科目对象 需要调用者自己判断空
  372. *
  373. * @param accountCode 会计科目代码
  374. * @return {@link Accounting} 可能为空 需要调用者自行判断
  375. */
  376. @Override
  377. public Accounting getByCode(String accountCode, Long hospId) {
  378. if (StrUtil.isEmpty(accountCode)) {
  379. throw new CostException("参数异常,accountCode 不能为空");
  380. }
  381. Accounting one = this.getOne(
  382. new LambdaQueryWrapper<Accounting>()
  383. .eq(Accounting::getAccountingCode, accountCode)
  384. .eq(Accounting::getHospId, hospId)
  385. .last(Constant.LIMIT)
  386. );
  387. return one;
  388. }
  389. @Override
  390. public Object getAccountTypeDict(Integer type) {
  391. DictDataVo dict = centerService.getDict(ACCOUNTING_TYPE);
  392. if(Objects.isNull(dict)){
  393. throw new CostException("未维护会计科目类别字典");
  394. }
  395. List<DictDataVo> dataVoList = dict.getDataVoList();
  396. if(CollectionUtils.isEmpty(dataVoList)){
  397. throw new CostException("未维护会计科目类别字典");
  398. }
  399. if(type.equals(NumberConstant.ONE)){
  400. //收入
  401. return dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.ONE_S)).collect(Collectors.toList());
  402. }else {
  403. //成本
  404. return dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.TWO_S)).collect(Collectors.toList());
  405. }
  406. }
  407. public List<Accounting> getAccountList(Long hospId, List<String> accountList){
  408. return this.list(
  409. new LambdaQueryWrapper<Accounting>().select(Accounting::getId,Accounting::getAccountingCode, Accounting::getAccountingName)
  410. .eq(Accounting::getHospId, hospId).in(Accounting::getAccountingCode,accountList)
  411. );
  412. }
  413. }