fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 24s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 3s

This commit is contained in:
SunCheng
2026-01-30 10:41:19 +08:00
parent d9703d31ae
commit 704f58b1a1
46 changed files with 6074 additions and 301 deletions

View File

@@ -21,7 +21,7 @@ public class BudgetStatsTest : BaseTest
public BudgetStatsTest()
{
_dateTimeProvider.Now.Returns(new DateTime(2024, 1, 15));
IBudgetStatsService budgetStatsService = new BudgetStatsService(
_budgetRepository,
_budgetArchiveRepository,
@@ -29,7 +29,7 @@ public class BudgetStatsTest : BaseTest
_dateTimeProvider,
Substitute.For<ILogger<BudgetStatsService>>()
);
_service = new BudgetService(
_budgetRepository,
_budgetArchiveRepository,
@@ -89,7 +89,7 @@ public class BudgetStatsTest : BaseTest
_budgetRepository.GetAllAsync().Returns(budgets);
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(0m); // 实际支出的金额为0
_dateTimeProvider.Now.Returns(referenceDate);
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
.Returns(new Dictionary<DateTime, decimal>());
@@ -117,7 +117,7 @@ public class BudgetStatsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
// 月度统计使用趋势统计数据(只包含月度预算的分类)
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
@@ -128,7 +128,7 @@ public class BudgetStatsTest : BaseTest
{
{ new DateTime(2024, 1, 15), 800m } // 1月15日月度吃饭累计800
});
// 年度统计使用GetCurrentAmountAsync
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(args =>
@@ -136,22 +136,22 @@ public class BudgetStatsTest : BaseTest
var b = (BudgetRecord)args[0];
var startDate = (DateTime)args[1];
var endDate = (DateTime)args[2];
// 月度范围查询 - 月度吃饭1月
if (startDate.Month == 1 && startDate.Day == 1 && endDate.Month == 1)
{
return b.Name == "月度吃饭" ? 800m : 0m;
}
// 年度范围查询 - 年度旅游
if (startDate.Month == 1 && startDate.Day == 1 && endDate.Month == 12)
{
return b.Name == "年度旅游" ? 2000m : 0m;
}
return 0m;
});
// 年度趋势统计(包含所有分类)
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
@@ -172,7 +172,7 @@ public class BudgetStatsTest : BaseTest
result.Month.Limit.Should().Be(3000); // 月度吃饭3000
result.Month.Current.Should().Be(800); // 月度吃饭已用800从GetCurrentAmountAsync获取
result.Month.Count.Should().Be(1); // 只包含1个月度预算
// 年度统计中:包含所有预算(月度预算按剩余月份折算)
// 1月时月度预算分为当前月(1月) + 剩余月份(2-12月共11个月)
result.Year.Limit.Should().Be(12000 + (3000 * 12)); // 年度旅游12000 + 月度吃饭折算年度(3000*12=36000) = 48000
@@ -239,7 +239,7 @@ public class BudgetStatsTest : BaseTest
{
// Arrange
var referenceDate = new DateTime(2024, 1, 15);
// 设置预算:包含月度预算和年度预算
var budgets = new List<BudgetRecord>
{
@@ -257,7 +257,7 @@ public class BudgetStatsTest : BaseTest
};
_budgetRepository.GetAllAsync().Returns(budgets);
// 设置月度预算的当前金额
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
.Returns(args =>
@@ -272,7 +272,7 @@ public class BudgetStatsTest : BaseTest
_ => 0m
};
});
// 设置月度趋势统计数据:只包含月度预算相关的分类(餐饮、零食、交通)
// 注意:不应包含年度预算的分类(旅游、度假、奖金、年终奖)
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
@@ -284,7 +284,7 @@ public class BudgetStatsTest : BaseTest
{
{ new DateTime(2024, 1, 15), 1500m } // 1月15日累计1500吃喝1200+交通300不包含年度旅游2000
});
// 设置年度趋势统计数据:包含所有预算相关的分类
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1 && d.Day == 1),
@@ -296,7 +296,7 @@ public class BudgetStatsTest : BaseTest
{
{ new DateTime(2024, 1, 1), 3500m } // 1月累计3500吃喝1200+交通300+年度旅游2000
});
// 设置收入相关的趋势统计数据
_transactionStatisticsService.GetFilteredTrendStatisticsAsync(
Arg.Is<DateTime>(d => d.Year == 2024 && d.Month == 1),
@@ -304,7 +304,7 @@ public class BudgetStatsTest : BaseTest
TransactionType.Income,
Arg.Any<List<string>>())
.Returns(new Dictionary<DateTime, decimal>()); // 月度收入为空
_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),
@@ -318,7 +318,7 @@ public class BudgetStatsTest : BaseTest
// Act - 测试支出统计
var expenseResult = await _service.GetCategoryStatsAsync(BudgetCategory.Expense, referenceDate);
// Act - 测试收入统计
var incomeResult = await _service.GetCategoryStatsAsync(BudgetCategory.Income, referenceDate);
@@ -345,17 +345,17 @@ public class BudgetStatsTest : BaseTest
incomeResult.Year.Count.Should().Be(1); // 包含1个年度收入预算
}
[Fact]
public async Task GetCategoryStats_年度_3月_2月预算变更_Test()
{
// Arrange
// 测试场景2024年3月查看年度预算统计其中2月份发生了预算变更吃喝预算从2000增加到2500
var referenceDate = new DateTime(2024, 3, 15);
// 设置当前时间确保3月被认为是当前月份
_dateTimeProvider.Now.Returns(new DateTime(2024, 3, 15));
// 当前3月份有效的预算
var currentBudgets = new List<BudgetRecord>
{
@@ -426,11 +426,11 @@ public class BudgetStatsTest : BaseTest
// 设置仓储响应
_budgetRepository.GetAllAsync().Returns(currentBudgets);
// 设置归档仓储响应
_budgetArchiveRepository.GetArchiveAsync(2024, 2).Returns(febArchive);
_budgetArchiveRepository.GetArchiveAsync(2024, 1).Returns(janArchive);
// 设置月度预算的当前金额查询仅用于3月份
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Is<DateTime>(d => d.Month == 3), Arg.Is<DateTime>(d => d.Month == 3))
.Returns(args =>
@@ -443,11 +443,11 @@ public class BudgetStatsTest : BaseTest
_ => 0m
};
});
// 年度旅游的年度金额查询
_budgetRepository.GetCurrentAmountAsync(
Arg.Is<BudgetRecord>(b => b.Id == 3),
Arg.Is<DateTime>(d => d.Month == 1),
Arg.Is<BudgetRecord>(b => b.Id == 3),
Arg.Is<DateTime>(d => d.Month == 1),
Arg.Is<DateTime>(d => d.Month == 12))
.Returns(2500m); // 年度旅游1-3月已花费2500
@@ -477,11 +477,11 @@ public class BudgetStatsTest : BaseTest
// 3月累计月度预算1000 + 年度旅游2500 = 3500
{ new DateTime(2024, 3, 1), 3500m }
});
// 补充年度旅游的GetCurrentAmountAsync调用用于计算Current
_budgetRepository.GetCurrentAmountAsync(
Arg.Is<BudgetRecord>(b => b.Id == 3),
Arg.Is<DateTime>(d => d.Month == 1),
Arg.Is<BudgetRecord>(b => b.Id == 3),
Arg.Is<DateTime>(d => d.Month == 1),
Arg.Is<DateTime>(d => d.Month == 12))
.Returns(2500m); // 年度旅游1-3月已花费2500
@@ -494,7 +494,7 @@ public class BudgetStatsTest : BaseTest
_dateTimeProvider,
Substitute.For<ILogger<BudgetStatsService>>()
);
var result = await budgetStatsService.GetCategoryStatsAsync(BudgetCategory.Expense, referenceDate);
// Assert - 月度统计3月份
@@ -502,7 +502,7 @@ public class BudgetStatsTest : BaseTest
result.Month.Limit.Should().Be(3000); // 吃喝2500 + 交通500使用变更后的预算
result.Month.Current.Should().Be(1000); // 吃喝800 + 交通200
result.Month.Count.Should().Be(2); // 包含2个月度预算
// Assert - 年度统计(需要考虑预算变更和剩余月份)
// 新逻辑:
// 1. 对于归档数据,直接使用归档的限额,不折算
@@ -515,7 +515,7 @@ public class BudgetStatsTest : BaseTest
// 年度旅游12000
// 总计2500 + 2500 + 30000 + 12000 = 47000
result.Year.Limit.Should().Be(47000);
// 预期年度实际金额:
// 根据趋势统计数据3月累计: 月度预算1000 + 年度旅游2500 = 3500
// 但业务代码会累加所有预算项的Current值
@@ -528,7 +528,7 @@ public class BudgetStatsTest : BaseTest
// - 年度旅游2500
// 总计1500+250+1800+300+800+200+2500 = 7350
result.Year.Current.Should().Be(7350);
// 应该包含:
// - 1月归档的月度预算吃喝、1个
// - 1月归档的月度预算交通、1个
@@ -541,7 +541,7 @@ public class BudgetStatsTest : BaseTest
// - 年度旅游1个
// 总计9个
result.Year.Count.Should().Be(9);
// 验证使用率计算正确
result.Month.Rate.Should().BeApproximately(1000m / 3000m * 100, 0.01m);
// 年度使用率7350 / 47000 * 100 = 15.64%