using FluentValidation; using FluentValidation.Results; using Vegasco.Server.Api.Cars; using Vegasco.Server.Api.Common; using Vegasco.Server.Api.Persistence; namespace Vegasco.Server.Api.Consumptions; public static class CreateConsumption { public record Request(DateTimeOffset DateTime, double Distance, double Amount, bool IgnoreInCalculation, Guid CarId); public record Response(Guid Id, DateTimeOffset DateTime, double Distance, double Amount, bool IgnoreInCalculation, Guid CarId); public static RouteHandlerBuilder MapEndpoint(IEndpointRouteBuilder builder) { return builder .MapPost("consumptions", Endpoint) .WithTags("Consumptions") .WithDescription("Creates a new consumption entry") .Produces(201); } 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); RuleFor(x => x.CarId) .NotEmpty(); } } private static async Task Endpoint( ApplicationDbContext dbContext, Request request, IEnumerable> validators, CancellationToken cancellationToken) { List failedValidations = await validators.ValidateAllAsync(request, cancellationToken); if (failedValidations.Count > 0) { return TypedResults.BadRequest(new HttpValidationProblemDetails(failedValidations.ToCombinedDictionary())); } Car? car = await dbContext.Cars.FindAsync([new CarId(request.CarId)], cancellationToken); if (car is null) { return TypedResults.NotFound(); } var consumption = new Consumption { DateTime = request.DateTime.ToUniversalTime(), Distance = request.Distance, Amount = request.Amount, IgnoreInCalculation = request.IgnoreInCalculation, CarId = new CarId(request.CarId) }; dbContext.Consumptions.Add(consumption); await dbContext.SaveChangesAsync(cancellationToken); return TypedResults.Created($"consumptions/{consumption.Id.Value}", new Response(consumption.Id.Value, consumption.DateTime, consumption.Distance, consumption.Amount, consumption.IgnoreInCalculation, consumption.CarId.Value)); } }