xuhy
2025-07-17 ca41616d33308050c52612177e515115f543de1b
财务数据汇总
5个文件已修改
4个文件已添加
371 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DataStatisticsController.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/YcFinancialManagementController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/YcFinancialManagement.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/DataStatisticsQuery.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ExpensesIncomeStatisticsVO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/TopDataStatisticsVO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/YcRevenueExpenditureTypeStatisticsVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/YcFinancialManagementMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/DataStatisticsController.java
@@ -1,20 +1,37 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.basic.PageInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.query.YcFinancialManagementQuery;
import com.ruoyi.system.model.YcFinancialManagement;
import com.ruoyi.system.model.YcRevenueExpenditureType;
import com.ruoyi.system.query.DataStatisticsQuery;
import com.ruoyi.system.service.YcFinancialManagementService;
import com.ruoyi.system.service.YcRevenueExpenditureTypeService;
import com.ruoyi.system.vo.YcFinancialManagementVO;
import com.ruoyi.system.vo.ExpensesIncomeStatisticsVO;
import com.ruoyi.system.vo.TopDataStatisticsVO;
import com.ruoyi.system.vo.YcRevenueExpenditureTypeStatisticsVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
 * <p>
@@ -42,12 +59,233 @@
    }
    /**
     * 查询财务管理列表
     * 顶部数据统计
     */
    @ApiOperation( value = "查询财务管理分页列表")
    @PostMapping(value = "/pageList")
    public R<PageInfo<YcFinancialManagementVO>> pageList(@RequestBody YcFinancialManagementQuery query) {
        return R.ok(ycFinancialManagementService.pageList(query));
    @ApiOperation( value = "顶部数据统计")
    @PostMapping(value = "/topDataStatistics")
    public R<List<TopDataStatisticsVO>> topDataStatistics(@RequestBody DataStatisticsQuery query) {
        List<TopDataStatisticsVO> topDataStatisticsVOList = new ArrayList<>();
        String startTime = query.getStartTime();
        String endTime = query.getEndTime();
        if (startTime == null || endTime == null) {
            if(Objects.isNull(query.getType())){
                return R.fail("请选择时间");
            }
            switch (query.getType()){
                case 1:
                    startTime = DateUtils.getYearDate(new Date()).get("first").toString();
                    endTime = DateUtils.getYearDate(new Date()).get("last").toString();
                    break;
                case 2:
                    startTime = DateUtils.getMonthDate(new Date()).get("first").toString();
                    endTime = DateUtils.getMonthDate(new Date()).get("last").toString();
                    break;
            }
        }else {
            LambdaQueryWrapper<YcFinancialManagement> wrapper = new LambdaQueryWrapper<>();
            if(StringUtils.hasLength(query.getProvinceCode())){
                wrapper.eq(YcFinancialManagement::getProvinceCode, query.getProvinceCode());
            }
            if(StringUtils.hasLength(query.getCityCode())){
                wrapper.eq(YcFinancialManagement::getCityCode, query.getCityCode());
            }
            wrapper.between(YcFinancialManagement::getPayTime, startTime, endTime);
            List<YcFinancialManagement> list = ycFinancialManagementService.list(wrapper);
            // 收入合计
            BigDecimal incomeSum = list.stream().filter(item -> item.getTypeId() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            TopDataStatisticsVO topDataStatisticsVO = new TopDataStatisticsVO();
            topDataStatisticsVO.setType(1);
            topDataStatisticsVO.setAmount(incomeSum);
            topDataStatisticsVOList.add(topDataStatisticsVO);
            // 支出合计
            BigDecimal expensesSum = list.stream().filter(item -> item.getTypeId() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            topDataStatisticsVO = new TopDataStatisticsVO();
            topDataStatisticsVO.setType(2);
            topDataStatisticsVO.setAmount(expensesSum);
            topDataStatisticsVOList.add(topDataStatisticsVO);
            // 盈亏合计
            BigDecimal profitSum = incomeSum.subtract(expensesSum);
            topDataStatisticsVO = new TopDataStatisticsVO();
            topDataStatisticsVO.setType(3);
            topDataStatisticsVO.setAmount(profitSum);
            topDataStatisticsVOList.add(topDataStatisticsVO);
        }
        LambdaQueryWrapper<YcFinancialManagement> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasLength(query.getProvinceCode())){
            wrapper.eq(YcFinancialManagement::getProvinceCode, query.getProvinceCode());
        }
        if(StringUtils.hasLength(query.getCityCode())){
            wrapper.eq(YcFinancialManagement::getCityCode, query.getCityCode());
        }
        wrapper.between(YcFinancialManagement::getPayTime, startTime, endTime);
        List<YcFinancialManagement> list = ycFinancialManagementService.list(wrapper);
        List<YcFinancialManagement> lastMonth = new ArrayList<>();
        List<YcFinancialManagement> lastYearMonth = new ArrayList<>();
        // 如果选择的是本月
        if(query.getType() == 2){
            // 获取上个月的数据
            LocalDateTime localDateTime = DateUtils.dateToLocalDateTime(new Date()).minusMonths(1);
            Date date = DateUtils.localDateTimeToDate(localDateTime);
            startTime = DateUtils.getMonthDate(date).get("first").toString();
            endTime = DateUtils.getMonthDate(date).get("last").toString();
            lastMonth = ycFinancialManagementService.list(Wrappers.lambdaQuery(YcFinancialManagement.class)
                    .between(YcFinancialManagement::getPayTime, startTime, endTime));
            // 获取去年本月的数据
            LocalDateTime localDateTimeYear = DateUtils.dateToLocalDateTime(new Date()).minusYears(1);
            Date dateYear = DateUtils.localDateTimeToDate(localDateTimeYear);
            startTime = DateUtils.getMonthDate(dateYear).get("first").toString();
            endTime = DateUtils.getMonthDate(dateYear).get("last").toString();
            lastYearMonth = ycFinancialManagementService.list(Wrappers.lambdaQuery(YcFinancialManagement.class)
                    .between(YcFinancialManagement::getPayTime, startTime, endTime));
        }
        // 收入合计
        BigDecimal incomeSum = list.stream().filter(item -> item.getRevenueType() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
        TopDataStatisticsVO topDataStatisticsVO = new TopDataStatisticsVO();
        topDataStatisticsVO.setType(1);
        topDataStatisticsVO.setAmount(incomeSum);
        if(!CollectionUtils.isEmpty(lastMonth)){
            // 环比
            BigDecimal lastMonthMoney = lastMonth.stream().filter(item -> item.getRevenueType() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal subtract = incomeSum.subtract(lastMonthMoney);
            topDataStatisticsVO.setChain(subtract.divide(incomeSum, 2, RoundingMode.HALF_UP));
        }
        if(!CollectionUtils.isEmpty(lastYearMonth)){
            // 同比
            BigDecimal lastYearMonthMoney = lastYearMonth.stream().filter(item -> item.getRevenueType() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal subtract = incomeSum.subtract(lastYearMonthMoney);
            topDataStatisticsVO.setProportion(subtract.divide(incomeSum, 2, RoundingMode.HALF_UP));
        }
        topDataStatisticsVOList.add(topDataStatisticsVO);
        // 支出合计
        BigDecimal expensesSum = list.stream().filter(item -> item.getRevenueType() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
        topDataStatisticsVO = new TopDataStatisticsVO();
        topDataStatisticsVO.setType(2);
        topDataStatisticsVO.setAmount(expensesSum);
        if(!CollectionUtils.isEmpty(lastMonth)){
            // 环比
            BigDecimal lastMonthMoney = lastMonth.stream().filter(item -> item.getRevenueType() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal subtract = expensesSum.subtract(lastMonthMoney);
            topDataStatisticsVO.setChain(subtract.divide(expensesSum, 2, RoundingMode.HALF_UP).negate());
        }
        if(!CollectionUtils.isEmpty(lastYearMonth)){
            // 同比
            BigDecimal lastYearMonthMoney = lastYearMonth.stream().filter(item -> item.getRevenueType() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal subtract = expensesSum.subtract(lastYearMonthMoney);
            topDataStatisticsVO.setProportion(subtract.divide(expensesSum, 2, RoundingMode.HALF_UP).negate());
        }
        topDataStatisticsVOList.add(topDataStatisticsVO);
        // 盈亏合计
        BigDecimal profitSum = incomeSum.subtract(expensesSum);
        topDataStatisticsVO = new TopDataStatisticsVO();
        topDataStatisticsVO.setType(3);
        topDataStatisticsVO.setAmount(profitSum);
        if(!CollectionUtils.isEmpty(lastMonth) && !CollectionUtils.isEmpty(lastYearMonth)){
            // 环比
            BigDecimal lastMonthMoneyIncome = lastMonth.stream().filter(item -> item.getRevenueType() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal lastMonthMoneyExpenses = lastMonth.stream().filter(item -> item.getRevenueType() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal monthProfitSum = lastMonthMoneyIncome.subtract(lastMonthMoneyExpenses);
            BigDecimal chain = profitSum.subtract(monthProfitSum).divide(profitSum, 2, RoundingMode.HALF_UP);
            topDataStatisticsVO.setChain(chain);
            // 同比
            BigDecimal lastYearMonthMoneyIncome = lastYearMonth.stream().filter(item -> item.getRevenueType() == 1).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal lastYearMonthMoneyExpenses = lastYearMonth.stream().filter(item -> item.getRevenueType() == 2).map(YcFinancialManagement::getPayMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal yearMonthProfitSum = lastYearMonthMoneyIncome.subtract(lastYearMonthMoneyExpenses);
            BigDecimal proportion = profitSum.subtract(yearMonthProfitSum).divide(profitSum, 2, RoundingMode.HALF_UP);
            topDataStatisticsVO.setProportion(proportion);
        }
        topDataStatisticsVOList.add(topDataStatisticsVO);
        return R.ok(topDataStatisticsVOList);
    }
    /**
     * 支出类型/收入类型占比统计
     */
    @ApiOperation( value = "支出类型/收入类型占比统计")
    @PostMapping(value = "/expensesIncomeStatistics")
    public R<ExpensesIncomeStatisticsVO> expensesIncomeStatistics(@RequestBody DataStatisticsQuery query) {
        String startTime = query.getStartTime();
        String endTime = query.getEndTime();
        if (startTime == null || endTime == null) {
            if(Objects.isNull(query.getType())){
                return R.fail("请选择时间");
            }
            switch (query.getType()){
                case 1:
                    startTime = DateUtils.getYearDate(new Date()).get("first").toString();
                    endTime = DateUtils.getYearDate(new Date()).get("last").toString();
                    break;
                case 2:
                    startTime = DateUtils.getMonthDate(new Date()).get("first").toString();
                    endTime = DateUtils.getMonthDate(new Date()).get("last").toString();
                    break;
            }
        }
        LambdaQueryWrapper<YcFinancialManagement> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasLength(query.getProvinceCode())){
            wrapper.eq(YcFinancialManagement::getProvinceCode, query.getProvinceCode());
        }
        if(StringUtils.hasLength(query.getCityCode())){
            wrapper.eq(YcFinancialManagement::getCityCode, query.getCityCode());
        }
        wrapper.between(YcFinancialManagement::getPayTime, startTime, endTime);
        ExpensesIncomeStatisticsVO expensesIncomeStatisticsVO = new ExpensesIncomeStatisticsVO();
        // 查询财务数据
        List<YcFinancialManagement> list = ycFinancialManagementService.list(wrapper);
        // 查询所有的类型
        List<YcRevenueExpenditureType> typeList = ycRevenueExpenditureTypeService.list();
        // 封装收入类型财务数据
        List<YcRevenueExpenditureTypeStatisticsVO> incomeStatistics = new ArrayList<>();
        List<YcRevenueExpenditureType> incomeTypes = typeList.stream().filter(type -> type.getRevenueType().equals(1)).collect(Collectors.toList());
        for (YcRevenueExpenditureType incomeType : incomeTypes) {
            YcRevenueExpenditureTypeStatisticsVO ycRevenueExpenditureTypeStatisticsVO = new YcRevenueExpenditureTypeStatisticsVO();
            ycRevenueExpenditureTypeStatisticsVO.setTypeName(incomeType.getTypeName());
            ycRevenueExpenditureTypeStatisticsVO.setCount(list.stream().filter(item -> item.getTypeId().equals(incomeType.getId())).count());
            incomeStatistics.add(ycRevenueExpenditureTypeStatisticsVO);
        }
        expensesIncomeStatisticsVO.setIncomeStatistics(incomeStatistics);
        // 封装支出类型财务数据
        List<YcRevenueExpenditureTypeStatisticsVO> expensesStatistics = new ArrayList<>();
        List<YcRevenueExpenditureType> expensesTypes = typeList.stream().filter(type -> type.getRevenueType().equals(2)).collect(Collectors.toList());
        for (YcRevenueExpenditureType expensesType : expensesTypes) {
            YcRevenueExpenditureTypeStatisticsVO ycRevenueExpenditureTypeStatisticsVO = new YcRevenueExpenditureTypeStatisticsVO();
            ycRevenueExpenditureTypeStatisticsVO.setTypeName(expensesType.getTypeName());
            ycRevenueExpenditureTypeStatisticsVO.setCount(list.stream().filter(item -> item.getTypeId().equals(expensesType.getId())).count());
            expensesStatistics.add(ycRevenueExpenditureTypeStatisticsVO);
        }
        expensesIncomeStatisticsVO.setExpensesStatistics(expensesStatistics);
        return R.ok(expensesIncomeStatisticsVO);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/YcFinancialManagementController.java
@@ -72,6 +72,10 @@
    @Log(title = "财务管理-添加", businessType = BusinessType.INSERT)
    @PostMapping(value = "/add")
    public R<Boolean> add(@RequestBody YcFinancialManagement dto) {
        YcRevenueExpenditureType ycRevenueExpenditureType = ycRevenueExpenditureTypeService.getById(dto.getTypeId());
        if(Objects.nonNull(ycRevenueExpenditureType)){
            dto.setRevenueType(ycRevenueExpenditureType.getRevenueType());
        }
        return R.ok(ycFinancialManagementService.save(dto));
    }
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -369,6 +369,15 @@
    }
    /**
     * 增加 LocalDateTime ==> Date
     */
    public static Date localDateTimeToDate(LocalDateTime time)
    {
        ZonedDateTime zdt = time.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
    /**
     * localdate转为字符串
     *
     * @param time localdate
ruoyi-system/src/main/java/com/ruoyi/system/model/YcFinancialManagement.java
@@ -68,5 +68,7 @@
    @TableField("pay_voucher")
    private String payVoucher;
    @ApiModelProperty(value = "收支类型 1=收入 2=支出")
    @TableField("revenue_type")
    private Integer revenueType;
}
ruoyi-system/src/main/java/com/ruoyi/system/query/DataStatisticsQuery.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.system.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "财务数据统计Query")
public class DataStatisticsQuery implements Serializable {
    @ApiModelProperty(value = "省份")
    private String provinceCode;
    @ApiModelProperty(value = "城市")
    private String cityCode;
    @ApiModelProperty(value = "开始时间")
    private String startTime;
    @ApiModelProperty(value = "结束时间")
    private String endTime;
    @ApiModelProperty(value = "时间类型 1=本年 2=本月")
    private Integer type;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/ExpensesIncomeStatisticsVO.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
@ApiModel(value = "支出收入统计VO")
public class ExpensesIncomeStatisticsVO implements Serializable {
    @ApiModelProperty(value = "支出类型统计")
    private List<YcRevenueExpenditureTypeStatisticsVO> expensesStatistics = new ArrayList<>();
    @ApiModelProperty(value = "收入类型统计")
    private List<YcRevenueExpenditureTypeStatisticsVO> incomeStatistics = new ArrayList<>();
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/TopDataStatisticsVO.java
New file
@@ -0,0 +1,26 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
@ApiModel(value = "顶部数据统计VO")
public class TopDataStatisticsVO implements Serializable {
    @ApiModelProperty(value = "类型 1=收入合计 2=支出合计 3=盈亏合计")
    private Integer type;
    @ApiModelProperty(value = "金额")
    private BigDecimal amount;
    @ApiModelProperty(value = "同比")
    private BigDecimal proportion;
    @ApiModelProperty(value = "环比")
    private BigDecimal chain;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/YcRevenueExpenditureTypeStatisticsVO.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.system.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
@ApiModel(value = "收入、支出统计详情")
public class YcRevenueExpenditureTypeStatisticsVO implements Serializable {
    @ApiModelProperty(value = "类型名称")
    private String typeName;
    @ApiModelProperty(value = "数量")
    private Long count;
}
ruoyi-system/src/main/resources/mapper/system/YcFinancialManagementMapper.xml
@@ -14,6 +14,7 @@
        <result column="pay_time" property="payTime" />
        <result column="pay_remark" property="payRemark" />
        <result column="pay_voucher" property="payVoucher" />
        <result column="revenue_type" property="revenueType" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
@@ -23,12 +24,12 @@
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, province_name,province_code, city_name,city_code, type_id, pay_money, pay_time, pay_remark, pay_voucher, create_time, update_time, create_by, update_by, disabled
        id, province_name,province_code, city_name,city_code, type_id, pay_money, pay_time, pay_remark, pay_voucher,revenue_type, create_time, update_time, create_by, update_by, disabled
    </sql>
    <select id="pageList" resultType="com.ruoyi.system.vo.YcFinancialManagementVO">
        SELECT
            fm.id, fm.province_name,fm.province_code, fm.city_name,fm.city_code, fm.type_id, fm.pay_money, fm.pay_time, fm.pay_remark,
            fm.pay_voucher, fm.create_time, fm.update_time, fm.create_by, fm.update_by, fm.disabled, ty.type_name, ty.revenue_type
            fm.pay_voucher,fm.revenue_type, fm.create_time, fm.update_time, fm.create_by, fm.update_by, fm.disabled, ty.type_name, ty.revenue_type
        FROM yc_financial_management fm
        LEFT JOIN yc_revenue_expenditure_type ty ON fm.type_id = ty.id
        <where>
@@ -54,7 +55,7 @@
    <select id="financialManagementExport" resultType="com.ruoyi.system.export.YcFinancialManagementExport">
        SELECT
        fm.id, fm.province_name,fm.province_code, fm.city_name,fm.city_code, fm.type_id, fm.pay_money, fm.pay_time, fm.pay_remark,
        fm.pay_voucher, fm.create_time, fm.update_time, fm.create_by, fm.update_by, fm.disabled, ty.type_name, ty.revenue_type
        fm.pay_voucher,fm.revenue_type, fm.create_time, fm.update_time, fm.create_by, fm.update_by, fm.disabled, ty.type_name, ty.revenue_type
        FROM yc_financial_management fm
        LEFT JOIN yc_revenue_expenditure_type ty ON fm.type_id = ty.id
        <where>