feat(api): add BudgetsController with status, create, update endpoints
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using MoneyMap.Models;
|
||||
using MoneyMap.Services;
|
||||
|
||||
namespace MoneyMap.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class BudgetsController : ControllerBase
|
||||
{
|
||||
private readonly IBudgetService _budgetService;
|
||||
|
||||
public BudgetsController(IBudgetService budgetService) => _budgetService = budgetService;
|
||||
|
||||
[HttpGet("status")]
|
||||
public async Task<IActionResult> GetStatus([FromQuery] string? asOfDate = null)
|
||||
{
|
||||
DateTime? date = null;
|
||||
if (!string.IsNullOrWhiteSpace(asOfDate) && DateTime.TryParse(asOfDate, out var parsed))
|
||||
date = parsed;
|
||||
|
||||
var statuses = await _budgetService.GetAllBudgetStatusesAsync(date);
|
||||
|
||||
var result = statuses.Select(s => new
|
||||
{
|
||||
s.Budget.Id,
|
||||
Category = s.Budget.DisplayName,
|
||||
s.Budget.Amount,
|
||||
Period = s.Budget.Period.ToString(),
|
||||
s.PeriodStart,
|
||||
s.PeriodEnd,
|
||||
s.Spent,
|
||||
s.Remaining,
|
||||
PercentUsed = Math.Round(s.PercentUsed, 1),
|
||||
s.IsOverBudget
|
||||
}).ToList();
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] CreateBudgetRequest request)
|
||||
{
|
||||
if (!Enum.TryParse<BudgetPeriod>(request.Period, true, out var budgetPeriod))
|
||||
return BadRequest(new { message = $"Invalid period '{request.Period}'. Must be Weekly, Monthly, or Yearly." });
|
||||
|
||||
if (!DateTime.TryParse(request.StartDate, out var startDate))
|
||||
return BadRequest(new { message = "Invalid start date format" });
|
||||
|
||||
var budget = new Budget
|
||||
{
|
||||
Category = request.Category,
|
||||
Amount = request.Amount,
|
||||
Period = budgetPeriod,
|
||||
StartDate = startDate,
|
||||
IsActive = true
|
||||
};
|
||||
|
||||
var result = await _budgetService.CreateBudgetAsync(budget);
|
||||
|
||||
return Ok(new { result.Success, result.Message, BudgetId = budget.Id });
|
||||
}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> Update(int id, [FromBody] UpdateBudgetRequest request)
|
||||
{
|
||||
var budget = await _budgetService.GetBudgetByIdAsync(id);
|
||||
if (budget == null)
|
||||
return NotFound(new { message = "Budget not found" });
|
||||
|
||||
if (request.Amount.HasValue)
|
||||
budget.Amount = request.Amount.Value;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.Period))
|
||||
{
|
||||
if (!Enum.TryParse<BudgetPeriod>(request.Period, true, out var budgetPeriod))
|
||||
return BadRequest(new { message = $"Invalid period '{request.Period}'. Must be Weekly, Monthly, or Yearly." });
|
||||
budget.Period = budgetPeriod;
|
||||
}
|
||||
|
||||
if (request.IsActive.HasValue)
|
||||
budget.IsActive = request.IsActive.Value;
|
||||
|
||||
var result = await _budgetService.UpdateBudgetAsync(budget);
|
||||
|
||||
return Ok(new { result.Success, result.Message });
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateBudgetRequest
|
||||
{
|
||||
public string? Category { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
public string Period { get; set; } = "";
|
||||
public string StartDate { get; set; } = "";
|
||||
}
|
||||
|
||||
public class UpdateBudgetRequest
|
||||
{
|
||||
public decimal? Amount { get; set; }
|
||||
public string? Period { get; set; }
|
||||
public bool? IsActive { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user