package com.ruoyi.web.controller.api;
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.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.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.text.SimpleDateFormat;
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;
/**
*
* 财务管理 前端控制器
*
*
* @author xiaochen
* @since 2025-07-15
*/
@Api(tags = "财务数据汇总")
@RestController
@RequestMapping("/dataStatistics")
public class DataStatisticsController {
private final YcRevenueExpenditureTypeService ycRevenueExpenditureTypeService;
private final YcFinancialManagementService ycFinancialManagementService;
private final TokenService tokenService;
@Autowired
public DataStatisticsController(YcRevenueExpenditureTypeService ycRevenueExpenditureTypeService, YcFinancialManagementService ycFinancialManagementService, TokenService tokenService) {
this.ycRevenueExpenditureTypeService = ycRevenueExpenditureTypeService;
this.ycFinancialManagementService = ycFinancialManagementService;
this.tokenService = tokenService;
}
/**
* 顶部数据统计
*/
@ApiOperation( value = "顶部数据统计")
@PostMapping(value = "/topDataStatistics")
public R> topDataStatistics(@RequestBody DataStatisticsQuery query) {
List topDataStatisticsVOList = new ArrayList<>();
String startTime = query.getStartTime();
String endTime = query.getEndTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (!StringUtils.hasLength(startTime) || !StringUtils.hasLength(endTime)) {
if(Objects.isNull(query.getType())){
return R.fail("请选择时间");
}
switch (query.getType()){
case 1:
Date startDate = DateUtils.getYearDate(new Date()).get("first");
Date endDate = DateUtils.getYearDate(new Date()).get("last");
startTime = format.format(startDate);
endTime = format.format(endDate);
break;
case 2:
Date startDate1 = DateUtils.getMonthDate(new Date()).get("first");
Date endDate1 = DateUtils.getMonthDate(new Date()).get("last");
startTime = format.format(startDate1);
endTime = format.format(endDate1);
break;
}
}else {
LambdaQueryWrapper 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 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 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 list = ycFinancialManagementService.list(wrapper);
List lastMonth = new ArrayList<>();
List lastYearMonth = new ArrayList<>();
// 如果选择的是本月
if(Objects.nonNull(query.getType()) && query.getType() == 2){
// 获取上个月的数据
LocalDateTime localDateTime = DateUtils.dateToLocalDateTime(new Date()).minusMonths(1);
Date date = DateUtils.localDateTimeToDate(localDateTime);
Date monthStartDate1 = DateUtils.getMonthDate(date).get("first");
Date monthEndDate1 = DateUtils.getMonthDate(date).get("last");
startTime = format.format(monthStartDate1);
endTime = format.format(monthEndDate1);
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);
Date monthStartDate2 = DateUtils.getMonthDate(dateYear).get("first");
Date monthEndDate2 = DateUtils.getMonthDate(dateYear).get("last");
startTime = format.format(monthStartDate2);
endTime = format.format(monthEndDate2);
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);
if(lastMonthMoney.compareTo(BigDecimal.ZERO) == 0){
topDataStatisticsVO.setChain(subtract.multiply(new BigDecimal(100)));
}else {
topDataStatisticsVO.setChain(subtract.divide(lastMonthMoney, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
}
}
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);
if(lastYearMonthMoney.compareTo(BigDecimal.ZERO) == 0){
topDataStatisticsVO.setProportion(subtract.multiply(new BigDecimal(100)));
}else {
topDataStatisticsVO.setProportion(subtract.divide(lastYearMonthMoney, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
}
}
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);
if(lastMonthMoney.compareTo(BigDecimal.ZERO) == 0){
topDataStatisticsVO.setChain(subtract.multiply(new BigDecimal(100)));
}else {
topDataStatisticsVO.setChain(subtract.divide(lastMonthMoney, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
}
}
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);
if(lastYearMonthMoney.compareTo(BigDecimal.ZERO) == 0){
topDataStatisticsVO.setProportion(subtract.multiply(new BigDecimal(100)));
}else {
topDataStatisticsVO.setProportion(subtract.divide(lastYearMonthMoney, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
}
}
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;
if(monthProfitSum.compareTo(BigDecimal.ZERO) == 0){
chain = profitSum.subtract(monthProfitSum).multiply(new BigDecimal(100));
}else {
chain = profitSum.subtract(monthProfitSum).divide(monthProfitSum, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
}
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;
if(yearMonthProfitSum.compareTo(BigDecimal.ZERO) == 0){
proportion = profitSum.subtract(yearMonthProfitSum).multiply(new BigDecimal(100));
}else {
proportion = profitSum.subtract(yearMonthProfitSum).divide(yearMonthProfitSum, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
}
topDataStatisticsVO.setProportion(proportion);
}
topDataStatisticsVOList.add(topDataStatisticsVO);
return R.ok(topDataStatisticsVOList);
}
/**
* 支出类型/收入类型占比统计
*/
@ApiOperation( value = "支出类型/收入类型占比统计")
@PostMapping(value = "/expensesIncomeStatistics")
public R expensesIncomeStatistics(@RequestBody DataStatisticsQuery query) {
String startTime = query.getStartTime();
String endTime = query.getEndTime();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (!StringUtils.hasLength(startTime) || !StringUtils.hasLength(endTime)) {
if(Objects.isNull(query.getType())){
return R.fail("请选择时间");
}
switch (query.getType()){
case 1:
Date startDate = DateUtils.getYearDate(new Date()).get("first");
Date endDate = DateUtils.getYearDate(new Date()).get("last");
startTime = format.format(startDate);
endTime = format.format(endDate);
break;
case 2:
Date startDate1 = DateUtils.getMonthDate(new Date()).get("first");
Date endDate1 = DateUtils.getMonthDate(new Date()).get("last");
startTime = format.format(startDate1);
endTime = format.format(endDate1);
break;
}
}
LambdaQueryWrapper 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 list = ycFinancialManagementService.list(wrapper);
// 查询所有的类型
List typeList = ycRevenueExpenditureTypeService.list();
// 封装收入类型财务数据
List incomeStatistics = new ArrayList<>();
List 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 expensesStatistics = new ArrayList<>();
List 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);
}
}