using FluentValidation; using FluentValidation.Results; using Vegasco.Server.Api.Common; using Vegasco.Server.Api.Persistence; namespace Vegasco.Server.Api.Consumptions; public static class UpdateConsumption { public record Request(DateTimeOffset DateTime, double Distance, double Amount); public record Response(Guid Id, DateTimeOffset DateTime, double Distance, double Amount, Guid CarId); public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) { return builder .MapPut("consumptions/{id:guid}", Endpoint) .WithTags("Consumptions") .WithDescription("Updates a consumption entry by ID") .Produces() .ProducesValidationProblem() .Produces(404); } public class Validator : AbstractValidator { public Validator(TimeProvider timeProvider) { RuleFor(x => x.DateTime.ToUniversalTime()) .LessThanOrEqualTo(timeProvider.GetUtcNow()) .WithName(nameof(Request.DateTime)); RuleFor(x => x.Distance) .GreaterThan(0); RuleFor(x => x.Amount) .GreaterThan(0); } } private static async Task Endpoint( ApplicationDbContext dbContext, Guid id, Request request, IEnumerable> validators, CancellationToken cancellationToken) { List failedValidations = await validators.ValidateAllAsync(request, cancellationToken); if (failedValidations.Count > 0) { return TypedResults.BadRequest(new HttpValidationProblemDetails(failedValidations.ToCombinedDictionary())); } Consumption? consumption = await dbContext.Consumptions.FindAsync([new ConsumptionId(id)], cancellationToken); if (consumption is null) { return TypedResults.NotFound(); } consumption.DateTime = request.DateTime.ToUniversalTime(); consumption.Distance = request.Distance; consumption.Amount = request.Amount; await dbContext.SaveChangesAsync(cancellationToken); return TypedResults.Ok(new Response(consumption.Id.Value, consumption.DateTime, consumption.Distance, consumption.Amount, consumption.CarId.Value)); } }