using Microsoft.AspNetCore.Mvc; using FinControl.Domain.Repositories; using FinControl.Contracts.Responses; using FinControl.Domain.Entities; using FinControl.Domain.Enums; using FinControl.Contracts.Requests; namespace FinControl.API.Controllers; [ApiController] [Route("api/[controller]")] public class TransactionsController : ControllerBase { private readonly ITransactionRepository _transactionRepository; private readonly IAccountRepository _accountRepository; public TransactionsController(ITransactionRepository transactionRepository, IAccountRepository accountRepository) { _transactionRepository = transactionRepository; _accountRepository = accountRepository; } [HttpGet("account/{accountId}")] public async Task>> GetByAccountId(Guid accountId) { var transactions = await _transactionRepository.GetByAccountIdAsync(accountId); var response = transactions.Select(t => new TransactionResponse { Id = t.Id, AccountId = t.AccountId, CategoryId = t.CategoryId, Amount = t.Amount, Type = (int)t.Type, Description = t.Description, Date = t.Date, CreatedAt = t.CreatedAt }).ToList(); return Ok(response); } [HttpGet("{id}")] public async Task> GetById(Guid id) { var transaction = await _transactionRepository.GetByIdAsync(id); if (transaction == null) return NotFound(); var response = new TransactionResponse { Id = transaction.Id, AccountId = transaction.AccountId, CategoryId = transaction.CategoryId, Amount = transaction.Amount, Type = (int)transaction.Type, Description = transaction.Description, Date = transaction.Date, CreatedAt = transaction.CreatedAt }; return Ok(response); } [HttpPost] public async Task> Create([FromBody] CreateTransactionRequest request) { var account = await _accountRepository.GetByIdAsync(request.AccountId); if (account == null) return BadRequest("Account not found"); var transaction = new Transaction { AccountId = request.AccountId, CategoryId = request.CategoryId, Amount = request.Amount, Type = (TransactionType)request.Type, Description = request.Description, Date = request.Date }; await _transactionRepository.AddAsync(transaction); // Update account balance if (request.Type == 0) // Income { account.CurrentBalance += request.Amount; } else // Expense { account.CurrentBalance -= request.Amount; } await _accountRepository.UpdateAsync(account); var response = new TransactionResponse { Id = transaction.Id, AccountId = transaction.AccountId, CategoryId = transaction.CategoryId, Amount = transaction.Amount, Type = (int)transaction.Type, Description = transaction.Description, Date = transaction.Date, CreatedAt = transaction.CreatedAt }; return CreatedAtAction(nameof(GetById), new { id = transaction.Id }, response); } [HttpDelete("{id}")] public async Task Delete(Guid id) { var transaction = await _transactionRepository.GetByIdAsync(id); if (transaction == null) return NotFound(); // Reverse the transaction effect on account balance var account = await _accountRepository.GetByIdAsync(transaction.AccountId); if (account != null) { if (transaction.Type == TransactionType.Income) { account.CurrentBalance -= transaction.Amount; } else { account.CurrentBalance += transaction.Amount; } await _accountRepository.UpdateAsync(account); } await _transactionRepository.DeleteAsync(id); return NoContent(); } } public class CreateTransactionRequest { public Guid AccountId { get; set; } public Guid CategoryId { get; set; } public decimal Amount { get; set; } public int Type { get; set; } // 0 = Income, 1 = Expense public string? Description { get; set; } public DateTime Date { get; set; } } public class TransactionResponse { public Guid Id { get; set; } public Guid AccountId { get; set; } public Guid CategoryId { get; set; } public decimal Amount { get; set; } public int Type { get; set; } public string? Description { get; set; } public DateTime Date { get; set; } public DateTime CreatedAt { get; set; } }