重构账单查询sql
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 26s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s

This commit is contained in:
SunCheng
2026-01-28 10:58:15 +08:00
parent 5c9d7c5db1
commit b71eadd4f9
19 changed files with 1433 additions and 730 deletions

View File

@@ -1,10 +1,10 @@
namespace WebApi.Test.Budget;
namespace WebApi.Test.Budget;
public class BudgetSavingsTest : BaseTest
{
private readonly IBudgetRepository _budgetRepository = Substitute.For<IBudgetRepository>();
private readonly IBudgetArchiveRepository _budgetArchiveRepository = Substitute.For<IBudgetArchiveRepository>();
private readonly ITransactionRecordRepository _transactionsRepository = Substitute.For<ITransactionRecordRepository>();
private readonly ITransactionStatisticsService _transactionStatisticsService = Substitute.For<ITransactionStatisticsService>();
private readonly IConfigService _configService = Substitute.For<IConfigService>();
private readonly IDateTimeProvider _dateTimeProvider = Substitute.For<IDateTimeProvider>();
private readonly BudgetSavingsService _service;
@@ -15,7 +15,7 @@ public class BudgetSavingsTest : BaseTest
_service = new BudgetSavingsService(
_budgetRepository,
_budgetArchiveRepository,
_transactionsRepository,
_transactionStatisticsService,
_configService,
_dateTimeProvider
);
@@ -47,7 +47,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(transactions);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -97,7 +97,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(transactions);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -141,7 +141,7 @@ public class BudgetSavingsTest : BaseTest
var transactions = new Dictionary<(string, TransactionType), decimal>();
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(transactions);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -183,7 +183,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(transactions);
_budgetArchiveRepository.GetArchivesByYearAsync(year).Returns(new List<BudgetArchive>());
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -280,7 +280,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(currentTransactions);
_budgetArchiveRepository.GetArchivesByYearAsync(year).Returns(archives);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -376,7 +376,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(currentTransactions);
_budgetArchiveRepository.GetArchivesByYearAsync(year).Returns(archives);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));
@@ -477,7 +477,7 @@ public class BudgetSavingsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
_transactionsRepository.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
_transactionStatisticsService.GetAmountGroupByClassifyAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(currentTransactions);
_budgetArchiveRepository.GetArchivesByYearAsync(year).Returns(archives);
_configService.GetConfigByKeyAsync<string>("SavingsCategories").Returns(Task.FromResult<string?>("存款"));

View File

@@ -7,6 +7,7 @@ public class BudgetStatsTest : BaseTest
private readonly IBudgetRepository _budgetRepository = Substitute.For<IBudgetRepository>();
private readonly IBudgetArchiveRepository _budgetArchiveRepository = Substitute.For<IBudgetArchiveRepository>();
private readonly ITransactionRecordRepository _transactionsRepository = Substitute.For<ITransactionRecordRepository>();
private readonly ITransactionStatisticsService _transactionStatisticsService = Substitute.For<ITransactionStatisticsService>();
private readonly IOpenAiService _openAiService = Substitute.For<IOpenAiService>();
private readonly IMessageService _messageService = Substitute.For<IMessageService>();
private readonly ILogger<BudgetService> _logger = Substitute.For<ILogger<BudgetService>>();
@@ -22,7 +23,7 @@ public class BudgetStatsTest : BaseTest
_budgetStatsService = new BudgetStatsService(
_budgetRepository,
_budgetArchiveRepository,
_transactionsRepository,
_transactionStatisticsService,
_dateTimeProvider,
Substitute.For<ILogger<BudgetStatsService>>()
);
@@ -31,6 +32,7 @@ public class BudgetStatsTest : BaseTest
_budgetRepository,
_budgetArchiveRepository,
_transactionsRepository,
_transactionStatisticsService,
_openAiService,
_messageService,
_logger,
@@ -58,7 +60,7 @@ public class BudgetStatsTest : BaseTest
var b = (BudgetRecord)args[0];
return b.Name == "吃喝" ? 1200m : 300m;
});
_transactionsRepository.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
.Returns(new Dictionary<DateTime, decimal>
{
{ new DateTime(2024, 1, 15), 1500m } // 1月15日累计1500吃喝1200+交通300
@@ -87,7 +89,7 @@ public class BudgetStatsTest : BaseTest
.Returns(0m); // 实际支出的金额为0
_dateTimeProvider.Now.Returns(referenceDate);
_transactionsRepository.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
.Returns(new Dictionary<DateTime, decimal>());
// Act
@@ -115,7 +117,7 @@ public class BudgetStatsTest : BaseTest
_budgetRepository.GetAllAsync().Returns(budgets);
// 月度统计使用趋势统计数据(只包含月度预算的分类)
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 31),
TransactionType.Expense,
@@ -150,7 +152,7 @@ public class BudgetStatsTest : BaseTest
});
// 年度趋势统计(包含所有分类)
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 12 && d.Day == 31),
TransactionType.Expense,
@@ -190,7 +192,7 @@ public class BudgetStatsTest : BaseTest
_budgetRepository.GetAllAsync().Returns(budgets);
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>()).Returns(0m);
_dateTimeProvider.Now.Returns(referenceDate);
_transactionsRepository.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
.Returns(new Dictionary<DateTime, decimal>());
// Act
@@ -217,7 +219,7 @@ public class BudgetStatsTest : BaseTest
_budgetRepository.GetAllAsync().Returns(budgets);
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>()).Returns(0m);
_dateTimeProvider.Now.Returns(referenceDate);
_transactionsRepository.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
.Returns(new Dictionary<DateTime, decimal>());
// Act
@@ -272,7 +274,7 @@ public class BudgetStatsTest : BaseTest
// 设置月度趋势统计数据:只包含月度预算相关的分类(餐饮、零食、交通)
// 注意:不应包含年度预算的分类(旅游、度假、奖金、年终奖)
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1),
TransactionType.Expense,
@@ -284,7 +286,7 @@ public class BudgetStatsTest : BaseTest
});
// 设置年度趋势统计数据:包含所有预算相关的分类
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 12 && d.Day == 31),
TransactionType.Expense,
@@ -296,7 +298,7 @@ public class BudgetStatsTest : BaseTest
});
// 设置收入相关的趋势统计数据
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1),
TransactionType.Income,
@@ -304,7 +306,7 @@ public class BudgetStatsTest : BaseTest
false)
.Returns(new Dictionary<DateTime, decimal>()); // 月度收入为空
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 12 && d.Day == 31),
TransactionType.Income,
@@ -451,7 +453,7 @@ public class BudgetStatsTest : BaseTest
.Returns(2500m); // 年度旅游1-3月已花费2500
// 设置趋势统计数据查询(用于月度统计)
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Month == 3),
Arg.Is<DateTime>(d => d.Month == 3),
Arg.Any<TransactionType>(),
@@ -465,7 +467,7 @@ public class BudgetStatsTest : BaseTest
// 年度趋势统计数据查询
// 注意年度统计使用GetFilteredTrendStatisticsAsync获取趋势数据
// 需要返回所有分类的累计金额包括年度旅游的2500
_transactionsRepository.GetFilteredTrendStatisticsAsync(
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Month == 1),
Arg.Is<DateTime>(d => d.Month == 12),
Arg.Any<TransactionType>(),
@@ -489,7 +491,7 @@ public class BudgetStatsTest : BaseTest
var budgetStatsService = new BudgetStatsService(
_budgetRepository,
_budgetArchiveRepository,
_transactionsRepository,
_transactionStatisticsService,
_dateTimeProvider,
Substitute.For<ILogger<BudgetStatsService>>()
);