AccountingServiceImpl.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. package com.imed.costaccount.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.imed.costaccount.common.exception.CostException;
  8. import com.imed.costaccount.mapper.AccountingMapper;
  9. import com.imed.costaccount.model.Accounting;
  10. import com.imed.costaccount.model.User;
  11. import com.imed.costaccount.model.dto.AccountingEditDTO;
  12. import com.imed.costaccount.model.dto.AccountingSaveDTO;
  13. import com.imed.costaccount.model.vo.AccountVO;
  14. import com.imed.costaccount.model.vo.SelectAccountingVO;
  15. import com.imed.costaccount.service.AccountingService;
  16. import com.imed.costaccount.service.CostShareParamService;
  17. import com.imed.costaccount.common.util.BeanUtil;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.springframework.stereotype.Service;
  20. import org.springframework.transaction.annotation.Propagation;
  21. import org.springframework.transaction.annotation.Transactional;
  22. import java.util.*;
  23. import java.util.stream.Collectors;
  24. import static com.imed.costaccount.common.constants.Constant.LIMIT;
  25. @Slf4j
  26. @Service("accountingService")
  27. public class AccountingServiceImpl extends ServiceImpl<AccountingMapper, Accounting> implements AccountingService {
  28. private final CostShareParamService shareParamService;
  29. public AccountingServiceImpl(CostShareParamService shareParamService) {
  30. this.shareParamService = shareParamService;
  31. }
  32. /**
  33. * 获取会计科目列表按收入支出类型
  34. *
  35. * @param accountType 会计科目类型1.收入,2.支出
  36. * @param user 当前用户
  37. * @param shareParamId 分摊id
  38. * @return
  39. */
  40. @Override
  41. public List<AccountVO> getListByAccountType(Integer accountType, User user, Integer shareParamId, Integer incomeGroutSetId) {
  42. // 1. 得到所有的会计科目
  43. List<Accounting> list = this.list(
  44. new LambdaQueryWrapper<Accounting>()
  45. .eq(Accounting::getHospId, user.getHospId())
  46. .eq(Accounting::getAccountingType, accountType)
  47. .orderByDesc(Accounting::getCreateTime)
  48. );
  49. if (CollUtil.isEmpty(list)) {
  50. return Collections.emptyList();
  51. }
  52. // 所有的
  53. // List<AccountVO> all = list.stream().map(i -> BeanUtil.con(i, AccountVO.class)).collect(Collectors.toList());
  54. List<AccountVO> all = BeanUtil.convertList(list, AccountVO.class);
  55. // 查询所有的已绑定的分摊参数
  56. if (Objects.nonNull(shareParamId)) {
  57. List<Long> ids = shareParamService.selectIsSelect(shareParamId);
  58. if (CollUtil.isNotEmpty(ids)) {
  59. all.forEach(i -> {
  60. if (ids.contains(i.getId())) {
  61. i.setIsShareParamSelect(true);
  62. }
  63. });
  64. }
  65. }
  66. return all.stream().filter(o -> o.getParentId() == 0)
  67. .peek(o -> o.setChildren(this.getAccountTree(o, all)))
  68. .collect(Collectors.toList());
  69. }
  70. /**
  71. * 递归处理
  72. *
  73. * @param accountVO
  74. * @param list
  75. * @return
  76. */
  77. private List<AccountVO> getAccountTree(AccountVO accountVO, List<AccountVO> list) {
  78. return list.stream().filter(o -> o.getParentId().equals(accountVO.getId()))
  79. .peek(o -> o.setChildren(this.getAccountTree(o, list)))
  80. .collect(Collectors.toList());
  81. }
  82. /**
  83. * 保存会计科目
  84. *
  85. * @param accountingSaveDTO
  86. * @param user
  87. */
  88. @Override
  89. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  90. public void saveAccounting(AccountingSaveDTO accountingSaveDTO, User user) {
  91. // 校验会计科目代码
  92. this.checkAccountingCode(accountingSaveDTO.getAccountingCode(), user.getHospId());
  93. // 新增逻辑
  94. Long parentId = accountingSaveDTO.getId();
  95. // 不是顶层的
  96. String allParentIds = "0";
  97. if (parentId != 0) {
  98. Accounting byId = this.getById(parentId);
  99. if (Objects.isNull(byId)) {
  100. throw new CostException(500, "上层级别会计科目已被移除");
  101. }
  102. // 如果父子节点的会计科目类型不一致,退出
  103. if (!byId.getAccountingType().equals(accountingSaveDTO.getAccountingType())) {
  104. throw new CostException(500, "会计科目类型要与上层一致");
  105. }
  106. String oldParentIds = byId.getAllParentIds();
  107. if ("0".equals(oldParentIds)) {
  108. allParentIds = parentId + "";
  109. } else {
  110. allParentIds = oldParentIds + "-" + parentId;
  111. }
  112. }
  113. Accounting accounting = BeanUtil.convertObj(accountingSaveDTO, Accounting.class);
  114. accounting.setHospId(user.getHospId());
  115. accounting.setParentId(parentId);
  116. accounting.setAllParentIds(allParentIds);
  117. accounting.setCreateTime(System.currentTimeMillis());
  118. // 如果是支出类型
  119. if (accountingSaveDTO.getAccountingType().equals(2)) {
  120. Integer isBaseCode = accountingSaveDTO.getIsBaseCode();
  121. if (Objects.isNull(isBaseCode)) {
  122. throw new CostException(500, "支出类型需要选择是否固定支出成本");
  123. }
  124. accounting.setIsBaseCost(isBaseCode);
  125. }
  126. this.save(accounting);
  127. }
  128. private void checkAccountingCode(String code, Long hospId) {
  129. List<Accounting> list = this.baseMapper.selectList(
  130. new QueryWrapper<Accounting>().lambda().select(Accounting::getId)
  131. .eq(Accounting::getAccountingCode, code)
  132. .eq(Accounting::getHospId, hospId)
  133. );
  134. if (CollUtil.isNotEmpty(list)) {
  135. throw new CostException(500, "会计科目代码已存在,请重新生成");
  136. }
  137. }
  138. /**
  139. * 选择会计科目列表
  140. *
  141. * @param user
  142. * @return
  143. */
  144. @Override
  145. public List<SelectAccountingVO> selectAccounting(User user) {
  146. List<Accounting> list = this.list(
  147. new LambdaQueryWrapper<Accounting>().select(Accounting::getId, Accounting::getAccountingName, Accounting::getParentId, Accounting::getAllParentIds)
  148. .eq(Accounting::getHospId, user.getHospId())
  149. );
  150. if (CollUtil.isEmpty(list)) {
  151. return Collections.emptyList();
  152. }
  153. // 所有的
  154. List<SelectAccountingVO> all = list.stream().map(i -> {
  155. SelectAccountingVO vo = new SelectAccountingVO();
  156. vo.setValue(i.getId());
  157. vo.setLabel(i.getAccountingName());
  158. vo.setChildren(null);
  159. vo.setParentId(i.getParentId());
  160. vo.setAllParentIds(i.getAllParentIds());
  161. return vo;
  162. }).collect(Collectors.toList());
  163. // 顶层的
  164. List<SelectAccountingVO> parents = all.stream().filter(i -> i.getParentId() == 0).collect(Collectors.toList());
  165. List<SelectAccountingVO> accountVOS = new ArrayList<>();
  166. for (SelectAccountingVO parent : parents) {
  167. List<SelectAccountingVO> accountTree = this.getSelectAccountTree(parent, all);
  168. accountVOS.addAll(accountTree);
  169. }
  170. return accountVOS;
  171. }
  172. private List<SelectAccountingVO> getSelectAccountTree(SelectAccountingVO parent, List<SelectAccountingVO> all) {
  173. List<SelectAccountingVO> accountVOS = new ArrayList<>();
  174. accountVOS.add(parent);
  175. for (SelectAccountingVO account : all) {
  176. // 如果是父子关系
  177. if (parent.getValue().equals(account.getParentId())) {
  178. List<SelectAccountingVO> child = parent.getChildren();
  179. if (CollUtil.isEmpty(child)) {
  180. child = new ArrayList<>();
  181. }
  182. child.add(account);
  183. parent.setChildren(child);
  184. // 处理子节点
  185. this.getSelectAccountTree(account, all);
  186. }
  187. }
  188. return accountVOS;
  189. }
  190. /**
  191. * 编辑科目代码
  192. *
  193. * @param accountingEditDTO
  194. * @param user
  195. */
  196. @Override
  197. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  198. public void updateAccount(AccountingEditDTO accountingEditDTO, User user) {
  199. // TODO: 2021/7/28 追踪溯源需求不满足
  200. Long id = accountingEditDTO.getId();
  201. // this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId());
  202. Accounting one = this.baseMapper.selectOne(
  203. new QueryWrapper<Accounting>().lambda()
  204. .eq(Accounting::getAccountingCode, accountingEditDTO.getAccountingCode())
  205. .eq(Accounting::getHospId, user.getHospId())
  206. .last("limit 1")
  207. );
  208. Accounting byId = this.getById(id);
  209. if (Objects.isNull(byId)) {
  210. throw new CostException(500, "当前选中会计科目已被移除");
  211. }
  212. if (Objects.nonNull(one) && !byId.getAccountingCode().equals(one.getAccountingCode())) {
  213. throw new CostException(500, "会计科目代码已存在,请重新生成");
  214. }
  215. // 直接修改 TODO 不修改会计科目Code
  216. byId.setAccountingCode(byId.getAccountingCode());
  217. byId.setAccountingName(accountingEditDTO.getAccountingName());
  218. byId.setCreateTime(System.currentTimeMillis());
  219. // byId.setAccountingType(accountingEditDTO.getAccountingType());
  220. this.updateById(byId);
  221. // this.removeById(id);
  222. // Accounting accounting = BeanUtil.convertObj(byId, Accounting.class);
  223. // saveAccount(accountingEditDTO, user, byId, accounting);
  224. // List<Accounting> list = new ArrayList<>();
  225. // this.getAndAllChild(Arrays.asList(id), user.getHospId(), list);
  226. // log.info("list:{}", list);
  227. // if (CollUtil.isEmpty(list)) {
  228. // return;
  229. // }
  230. // // 第一个子节点
  231. // List<Accounting> childList = list.stream().filter(i -> i.getParentId().equals(id)).collect(Collectors.toList());
  232. // if (CollUtil.isEmpty(childList)) {
  233. // throw new CostException(500, "数据异常");
  234. // }
  235. // childList.forEach(i -> {
  236. // i.setParentId(accounting.getId());
  237. // String allParentIds = setAllParentIds(byId);
  238. // i.setAllParentIds(allParentIds);
  239. // });
  240. // this.updateBatchById(childList);
  241. //
  242. //
  243. }
  244. // private String setAllParentIds(Accounting byId) {
  245. // Integer parentId = byId.getParentId();
  246. // // 不是顶层的
  247. // String allParentIds = "0";
  248. // if (parentId != 0) {
  249. // String oldParentIds = byId.getAllParentIds();
  250. // if ("0".equals(oldParentIds)) {
  251. // allParentIds = parentId + "";
  252. // } else {
  253. // allParentIds = oldParentIds + "-" + parentId;
  254. // }
  255. // }
  256. // return allParentIds;
  257. // }
  258. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  259. public void saveAccount(AccountingEditDTO accountingEditDTO, User user, Accounting byId, Accounting accounting) {
  260. this.checkAccountingCode(accountingEditDTO.getAccountingCode(), user.getHospId());
  261. accounting.setAccountingCode(accounting.getAccountingCode());
  262. accounting.setCreateTime(System.currentTimeMillis());
  263. // 新增逻辑
  264. Long parentId = byId.getParentId();
  265. // 不是顶层的
  266. String allParentIds = "0";
  267. if (parentId != 0) {
  268. String oldParentIds = byId.getAllParentIds();
  269. if ("0".equals(oldParentIds)) {
  270. allParentIds = parentId + "";
  271. } else {
  272. allParentIds = oldParentIds + "-" + parentId;
  273. }
  274. }
  275. accounting.setHospId(user.getHospId());
  276. accounting.setParentId(parentId);
  277. accounting.setAllParentIds(allParentIds);
  278. accounting.setCreateTime(System.currentTimeMillis());
  279. this.save(accounting);
  280. }
  281. /**
  282. * 得到自己还有所有的子节点
  283. *
  284. * @param ids
  285. * @param accounts
  286. * @return
  287. */
  288. private List<Accounting> getAndAllChild(List<Long> ids, Long hospId, List<Accounting> accounts) {
  289. List<Accounting> list = this.list(
  290. new LambdaQueryWrapper<Accounting>()
  291. .in(Accounting::getParentId, ids).eq(Accounting::getHospId, hospId)
  292. );
  293. if (CollUtil.isEmpty(list)) {
  294. return accounts;
  295. }
  296. accounts.addAll(list);
  297. this.getAndAllChild(list.stream().map(Accounting::getId).collect(Collectors.toList()), hospId, accounts);
  298. return accounts;
  299. }
  300. /**
  301. * 删除
  302. *
  303. * @param id
  304. * @param user
  305. */
  306. @Override
  307. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  308. public void deleteAccount(Long id, User user) {
  309. List<Accounting> list = new ArrayList<>();
  310. List<Accounting> andAllChild = this.getAndAllChild(Arrays.asList(id), user.getHospId(), list);
  311. if (CollUtil.isEmpty(andAllChild)) {
  312. this.removeById(id);
  313. }
  314. List<Long> collect = andAllChild.stream().map(Accounting::getId).collect(Collectors.toList());
  315. collect.add(id);
  316. this.removeByIds(collect);
  317. }
  318. /**
  319. * 通过code得到对应的会计科目对象 需要调用者自己判断空
  320. *
  321. * @param accountCode 会计科目代码
  322. * @return {@link Accounting} 可能为空 需要调用者自行判断
  323. */
  324. @Override
  325. public Accounting getByCode(String accountCode, Long hospId) {
  326. if (StrUtil.isEmpty(accountCode)) {
  327. throw new CostException("参数异常,accountCode 不能为空");
  328. }
  329. Accounting one = this.getOne(
  330. new LambdaQueryWrapper<Accounting>()
  331. .eq(Accounting::getAccountingCode, accountCode)
  332. .eq(Accounting::getHospId, hospId)
  333. .last(LIMIT)
  334. );
  335. return one;
  336. }
  337. }