fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 23s
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
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 23s
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:
@@ -1,4 +1,4 @@
|
|||||||
namespace Service.Budget;
|
namespace Service.Budget;
|
||||||
|
|
||||||
public interface IBudgetService
|
public interface IBudgetService
|
||||||
{
|
{
|
||||||
@@ -183,6 +183,12 @@ public class BudgetService(
|
|||||||
.Where(b => b.Category == category && !b.NoLimit)
|
.Where(b => b.Category == category && !b.NoLimit)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
// 月度统计中,只包含月度预算;年度统计中,包含所有预算
|
||||||
|
if (statType == BudgetPeriodType.Month)
|
||||||
|
{
|
||||||
|
relevant = relevant.Where(b => b.Type == BudgetPeriodType.Month).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
if (relevant.Count == 0)
|
if (relevant.Count == 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -204,12 +210,7 @@ public class BudgetService(
|
|||||||
{
|
{
|
||||||
// 限额折算
|
// 限额折算
|
||||||
var itemLimit = budget.Limit;
|
var itemLimit = budget.Limit;
|
||||||
if (statType == BudgetPeriodType.Month && budget.Type == BudgetPeriodType.Year)
|
if (statType == BudgetPeriodType.Year && budget.Type == BudgetPeriodType.Month)
|
||||||
{
|
|
||||||
// 月度视图下,年度预算不参与限额计算
|
|
||||||
itemLimit = 0;
|
|
||||||
}
|
|
||||||
else if (statType == BudgetPeriodType.Year && budget.Type == BudgetPeriodType.Month)
|
|
||||||
{
|
{
|
||||||
// 年度视图下,月度预算折算为年度
|
// 年度视图下,月度预算折算为年度
|
||||||
itemLimit = budget.Limit * 12;
|
itemLimit = budget.Limit * 12;
|
||||||
@@ -229,13 +230,13 @@ public class BudgetService(
|
|||||||
IsMandatoryExpense = budget.IsMandatoryExpense
|
IsMandatoryExpense = budget.IsMandatoryExpense
|
||||||
}, referenceDate);
|
}, referenceDate);
|
||||||
|
|
||||||
if (budget.Type == statType)
|
if (statType == BudgetPeriodType.Month)
|
||||||
{
|
{
|
||||||
totalCurrent += currentAmount;
|
totalCurrent += currentAmount;
|
||||||
}
|
}
|
||||||
else if (statType == BudgetPeriodType.Year && budget.Type == BudgetPeriodType.Month)
|
else if (statType == BudgetPeriodType.Year)
|
||||||
{
|
{
|
||||||
// 年度视图下,月度预算计入其当前值(作为对年度目前的贡献)
|
// 年度视图下,累加所有预算的当前值
|
||||||
totalCurrent += currentAmount;
|
totalCurrent += currentAmount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Common;
|
using Common;
|
||||||
|
|
||||||
namespace WebApi.Test.Budget;
|
namespace WebApi.Test.Budget;
|
||||||
@@ -55,10 +55,8 @@ public class BudgetTest : BaseTest
|
|||||||
var result = await _service.GetCategoryStatsAsync(BudgetCategory.Expense, referenceDate);
|
var result = await _service.GetCategoryStatsAsync(BudgetCategory.Expense, referenceDate);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Month.Limit.Should().Be(2500);
|
result.Month.Limit.Should().Be(2500); // 吃喝2000 + 交通500
|
||||||
result.Month.Current.Should().Be(1500);
|
result.Month.Current.Should().Be(1500); // 吃喝1200 + 交通300
|
||||||
result.Month.Count.Should().Be(2);
|
|
||||||
result.Month.Rate.Should().Be(1500m / 2500m * 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -169,4 +167,75 @@ public class BudgetTest : BaseTest
|
|||||||
result.Year.Limit.Should().Be(3660);
|
result.Year.Limit.Should().Be(3660);
|
||||||
result.Year.Current.Should().Be(910);
|
result.Year.Current.Should().Be(910);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetCategoryStats_月度_发生年度收支_Test()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var referenceDate = new DateTime(2024, 1, 15);
|
||||||
|
|
||||||
|
// 设置预算:包含月度预算和年度预算
|
||||||
|
var budgets = new List<BudgetRecord>
|
||||||
|
{
|
||||||
|
// 月度预算:吃喝
|
||||||
|
new() { Id = 1, Name = "吃喝", Limit = 2000, Category = BudgetCategory.Expense, Type = BudgetPeriodType.Month, SelectedCategories = "餐饮,零食" },
|
||||||
|
|
||||||
|
// 月度预算:交通
|
||||||
|
new() { Id = 2, Name = "交通", Limit = 500, Category = BudgetCategory.Expense, Type = BudgetPeriodType.Month, SelectedCategories = "交通" },
|
||||||
|
|
||||||
|
// 年度预算:年度旅游(当前月度发生了相关支出)
|
||||||
|
new() { Id = 3, Name = "年度旅游", Limit = 12000, Category = BudgetCategory.Expense, Type = BudgetPeriodType.Year, SelectedCategories = "旅游,度假" },
|
||||||
|
|
||||||
|
// 年度预算:年度奖金(当前月度发生了相关收入)
|
||||||
|
new() { Id = 4, Name = "年度奖金", Limit = 50000, Category = BudgetCategory.Income, Type = BudgetPeriodType.Year, SelectedCategories = "奖金,年终奖" }
|
||||||
|
};
|
||||||
|
|
||||||
|
_budgetRepository.GetAllAsync().Returns(budgets);
|
||||||
|
|
||||||
|
// 设置月度预算的当前金额
|
||||||
|
_budgetRepository.GetCurrentAmountAsync(Arg.Any<BudgetRecord>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||||||
|
.Returns(args =>
|
||||||
|
{
|
||||||
|
var b = (BudgetRecord)args[0];
|
||||||
|
return b.Name switch
|
||||||
|
{
|
||||||
|
"吃喝" => 1200m, // 月度预算:已用1200元
|
||||||
|
"交通" => 300m, // 月度预算:已用300元
|
||||||
|
"年度旅游" => 2000m, // 年度预算:1月份已用2000元
|
||||||
|
"年度奖金" => 10000m, // 年度预算:1月份已收10000元
|
||||||
|
_ => 0m
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置趋势统计数据为空(简化测试)
|
||||||
|
_transactionsRepository.GetFilteredTrendStatisticsAsync(Arg.Any<DateTime>(), Arg.Any<DateTime>(), Arg.Any<TransactionType>(), Arg.Any<List<string>>(), Arg.Any<bool>())
|
||||||
|
.Returns(new Dictionary<DateTime, decimal>());
|
||||||
|
|
||||||
|
// Act - 测试支出统计
|
||||||
|
var expenseResult = await _service.GetCategoryStatsAsync(BudgetCategory.Expense, referenceDate);
|
||||||
|
|
||||||
|
// Act - 测试收入统计
|
||||||
|
var incomeResult = await _service.GetCategoryStatsAsync(BudgetCategory.Income, referenceDate);
|
||||||
|
|
||||||
|
// Assert - 支出月度统计:只包含月度预算
|
||||||
|
expenseResult.Month.Limit.Should().Be(2500); // 吃喝2000 + 交通500
|
||||||
|
expenseResult.Month.Current.Should().Be(1500); // 吃喝1200 + 交通300
|
||||||
|
expenseResult.Month.Count.Should().Be(2); // 只包含2个月度预算
|
||||||
|
expenseResult.Month.Rate.Should().Be(1500m / 2500m * 100); // 60%
|
||||||
|
|
||||||
|
// Assert - 支出年度统计:包含所有预算(月度+年度)
|
||||||
|
expenseResult.Year.Limit.Should().Be(12000 + (2500 * 12)); // 年度旅游12000 + 月度预算折算为年度(2500*12)
|
||||||
|
expenseResult.Year.Current.Should().Be(2000 + 1500); // 年度旅游2000 + 月度预算1500
|
||||||
|
expenseResult.Year.Count.Should().Be(3); // 包含3个预算(2个月度+1个年度)
|
||||||
|
|
||||||
|
// Assert - 收入月度统计:只包含月度预算(这里没有月度收入预算,所以应该为0)
|
||||||
|
incomeResult.Month.Limit.Should().Be(0); // 没有月度收入预算
|
||||||
|
incomeResult.Month.Current.Should().Be(0); // 没有月度收入预算
|
||||||
|
incomeResult.Month.Count.Should().Be(0); // 没有月度收入预算
|
||||||
|
|
||||||
|
// Assert - 收入年度统计:包含所有预算(只有年度收入预算)
|
||||||
|
incomeResult.Year.Limit.Should().Be(50000); // 年度奖金50000
|
||||||
|
incomeResult.Year.Current.Should().Be(10000); // 年度奖金已收10000
|
||||||
|
incomeResult.Year.Count.Should().Be(1); // 包含1个年度收入预算
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user