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<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
|
||||
|
||||
@@ -225,7 +225,6 @@ const handleQueryBills = async () => {
|
||||
billLoading.value = true
|
||||
|
||||
try {
|
||||
debugger
|
||||
const classify = props.budget.selectedCategories
|
||||
? props.budget.selectedCategories.join(',')
|
||||
: ''
|
||||
|
||||
@@ -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)
|
||||
@@ -204,11 +210,11 @@ public class BudgetController(
|
||||
{
|
||||
var msg = await budgetService.ArchiveBudgetsAsync(year, month);
|
||||
|
||||
if(!string.IsNullOrEmpty(msg))
|
||||
if (!string.IsNullOrEmpty(msg))
|
||||
{
|
||||
return msg.Fail();
|
||||
}
|
||||
|
||||
|
||||
return BaseResponse.Done();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
Reference in New Issue
Block a user