feat: 更新预算服务和控制器,优化统计信息获取逻辑,增强参数验证
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 25s
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:
孙诚
2026-01-09 16:59:08 +08:00
parent b5d0524868
commit 76fd0d23dc
3 changed files with 97 additions and 20 deletions

View File

@@ -4,7 +4,7 @@ public interface IBudgetService
{
Task<List<BudgetResult>> GetListAsync(DateTime? referenceDate = null);
Task<BudgetResult?> GetStatisticsAsync(long id, DateTime? referenceDate = null);
Task<BudgetResult?> GetStatisticsAsync(long id, DateTime referenceDate);
Task<string> ArchiveBudgetsAsync(int year, int month);
@@ -48,8 +48,54 @@ public class BudgetService(
return dtos.Where(dto => dto != null).Cast<BudgetResult>().ToList();
}
public async Task<BudgetResult?> GetStatisticsAsync(long id, DateTime? referenceDate = null)
public async Task<BudgetResult?> GetStatisticsAsync(long id, DateTime referenceDate)
{
bool isArchive = false;
BudgetRecord? budget = null;
if (id == -1)
{
if (isAcrhiveFunc(BudgetPeriodType.Year))
{
isArchive = true;
budget = await BuildVirtualSavingsBudgetRecordAsync(-1, referenceDate, 0);
}
}
else if (id == -2)
{
if (isAcrhiveFunc(BudgetPeriodType.Month))
{
isArchive = true;
budget = await BuildVirtualSavingsBudgetRecordAsync(-2, referenceDate, 0);
}
}
else
{
budget = await budgetRepository.GetByIdAsync(id);
if (budget == null)
{
return null;
}
isArchive = isAcrhiveFunc(budget.Type);
}
if (isArchive && budget != null)
{
var archive = await budgetArchiveRepository.GetArchiveAsync(
id,
referenceDate.Year,
referenceDate.Month);
if (archive != null) // 存在归档 直接读取归档数据
{
budget.Limit = archive.BudgetedAmount;
return BudgetResult.FromEntity(budget, archive.RealizedAmount, referenceDate);
}
}
if (id == -1)
{
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Year, referenceDate);
@@ -59,7 +105,7 @@ public class BudgetService(
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Month, referenceDate);
}
var budget = await budgetRepository.GetByIdAsync(id);
budget = await budgetRepository.GetByIdAsync(id);
if (budget == null)
{
return null;
@@ -67,6 +113,21 @@ public class BudgetService(
var currentAmount = await CalculateCurrentAmountAsync(budget, referenceDate);
return BudgetResult.FromEntity(budget, currentAmount, referenceDate);
bool isAcrhiveFunc(BudgetPeriodType periodType)
{
if (periodType == BudgetPeriodType.Year)
{
return DateTime.Now.Year > referenceDate.Year;
}
else if (periodType == BudgetPeriodType.Month)
{
return DateTime.Now.Year > referenceDate.Year
|| (DateTime.Now.Year == referenceDate.Year
&& DateTime.Now.Month > referenceDate.Month);
}
return false;
}
}
public async Task<BudgetCategoryStats> GetCategoryStatsAsync(BudgetCategory category, DateTime? referenceDate = null)
@@ -481,19 +542,10 @@ public class BudgetService(
description.Append($"<p>计划存款 = 收入 <span class='income-value'>{incomeLimitAtPeriod:N0}</span> - 支出 <span class='expense-value'>{expenseLimitAtPeriod:N0}</span></p>");
description.Append($"<p>最终目标:<span class='highlight'><strong>{incomeLimitAtPeriod - expenseLimitAtPeriod:N0}</strong></span></p>");
var savingsCategories = await configService.GetConfigByKeyAsync<string>("SavingsCategories") ?? string.Empty;
var virtualBudget = new BudgetRecord
{
Id = periodType == BudgetPeriodType.Year ? -1 : -2,
Name = periodType == BudgetPeriodType.Year ? "年度存款" : "月度存款",
Category = BudgetCategory.Savings,
Type = periodType,
Limit = incomeLimitAtPeriod - expenseLimitAtPeriod,
StartDate = periodType == BudgetPeriodType.Year
? new DateTime(date.Year, 1, 1)
: new DateTime(date.Year, date.Month, 1),
SelectedCategories = savingsCategories
};
var virtualBudget = await BuildVirtualSavingsBudgetRecordAsync(
periodType == BudgetPeriodType.Year ? -1 : -2,
date,
incomeLimitAtPeriod - expenseLimitAtPeriod);
// 计算实际发生的 收入 - 支出
var current = await CalculateCurrentAmountAsync(new BudgetRecord
@@ -506,6 +558,26 @@ public class BudgetService(
return BudgetResult.FromEntity(virtualBudget, current, date, description.ToString());
}
private async Task<BudgetRecord> BuildVirtualSavingsBudgetRecordAsync(
long id,
DateTime date,
decimal limit)
{
var savingsCategories = await configService.GetConfigByKeyAsync<string>("SavingsCategories") ?? string.Empty;
return new BudgetRecord
{
Id = id,
Name = id == -1 ? "年度存款" : "月度存款",
Category = BudgetCategory.Savings,
Type = id == -1 ? BudgetPeriodType.Year : BudgetPeriodType.Month,
Limit = limit,
StartDate = id == -1
? new DateTime(date.Year, 1, 1)
: new DateTime(date.Year, date.Month, 1),
SelectedCategories = savingsCategories
};
}
}
public record BudgetResult

View File

@@ -225,7 +225,6 @@ const handleQueryBills = async () => {
billLoading.value = true
try {
debugger
const classify = props.budget.selectedCategories
? props.budget.selectedCategories.join(',')
: ''

View File

@@ -35,10 +35,16 @@ public class BudgetController(
/// 获取单个预算统计信息
/// </summary>
[HttpGet]
public async Task<BaseResponse<BudgetResult>> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime? referenceDate = null)
public async Task<BaseResponse<BudgetResult>> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime referenceDate)
{
try
{
// 参数验证
if (id == 0)
{
return "预算 Id 无效".Fail<BudgetResult>();
}
var result = await budgetService.GetStatisticsAsync(id, referenceDate);
if (result == null)