CostCostingGroupServiceImpl.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. package com.imed.costaccount.service.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.alibaba.druid.util.StringUtils;
  6. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  8. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  9. import com.imed.costaccount.common.exception.CostException;
  10. import com.imed.costaccount.common.util.*;
  11. import com.imed.costaccount.constants.NumberConstant;
  12. import com.imed.costaccount.enums.DateStyleEnum;
  13. import com.imed.costaccount.mapper.CostCostingGroupMapper;
  14. import com.imed.costaccount.model.*;
  15. import com.imed.costaccount.model.dto.StartDTO;
  16. import com.imed.costaccount.model.vo.AllocationVO;
  17. import com.imed.costaccount.model.vo.CostingGroupStartVO;
  18. import com.imed.costaccount.model.vo.IncomeErrorMessage;
  19. import com.imed.costaccount.service.*;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Propagation;
  23. import org.springframework.transaction.annotation.Transactional;
  24. import org.springframework.util.CollectionUtils;
  25. import org.springframework.web.multipart.MultipartFile;
  26. import java.math.BigDecimal;
  27. import java.util.*;
  28. @Service("costCostingGroupService")
  29. @Slf4j
  30. public class CostCostingGroupServiceImpl extends ServiceImpl<CostCostingGroupMapper, CostCostingGroup> implements CostCostingGroupService {
  31. private final CostIncomeGroupServiceImpl costIncomeGroupService;
  32. private final AccountingProductService accountingProductService;
  33. private final CostIncomeFileService costIncomeFileService;
  34. private final ResponsibilityService responsibilityService;
  35. private final CostCostingCollectionService costingCollectionService;
  36. public CostCostingGroupServiceImpl(CostIncomeGroupServiceImpl costIncomeGroupService,
  37. AccountingProductService accountingProductService,
  38. CostIncomeFileService costIncomeFileService,
  39. ResponsibilityService responsibilityService,
  40. CostCostingCollectionService costingCollectionService) {
  41. this.costIncomeGroupService = costIncomeGroupService;
  42. this.accountingProductService = accountingProductService;
  43. this.costIncomeFileService = costIncomeFileService;
  44. this.responsibilityService = responsibilityService;
  45. this.costingCollectionService = costingCollectionService;
  46. }
  47. /**
  48. * 分摊前查询
  49. *
  50. * @param current 当前页
  51. * @param pageSize 每页数据大小
  52. * @param responsibilityCode 责任中心代码
  53. * @param accountCode 会计中心代码
  54. * @param date 日期 yyyy-MM
  55. * @param hospId 医院id
  56. * @return 分摊前查询列表
  57. */
  58. @Override
  59. public PageUtils queryStartAllocation(Integer current, Integer pageSize, String responsibilityCode, String accountCode, String date, Long hospId) {
  60. Integer startIndex = (current - 1) * pageSize;
  61. int year = 0;
  62. int month = 0;
  63. if (StrUtil.isNotBlank(date)) {
  64. Date dateTime = DateUtils.StringToDate(date, DateStyleEnum.YYYY_MM);
  65. year = DateUtil.year(dateTime);
  66. month = DateUtil.month(dateTime) + 1;
  67. }
  68. // DateTime dateTime = DateUtil.parseDate(date);
  69. //
  70. // Integer year = DateUtil.year(dateTime);
  71. // Integer month = DateUtil.month(dateTime) + 1;
  72. List<CostingGroupStartVO> list = baseMapper.queryStartAllocation(startIndex, pageSize, responsibilityCode, accountCode, year, month, hospId);
  73. int count = baseMapper.queryStartAllocationCount(responsibilityCode, accountCode, year, month, hospId);
  74. BigDecimal totalAmount = baseMapper.queryStartAllocationTotalAmount(responsibilityCode, accountCode, year, month, hospId);
  75. return new PageUtils(list, count, pageSize, current, totalAmount);
  76. }
  77. /**
  78. * 成本分摊列表
  79. *
  80. * @param current 当前页
  81. * @param pageSize 每页数据大小
  82. * @param date 日期 这里是 yyyy-MM-dd
  83. * @param hospId
  84. * @return 分页对象
  85. */
  86. @Override
  87. public PageUtils queryAllocation(Integer current, Integer pageSize, String date, Long hospId) {
  88. Integer year = null;
  89. Integer month = null;
  90. if (StrUtil.isNotBlank(date)) {
  91. DateTime dateTime = DateUtil.parseDate(date);
  92. year = DateUtil.year(dateTime);
  93. month = DateUtil.month(dateTime) + 1;
  94. }
  95. Integer startIndex = (current - 1) * pageSize;
  96. List<AllocationVO> list = baseMapper.queryAllocation(startIndex, pageSize, year, month, hospId);
  97. list.forEach(i -> {
  98. List<CostCostingCollection> collections = costingCollectionService.list(new LambdaQueryWrapper<CostCostingCollection>().eq(CostCostingCollection::getYear, i.getYear())
  99. .eq(CostCostingCollection::getMonth, i.getMonth())
  100. .eq(CostCostingCollection::getHospId, hospId)
  101. );
  102. if (!collections.isEmpty()) {
  103. i.setIsAllocation(true);
  104. }
  105. });
  106. int count = baseMapper.queryAllocationCount(year, month, hospId);
  107. return new PageUtils(list, count, pageSize, current);
  108. }
  109. /**
  110. * 开始成本分摊
  111. *
  112. * @param startDTO {@link StartDTO}
  113. * @param hospId 医院id
  114. */
  115. @Override
  116. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
  117. public void startAllocation(StartDTO startDTO, Long hospId) {
  118. // 先拿到这个月数据 如果数据量很大 优化处理
  119. List<CostCostingGroup> list = this.list(
  120. new LambdaQueryWrapper<CostCostingGroup>()
  121. .eq(CostCostingGroup::getDateYear, startDTO.getYear())
  122. .eq(CostCostingGroup::getDateMonth, startDTO.getMonth())
  123. .eq(CostCostingGroup::getHospId, hospId)
  124. );
  125. // 删除该年月已经过的数据
  126. costingCollectionService.remove(
  127. new LambdaQueryWrapper<CostCostingCollection>()
  128. .eq(CostCostingCollection::getYear, startDTO.getYear())
  129. .eq(CostCostingCollection::getMonth, startDTO.getMonth())
  130. .eq(CostCostingCollection::getHospId, hospId)
  131. );
  132. // 得到分摊层级为1 的
  133. // list.stream().map(get)
  134. }
  135. /**
  136. * 批量导入成本数据
  137. *
  138. * @param list
  139. * @param user
  140. * @param file
  141. * @param dateTime
  142. * @param fileType
  143. * @return
  144. */
  145. @Override
  146. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  147. public Result importCostingGroup(List<List<Object>> list, User user, MultipartFile file, String dateTime, Integer fileType) {
  148. // 先检验当前年月是否存在数据
  149. int year = 0;
  150. int month = 0;
  151. if (StrUtil.isNotBlank(dateTime)) {
  152. Date date = DateUtils.StringToDate(dateTime, DateStyleEnum.YYYY_MM);
  153. year = DateUtil.year(date);
  154. month = DateUtil.month(date) + 1;
  155. }
  156. Long hospId = user.getHospId();
  157. List<CostCostingGroup> groups = this.list(new QueryWrapper<CostCostingGroup>().lambda().eq(CostCostingGroup::getHospId, hospId)
  158. .eq(CostCostingGroup::getDateYear, year).eq(CostCostingGroup::getDateMonth, month));
  159. if (!CollectionUtils.isEmpty(groups)) {
  160. throw new CostException(500, year + "年" + month + "月数据已存在");
  161. }
  162. for (int i = list.size() - 1; i >= 0; i--) {
  163. if (i == NumberConstant.ZERO || i == NumberConstant.ONE || i == NumberConstant.TWO || i == NumberConstant.THREE) {
  164. list.remove(list.get(i));
  165. }
  166. }
  167. List<IncomeErrorMessage> incomeErrorMessageList = new ArrayList<>();
  168. //获取所有的科室 成本项目 责任中心 会计科目
  169. Map<String, Department> departmentMap = costIncomeGroupService.getDepartmentByCodeNameMap(hospId);
  170. Map<String, Product> productMap = costIncomeGroupService.getProductByCodeNameMap(hospId);
  171. Map<Long, Responsibility> responsibilityMap = costIncomeGroupService.getResponsibilityIdResponsibilityMap(hospId);
  172. Map<Long, Accounting> accountingMap = costIncomeGroupService.getAccountIdAccountingMap(hospId);
  173. List<ResponsibilityDepartment> responsibilityDepartmentList = costIncomeGroupService.getResponsibilityDepartments(hospId);
  174. if (CollectionUtils.isEmpty(responsibilityDepartmentList)) {
  175. throw new CostException(500, "没有科室责任中心对照数据");
  176. }
  177. List<AccountingProduct> accountingProductList = accountingProductService.list(new QueryWrapper<AccountingProduct>().lambda().eq(AccountingProduct::getHospId, hospId));
  178. if (CollectionUtils.isEmpty(accountingProductList)) {
  179. throw new CostException(500, "没有成本会计对照数据");
  180. }
  181. Map<Long, Long> responsibilityDepMap = costIncomeGroupService.getDepartmentIdResponsibilityIdMap(responsibilityDepartmentList);
  182. Map<Long, Long> accountProMap = costIncomeGroupService.getProductIdAccountIdMap(accountingProductList);
  183. String endStatus = list.get(0).get(list.get(0).size() - 1).toString();
  184. // 要保存的数据
  185. List<CostCostingGroup> costCostingGroupArrayList = new LinkedList<>();
  186. // 判断最后科室代码的最后一个字符是否是-1
  187. if (!"-1".equals(endStatus)) {
  188. // 如果没有-1说明终结符
  189. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  190. incomeErrorMessage.setTotal(5);
  191. incomeErrorMessage.setErrMessage("科室代码末尾没有-1终结符");
  192. incomeErrorMessageList.add(incomeErrorMessage);
  193. // 文件上传
  194. String uploadFile = costIncomeGroupService.uploadFile(file, UserContext.getCurrentUser());
  195. // 上传记录保存
  196. if (StrUtil.isBlank(uploadFile)) {
  197. throw new CostException(500, "文件上传异常");
  198. }
  199. // 记录文件上传记录
  200. CostIncomeFile costIncomeFile = costIncomeFileService.saveCostIncomeFile(list, user, file, hospId, incomeErrorMessageList, uploadFile, fileType, year, month);
  201. return Result.build(500, "数据未成功导入", null);
  202. }
  203. // 检验数据的合理性
  204. // 检验成本数据
  205. checkCostData(list, incomeErrorMessageList, departmentMap, productMap, responsibilityMap, accountingMap, responsibilityDepMap, accountProMap, costCostingGroupArrayList, year, month);
  206. // 文件上传
  207. String uploadFile = costIncomeGroupService.uploadFile(file, UserContext.getCurrentUser());
  208. // 上传记录保存
  209. if (StrUtil.isBlank(uploadFile)) {
  210. throw new CostException(500, "文件上传异常");
  211. }
  212. // 记录文件上传记录
  213. CostIncomeFile costIncomeFile = costIncomeFileService.saveCostIncomeFile(list, user, file, hospId, incomeErrorMessageList, uploadFile, fileType, year, month);
  214. Long id = costIncomeFile.getId();
  215. costCostingGroupArrayList.forEach(i -> {
  216. // 设置文件Id
  217. i.setFileId(id);
  218. });
  219. if (CollectionUtils.isEmpty(incomeErrorMessageList)) {
  220. this.saveBatch(costCostingGroupArrayList);
  221. return Result.build(200, "数据导入成功", null);
  222. } else {
  223. return Result.build(200, "数据未成功导入", null);
  224. }
  225. }
  226. /**
  227. * 检验成本数据
  228. *
  229. * @param list
  230. * @param incomeErrorMessageList
  231. * @param departmentMap
  232. * @param productMap
  233. * @param responsibilityMap
  234. * @param accountingMap
  235. * @param responsibilityDepMap
  236. * @param accountProMap
  237. * @param costCostingGroupArrayList
  238. */
  239. private void checkCostData(List<List<Object>> list, List<IncomeErrorMessage> incomeErrorMessageList, Map<String, Department> departmentMap, Map<String, Product> productMap, Map<Long, Responsibility> responsibilityMap, Map<Long, Accounting> accountingMap, Map<Long, Long> responsibilityDepMap, Map<Long, Long> accountProMap, List<CostCostingGroup> costCostingGroupArrayList, Integer year, Integer month) {
  240. List<Object> departmentCodes = list.get(0);
  241. List<Object> departmentNames = list.get(1);
  242. //检验数据是否准确
  243. for (int i = 2; i < list.size(); i++) {
  244. int row = i + 5;
  245. List<Object> data = list.get(i);
  246. for (int j = 2; j < departmentCodes.size(); j++) {
  247. int column = j + 1;
  248. if (data.size() > j) {
  249. if (Objects.isNull(data.get(j))) {
  250. data.set(j, NumberConstant.ZERO);
  251. } else if (data.get(j).toString().contains("-") || !StringUtils.isNumber(data.get(j).toString())) {
  252. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  253. incomeErrorMessage.setTotal(row);
  254. incomeErrorMessage.setErrMessage("第" + row + "行 第" + column + "列数据不符合规范");
  255. incomeErrorMessageList.add(incomeErrorMessage);
  256. } else {
  257. data.set(j, Double.parseDouble(data.get(j).toString()));
  258. }
  259. } else {
  260. data.add(NumberConstant.ZERO);
  261. }
  262. }
  263. if (CollectionUtils.isEmpty(incomeErrorMessageList)) {
  264. incomeErrorMessageList = new ArrayList<>();
  265. int emptyStatus = 0;
  266. for (int j = 2; j < data.size() - 1; j++) {
  267. BigDecimal parseInt = new BigDecimal(data.get(j).toString());
  268. if (!BigDecimal.ZERO.equals(parseInt)) {
  269. emptyStatus = 1;
  270. break;
  271. }
  272. }
  273. // 检验成本项目是否正确
  274. CostCostingGroup costCostingGroupRequest = new CostCostingGroup();
  275. if (Objects.nonNull(data.get(0)) && Objects.nonNull(data.get(1))) {
  276. String productCode = data.get(0).toString();
  277. String productName = data.get(1).toString();
  278. Product product = productMap.get(productCode + productName);
  279. AfterCostGroup afterCostGroupRequest = new AfterCostGroup();
  280. if (Objects.nonNull(product)) {
  281. Long id = product.getId();
  282. Long accountTingId = accountProMap.get(id);
  283. if (Objects.nonNull(accountTingId)) {
  284. Accounting accounting = accountingMap.get(accountTingId);
  285. if (Objects.nonNull(accounting)) {
  286. costCostingGroupRequest.setProductCode(productCode);
  287. costCostingGroupRequest.setProductName(productName);
  288. costCostingGroupRequest.setAccountCode(accounting.getAccountingCode());
  289. costCostingGroupRequest.setAccountName(accounting.getAccountingName());
  290. afterCostGroupRequest.setProductCode(productCode);
  291. afterCostGroupRequest.setProductName(productName);
  292. afterCostGroupRequest.setAccountCode(accounting.getAccountingCode());
  293. afterCostGroupRequest.setAccountName(accounting.getAccountingName());
  294. } else {
  295. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  296. incomeErrorMessage.setTotal(1);
  297. incomeErrorMessage.setErrMessage("成本代码" + productCode + " 成本名称" + productName + " 不存在对应的会计科目不存在");
  298. incomeErrorMessageList.add(incomeErrorMessage);
  299. }
  300. } else {
  301. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  302. incomeErrorMessage.setTotal(1);
  303. incomeErrorMessage.setErrMessage("成本代码" + productCode + " 成本名称" + productName + " 不存在对应的会计科目不存在");
  304. incomeErrorMessageList.add(incomeErrorMessage);
  305. }
  306. } else {
  307. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  308. incomeErrorMessage.setTotal(1);
  309. incomeErrorMessage.setErrMessage("成本代码" + productCode + " 成本名称" + productName + "不存在");
  310. incomeErrorMessageList.add(incomeErrorMessage);
  311. }
  312. // 0表示全为0 1表示不全为0
  313. BigDecimal combined = new BigDecimal(data.get(data.size() - 1).toString());
  314. if (!BigDecimal.ZERO.equals(combined) && NumberConstant.ZERO.equals(emptyStatus)) {
  315. // 这条数据是保存到其他责任中心的
  316. CostCostingGroup costCostingGroup = costCostingGroupRequest;
  317. AfterCostGroup afterCostGroup = BeanUtil.convertObj(afterCostGroupRequest, AfterCostGroup.class);
  318. // TODO 设置其他责任中心
  319. Responsibility responsibilityServiceOne = responsibilityService.getOne(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, UserContext.getHospId()).eq(Responsibility::getIsDefault, NumberConstant.ONE));
  320. if (Objects.nonNull(responsibilityServiceOne)) {
  321. costCostingGroup.setResponsibilityCode(responsibilityServiceOne.getResponsibilityCode());
  322. costCostingGroup.setResponsibilityName(responsibilityServiceOne.getResponsibilityName());
  323. // 设置统计数据
  324. afterCostGroup.setOtherResponsibilityCode(responsibilityServiceOne.getResponsibilityCode());
  325. afterCostGroup.setOtherResponsibilityName(responsibilityServiceOne.getResponsibilityName());
  326. } else {
  327. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  328. incomeErrorMessage.setTotal(row);
  329. incomeErrorMessage.setErrMessage("不存在默认责任中心");
  330. incomeErrorMessageList.add(incomeErrorMessage);
  331. }
  332. costCostingGroup.setProductCode(costCostingGroupRequest.getProductCode());
  333. costCostingGroup.setProductName(costCostingGroupRequest.getProductName());
  334. costCostingGroup.setAccountCode(costCostingGroupRequest.getAccountCode());
  335. costCostingGroup.setAccountName(costCostingGroupRequest.getAccountName());
  336. costCostingGroup.setAmount(combined);
  337. costCostingGroup.setHospId(UserContext.getHospId());
  338. costCostingGroup.setCreateTime(System.currentTimeMillis());
  339. costCostingGroup.setDateYear(year);
  340. costCostingGroup.setDateMonth(month);
  341. afterCostGroup.setAmount(combined);
  342. // String s = -JsonUtil.toJSONString(afterCostGroup);
  343. String s = JacksonUtil.obj2Str(combined);
  344. costCostingGroup.setAfterCostGroup(s);
  345. costCostingGroupArrayList.add(costCostingGroup);
  346. } else {
  347. for (int j = 2; j < data.size() - 1; j++) {
  348. AfterCostGroup afterCostGroup = BeanUtil.convertObj(afterCostGroupRequest, AfterCostGroup.class);
  349. CostCostingGroup costCostingGroup = BeanUtil.convertObj(costCostingGroupRequest, CostCostingGroup.class);
  350. // 检验科室信息是否准确
  351. String departmentCode = departmentCodes.get(j).toString();
  352. String departmentName = departmentNames.get(j).toString();
  353. Department department = departmentMap.get(departmentCode + departmentName);
  354. if (Objects.nonNull(department)) {
  355. // 检测责任中心是否存在
  356. Long id = department.getId();
  357. Long responsibilityId = responsibilityDepMap.get(id);
  358. if (Objects.nonNull(responsibilityId)) {
  359. Responsibility responsibility = responsibilityMap.get(responsibilityId);
  360. if (Objects.nonNull(responsibility)) {
  361. costCostingGroup.setDepartmentCode(departmentCode);
  362. costCostingGroup.setDepartmentName(departmentName);
  363. costCostingGroup.setResponsibilityCode(responsibility.getResponsibilityCode());
  364. costCostingGroup.setResponsibilityName(responsibility.getResponsibilityName());
  365. afterCostGroup.setResponsibilityCode(responsibility.getResponsibilityCode());
  366. afterCostGroup.setResponsibilityName(responsibility.getResponsibilityName());
  367. afterCostGroup.setDepartmentCode(departmentCode);
  368. afterCostGroup.setDepartmentName(departmentName);
  369. } else {
  370. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  371. incomeErrorMessage.setTotal(j);
  372. incomeErrorMessage.setErrMessage("第" + j + "列科室信息对应的责任中心不存在");
  373. incomeErrorMessageList.add(incomeErrorMessage);
  374. }
  375. } else {
  376. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  377. incomeErrorMessage.setTotal(j);
  378. incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在对应的责任中心");
  379. incomeErrorMessageList.add(incomeErrorMessage);
  380. }
  381. } else {
  382. IncomeErrorMessage incomeErrorMessage = new IncomeErrorMessage();
  383. incomeErrorMessage.setTotal(j);
  384. incomeErrorMessage.setErrMessage("第" + j + "列科室信息不存在");
  385. incomeErrorMessageList.add(incomeErrorMessage);
  386. }
  387. costCostingGroup.setAmount(new BigDecimal((Objects.isNull(data.get(j)) || "0".equals(data.get(j).toString())) ? "0.00" : data.get(j).toString()));
  388. costCostingGroup.setHospId(UserContext.getHospId());
  389. costCostingGroup.setCreateTime(System.currentTimeMillis());
  390. costCostingGroup.setDateYear(year);
  391. costCostingGroup.setDateMonth(month);
  392. afterCostGroup.setAmount(new BigDecimal((Objects.isNull(data.get(j)) || "0".equals(data.get(j).toString())) ? "0.00" : data.get(j).toString()));
  393. // String s = JsonUtil.toJSONString(afterCostGroup);
  394. String s = JacksonUtil.obj2Str(afterCostGroup);
  395. costCostingGroup.setAfterCostGroup(s);
  396. costCostingGroupArrayList.add(costCostingGroup);
  397. }
  398. }
  399. }
  400. }
  401. }
  402. }
  403. }