gongchunyi
6 天以前 b3712bb9c618d3cb74b6a200fd83c2ba0577ac3d
src/main/java/com/ruoyi/account/service/impl/AccountingServiceImpl.java
@@ -8,7 +8,15 @@
import com.ruoyi.account.bean.dto.AccountReportDto;
import com.ruoyi.account.bean.dto.DeviceTypeDetail;
import com.ruoyi.account.bean.dto.DeviceTypeDistributionVO;
import com.ruoyi.account.bean.dto.purchase.PurchaseInboundDto;
import com.ruoyi.account.bean.dto.purchase.PurchaseReturnDto;
import com.ruoyi.account.bean.dto.sales.SalesOutboundDto;
import com.ruoyi.account.bean.dto.sales.SalesReturnDto;
import com.ruoyi.account.bean.vo.AccountReportVo;
import com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo;
import com.ruoyi.account.bean.vo.purchase.PurchaseReturnVo;
import com.ruoyi.account.bean.vo.sales.SalesOutboundVo;
import com.ruoyi.account.bean.vo.sales.SalesReturnVo;
import com.ruoyi.account.mapper.purchase.AccountPurchasePaymentMapper;
import com.ruoyi.account.mapper.sales.AccountSalesCollectionMapper;
import com.ruoyi.account.pojo.purchase.AccountPurchasePayment;
@@ -20,16 +28,22 @@
import com.ruoyi.procurementrecord.mapper.CustomStorageMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper;
import com.ruoyi.procurementrecord.mapper.ProcurementRecordOutMapper;
import com.ruoyi.procurementrecord.mapper.ReturnManagementMapper;
import com.ruoyi.procurementrecord.pojo.CustomStorage;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordOut;
import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage;
import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
import com.ruoyi.stock.mapper.StockInRecordMapper;
import com.ruoyi.stock.mapper.StockOutRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
@@ -49,6 +63,10 @@
    private final ProcurementRecordOutMapper procurementRecordOutMapper;
    private final AccountSalesCollectionMapper accountSalesCollectionMapper;
    private final AccountPurchasePaymentMapper accountPurchasePaymentMapper;
    private final StockOutRecordMapper stockOutRecordMapper;
    private final ReturnManagementMapper returnManagementMapper;
    private final StockInRecordMapper stockInRecordMapper;
    private final PurchaseReturnOrdersMapper purchaseReturnOrdersMapper;
    @Override
@@ -285,20 +303,155 @@
    @Override
    public AccountReportVo getAccountStatementDetailsByMonth(AccountReportDto accountReportDto) {
        AccountReportVo accountReportVo = new AccountReportVo();
        //总营收=收款单总金额
        //总收入笔数=收款单总笔数
        List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(Wrappers.<AccountSalesCollection>lambdaQuery()
                .between(AccountSalesCollection::getCollectionDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd()));
        accountReportVo.setTotalIncome(accountSalesCollections.stream().map(AccountSalesCollection::getCollectionAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        accountReportVo.setIncomeNumber(accountSalesCollections.size());
        //总支出=付款单总金额
        //总支出笔数=付款单总笔数
        List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(Wrappers.<AccountPurchasePayment>lambdaQuery()
                .between(AccountPurchasePayment::getPaymentDate, accountReportDto.getEntryDateStart(), accountReportDto.getEntryDateEnd()));
        accountReportVo.setTotalExpense(accountPurchasePayments.stream().map(AccountPurchasePayment::getPaymentAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
        accountReportVo.setExpenseNumber(accountPurchasePayments.size());
        //净利润=总营收-总支出
        accountReportVo.setNetRevenue(accountReportVo.getTotalIncome().subtract(accountReportVo.getTotalExpense()));
        LocalDate start = accountReportDto.getEntryDateStart();
        LocalDate end = accountReportDto.getEntryDateEnd();
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        // ========== 1. 顶部卡片数据 ==========
        // 1.1 总营收 = 收款单总金额
        List<AccountSalesCollection> accountSalesCollections = accountSalesCollectionMapper.selectList(
                Wrappers.<AccountSalesCollection>lambdaQuery()
                        .between(AccountSalesCollection::getCollectionDate, start, end)
        );
        BigDecimal totalIncome = Optional.of(
                accountSalesCollections.stream()
                        .map(AccountSalesCollection::getCollectionAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        accountReportVo.setTotalIncome(totalIncome);
        // 1.2 总支出 = 付款单总金额
        List<AccountPurchasePayment> accountPurchasePayments = accountPurchasePaymentMapper.selectList(
                Wrappers.<AccountPurchasePayment>lambdaQuery()
                        .between(AccountPurchasePayment::getPaymentDate, start, end)
        );
        BigDecimal totalExpense = Optional.of(
                accountPurchasePayments.stream()
                        .map(AccountPurchasePayment::getPaymentAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        accountReportVo.setTotalExpense(totalExpense);
        // 1.3 应收账款 = 销售出库金额合计 - 销售退货金额合计
        SalesOutboundDto salesOutboundDto = new SalesOutboundDto();
        salesOutboundDto.setStartDate(accountReportDto.getEntryDateStart());
        salesOutboundDto.setEndDate(accountReportDto.getEntryDateEnd());
        List<SalesOutboundVo> salesOutboundVos = stockOutRecordMapper.listPageAccountSales(new Page(1, -1), salesOutboundDto).getRecords();
        BigDecimal salesOutAmount = Optional.of(
                salesOutboundVos.stream()
                        .map(SalesOutboundVo::getOutboundAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        SalesReturnDto salesReturnDto = new SalesReturnDto();
        salesReturnDto.setStartDate(accountReportDto.getEntryDateStart());
        salesReturnDto.setEndDate(accountReportDto.getEntryDateEnd());
        List<SalesReturnVo> salesReturnVos = returnManagementMapper.listPageAccountSalesReturn(new Page(1, -1), salesReturnDto).getRecords();
        BigDecimal salesReturnAmount = Optional.of(
                salesReturnVos.stream()
                        .map(SalesReturnVo::getRefundAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        accountReportVo.setAccountsReceivable(salesOutAmount.subtract(salesReturnAmount));
        // 1.4 应付账款 = 采购入库金额合计 - 采购退货金额合计
        PurchaseInboundDto purchaseInboundDto = new PurchaseInboundDto();
        purchaseInboundDto.setStartDate(accountReportDto.getEntryDateStart());
        purchaseInboundDto.setEndDate(accountReportDto.getEntryDateEnd());
        List<PurchaseInboundVo> purchaseInboundVos = stockInRecordMapper.listPageAccountPurchase(new Page(1, -1), purchaseInboundDto).getRecords();
        BigDecimal purchaseInAmount = Optional.of(
                purchaseInboundVos.stream()
                        .map(PurchaseInboundVo::getInboundAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        PurchaseReturnDto purchaseReturnDto = new PurchaseReturnDto();
        purchaseReturnDto.setStartDate(accountReportDto.getEntryDateStart());
        purchaseReturnDto.setEndDate(accountReportDto.getEntryDateEnd());
        List<PurchaseReturnVo> purchaseReturnVos = purchaseReturnOrdersMapper.listPageAccountPurchaseReturn(new Page(1, -1), purchaseReturnDto).getRecords();
        BigDecimal purchaseReturnAmount = Optional.of(
                purchaseReturnVos.stream()
                        .map(PurchaseReturnVo::getTotalAmount)
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ).orElse(BigDecimal.ZERO);
        accountReportVo.setAccountsPayable(purchaseInAmount.subtract(purchaseReturnAmount));
        // 1.5 净利润 = 总营收 - 总支出
        BigDecimal netProfit = totalIncome.subtract(totalExpense);
        accountReportVo.setNetRevenue(netProfit);
        // ========== 2. 折线图:月度营收/支出/净利润趋势 ==========
        Map<String, BigDecimal> monthIncomeMap = new HashMap<>();
        Map<String, BigDecimal> monthExpenseMap = new HashMap<>();
        // 月度营收
        accountSalesCollections.forEach(item -> {
            String month = item.getCollectionDate().format(monthFormatter);
            monthIncomeMap.put(month, monthIncomeMap.getOrDefault(month, BigDecimal.ZERO)
                    .add(Optional.ofNullable(item.getCollectionAmount()).orElse(BigDecimal.ZERO)));
        });
        // 月度支出
        accountPurchasePayments.forEach(item -> {
            String month = item.getPaymentDate().format(monthFormatter);
            monthExpenseMap.put(month, monthExpenseMap.getOrDefault(month, BigDecimal.ZERO)
                    .add(Optional.ofNullable(item.getPaymentAmount()).orElse(BigDecimal.ZERO)));
        });
        // 生成连续月份列表
        List<String> monthList = new ArrayList<>();
        LocalDate current = start.withDayOfMonth(1);
        while (!current.isAfter(end.withDayOfMonth(1))) {
            monthList.add(current.format(monthFormatter));
            current = current.plusMonths(1);
        }
        // 组装趋势数据
        List<AccountReportVo.MonthlyTrendVO> trendList = new ArrayList<>();
        for (String month : monthList) {
            BigDecimal income = monthIncomeMap.getOrDefault(month, BigDecimal.ZERO);
            BigDecimal expense = monthExpenseMap.getOrDefault(month, BigDecimal.ZERO);
            AccountReportVo.MonthlyTrendVO trend = new AccountReportVo.MonthlyTrendVO();
            trend.setMonth(month);
            trend.setIncome(income);
            trend.setExpense(expense);
            trend.setProfit(income.subtract(expense));
            trendList.add(trend);
        }
        accountReportVo.setMonthlyTrendList(trendList);
        // ========== 3. 柱状图:月度应收/应付数据 ==========
        Map<String, BigDecimal> monthReceivableMap = new HashMap<>();
        Map<String, BigDecimal> monthPayableMap = new HashMap<>();
        // 月度应收(销售出库-退货)
        salesOutboundVos.forEach(item -> {
            String month = item.getShippingDate().format(monthFormatter);
            monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)
                    .add(Optional.ofNullable(item.getOutboundAmount()).orElse(BigDecimal.ZERO)));
        });
        salesReturnVos.forEach(item -> {
            String month = item.getMakeTime().format(monthFormatter);
            monthReceivableMap.put(month, monthReceivableMap.getOrDefault(month, BigDecimal.ZERO)
                    .subtract(Optional.ofNullable(item.getRefundAmount()).orElse(BigDecimal.ZERO)));
        });
        // 月度应付(采购入库-退货)
        purchaseInboundVos.forEach(item -> {
            String month = item.getInboundDate().format(monthFormatter);
            monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO)
                    .add(Optional.ofNullable(item.getInboundAmount()).orElse(BigDecimal.ZERO)));
        });
        purchaseReturnVos.forEach(item -> {
            String month = item.getPreparedAt().format(monthFormatter);
            monthPayableMap.put(month, monthPayableMap.getOrDefault(month, BigDecimal.ZERO)
                    .subtract(Optional.ofNullable(item.getTotalAmount()).orElse(BigDecimal.ZERO)));
        });
        // 组装应收应付数据
        List<AccountReportVo.ReceivablePayableVO> rpList = new ArrayList<>();
        for (String month : monthList) {
            AccountReportVo.ReceivablePayableVO rp = new AccountReportVo.ReceivablePayableVO();
            rp.setMonth(month);
            rp.setReceivable(monthReceivableMap.getOrDefault(month, BigDecimal.ZERO));
            rp.setPayable(monthPayableMap.getOrDefault(month, BigDecimal.ZERO));
            rpList.add(rp);
        }
        accountReportVo.setReceivablePayableList(rpList);
        return accountReportVo;
    }
}