AllocationServiceImpl.java 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. package com.imed.costaccount.service.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import cn.hutool.poi.excel.ExcelWriter;
  7. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  8. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  10. import com.imed.costaccount.common.constants.NumberConstant;
  11. import com.imed.costaccount.common.exception.CostException;
  12. import com.imed.costaccount.common.util.BeanUtil;
  13. import com.imed.costaccount.common.util.JacksonUtil;
  14. import com.imed.costaccount.common.util.PageUtils;
  15. import com.imed.costaccount.common.util.UserContext;
  16. import com.imed.costaccount.mapper.AllocationMapper;
  17. import com.imed.costaccount.model.*;
  18. import com.imed.costaccount.model.dto.StartDTO;
  19. import com.imed.costaccount.model.vo.*;
  20. import com.imed.costaccount.service.*;
  21. import lombok.extern.slf4j.Slf4j;
  22. import org.apache.poi.ss.usermodel.Sheet;
  23. import org.springframework.stereotype.Service;
  24. import org.springframework.transaction.annotation.Propagation;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import java.math.BigDecimal;
  27. import java.util.*;
  28. import java.util.concurrent.atomic.AtomicReference;
  29. import java.util.stream.Collectors;
  30. @Slf4j
  31. @Service("allocationService")
  32. public class AllocationServiceImpl extends ServiceImpl<AllocationMapper, Allocation> implements AllocationService {
  33. private final CostCostingGroupService costCostingGroupService;
  34. private final CostShareLevelService shareLevelService;
  35. private final ResponsibilityService responsibilityService;
  36. private final CostAccountShareService accountShareService;
  37. private final ShareParamValueService shareParamValueService;
  38. private final CostShareParamService shareParamService;
  39. private final AllocationQueryService allocationQueryService;
  40. public AllocationServiceImpl(CostCostingGroupService costCostingGroupService,
  41. CostShareLevelService shareLevelService,
  42. ResponsibilityService responsibilityService,
  43. CostAccountShareService accountShareService,
  44. ShareParamValueService shareParamValueService, CostShareParamService shareParamService, AllocationQueryService allocationQueryService, AllocationQueryService allocationQueryService1) {
  45. this.costCostingGroupService = costCostingGroupService;
  46. this.shareLevelService = shareLevelService;
  47. this.responsibilityService = responsibilityService;
  48. this.accountShareService = accountShareService;
  49. this.shareParamValueService = shareParamValueService;
  50. this.shareParamService = shareParamService;
  51. this.allocationQueryService = allocationQueryService1;
  52. }
  53. /**
  54. * 分摊成本数据
  55. *
  56. * @param startDTO {@link StartDTO}
  57. * @param hospId 医院id
  58. */
  59. @Override
  60. @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
  61. public void startAllocation(StartDTO startDTO, Long hospId) {
  62. // 得到这个月的所有导入的成本数据
  63. List<CostCostingGroup> costingGroups = costCostingGroupService.getByYearAndDate(startDTO.getYear(), startDTO.getMonth(), hospId);
  64. // 没有重新导入
  65. if (costingGroups.isEmpty()) {
  66. throw new CostException("本月分摊参数值数据未导入");
  67. }
  68. Map<String, List<CostCostingGroup>> responsibilityCodeMap = costingGroups.stream().collect(Collectors.groupingBy(CostCostingGroup::getResponsibilityCode));
  69. // 得到这个月导入的成本分摊参数值列表
  70. List<ShareParamValue> shareParamValues = shareParamValueService.getListByYearAndMonth(startDTO.getYear(), startDTO.getMonth(), hospId);
  71. if (shareParamValues.isEmpty()) {
  72. throw new CostException("本月成本分摊参数值未导入");
  73. }
  74. Map<String, List<ShareParamValue>> paramValueRespCodeMap = shareParamValues.stream().collect(Collectors.groupingBy(ShareParamValue::getResponsibilityCode));
  75. // 删除该年月已经分摊过的数据
  76. removeData(startDTO, hospId);
  77. // 得到这个医院所有的分摊层级列表排序
  78. List<CostShareLevelVO> shareLevelVOs = shareLevelService.getAll(hospId);
  79. if (CollUtil.isEmpty(shareLevelVOs)) {
  80. throw new CostException("请先设置医院分摊层级");
  81. }
  82. List<Allocation> allocations = new LinkedList<>();
  83. // key 责任中心代码, value 分摊过来的钱
  84. // Map<String, BigDecimal> costMap = new ConcurrentReaderHashMap();
  85. List<Allocation> costList = new ArrayList();
  86. for (CostShareLevelVO shareLevelVO : shareLevelVOs) {
  87. // 分摊层级id
  88. Long levelId = shareLevelVO.getId();
  89. // 目标分摊层级,可能不存在
  90. String targetLevel = shareLevelVO.getTargetLevel();
  91. if (StrUtil.isBlank(targetLevel)) {
  92. throw new CostException("未设置目标层级");
  93. }
  94. // 计算方式 0是合并计算 1是分开计算
  95. Integer calcType = shareLevelVO.getCalcType();
  96. // 得到该分摊层级下责任中心列表,如果不存在,下一个
  97. List<Responsibility> responsibilities = responsibilityService.getByLevelId(levelId, hospId);
  98. if (responsibilities.isEmpty()) {
  99. continue;
  100. }
  101. // 遍历责任中心得到对应的分摊参数对应
  102. for (Responsibility responsibility : responsibilities) {
  103. String responsibilityCode = responsibility.getResponsibilityCode();
  104. // 得到分摊参数对应记录,不存在,下一个
  105. if (responsibilityCode.equals("123")) {
  106. System.out.println(1);
  107. }
  108. List<CostAccountShare> accountShares = accountShareService.getByResponsibility(responsibilityCode, hospId);
  109. if (accountShares.isEmpty()) {
  110. continue;
  111. }
  112. // 遍历分摊参数对应记录
  113. for (CostAccountShare accountShare : accountShares) {
  114. Long accountShareId = accountShare.getId();
  115. String paramList = accountShare.getParamList();
  116. List<AccountShareVO> accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class);
  117. // 如果分摊比例未设置直接报错
  118. if (StrUtil.isBlank(paramList)) {
  119. throw new CostException("责任中心:" + accountShare.getResponsibilityName() + ";会计中心为:" + accountShare.getAccountingNames() + ";未设置分摊参数比例");
  120. }
  121. List<CostCostingGroup> groups = responsibilityCodeMap.get(responsibilityCode);
  122. if (CollUtil.isEmpty(groups)) {
  123. continue;
  124. }
  125. // 计算本次分摊的钱
  126. BigDecimal totalAmount = this.getCostAmount(accountShare, calcType, responsibilityCodeMap, costList);
  127. if (totalAmount.equals(BigDecimal.ZERO)) {
  128. continue;
  129. }
  130. // 相关的分摊参数比例
  131. for (AccountShareVO accountShareVO : accountShareVOs) {
  132. String paramCode = accountShareVO.getShareParamCode();
  133. String shareParamPopout = accountShareVO.getShareParamPopout();
  134. BigDecimal rate = new BigDecimal("1");
  135. if (!"100".equals(shareParamPopout)) {
  136. rate = new BigDecimal("0." + shareParamPopout);
  137. }
  138. // 本次的分摊比例计算
  139. BigDecimal thisAmount = rate.multiply(totalAmount);
  140. // 得到目标层级责任中心列表
  141. List<Responsibility> targetResponsibilities = this.getTargetResponsibility(targetLevel, hospId, shareLevelVO.getLeverSort());
  142. if (targetResponsibilities.isEmpty()) {
  143. throw new CostException("找不到目标责任中心");
  144. }
  145. // 目标责任中心得到对应
  146. List<ShareParamValue> targetShareParmValue = getTarget(targetResponsibilities, accountShareVO, paramValueRespCodeMap);
  147. if (CollUtil.isEmpty(targetResponsibilities)) {
  148. throw new CostException("找不到目标责任中心对应的分摊参数值");
  149. }
  150. // 分母
  151. BigDecimal reduce = targetShareParmValue.stream().map(ShareParamValue::getValueNum).reduce(BigDecimal.ZERO, BigDecimal::add);
  152. for (ShareParamValue paramValue : targetShareParmValue) {
  153. // 分子
  154. BigDecimal numerator = paramValue.getValueNum();
  155. BigDecimal targetAmount = thisAmount.multiply(numerator).divide(reduce, 4);
  156. Allocation targetAllocation = new Allocation();
  157. String valueResponsibilityCode = paramValue.getResponsibilityCode();
  158. String targetRespName = responsibilityService.getByCode(valueResponsibilityCode, hospId);
  159. String shareParamName = shareParamService.getByCode(paramValue.getShareParamCode(), hospId);
  160. targetAllocation.setDateMonth(startDTO.getMonth()).setDateYear(startDTO.getYear()).setLevelSort(shareLevelVO.getLeverSort())
  161. .setLevelName(shareLevelVO.getShareName()).setHospId(hospId).setResponsibilityCode(responsibility.getResponsibilityCode())
  162. .setResponsibilityName(responsibility.getResponsibilityName()).setAccountShareId(accountShareId).setAmount(targetAmount)
  163. .setCreateTime(System.currentTimeMillis()).setTargetResponsibilityCode(valueResponsibilityCode).setTargetResponsibilityName(targetRespName)
  164. .setShareParamCode(paramValue.getShareParamCode()).setShareParamName(shareParamName).setTotalAmount(totalAmount).setShareParamValueNum(paramValue.getValueNum())
  165. .setShareParamRate(numerator.divide(reduce, 4))
  166. ;
  167. // todo 目标分摊层级责任中心 就是当前列个表中的责任中心
  168. allocations.add(targetAllocation);
  169. costList.add(targetAllocation);
  170. }
  171. }
  172. }
  173. }
  174. }
  175. this.saveBatch(allocations);
  176. List<Allocation> list = this.list(
  177. new LambdaQueryWrapper<Allocation>()
  178. .eq(Allocation::getHospId, hospId).eq(Allocation::getDateYear, startDTO.getYear()).eq(Allocation::getDateMonth, startDTO.getMonth())
  179. );
  180. if (list.isEmpty()) {
  181. log.error("未分摊到数据......");
  182. return;
  183. }
  184. // 入cost_allocation_query 表 便于后续操作
  185. this.saveAllocationQuery(list, costingGroups, hospId);
  186. }
  187. private void removeData(StartDTO startDTO, Long hospId) {
  188. this.remove(
  189. new LambdaQueryWrapper<Allocation>()
  190. .eq(Allocation::getDateYear, startDTO.getYear())
  191. .eq(Allocation::getDateMonth, startDTO.getMonth())
  192. .eq(Allocation::getHospId, hospId)
  193. );
  194. allocationQueryService.remove(
  195. new LambdaQueryWrapper<AllocationQuery>()
  196. .eq(AllocationQuery::getDateYear, startDTO.getYear())
  197. .eq(AllocationQuery::getDateMonth, startDTO.getMonth())
  198. .eq(AllocationQuery::getHospId, hospId)
  199. );
  200. }
  201. @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
  202. public void saveAllocationQuery(List<Allocation> list, List<CostCostingGroup> costingGroups, Long hospId) {
  203. List<AllocationQuery> saveList = new ArrayList<>();
  204. list.forEach(i -> {
  205. Long accountShareId = i.getAccountShareId();
  206. CostAccountShare byId = accountShareService.getById(accountShareId);
  207. if (Objects.isNull(byId)) {
  208. return;
  209. }
  210. String accountingCodes = byId.getAccountingCodes();
  211. if (StrUtil.isBlank(accountingCodes)) {
  212. return;
  213. }
  214. String accountingNames = byId.getAccountingNames();
  215. String alias = byId.getAlias();
  216. if (StrUtil.isNotBlank(alias)) {
  217. accountingNames = alias;
  218. }
  219. AllocationQuery allocationQuery = new AllocationQuery();
  220. allocationQuery.setDateYear(i.getDateYear()).setDateMonth(i.getDateMonth())
  221. .setHospId(hospId).setResponsibilityCode(i.getResponsibilityCode()).setResponsibilityName(i.getResponsibilityName())
  222. .setOriginId(i.getId()).setOriginType(2L).setAmount(i.getAmount()).setAccountingCode(accountingCodes).setAccountingName(accountingNames)
  223. .setCreateTime(System.currentTimeMillis())
  224. ;
  225. saveList.add(allocationQuery);
  226. });
  227. costingGroups.forEach(i -> {
  228. AllocationQuery allocationQuery = new AllocationQuery();
  229. allocationQuery.setDateYear(i.getDateYear()).setDateMonth(i.getDateMonth())
  230. .setHospId(hospId).setResponsibilityCode(i.getResponsibilityCode()).setResponsibilityName(i.getResponsibilityName())
  231. .setOriginId(i.getId()).setOriginType(2L).setAmount(i.getAmount()).setAccountingCode(i.getAccountCode()).setAccountingName(i.getAccountName())
  232. .setCreateTime(System.currentTimeMillis())
  233. ;
  234. saveList.add(allocationQuery);
  235. });
  236. allocationQueryService.saveBatch(saveList);
  237. }
  238. /**
  239. * 得到目标月成本分摊参数值数据
  240. *
  241. * @param targetResponsibilities
  242. * @param map
  243. * @return
  244. */
  245. private List<ShareParamValue> getTarget(List<Responsibility> targetResponsibilities, AccountShareVO accountShareVO, Map<String, List<ShareParamValue>> map) {
  246. // 目标的责任中心
  247. List<ShareParamValue> shareParamValues = map.entrySet().stream().map(Map.Entry::getValue).flatMap(Collection::stream).collect(Collectors.toList());
  248. List<String> originRespCodes = targetResponsibilities.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
  249. return shareParamValues.stream().filter(j -> originRespCodes.contains(j.getResponsibilityCode()))
  250. .filter(i -> i.getShareParamCode().equals(accountShareVO.getShareParamCode())).collect(Collectors.toList());
  251. }
  252. /**
  253. * 计算本次的成本金额
  254. *
  255. * @return
  256. */
  257. private BigDecimal getCostAmount(CostAccountShare accountShare, Integer calcType, Map<String, List<CostCostingGroup>> map, List<Allocation> costList) {
  258. // 是否包含分摊成本 0不包含 1 包含
  259. Integer isShareCost = accountShare.getIsShareCost();
  260. String accountingCodes = accountShare.getAccountingCodes();
  261. String responsibilityCode = accountShare.getResponsibilityCode();
  262. List<CostCostingGroup> costingGroups = map.get(responsibilityCode);
  263. if (CollUtil.isEmpty(costingGroups)) {
  264. return BigDecimal.ZERO;
  265. }
  266. // 计算方式 0是合并计算 1是分开计算
  267. BigDecimal costAmount = BigDecimal.ZERO;
  268. List<Allocation> all = new ArrayList<>();
  269. if (!costList.isEmpty()) {
  270. all = costList.stream().filter(i -> i.getTargetResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList());
  271. // Stream<Allocation> allocationStream = costList.stream().filter(i -> i.getTargetResponsibilityCode().equals(responsibilityCode));
  272. // if (Objects.nonNull(allocationStream)) {
  273. // all = allocationStream.collect(Collectors.toList());
  274. // }
  275. }
  276. if (calcType == 0) {
  277. costAmount = costingGroups.stream().map(CostCostingGroup::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  278. if (!all.isEmpty()) {
  279. BigDecimal bigDecimal = all.stream()
  280. .map(Allocation::getAmount)
  281. .reduce(BigDecimal.ZERO, BigDecimal::add);
  282. if (Objects.nonNull(bigDecimal)) {
  283. costAmount = costAmount.add(bigDecimal);
  284. }
  285. }
  286. } else {
  287. if (StrUtil.isBlank(accountingCodes)) {
  288. return BigDecimal.ZERO;
  289. }
  290. ArrayList<String> accountCodes = CollUtil.newArrayList(accountingCodes.split(StrUtil.COMMA));
  291. List<CostCostingGroup> costGroups = costingGroups.stream().filter(i -> accountCodes.contains(i.getAccountCode())).collect(Collectors.toList());
  292. costAmount = costGroups.stream().map(CostCostingGroup::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
  293. if (isShareCost == 1) {
  294. if (!all.isEmpty()) {
  295. BigDecimal bigDecimal = all.stream()
  296. .map(Allocation::getAmount)
  297. .reduce(BigDecimal.ZERO, BigDecimal::add);
  298. if (Objects.nonNull(bigDecimal)) {
  299. costAmount = costAmount.add(bigDecimal);
  300. }
  301. }
  302. }
  303. }
  304. return costAmount;
  305. }
  306. /**
  307. * 通过目标层级获取目标责任中心
  308. *
  309. * @param targetLevel 目标层级 2,3,4
  310. * @param leverSort
  311. * @return List
  312. */
  313. private List<Responsibility> getTargetResponsibility(String targetLevel, Long hospId, Integer leverSort) {
  314. ArrayList<String> targetLevelList = CollUtil.newArrayList(StrUtil.split(targetLevel, StrUtil.COMMA));
  315. if (targetLevelList.size() == 1) {
  316. if (leverSort.equals(Integer.parseInt(targetLevelList.get(0)))) {
  317. return new ArrayList<>();
  318. }
  319. }
  320. List<CostShareLevel> shareLevels = shareLevelService.getListByLevelSort(targetLevelList, hospId);
  321. if (shareLevels.isEmpty()) {
  322. throw new CostException("请重新设置分摊层级");
  323. }
  324. List<Long> shareLevelIds = shareLevels.stream().map(CostShareLevel::getId).collect(Collectors.toList());
  325. return responsibilityService.getByLevelIds(shareLevelIds, hospId);
  326. }
  327. /**
  328. * 分摊后查询列表
  329. *
  330. * @param year 年月 (yyyy-MM-dd)
  331. * @param responsibilityCode 责任中心代码
  332. * @param current 当前页
  333. * @param pageSize 当前页展示的数据大小
  334. * @param hospId 医院id
  335. * @return PageUtils
  336. */
  337. @Override
  338. public PageUtils queryAfterAllocation(String year, String responsibilityCode, Integer current, Integer pageSize, Long hospId) {
  339. Integer dateYear = null;
  340. Integer dateMonth = null;
  341. if (StrUtil.isNotBlank(year)) {
  342. DateTime dateTime = DateUtil.parseDate(year);
  343. dateYear = DateUtil.year(dateTime);
  344. dateMonth = DateUtil.month(dateTime) + 1;
  345. }
  346. Integer startIndex = (current - 1) * pageSize;
  347. List<AfterAllocationVO> list = baseMapper.queryAfterAllocationList(dateYear, dateMonth, responsibilityCode, startIndex, pageSize, hospId);
  348. int totalCount = baseMapper.queryAfterAllocationListCount(dateYear, dateMonth, responsibilityCode, hospId);
  349. BigDecimal sum = baseMapper.queryAfterAllocationListSum(dateYear, dateMonth, responsibilityCode, hospId);
  350. return new PageUtils(list, totalCount, pageSize, current, sum);
  351. }
  352. /**
  353. * 分摊报表导出
  354. *
  355. * @param writer {@link ExcelWriter}
  356. * @param levelSort 分摊层级 就是第几次分摊
  357. * @param sheet 报表
  358. * @param year 年
  359. * @param month 月
  360. * @return
  361. */
  362. @Override
  363. public ExcelWriter getShareReportTemplate(ExcelWriter writer, Integer levelSort, Sheet sheet, Integer year, Integer month) {
  364. // 获取数据
  365. List<AllocationReportVO> allocationReportVOList = getAllocationReportVOS(levelSort, year, month);
  366. // 设置导出
  367. Map<String, List<AllocationReportVO>> responsibilityMap = allocationReportVOList.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode));
  368. Map<String, List<AllocationReportVO>> targetResponsibilityMap = allocationReportVOList.stream().collect(Collectors.groupingBy(AllocationReportVO::getTargetResponsibilityCode));
  369. Map<String, AllocationReportVO> allAccMap = allocationReportVOList.stream().collect(Collectors.toMap(k -> k.getResponsibilityName() + k.getAccountName() + k.getTargetResponsibilityName() + k.getShareParamName(), synOne -> synOne));
  370. Map<String, AllocationReportVO> allAliMap = allocationReportVOList.stream().collect(Collectors.toMap(k -> k.getResponsibilityName() + k.getAlias() + k.getTargetResponsibilityName() + k.getShareParamName(), synOne -> synOne));
  371. // 当前责任中心下面有几个会计科目 后面进行合并使用
  372. int numResponsibility;
  373. // // 从第几列开始编写数据
  374. int column = levelSort + 3;
  375. Set<String> keySet = responsibilityMap.keySet();
  376. for (String key : keySet) {
  377. List<AllocationReportVO> allocationReportVOS = responsibilityMap.get(key);
  378. Map<String, AllocationReportVO> linkedHashMap = new LinkedHashMap<>();
  379. allocationReportVOS.forEach(i -> {
  380. String s = i.getResponsibilityCode() + i.getAccountCode();
  381. if (!linkedHashMap.containsKey(s)) {
  382. linkedHashMap.put(s, i);
  383. }
  384. });
  385. numResponsibility = linkedHashMap.size();
  386. if (numResponsibility >= NumberConstant.TWO) {
  387. Set<String> strings = linkedHashMap.keySet();
  388. for (String s : strings) {
  389. AllocationReportVO allocationReportVO = linkedHashMap.get(s);
  390. if (StrUtil.isBlank(allocationReportVO.getAlias())) {
  391. writer.writeCellValue(column, 0, allocationReportVO.getResponsibilityName());
  392. // 别名不存在
  393. writer.writeCellValue(column, 1, allocationReportVO.getAccountName());
  394. } else {
  395. // 不为空 设置别名
  396. writer.writeCellValue(column, 0, allocationReportVO.getResponsibilityName());
  397. writer.writeCellValue(column, 1, allocationReportVO.getAlias());
  398. }
  399. writer.writeCellValue(column, 2, allocationReportVO.getTotalAmounts());
  400. column++;
  401. }
  402. } else {
  403. // 不需要合并单元格
  404. writer.writeCellValue(column, 0, allocationReportVOS.get(0).getResponsibilityName());
  405. if (StrUtil.isNotBlank(allocationReportVOS.get(0).getAlias())) {
  406. writer.writeCellValue(column, 1, allocationReportVOS.get(0).getAlias());
  407. } else {
  408. writer.writeCellValue(column, 1, allocationReportVOS.get(0).getAccountName());
  409. }
  410. writer.writeCellValue(column, 2, allocationReportVOS.get(0).getTotalAmounts());
  411. column++;
  412. }
  413. }
  414. // 设置单元格合并
  415. for (int j = 1; j < levelSort; j++) {
  416. writer.merge(0, 1, j, j, "第" + j + "次分摊", false);
  417. }
  418. // 目标责任集合
  419. writer.passCurrentRow();
  420. // 从第三行开始
  421. int num = 3;
  422. Set<String> targetSet = targetResponsibilityMap.keySet();
  423. for (String target : targetSet) {
  424. List<AllocationReportVO> allocationReportVOS = targetResponsibilityMap.get(target);
  425. Map<String, AllocationReportVO> linkedHashMap = new LinkedHashMap<>();
  426. allocationReportVOS.forEach(i -> {
  427. String s = i.getTargetResponsibilityCode() + i.getShareParamName();
  428. if (!linkedHashMap.containsKey(s)) {
  429. linkedHashMap.put(s, i);
  430. }
  431. });
  432. int shareParamSize = linkedHashMap.size();
  433. if (shareParamSize >= NumberConstant.TWO) {
  434. // 责任中心
  435. AllocationReportVO costCostingVO = allocationReportVOS.get(0);
  436. // 设置第几次分摊的值
  437. for (int k = 0; k < levelSort - 1; k++) {
  438. writer.merge(num, num + shareParamSize - 1, k + 1, k + 1, costCostingVO.getTargetShareMoneys().get(k), false);
  439. }
  440. // 设置对应的分摊参数值
  441. Set<String> strings = linkedHashMap.keySet();
  442. for (String s : strings) {
  443. AllocationReportVO allocationReportVO = linkedHashMap.get(s);
  444. writer.writeCellValue(0, num, allocationReportVO.getTargetResponsibilityName());
  445. writer.writeCellValue(levelSort, num, allocationReportVO.getShareParamName());
  446. writer.writeCellValue(levelSort + 1, num, allocationReportVO.getShareParamValueNums());
  447. writer.writeCellValue(levelSort + 2, num, allocationReportVO.getShareParamRates());
  448. for (int m = levelSort + 3; m < column; m++) {
  449. // x是m y是num
  450. // 获取当前这一列对应的责任中心 以及会计科目
  451. // 第一行责任中心
  452. String responsibilityName = sheet.getRow(0).getCell(m).getStringCellValue();
  453. // 第二行的会计科目或者
  454. String accountNameOrAlias = sheet.getRow(1).getCell(m).getStringCellValue();
  455. // 这一行的目标责任中心
  456. String otherResponsibilityName = sheet.getRow(num).getCell(0).getStringCellValue();
  457. // 分摊参数
  458. String shareName = sheet.getRow(num).getCell(levelSort).getStringCellValue();
  459. String sss = responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName;
  460. AllocationReportVO vo = allAliMap.get(sss);
  461. AllocationReportVO allocationReportVO2 = allAccMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName);
  462. AllocationReportVO allocationReportVO3 = allAliMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName);
  463. if (Objects.nonNull(allocationReportVO2)) {
  464. writer.writeCellValue(m, num, allocationReportVO2.getAmounts());
  465. } else if (Objects.nonNull(allocationReportVO3)) {
  466. writer.writeCellValue(m, num, allocationReportVO3.getAmounts());
  467. } else {
  468. writer.writeCellValue(m, num, 0);
  469. }
  470. }
  471. num++;
  472. }
  473. }
  474. if (shareParamSize < NumberConstant.TWO) {
  475. writer.writeCellValue(0, num, allocationReportVOS.get(0).getTargetResponsibilityName());
  476. for (int k = 0; k < levelSort - 1; k++) {
  477. writer.writeCellValue(k + 1, num, allocationReportVOS.get(0).getTargetShareMoneys().get(k));
  478. }
  479. writer.writeCellValue(levelSort, num, allocationReportVOS.get(0).getShareParamName());
  480. writer.writeCellValue(levelSort + 1, num, allocationReportVOS.get(0).getShareParamValueNums());
  481. writer.writeCellValue(levelSort + 2, num, allocationReportVOS.get(0).getShareParamRates());
  482. for (int m = levelSort + 4; m < column; m++) {
  483. // x是m y是num
  484. // 获取当前这一列对应的责任中心 以及会计科目
  485. // 第一行责任中心
  486. String responsibilityName = sheet.getRow(0).getCell(m).getStringCellValue();
  487. // 第二行的会计科目或者
  488. String accountNameOrAlias = sheet.getRow(1).getCell(m).getStringCellValue();
  489. // 这一行的目标责任中心
  490. String otherResponsibilityName = sheet.getRow(num).getCell(0).getStringCellValue();
  491. // 分摊参数
  492. String shareName = sheet.getRow(num).getCell(levelSort).getStringCellValue();
  493. AllocationReportVO allocationReportVO2 = allAccMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName);
  494. AllocationReportVO allocationReportVO3 = allAliMap.get(responsibilityName + accountNameOrAlias + otherResponsibilityName + shareName);
  495. if (Objects.nonNull(allocationReportVO2)) {
  496. writer.writeCellValue(m, num, allocationReportVO2.getAmounts());
  497. } else if (Objects.nonNull(allocationReportVO3)) {
  498. writer.writeCellValue(m, num, allocationReportVO3.getAmounts());
  499. } else {
  500. writer.writeCellValue(m, num, 0);
  501. }
  502. }
  503. num++;
  504. }
  505. }
  506. for (int i = 0; i < 30; i++) {
  507. // 调整每一列宽度
  508. sheet.autoSizeColumn((short) i);
  509. // 解决自动设置列宽中文失效的问题
  510. sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 14 / 10);
  511. }
  512. return writer;
  513. }
  514. /**
  515. * 查询数据
  516. *
  517. * @param levelSort
  518. * @param year
  519. * @param month
  520. * @return
  521. */
  522. private List<AllocationReportVO> getAllocationReportVOS(Integer levelSort, Integer year, Integer month) {
  523. Long hospId = UserContext.getHospId();
  524. if (Objects.isNull(levelSort) || Objects.isNull(year) || Objects.isNull(month)) {
  525. throw new CostException(500, "参数异常");
  526. }
  527. List<Allocation> allocationList = baseMapper.selectList(new QueryWrapper<Allocation>().lambda()
  528. .eq(Allocation::getHospId, hospId).eq(Allocation::getLevelSort, levelSort).eq(Allocation::getDateYear, year)
  529. .eq(Allocation::getDateMonth, month));
  530. // 处理第几次分摊计算值
  531. List<Allocation> allocations = baseMapper.selectList(new QueryWrapper<Allocation>().lambda()
  532. .eq(Allocation::getHospId, hospId).eq(Allocation::getDateYear, year)
  533. .eq(Allocation::getDateMonth, month));
  534. Map<String, List<Allocation>> accrepMap = allocations.stream().collect(Collectors.groupingBy(k -> k.getLevelSort() + "cost" + k.getResponsibilityCode()));
  535. LinkedList<String> shareMoney = new LinkedList<>();
  536. List<CostAccountShare> costAccountShareList = accountShareService.list(new QueryWrapper<CostAccountShare>().lambda()
  537. .eq(CostAccountShare::getHospId, hospId));
  538. Map<Long, CostAccountShare> accountShareMap = costAccountShareList.stream().collect(Collectors.toMap(CostAccountShare::getId, synOne -> synOne));
  539. List<AllocationReportVO> allocationReportVOList = BeanUtil.convertList(allocationList, AllocationReportVO.class);
  540. allocationReportVOList.forEach(i -> {
  541. Long accountShareId = i.getAccountShareId();
  542. CostAccountShare costAccountShare = accountShareMap.get(accountShareId);
  543. if (Objects.isNull(costAccountShare)) {
  544. throw new CostException(500, "成本参数参数设置对应不存在");
  545. }
  546. i.setAccountCode(costAccountShare.getAccountingCodes());
  547. i.setAccountName(costAccountShare.getAccountingNames());
  548. i.setAlias(costAccountShare.getAlias());
  549. if (levelSort > 1) {
  550. for (int j = 1; j < levelSort; j++) {
  551. AtomicReference<BigDecimal> money = new AtomicReference<>(new BigDecimal("0.0000"));
  552. List<Allocation> allocations1 = accrepMap.get(j + "cost" + i.getResponsibilityCode());
  553. if (CollUtil.isNotEmpty(allocations1)) {
  554. allocations1.forEach(m -> {
  555. money.updateAndGet(v -> v.add(m.getAmount()));
  556. shareMoney.add(month.toString());
  557. });
  558. } else {
  559. // TODO 封装测试数据
  560. shareMoney.add("1000");
  561. }
  562. }
  563. }
  564. i.setTargetShareMoneys(shareMoney);
  565. // 设置字符串类型数据
  566. i.setTotalAmounts(i.getTotalAmount().toString());
  567. i.setShareParamValueNums(i.getShareParamValueNum().toString());
  568. i.setShareParamRates(i.getShareParamRate().toString());
  569. i.setAmounts(i.getAmount().toString());
  570. });
  571. return allocationReportVOList;
  572. }
  573. /**
  574. * 分摊后报表
  575. *
  576. * @param year 年月(yyyy-MM-dd)
  577. * @param responsibilityCode 责任中心代码
  578. * @param hospId 医院id
  579. * @return List
  580. */
  581. @Override
  582. public CollectDataFormVO queryAfterAllocationForm(String year, String responsibilityCode, Long hospId) {
  583. DateTime dateTime = DateUtil.parseDate(year);
  584. int dateYear = DateUtil.year(dateTime);
  585. int month = DateUtil.month(dateTime) + 1;
  586. List<CodeAndNameVO> responsibilityCodeAndNames = allocationQueryService.getRespCodeAndName(hospId, dateYear, month);
  587. List<CodeAndNameVO> accountCodeAndNames = allocationQueryService.getAccountCodeAndName(hospId, dateYear, month);
  588. // todo 校验两个List是否为空
  589. // 填充
  590. responsibilityCodeAndNames.add(0, new CodeAndNameVO("#", "#"));
  591. responsibilityCodeAndNames.add(responsibilityCodeAndNames.size(), new CodeAndNameVO("合计", "合计"));
  592. List<String> titleData = responsibilityCodeAndNames.stream().map(CodeAndNameVO::getName).collect(Collectors.toList());
  593. List<String> respCodes = responsibilityCodeAndNames.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
  594. Map<Integer, String> titleMap = new HashMap<>();
  595. for (int i = 0; i < titleData.size(); i++) {
  596. titleMap.put(i + 1, titleData.get(i));
  597. }
  598. List<Map<Integer, Object>> realDatas = new ArrayList<>();
  599. List<String> accountCodes = accountCodeAndNames.stream().map(CodeAndNameVO::getCode).collect(Collectors.toList());
  600. for (CodeAndNameVO account : accountCodeAndNames) {
  601. Map<Integer, Object> map = new HashMap<>();
  602. for (int i = 0; i < responsibilityCodeAndNames.size(); i++) {
  603. if (i == 0) {
  604. map.put(i + 1, account.getName());
  605. continue;
  606. } else if (i == responsibilityCodeAndNames.size() - 1) {
  607. // todo 计算最右侧合计的钱
  608. BigDecimal amount = allocationQueryService.getTotalByAccountAndResps(hospId, dateYear, month, account.getCode(), respCodes);
  609. map.put(i + 1, amount);
  610. continue;
  611. }
  612. // TODO: 2021/8/26 计算 中间的钱
  613. BigDecimal amount = allocationQueryService.getTotalByAccountAndRespCode(hospId, dateYear, month, account.getCode(), respCodes.get(i));
  614. map.put(i + 1, amount);
  615. }
  616. realDatas.add(map);
  617. }
  618. // 尾栏计算
  619. Map<Integer, Object> map = new HashMap<>();
  620. for (int i = 0; i < titleData.size(); i++) {
  621. if (i == 0) {
  622. map.put(i + 1, "合计");
  623. continue;
  624. } else if (i == titleData.size() - 1) {
  625. // TODO: 2021/8/26 计算
  626. BigDecimal bigDecimal = allocationQueryService.getTotalMoney(dateYear, month, hospId);
  627. map.put(i + 1, bigDecimal);
  628. continue;
  629. }
  630. BigDecimal bigDecimal = allocationQueryService.getCountByRespAndAccounts(hospId, dateYear, month, responsibilityCodeAndNames.get(i).getCode(), accountCodes);
  631. map.put(i + 1, bigDecimal);
  632. }
  633. return new CollectDataFormVO(titleMap, realDatas, map);
  634. }
  635. /**
  636. * 这年月的数据
  637. */
  638. private List<AllocationQuery> getAllocationQueriesByYear(Long hospId, int dateYear, int month) {
  639. List<AllocationQuery> list = allocationQueryService.list(
  640. new LambdaQueryWrapper<AllocationQuery>()
  641. .eq(AllocationQuery::getDateYear, dateYear)
  642. .eq(AllocationQuery::getDateMonth, month)
  643. .eq(AllocationQuery::getHospId, hospId)
  644. );
  645. return list;
  646. }
  647. }