|
@@ -0,0 +1,366 @@
|
|
|
+package com.fjhx.account.service.account.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.date.DateException;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.fjhx.account.entity.account.bo.CapitalDailyBo;
|
|
|
+import com.fjhx.account.entity.account.dto.CapitalDailyDto;
|
|
|
+import com.fjhx.account.entity.account.po.AccountManagement;
|
|
|
+import com.fjhx.account.entity.account.po.AccountRemainder;
|
|
|
+import com.fjhx.account.entity.account.po.AccountRunningWater;
|
|
|
+import com.fjhx.account.entity.account.vo.CapitalDailyVo;
|
|
|
+import com.fjhx.account.service.account.AccountManagementService;
|
|
|
+import com.fjhx.account.service.account.AccountRemainderService;
|
|
|
+import com.fjhx.account.service.account.AccountRunningWaterService;
|
|
|
+import com.fjhx.account.service.account.StatementService;
|
|
|
+import com.fjhx.common.entity.corporation.po.Corporation;
|
|
|
+import com.fjhx.common.service.corporation.CorporationService;
|
|
|
+import com.ruoyi.common.core.domain.BaseIdPo;
|
|
|
+import com.ruoyi.common.core.domain.BasePo;
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.util.*;
|
|
|
+import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class StatementServiceImpl implements StatementService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CorporationService corporationService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AccountManagementService accountManagementService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AccountRemainderService accountRemainderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AccountRunningWaterService accountRunningWaterService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<CapitalDailyVo> getCapitalDaily(CapitalDailyDto dto) {
|
|
|
+
|
|
|
+ Date beginDate, endDate;
|
|
|
+
|
|
|
+ Date date = new Date();
|
|
|
+ try {
|
|
|
+ Date parse = DateUtil.parse(dto.getDateBetween(), "yyyy-MM");
|
|
|
+ if (parse.after(DateUtil.endOfMonth(new Date()))) {
|
|
|
+ throw new ServiceException("统计日期不能大于本月");
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean sameMonth = DateUtil.isSameMonth(parse, date);
|
|
|
+
|
|
|
+ beginDate = DateUtil.beginOfMonth(parse);
|
|
|
+ endDate = sameMonth ? DateUtil.endOfDay(date) : DateUtil.endOfMonth(parse);
|
|
|
+ } catch (DateException dateException) {
|
|
|
+ throw new ServiceException("范围期间日期格式错误,应为 'yyyy-MM' 格式");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取归属公司
|
|
|
+ List<Corporation> corporationList = getCorporationList(dto.getCorporationId());
|
|
|
+ if (corporationList.size() == 0) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取账户
|
|
|
+ List<AccountManagement> managementList = getManagementList(dto.getManagementId(), corporationList);
|
|
|
+ if (managementList.size() == 0) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取账户余额
|
|
|
+ List<AccountRemainder> remainderList = getRemainderList(managementList);
|
|
|
+ if (remainderList.size() == 0) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 合并数据成bo对象
|
|
|
+ List<CapitalDailyBo> capitalDailyBoList = mergeBo(corporationList, managementList, remainderList);
|
|
|
+ if (capitalDailyBoList.size() == 0) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询流水记录
|
|
|
+ List<AccountRunningWater> runningWaterList = getRunningWaterList(beginDate, managementList);
|
|
|
+
|
|
|
+ // 计算出结束时间余额
|
|
|
+ if (!DateUtil.isSameMonth(endDate, date)) {
|
|
|
+ calculationEndDateBalance(endDate, capitalDailyBoList, runningWaterList);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 赋值收支流水明细
|
|
|
+ setRunningWaterDetail(capitalDailyBoList, endDate, runningWaterList);
|
|
|
+
|
|
|
+ // 格式化成vo
|
|
|
+ return formatVo(capitalDailyBoList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取归属公司列表
|
|
|
+ */
|
|
|
+ private List<Corporation> getCorporationList(Long corporationId) {
|
|
|
+ return corporationService.list(q -> q
|
|
|
+ .select(BaseIdPo::getId, Corporation::getName)
|
|
|
+ .eq(ObjectUtil.isNotEmpty(corporationId), Corporation::getId, corporationId));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取账户
|
|
|
+ */
|
|
|
+ private List<AccountManagement> getManagementList(Long managementId, List<Corporation> corporationList) {
|
|
|
+ List<Long> corporationIdList = corporationList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
|
|
|
+
|
|
|
+ return accountManagementService.list(q -> q
|
|
|
+ .select(BaseIdPo::getId, AccountManagement::getAlias, AccountManagement::getCorporationId)
|
|
|
+ .in(AccountManagement::getCorporationId, corporationIdList)
|
|
|
+ .eq(ObjectUtil.isNotEmpty(managementId), BaseIdPo::getId, managementId)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取货币并合并获取归属公司和账户数据
|
|
|
+ */
|
|
|
+ private List<AccountRemainder> getRemainderList(List<AccountManagement> accountManagementList) {
|
|
|
+
|
|
|
+ // 账户id
|
|
|
+ List<Long> accountManagementIdList =
|
|
|
+ accountManagementList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
|
|
|
+
|
|
|
+ return accountRemainderService.list(q -> q
|
|
|
+ .select(AccountRemainder::getCurrency, AccountRemainder::getRemainder, AccountRemainder::getAccountManagementId)
|
|
|
+ .in(AccountRemainder::getAccountManagementId, accountManagementIdList)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 合并数据成bo对象
|
|
|
+ */
|
|
|
+ private List<CapitalDailyBo> mergeBo(List<Corporation> corporationList,
|
|
|
+ List<AccountManagement> accountManagementList,
|
|
|
+ List<AccountRemainder> remainderList) {
|
|
|
+
|
|
|
+ Map<Long, List<AccountManagement>> accountManagementMap = accountManagementList.stream()
|
|
|
+ .collect(Collectors.groupingBy(AccountManagement::getCorporationId));
|
|
|
+
|
|
|
+ Map<Long, List<AccountRemainder>> AccountRemainderMap = remainderList.stream()
|
|
|
+ .collect(Collectors.groupingBy(AccountRemainder::getAccountManagementId));
|
|
|
+
|
|
|
+ List<CapitalDailyBo> capitalDailyBoList = new ArrayList<>();
|
|
|
+
|
|
|
+ for (Corporation corporation : corporationList) {
|
|
|
+
|
|
|
+ List<AccountManagement> accountManagementItemList = accountManagementMap.get(corporation.getId());
|
|
|
+ if (accountManagementItemList == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (AccountManagement accountManagement : accountManagementItemList) {
|
|
|
+
|
|
|
+ List<AccountRemainder> accountRemainderList = AccountRemainderMap.get(accountManagement.getId());
|
|
|
+ if (accountRemainderList == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<CapitalDailyBo> itemCapitalDailyBoList = accountRemainderList.stream()
|
|
|
+ .map(item -> {
|
|
|
+ CapitalDailyBo capitalDailyBo = new CapitalDailyBo();
|
|
|
+ capitalDailyBo.setCorporationId(corporation.getId());
|
|
|
+ capitalDailyBo.setCorporationName(corporation.getName());
|
|
|
+ capitalDailyBo.setAccountManagementId(accountManagement.getId());
|
|
|
+ capitalDailyBo.setAccountManagementAlias(accountManagement.getAlias());
|
|
|
+ capitalDailyBo.setCurrencyType(item.getCurrency());
|
|
|
+ capitalDailyBo.setRemainder(item.getRemainder());
|
|
|
+ return capitalDailyBo;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ capitalDailyBoList.addAll(itemCapitalDailyBoList);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return capitalDailyBoList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询流水记录
|
|
|
+ */
|
|
|
+ private List<AccountRunningWater> getRunningWaterList(Date beginDate, List<AccountManagement> managementList) {
|
|
|
+
|
|
|
+ List<Long> managementIdList = managementList.stream().map(BaseIdPo::getId).collect(Collectors.toList());
|
|
|
+
|
|
|
+ return accountRunningWaterService.list(q -> q
|
|
|
+ .ge(BasePo::getCreateTime, beginDate)
|
|
|
+ .in(AccountRunningWater::getAccountManagementId, managementIdList)
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算出结束时间余额
|
|
|
+ */
|
|
|
+ private void calculationEndDateBalance(Date endDate,
|
|
|
+ List<CapitalDailyBo> capitalDailyBoList,
|
|
|
+ List<AccountRunningWater> runningWaterList) {
|
|
|
+
|
|
|
+ Map<Long, Map<String, List<AccountRunningWater>>> managementIdCurrencyRunningWaterMap =
|
|
|
+ runningWaterList.stream().collect(Collectors.groupingBy(
|
|
|
+ AccountRunningWater::getAccountManagementId,
|
|
|
+ Collectors.groupingBy(AccountRunningWater::getCurrency)
|
|
|
+ ));
|
|
|
+
|
|
|
+ for (CapitalDailyBo capitalDailyBo : capitalDailyBoList) {
|
|
|
+ Long accountManagementId = capitalDailyBo.getAccountManagementId();
|
|
|
+ Map<String, List<AccountRunningWater>> currencyRunningWaterMap = managementIdCurrencyRunningWaterMap.get(accountManagementId);
|
|
|
+
|
|
|
+ if (currencyRunningWaterMap.size() == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<AccountRunningWater> itemRunningWaterList = currencyRunningWaterMap.get(capitalDailyBo.getCurrencyType());
|
|
|
+
|
|
|
+ if (itemRunningWaterList.size() == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算结束时间至今金额改变值
|
|
|
+ BigDecimal reduce = itemRunningWaterList.stream()
|
|
|
+ .filter(item -> item.getCreateTime().after(endDate))
|
|
|
+ .map(item -> Objects.equals(item.getStatus(), "10") ? BigDecimal.ZERO.subtract(item.getAmount()) : item.getAmount())
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+
|
|
|
+ // 赋值结束时间余额
|
|
|
+ capitalDailyBo.setRemainder(capitalDailyBo.getRemainder().subtract(reduce));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 收支流水明细
|
|
|
+ */
|
|
|
+ private void setRunningWaterDetail(List<CapitalDailyBo> capitalDailyBoList, Date endDate,
|
|
|
+ List<AccountRunningWater> runningWaterList) {
|
|
|
+
|
|
|
+
|
|
|
+ // 账户id 币种 天数 收支类型 收支金额
|
|
|
+ Map<Long, Map<String, Map<Integer, Map<String, BigDecimal>>>> collect = runningWaterList.stream()
|
|
|
+ .filter(item -> !item.getCreateTime().after(endDate))
|
|
|
+ .collect(
|
|
|
+ Collectors.groupingBy(AccountRunningWater::getAccountManagementId,
|
|
|
+ Collectors.groupingBy(AccountRunningWater::getCurrency,
|
|
|
+ Collectors.groupingBy(item -> DateUtil.dayOfMonth(item.getCreateTime()),
|
|
|
+ Collectors.toMap(
|
|
|
+ AccountRunningWater::getStatus,
|
|
|
+ AccountRunningWater::getAmount,
|
|
|
+ BigDecimal::add
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+
|
|
|
+ int day = DateUtil.dayOfMonth(endDate);
|
|
|
+
|
|
|
+ for (CapitalDailyBo capitalDailyBo : capitalDailyBoList) {
|
|
|
+ Map<String, Map<Integer, Map<String, BigDecimal>>> item1 = collect.get(capitalDailyBo.getAccountManagementId());
|
|
|
+ Map<Integer, Map<String, BigDecimal>> item2 = null;
|
|
|
+ if (item1 != null) {
|
|
|
+ item2 = item1.get(capitalDailyBo.getCurrencyType());
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map<String, Object>> flowingWaterList = new ArrayList<>();
|
|
|
+
|
|
|
+ for (int i = day; i > 0; i--) {
|
|
|
+ Map<String, BigDecimal> item3 = null;
|
|
|
+ if (item2 != null) {
|
|
|
+ item3 = item2.get(i);
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Object> flowingWaterMap = new LinkedHashMap<>();
|
|
|
+ if (item3 != null) {
|
|
|
+ flowingWaterMap.put("income", ObjectUtil.defaultIfNull(item3.get("10"), BigDecimal.ZERO));
|
|
|
+ flowingWaterMap.put("expenditure", ObjectUtil.defaultIfNull(item3.get("20"), BigDecimal.ZERO));
|
|
|
+ } else {
|
|
|
+ flowingWaterMap.put("income", BigDecimal.ZERO);
|
|
|
+ flowingWaterMap.put("expenditure", BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ BigDecimal remainder = capitalDailyBo.getRemainder();
|
|
|
+ flowingWaterMap.put("balance", remainder);
|
|
|
+ flowingWaterMap.put("day", i);
|
|
|
+
|
|
|
+ capitalDailyBo.setRemainder(
|
|
|
+ remainder.subtract((BigDecimal) flowingWaterMap.get("income"))
|
|
|
+ .add((BigDecimal) flowingWaterMap.get("expenditure")));
|
|
|
+
|
|
|
+ flowingWaterList.add(flowingWaterMap);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ capitalDailyBo.setFlowingWaterList(flowingWaterList);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private List<CapitalDailyVo> formatVo(List<CapitalDailyBo> capitalDailyBoList) {
|
|
|
+
|
|
|
+ Map<Long, CapitalDailyVo> collect = capitalDailyBoList.stream().map(item -> {
|
|
|
+
|
|
|
+ List<CapitalDailyVo.Management> managementList = new ArrayList<>();
|
|
|
+ List<CapitalDailyVo.Currency> currencyList = new ArrayList<>();
|
|
|
+
|
|
|
+ CapitalDailyVo capitalDailyVo = new CapitalDailyVo();
|
|
|
+ capitalDailyVo.setCorporationId(item.getCorporationId());
|
|
|
+ capitalDailyVo.setCorporationName(item.getCorporationName());
|
|
|
+ capitalDailyVo.setManagementList(managementList);
|
|
|
+
|
|
|
+ CapitalDailyVo.Management management = new CapitalDailyVo.Management();
|
|
|
+ management.setAccountManagementId(item.getAccountManagementId());
|
|
|
+ management.setAccountManagementAlias(item.getAccountManagementAlias());
|
|
|
+ management.setCurrencyList(currencyList);
|
|
|
+ managementList.add(management);
|
|
|
+
|
|
|
+ CapitalDailyVo.Currency currency = new CapitalDailyVo.Currency();
|
|
|
+ currency.setCurrencyType(item.getCurrencyType());
|
|
|
+ currency.setFlowingWaterList(item.getFlowingWaterList());
|
|
|
+ currencyList.add(currency);
|
|
|
+
|
|
|
+ return capitalDailyVo;
|
|
|
+ }).collect(Collectors.toMap(
|
|
|
+ CapitalDailyVo::getCorporationId,
|
|
|
+ Function.identity(),
|
|
|
+ (v1, v2) -> {
|
|
|
+ List<CapitalDailyVo.Management> managementList = v1.getManagementList();
|
|
|
+ CapitalDailyVo.Management management = v2.getManagementList().get(0);
|
|
|
+
|
|
|
+ boolean flag = false;
|
|
|
+
|
|
|
+ for (CapitalDailyVo.Management item : managementList) {
|
|
|
+ if (item.getAccountManagementId().equals(management.getAccountManagementId())) {
|
|
|
+ flag = true;
|
|
|
+ List<CapitalDailyVo.Currency> currencyList = item.getCurrencyList();
|
|
|
+ currencyList.add(management.getCurrencyList().get(0));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!flag) {
|
|
|
+ managementList.add(management);
|
|
|
+ }
|
|
|
+ return v1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ));
|
|
|
+
|
|
|
+ return new ArrayList<>(collect.values());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|