diff --git a/.gitignore b/.gitignore index c6cc67a..7d240a3 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ _UpgradeReport_Files/ Thumbs.db Desktop.ini -.DS_Store \ No newline at end of file +.DS_Store +.fake \ No newline at end of file diff --git a/Okane.Application/CreateExpenseRequest.cs b/Okane.Application/CreateExpenseRequest.cs index 1e59ee8..09c1e96 100644 --- a/Okane.Application/CreateExpenseRequest.cs +++ b/Okane.Application/CreateExpenseRequest.cs @@ -1,17 +1,22 @@ +using System; using System.ComponentModel.DataAnnotations; -namespace Okane.Application; - -public class CreateExpenseRequest +namespace Okane.Application { - [Required] - [Range(1, 1_000_000, ErrorMessage = "Amount is out of range")] - public int Amount { get; set; } - - [Required] - [MaxLength(80, ErrorMessage = "Category is too long")] - public required string Category { get; set; } - - [MaxLength(250, ErrorMessage = "Description is too long")] - public string? Description { get; set; } -} \ No newline at end of file + public class CreateExpenseRequest + { + [Required] + [Range(1, 1_000_000, ErrorMessage = "Amount is out of range")] + public int Amount { get; set; } + + [Required] + [MaxLength(80, ErrorMessage = "Category is too long")] + public string Category { get; set; } + + [MaxLength(250, ErrorMessage = "Description is too long")] + public string? Description { get; set; } + + [Required] + public DateTime DateCreated { get; set; } // Nueva propiedad para la fecha + } +} diff --git a/Okane.Application/DataAnnotationsValidator.cs b/Okane.Application/DataAnnotationsValidator.cs index 389623c..8351889 100644 --- a/Okane.Application/DataAnnotationsValidator.cs +++ b/Okane.Application/DataAnnotationsValidator.cs @@ -1,25 +1,33 @@ +using System; +using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using System.Linq; -namespace Okane.Application; - -public class DataAnnotationsValidator +namespace Okane.Application { - public IDictionary Validate(T obj) + public class DataAnnotationsValidator { - var results = new List(); + public IDictionary Validate(T obj) + { + if (obj == null) + { + throw new ArgumentNullException(nameof(obj)); + } + + var results = new List(); + var context = new ValidationContext( + obj, serviceProvider: null, items: null); - var context = new ValidationContext( - obj, serviceProvider: null, items: null); + Validator.TryValidateObject(obj, context, results, validateAllProperties: true); - Validator.TryValidateObject(obj, context, results, validateAllProperties: true); + return results + .GroupBy(result => string.Join('+', result.MemberNames)) + .ToDictionary( + grouping => grouping.Key, + ToArray); + } - return results - .GroupBy(result => string.Join('+', result.MemberNames)) - .ToDictionary( - grouping => grouping.Key, - ToArray); + private static string[] ToArray(IGrouping grouping) => + grouping.Select(result => result.ErrorMessage ?? string.Empty).ToArray(); } - - private static string[] ToArray(IGrouping grouping) => - grouping.Select(result => result.ErrorMessage ?? string.Empty).ToArray(); } \ No newline at end of file diff --git a/Okane.Application/ExpenseResponse.cs b/Okane.Application/ExpenseResponse.cs index e3afef4..a46d866 100644 --- a/Okane.Application/ExpenseResponse.cs +++ b/Okane.Application/ExpenseResponse.cs @@ -6,4 +6,5 @@ public class ExpenseResponse public int Amount { get; set; } public required string Category { get; set; } public string? Description { get; set; } + public DateTime DateCreated { get; set; } } \ No newline at end of file diff --git a/Okane.Application/ExpenseService.cs b/Okane.Application/ExpenseService.cs index 4c02a53..3e8de1e 100644 --- a/Okane.Application/ExpenseService.cs +++ b/Okane.Application/ExpenseService.cs @@ -1,57 +1,82 @@ using Okane.Domain; +using System; +using System.Collections.Generic; +using System.Linq; -namespace Okane.Application; -public class ExpenseService : IExpenseService +namespace Okane.Application { - private readonly IExpensesRepository _expensesRepository; + public class ExpenseService : IExpenseService + { + private readonly IExpensesRepository _expensesRepository; - public ExpenseService(IExpensesRepository expensesRepository) => - _expensesRepository = expensesRepository; + public ExpenseService(IExpensesRepository expensesRepository) => + _expensesRepository = expensesRepository; - public ExpenseResponse RegisterExpense(CreateExpenseRequest request) - { - var expense = new Expense + public ExpenseResponse RegisterExpense(CreateExpenseRequest request) { - Amount = request.Amount, - Description = request.Description, - Category = request.Category - }; + var expense = new Expense + { + Amount = request.Amount, + Description = request.Description, + Category = request.Category, + DateCreated = DateTime.UtcNow // Incluir la fecha actual al registrar + }; - _expensesRepository.Add(expense); + _expensesRepository.Add(expense); - return CreateExpenseResponse(expense); - } + return CreateExpenseResponse(expense); + } - public ExpenseResponse? ById(int id) - { - var expense = _expensesRepository.ById(id); + public ExpenseResponse? ById(int id) + { + var expense = _expensesRepository.ById(id); - return expense == null ? null : CreateExpenseResponse(expense); - } + return expense == null ? null : CreateExpenseResponse(expense); + } - public IEnumerable Search(string? category = null) => - _expensesRepository - .Search(category) - .Select(CreateExpenseResponse); + public IEnumerable Search(string? category = null) => + _expensesRepository + .Search(category) + .Select(CreateExpenseResponse); - public bool Delete(int id) - { - var expenseToDelete = _expensesRepository.ById(id); + public bool Delete(int id) + { + var expenseToDelete = _expensesRepository.ById(id); - if (expenseToDelete == null) - return false; + if (expenseToDelete == null) + return false; - _expensesRepository.Delete(id); - return true; - } + _expensesRepository.Delete(id); + return true; + } - private static ExpenseResponse CreateExpenseResponse(Expense expense) => - new() + public ExpenseResponse? UpdateExpense(int id, UpdateExpenseRequest request) { - Id = expense.Id, - Category = expense.Category, - Description = expense.Description, - Amount = expense.Amount - }; -} \ No newline at end of file + var existingExpense = _expensesRepository.ById(id); + if (existingExpense == null) + return null; // No se encontró el gasto para actualizar + + // Actualizar la información del gasto + existingExpense.Amount = request.Amount; + existingExpense.Category = request.Category; + existingExpense.Description = request.Description; + + // Guardar los cambios + _expensesRepository.Update(existingExpense); + + // Devolver la respuesta actualizada + return CreateExpenseResponse(existingExpense); + } + + private static ExpenseResponse CreateExpenseResponse(Expense expense) => + new() + { + Id = expense.Id, + Category = expense.Category, + Description = expense.Description, + Amount = expense.Amount, + DateCreated = expense.DateCreated // Asegúrate de incluir la fecha al crear la respuesta + }; + } +} diff --git a/Okane.Application/IExpenseService.cs b/Okane.Application/IExpenseService.cs index 114f28c..42af95b 100644 --- a/Okane.Application/IExpenseService.cs +++ b/Okane.Application/IExpenseService.cs @@ -1,9 +1,29 @@ -namespace Okane.Application; - -public interface IExpenseService +using Okane.Application; +namespace Okane.Application { - ExpenseResponse RegisterExpense(CreateExpenseRequest request); - ExpenseResponse? ById(int id); - IEnumerable Search(string? category = null); - bool Delete(int id); -} \ No newline at end of file + public interface IExpenseService + { + ExpenseResponse RegisterExpense(CreateExpenseRequest request); + ExpenseResponse? ById(int id); + IEnumerable Search(string? category = null); + bool Delete(int id); + ExpenseResponse? UpdateExpense(int id, UpdateExpenseRequest request); + + } + + public class UpdateExpenseRequest + + { + [Required] + [Range(1, 1_000_000, ErrorMessage = "Amount is out of range")] + public int Amount { get; set; } + + [Required] + [MaxLength(80, ErrorMessage = "Category is too long")] + public string Category { get; set; } + + [MaxLength(250, ErrorMessage = "Description is too long")] + public string? Description { get; set; } + } +} + diff --git a/Okane.Application/IExpensesRepository.cs b/Okane.Application/IExpensesRepository.cs index 95a565c..96cab21 100644 --- a/Okane.Application/IExpensesRepository.cs +++ b/Okane.Application/IExpensesRepository.cs @@ -8,4 +8,5 @@ public interface IExpensesRepository IEnumerable Search(string? categoryName = null); void Delete(int id); Expense? ById(int id); + void Update(Expense existingExpense); } \ No newline at end of file diff --git a/Okane.Domain/Expense.cs b/Okane.Domain/Expense.cs index 0832e55..5de2b6e 100644 --- a/Okane.Domain/Expense.cs +++ b/Okane.Domain/Expense.cs @@ -6,4 +6,5 @@ public class Expense public int Amount { get; set; } public required string Category { get; set; } public string? Description { get; set; } + public DateTime DateCreated { get; set; } } \ No newline at end of file