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
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:
@@ -4,7 +4,7 @@ public interface IBudgetService
|
|||||||
{
|
{
|
||||||
Task<List<BudgetResult>> GetListAsync(DateTime? referenceDate = null);
|
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);
|
Task<string> ArchiveBudgetsAsync(int year, int month);
|
||||||
|
|
||||||
@@ -48,8 +48,54 @@ public class BudgetService(
|
|||||||
return dtos.Where(dto => dto != null).Cast<BudgetResult>().ToList();
|
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)
|
if (id == -1)
|
||||||
{
|
{
|
||||||
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Year, referenceDate);
|
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Year, referenceDate);
|
||||||
@@ -59,7 +105,7 @@ public class BudgetService(
|
|||||||
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Month, referenceDate);
|
return await GetVirtualSavingsDtoAsync(BudgetPeriodType.Month, referenceDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
var budget = await budgetRepository.GetByIdAsync(id);
|
budget = await budgetRepository.GetByIdAsync(id);
|
||||||
if (budget == null)
|
if (budget == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -67,6 +113,21 @@ public class BudgetService(
|
|||||||
|
|
||||||
var currentAmount = await CalculateCurrentAmountAsync(budget, referenceDate);
|
var currentAmount = await CalculateCurrentAmountAsync(budget, referenceDate);
|
||||||
return BudgetResult.FromEntity(budget, currentAmount, 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)
|
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='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>");
|
description.Append($"<p>最终目标:<span class='highlight'><strong>{incomeLimitAtPeriod - expenseLimitAtPeriod:N0}</strong></span></p>");
|
||||||
|
|
||||||
var savingsCategories = await configService.GetConfigByKeyAsync<string>("SavingsCategories") ?? string.Empty;
|
var virtualBudget = await BuildVirtualSavingsBudgetRecordAsync(
|
||||||
var virtualBudget = new BudgetRecord
|
periodType == BudgetPeriodType.Year ? -1 : -2,
|
||||||
{
|
date,
|
||||||
Id = periodType == BudgetPeriodType.Year ? -1 : -2,
|
incomeLimitAtPeriod - expenseLimitAtPeriod);
|
||||||
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 current = await CalculateCurrentAmountAsync(new BudgetRecord
|
var current = await CalculateCurrentAmountAsync(new BudgetRecord
|
||||||
@@ -506,6 +558,26 @@ public class BudgetService(
|
|||||||
|
|
||||||
return BudgetResult.FromEntity(virtualBudget, current, date, description.ToString());
|
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
|
public record BudgetResult
|
||||||
|
|||||||
@@ -225,7 +225,6 @@ const handleQueryBills = async () => {
|
|||||||
billLoading.value = true
|
billLoading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
debugger
|
|
||||||
const classify = props.budget.selectedCategories
|
const classify = props.budget.selectedCategories
|
||||||
? props.budget.selectedCategories.join(',')
|
? props.budget.selectedCategories.join(',')
|
||||||
: ''
|
: ''
|
||||||
|
|||||||
@@ -35,10 +35,16 @@ public class BudgetController(
|
|||||||
/// 获取单个预算统计信息
|
/// 获取单个预算统计信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpGet]
|
[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
|
try
|
||||||
{
|
{
|
||||||
|
// 参数验证
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
return "预算 Id 无效".Fail<BudgetResult>();
|
||||||
|
}
|
||||||
|
|
||||||
var result = await budgetService.GetStatisticsAsync(id, referenceDate);
|
var result = await budgetService.GetStatisticsAsync(id, referenceDate);
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
|
|||||||
Reference in New Issue
Block a user