All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 4m27s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
203 lines
8.1 KiB
C#
203 lines
8.1 KiB
C#
using Application.Dto.Statistics;
|
||
using Service.Transaction;
|
||
|
||
namespace Application;
|
||
|
||
/// <summary>
|
||
/// 交易统计应用服务接口
|
||
/// </summary>
|
||
public interface ITransactionStatisticsApplication
|
||
{
|
||
// === 新统一接口(推荐使用) ===
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取每日统计(新统一接口)
|
||
/// </summary>
|
||
Task<List<DailyStatisticsDto>> GetDailyStatisticsByRangeAsync(DateTime startDate, DateTime endDate, string? savingClassify = null);
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取汇总统计(新统一接口)
|
||
/// </summary>
|
||
Task<MonthlyStatistics> GetSummaryByRangeAsync(DateTime startDate, DateTime endDate);
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取分类统计(新统一接口)
|
||
/// </summary>
|
||
Task<List<CategoryStatistics>> GetCategoryStatisticsByRangeAsync(DateTime startDate, DateTime endDate, TransactionType type);
|
||
|
||
/// <summary>
|
||
/// 获取趋势统计数据
|
||
/// </summary>
|
||
Task<List<TrendStatistics>> GetTrendStatisticsAsync(int startYear, int startMonth, int monthCount);
|
||
|
||
// === 旧接口(保留用于向后兼容,建议迁移到新接口) ===
|
||
|
||
[Obsolete("请使用 GetDailyStatisticsByRangeAsync")]
|
||
Task<List<BalanceStatisticsDto>> GetBalanceStatisticsAsync(int year, int month);
|
||
|
||
[Obsolete("请使用 GetDailyStatisticsByRangeAsync")]
|
||
Task<List<DailyStatisticsDto>> GetDailyStatisticsAsync(int year, int month);
|
||
|
||
[Obsolete("请使用 GetDailyStatisticsByRangeAsync")]
|
||
Task<List<DailyStatisticsDto>> GetWeeklyStatisticsAsync(DateTime startDate, DateTime endDate);
|
||
|
||
[Obsolete("请使用 GetSummaryByRangeAsync")]
|
||
Task<MonthlyStatistics> GetRangeStatisticsAsync(DateTime startDate, DateTime endDate);
|
||
|
||
[Obsolete("请使用 GetSummaryByRangeAsync")]
|
||
Task<MonthlyStatistics> GetMonthlyStatisticsAsync(int year, int month);
|
||
|
||
[Obsolete("请使用 GetCategoryStatisticsByRangeAsync")]
|
||
Task<List<CategoryStatistics>> GetCategoryStatisticsAsync(int year, int month, TransactionType type);
|
||
|
||
[Obsolete("请使用 GetCategoryStatisticsByRangeAsync")]
|
||
Task<List<CategoryStatistics>> GetCategoryStatisticsByDateRangeAsync(string startDate, string endDate, TransactionType type);
|
||
|
||
Task<(List<ReasonGroupDto> list, int total)> GetReasonGroupsAsync(int pageIndex, int pageSize);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 交易统计应用服务实现
|
||
/// </summary>
|
||
public class TransactionStatisticsApplication(
|
||
ITransactionStatisticsService statisticsService,
|
||
IConfigService configService
|
||
) : ITransactionStatisticsApplication
|
||
{
|
||
// === 新统一接口实现 ===
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取每日统计(新统一接口)
|
||
/// </summary>
|
||
public async Task<List<DailyStatisticsDto>> GetDailyStatisticsByRangeAsync(DateTime startDate, DateTime endDate, string? savingClassify = null)
|
||
{
|
||
// 如果未指定 savingClassify,从配置读取
|
||
savingClassify ??= await configService.GetConfigByKeyAsync<string>("SavingsCategories");
|
||
|
||
var statistics = await statisticsService.GetDailyStatisticsByRangeAsync(startDate, endDate, savingClassify);
|
||
|
||
return statistics.Select(s => new DailyStatisticsDto(
|
||
DateTime.Parse(s.Key).Day,
|
||
s.Value.count,
|
||
s.Value.expense,
|
||
s.Value.income,
|
||
s.Value.saving
|
||
)).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取汇总统计(新统一接口)
|
||
/// </summary>
|
||
public async Task<MonthlyStatistics> GetSummaryByRangeAsync(DateTime startDate, DateTime endDate)
|
||
{
|
||
return await statisticsService.GetSummaryByRangeAsync(startDate, endDate);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按日期范围获取分类统计(新统一接口)
|
||
/// </summary>
|
||
public async Task<List<CategoryStatistics>> GetCategoryStatisticsByRangeAsync(DateTime startDate, DateTime endDate, TransactionType type)
|
||
{
|
||
return await statisticsService.GetCategoryStatisticsByDateRangeAsync(startDate, endDate, type);
|
||
}
|
||
|
||
// === 旧接口实现(保留用于向后兼容) ===
|
||
|
||
public async Task<List<BalanceStatisticsDto>> GetBalanceStatisticsAsync(int year, int month)
|
||
{
|
||
var savingClassify = await configService.GetConfigByKeyAsync<string>("SavingsCategories");
|
||
var statistics = await statisticsService.GetDailyStatisticsAsync(year, month, savingClassify);
|
||
|
||
var sortedStats = statistics.OrderBy(s => DateTime.Parse(s.Key)).ToList();
|
||
var result = new List<BalanceStatisticsDto>();
|
||
decimal cumulativeBalance = 0;
|
||
|
||
foreach (var item in sortedStats)
|
||
{
|
||
var dailyBalance = item.Value.income - item.Value.expense;
|
||
cumulativeBalance += dailyBalance;
|
||
result.Add(new BalanceStatisticsDto(DateTime.Parse(item.Key).Day, cumulativeBalance));
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
public async Task<List<DailyStatisticsDto>> GetDailyStatisticsAsync(int year, int month)
|
||
{
|
||
var savingClassify = await configService.GetConfigByKeyAsync<string>("SavingsCategories");
|
||
var statistics = await statisticsService.GetDailyStatisticsAsync(year, month, savingClassify);
|
||
|
||
return statistics.Select(s => new DailyStatisticsDto(
|
||
DateTime.Parse(s.Key).Day, // 从完整日期字符串 "yyyy-MM-dd" 中提取 day
|
||
s.Value.count,
|
||
s.Value.expense,
|
||
s.Value.income,
|
||
s.Value.saving
|
||
)).ToList();
|
||
}
|
||
|
||
public async Task<List<DailyStatisticsDto>> GetWeeklyStatisticsAsync(DateTime startDate, DateTime endDate)
|
||
{
|
||
var savingClassify = await configService.GetConfigByKeyAsync<string>("SavingsCategories");
|
||
var statistics = await statisticsService.GetDailyStatisticsByRangeAsync(startDate, endDate, savingClassify);
|
||
|
||
return statistics.Select(s => new DailyStatisticsDto(
|
||
DateTime.Parse(s.Key).Day, // 从完整日期字符串 "yyyy-MM-dd" 中提取 day
|
||
s.Value.count,
|
||
s.Value.expense,
|
||
s.Value.income,
|
||
s.Value.saving
|
||
)).ToList();
|
||
}
|
||
|
||
public async Task<MonthlyStatistics> GetRangeStatisticsAsync(DateTime startDate, DateTime endDate)
|
||
{
|
||
var records = await statisticsService.GetDailyStatisticsByRangeAsync(startDate, endDate, null);
|
||
|
||
var totalExpense = records.Sum(r => r.Value.expense);
|
||
var totalIncome = records.Sum(r => r.Value.income);
|
||
var totalCount = records.Sum(r => r.Value.count);
|
||
var expenseCount = records.Count(r => r.Value.expense > 0);
|
||
var incomeCount = records.Count(r => r.Value.income > 0);
|
||
|
||
return new MonthlyStatistics
|
||
{
|
||
Year = startDate.Year,
|
||
Month = startDate.Month,
|
||
TotalExpense = totalExpense,
|
||
TotalIncome = totalIncome,
|
||
Balance = totalIncome - totalExpense,
|
||
ExpenseCount = expenseCount,
|
||
IncomeCount = incomeCount,
|
||
TotalCount = totalCount
|
||
};
|
||
}
|
||
|
||
public async Task<MonthlyStatistics> GetMonthlyStatisticsAsync(int year, int month)
|
||
{
|
||
return await statisticsService.GetMonthlyStatisticsAsync(year, month);
|
||
}
|
||
|
||
public async Task<List<CategoryStatistics>> GetCategoryStatisticsAsync(int year, int month, TransactionType type)
|
||
{
|
||
return await statisticsService.GetCategoryStatisticsAsync(year, month, type);
|
||
}
|
||
|
||
public async Task<List<CategoryStatistics>> GetCategoryStatisticsByDateRangeAsync(string startDate, string endDate, TransactionType type)
|
||
{
|
||
var start = DateTime.Parse(startDate);
|
||
var end = DateTime.Parse(endDate);
|
||
return await statisticsService.GetCategoryStatisticsByDateRangeAsync(start, end, type);
|
||
}
|
||
|
||
public async Task<List<TrendStatistics>> GetTrendStatisticsAsync(int startYear, int startMonth, int monthCount)
|
||
{
|
||
return await statisticsService.GetTrendStatisticsAsync(startYear, startMonth, monthCount);
|
||
}
|
||
|
||
public async Task<(List<ReasonGroupDto> list, int total)> GetReasonGroupsAsync(int pageIndex, int pageSize)
|
||
{
|
||
return await statisticsService.GetReasonGroupsAsync(pageIndex, pageSize);
|
||
}
|
||
}
|