diff --git a/Service/BudgetService.cs b/Service/BudgetService.cs index ad7ea9d..879f77b 100644 --- a/Service/BudgetService.cs +++ b/Service/BudgetService.cs @@ -4,7 +4,7 @@ public interface IBudgetService { Task> GetListAsync(DateTime? referenceDate = null); - Task GetStatisticsAsync(long id, DateTime? referenceDate = null); + Task GetStatisticsAsync(long id, DateTime referenceDate); Task ArchiveBudgetsAsync(int year, int month); @@ -48,8 +48,54 @@ public class BudgetService( return dtos.Where(dto => dto != null).Cast().ToList(); } - public async Task GetStatisticsAsync(long id, DateTime? referenceDate = null) + public async Task 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 GetCategoryStatsAsync(BudgetCategory category, DateTime? referenceDate = null) @@ -481,19 +542,10 @@ public class BudgetService( description.Append($"

计划存款 = 收入 {incomeLimitAtPeriod:N0} - 支出 {expenseLimitAtPeriod:N0}

"); description.Append($"

最终目标:{incomeLimitAtPeriod - expenseLimitAtPeriod:N0}

"); - var savingsCategories = await configService.GetConfigByKeyAsync("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 BuildVirtualSavingsBudgetRecordAsync( + long id, + DateTime date, + decimal limit) + { + var savingsCategories = await configService.GetConfigByKeyAsync("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 diff --git a/Web/src/components/Budget/BudgetCard.vue b/Web/src/components/Budget/BudgetCard.vue index 0ff5634..759f327 100644 --- a/Web/src/components/Budget/BudgetCard.vue +++ b/Web/src/components/Budget/BudgetCard.vue @@ -225,7 +225,6 @@ const handleQueryBills = async () => { billLoading.value = true try { - debugger const classify = props.budget.selectedCategories ? props.budget.selectedCategories.join(',') : '' diff --git a/WebApi/Controllers/BudgetController.cs b/WebApi/Controllers/BudgetController.cs index 82692c3..80ee5d4 100644 --- a/WebApi/Controllers/BudgetController.cs +++ b/WebApi/Controllers/BudgetController.cs @@ -35,10 +35,16 @@ public class BudgetController( /// 获取单个预算统计信息 /// [HttpGet] - public async Task> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime? referenceDate = null) + public async Task> GetStatisticsAsync([FromQuery] long id, [FromQuery] DateTime referenceDate) { try { + // 参数验证 + if (id == 0) + { + return "预算 Id 无效".Fail(); + } + 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)