yys
maven
2025-12-12 d0eaee38a59ec4f2600bfec41b3db5f80500af32
src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java
@@ -7,22 +7,27 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.dto.AccountDto;
import com.ruoyi.account.dto.AccountDto2;
import com.ruoyi.account.dto.AccountDto3;
import com.ruoyi.account.mapper.AccountExpenseMapper;
import com.ruoyi.account.mapper.AccountFileMapper;
import com.ruoyi.account.mapper.AccountIncomeMapper;
import com.ruoyi.account.pojo.AccountExpense;
import com.ruoyi.account.pojo.AccountIncome;
import com.ruoyi.account.service.AccountExpenseService;
import com.ruoyi.account.service.AccountIncomeService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.dto.DateQueryDto;
import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.mapper.SysDictDataMapper;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
@AllArgsConstructor
@Service
@@ -31,6 +36,8 @@
    private AccountExpenseMapper accountExpenseMapper;
    private AccountIncomeMapper accountIncomeMapper;
    private SysDictDataMapper sysDictDataMapper;
    //分页查询
@@ -53,12 +60,16 @@
        AccountDto accountDto = new AccountDto();
        //获取该段时间内的所有收入
        List<AccountDto2> accountIncomes =accountIncomeMapper.report(dateQueryDto);
        accountDto.setIncomeType(accountIncomes);
        Long incomeNumber = accountIncomeMapper.selectCount(Wrappers.<AccountIncome>lambdaQuery()
                .between(AccountIncome::getIncomeDate, dateQueryDto.getEntryDateStart(), dateQueryDto.getEntryDateEnd()));
        accountDto.setIncomeNumber(incomeNumber);
        BigDecimal totalIncome = accountIncomes.stream().map(AccountDto2::getAccount).reduce(BigDecimal.ZERO, BigDecimal::add);
        accountDto.setTotalIncome(totalIncome);
        accountIncomes.stream().forEach(accountDto2 -> {
            accountDto2.setProportion(accountDto2.getAccount().divide(totalIncome,2,BigDecimal.ROUND_HALF_UP));
        });
        accountDto.setIncomeType(accountIncomes);
        //获取该段时间内的所有支出
        List<AccountDto2> accountExpenses =accountExpenseMapper.report(dateQueryDto);
        accountDto.setExpenseType(accountExpenses);
@@ -67,11 +78,141 @@
        accountDto.setExpenseNumber(expenseNumber);
        BigDecimal totalExpense = accountExpenses.stream().map(AccountDto2::getAccount).reduce(BigDecimal.ZERO, BigDecimal::add);
        accountDto.setTotalExpense(totalExpense);
        accountExpenses.stream().forEach(accountDto2 -> {
            accountDto2.setProportion(accountDto2.getAccount().divide(totalExpense,2,BigDecimal.ROUND_HALF_UP));
        });
        accountDto.setExpenseType(accountExpenses);
        //净收入
        BigDecimal netRevenue = totalIncome.subtract(totalExpense);
        accountDto.setNetRevenue(netRevenue);
        return accountDto;
    }
    //财务报表年查询
    @Override
    public  List<AccountDto3> reportExpense() {
        List<AccountDto3> accountDto3s = new ArrayList<>();
        //先查询收入类型有哪些
        List<SysDictData> incomeTypes = sysDictDataMapper.selectDictDataByType("expense_types");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        int currentYear = LocalDate.now().getYear(); // 获取当前年份(如2025)
        for (SysDictData incomeType : incomeTypes) {
            AccountDto3 accountDto3 = new AccountDto3();
            accountDto3.setTypeName(incomeType.getDictLabel());//类型
            List<BigDecimal> account=new ArrayList<>();
            for (int i = 1; i <= 12; i++) {
                // 当月第一天:年份为当前年,月份为i,日期为1
                LocalDate firstDay = LocalDate.of(currentYear, i, 1);
                DateQueryDto dateQueryDto = new DateQueryDto();
                dateQueryDto.setEntryDateStart(firstDay.format(formatter));
                // 当月最后一天:第一天的月份的最后一天
                dateQueryDto.setEntryDateEnd(firstDay.plusMonths(1).minusDays(1).format(formatter));
                account.add(accountExpenseMapper.report1(dateQueryDto,incomeType.getDictValue()));
            }
            accountDto3.setAccount(account);//类型
            accountDto3s.add(accountDto3);
        }
        return accountDto3s;
    }
    @Override
    public Map<String, List<String>> analysis() {
        // 获取最近四个月(当前月 + 前3个月)的时间范围
        LocalDate today = LocalDate.now();
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM"); // 年月格式化器
        Map<String, List<String>> result = new HashMap<>();
        List<String> months = new ArrayList<>(); // 存储年月(如 2025-12、2025-11)
        List<String> totalIncomeList = new ArrayList<>(); // 每月总收入
        List<String> totalExpenseList = new ArrayList<>(); // 每月总支出
        List<String> netIncomeList = new ArrayList<>(); // 每月净收入(收入-支出)
        // 步骤1:计算近4个月的年月列表(当前月、前1月、前2月、前3月)
        List<String> targetMonths = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            LocalDate currentMonth = today.minusMonths(i);
            String monthStr = currentMonth.format(monthFormatter);
            targetMonths.add(monthStr);
        }
        // 反转列表,确保顺序为「前3月 → 当前月」(可选,按需求调整顺序)
        Collections.reverse(targetMonths);
        // 步骤2:一次性查询近4个月所有收入数据,按“年月”分组汇总
        LocalDate fourMonthsAgo = today.minusMonths(3).withDayOfMonth(1); // 近4个月起始日(前3月1号)
        LocalDate currentMonthEnd = today.withDayOfMonth(today.lengthOfMonth()); // 当前月结束日
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        // 查询近4个月所有收入
        List<AccountIncome> allIncomes = accountIncomeMapper.selectList(
                Wrappers.<AccountIncome>lambdaQuery()
                        .ge(AccountIncome::getIncomeDate, fourMonthsAgo.toString()) // 大于等于起始日
                        .le(AccountIncome::getIncomeDate, currentMonthEnd.toString()) // 小于等于结束日
        );
        // 收入按“年月”分组汇总(key:年月字符串,value:当月总收入)
        Map<String, BigDecimal> monthlyIncomeMap = allIncomes.stream()
                .filter(income -> income.getIncomeMoney() != null) // 过滤空金额
                .collect(Collectors.groupingBy(
                        income -> {
                            // 将输入时间(字符串)转换为LocalDate,再格式化为年月
                            LocalDate inputDate = income.getIncomeDate().toInstant().atZone(zoneId).toLocalDate();
                            return inputDate.format(monthFormatter);
                        },
                        Collectors.reducing(BigDecimal.ZERO, AccountIncome::getIncomeMoney, BigDecimal::add)
                ));
        // 步骤3:一次性查询近4个月所有支出数据,按“年月”分组汇总
        List<AccountExpense> allExpenses = accountExpenseMapper.selectList(
                Wrappers.<AccountExpense>lambdaQuery()
                        .ge(AccountExpense::getExpenseDate, fourMonthsAgo.toString())
                        .le(AccountExpense::getExpenseDate, currentMonthEnd.toString())
        );
        // 支出按“年月”分组汇总
        Map<String, BigDecimal> monthlyExpenseMap = allExpenses.stream()
                .filter(expense -> expense.getExpenseMoney() != null) // 过滤空金额
                .collect(Collectors.groupingBy(
                        expense -> {
                            LocalDate inputDate = expense.getExpenseDate().toInstant().atZone(zoneId).toLocalDate();
                            return inputDate.format(monthFormatter);
                        },
                        Collectors.reducing(BigDecimal.ZERO, AccountExpense::getExpenseMoney, BigDecimal::add)
                ));
        // 步骤4:循环4个目标月份,填充统计数据(无数据时默认为0)
        for (String month : targetMonths) {
            // 当月总收入(无数据则为0)
            BigDecimal totalIncome = monthlyIncomeMap.getOrDefault(month, BigDecimal.ZERO);
            // 当月总支出(无数据则为0)
            BigDecimal totalExpense = monthlyExpenseMap.getOrDefault(month, BigDecimal.ZERO);
            // 当月净收入(收入 - 支出)
            BigDecimal netIncome = totalIncome.subtract(totalExpense);
            // 填充列表
            months.add(month);
            totalIncomeList.add(totalIncome.toString());
            totalExpenseList.add(totalExpense.toString());
            netIncomeList.add(netIncome.toString());
        }
        // 组装结果
        result.put("days", months); // 年月(如 ["2025-09", "2025-10", "2025-11", "2025-12"])
        result.put("totalIncome", totalIncomeList); // 对应月份总收入
        result.put("totalExpense", totalExpenseList); // 对应月份总支出
        result.put("netIncome", netIncomeList); // 对应月份净收入
        return result;
    }
    @Override
    public AccountExpense getByInvoiceNumber(String purchaseContractNumber) {
        return accountExpenseMapper.selectOne(Wrappers.<AccountExpense>lambdaQuery()
                .eq(AccountExpense::getInvoiceNumber, purchaseContractNumber));
    }
    @Override
    public List<AccountExpense> getByInvoiceNumberList(String purchaseContractNumber) {
        return accountExpenseMapper.selectList(Wrappers.<AccountExpense>lambdaQuery()
                .eq(AccountExpense::getInvoiceNumber, purchaseContractNumber));
    }
}