refactor all properties and dtos

This commit is contained in:
meysamhadeli 2022-11-21 04:31:21 +03:30
parent 1168fd7bbd
commit acb618a6fd
77 changed files with 253 additions and 511 deletions

View File

@ -39,13 +39,13 @@ Content-Type: application/json
authorization: bearer {{Authenticate.response.body.access_token}}
{
"firstName": "4John",
"lastName": "4Do",
"username": "4admin",
"firstName": "John",
"lastName": "Do",
"username": "admin",
"passportNumber": "412900000000",
"email": "4admin@admin.com",
"password": "4Admin@12345",
"confirmPassword": "4Admin@12345"
"email": "admin@admin.com",
"password": "Admin@12345",
"confirmPassword": "Admin@12345"
}
###

View File

@ -8,28 +8,25 @@ public class CachingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest,
where TRequest : notnull, IRequest<TResponse>
where TResponse : notnull
{
private readonly ICacheRequest _cacheRequest;
private readonly IEasyCachingProvider _cachingProvider;
private readonly ILogger<CachingBehavior<TRequest, TResponse>> _logger;
private readonly int defaultCacheExpirationInHours = 1;
public CachingBehavior(IEasyCachingProviderFactory cachingFactory,
ILogger<CachingBehavior<TRequest, TResponse>> logger,
ICacheRequest cacheRequest)
ILogger<CachingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
_cachingProvider = cachingFactory.GetCachingProvider("mem");
_cacheRequest = cacheRequest;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,
CancellationToken cancellationToken)
{
if (request is not ICacheRequest || _cacheRequest == null)
if (request is not ICacheRequest cacheRequest)
// No cache request found, so just continue through the pipeline
return await next();
var cacheKey = _cacheRequest.CacheKey;
var cacheKey = cacheRequest.CacheKey;
var cachedResponse = await _cachingProvider.GetAsync<TResponse>(cacheKey);
if (cachedResponse.Value != null)
{
@ -40,7 +37,7 @@ public class CachingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest,
var response = await next();
var expirationTime = _cacheRequest.AbsoluteExpirationRelativeToNow ??
var expirationTime = cacheRequest.AbsoluteExpirationRelativeToNow ??
DateTime.Now.AddHours(defaultCacheExpirationInHours);
await _cachingProvider.SetAsync(cacheKey, response, expirationTime.TimeOfDay);

View File

@ -1,29 +0,0 @@
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
namespace BuildingBlocks.Caching;
public static class Extensions
{
public static IServiceCollection AddCachingRequest(this IServiceCollection services,
IList<Assembly> assembliesToScan, ServiceLifetime lifetime = ServiceLifetime.Transient)
{
// ICacheRequest discovery and registration
services.Scan(scan => scan
.FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies())
.AddClasses(classes => classes.AssignableTo(typeof(ICacheRequest)),
false)
.AsImplementedInterfaces()
.WithLifetime(lifetime));
// IInvalidateCacheRequest discovery and registration
services.Scan(scan => scan
.FromAssemblies(assembliesToScan ?? AppDomain.CurrentDomain.GetAssemblies())
.AddClasses(classes => classes.AssignableTo(typeof(IInvalidateCacheRequest)),
false)
.AsImplementedInterfaces()
.WithLifetime(lifetime));
return services;
}
}

View File

@ -1,5 +1,3 @@
using MediatR;
namespace BuildingBlocks.Caching;
public interface ICacheRequest

View File

@ -1,7 +1,3 @@
using System;
using System.Linq;
using MediatR;
namespace BuildingBlocks.Caching
{
public interface IInvalidateCacheRequest

View File

@ -10,27 +10,23 @@ namespace BuildingBlocks.Caching
{
private readonly ILogger<InvalidateCachingBehavior<TRequest, TResponse>> _logger;
private readonly IEasyCachingProvider _cachingProvider;
private readonly IInvalidateCacheRequest _invalidateCacheRequest;
public InvalidateCachingBehavior(IEasyCachingProviderFactory cachingFactory,
ILogger<InvalidateCachingBehavior<TRequest, TResponse>> logger,
IInvalidateCacheRequest invalidateCacheRequest)
ILogger<InvalidateCachingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
_cachingProvider = cachingFactory.GetCachingProvider("mem");
_invalidateCacheRequest = invalidateCacheRequest;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
if (request is not IInvalidateCacheRequest || _invalidateCacheRequest == null)
if (request is not IInvalidateCacheRequest invalidateCacheRequest)
{
// No cache request found, so just continue through the pipeline
return await next();
}
var cacheKey = _invalidateCacheRequest.CacheKey;
var cacheKey = invalidateCacheRequest.CacheKey;
var response = await next();
await _cachingProvider.RemoveAsync(cacheKey);

View File

@ -3,7 +3,4 @@ using BuildingBlocks.IdsGenerator;
namespace BuildingBlocks.Core.Event;
public class InternalCommand : IInternalCommand, ICommand
{
public long Id { get; init; } = SnowFlakIdGenerator.NewId();
}
public record InternalCommand : IInternalCommand, ICommand;

View File

@ -27,6 +27,6 @@ namespace BuildingBlocks.Core.Model
public long Version { get; set; } = -1;
public TId Id { get; protected set; }
public TId Id { get; set; }
}
}

View File

@ -1,7 +1,5 @@
using System.Data;
using System.Text.Json;
using BuildingBlocks.Core;
using BuildingBlocks.Core.Event;
using MediatR;
using Microsoft.Extensions.Logging;

View File

@ -1,25 +1,5 @@
using Booking;
using Booking.Data;
using Booking.Extensions;
using Booking.Extensions.Infrastructure;
using BuildingBlocks.EventStoreDB;
using BuildingBlocks.HealthCheck;
using BuildingBlocks.IdsGenerator;
using BuildingBlocks.Jwt;
using BuildingBlocks.Logging;
using BuildingBlocks.Mapster;
using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo;
using BuildingBlocks.OpenTelemetry;
using BuildingBlocks.PersistMessageProcessor;
using BuildingBlocks.Swagger;
using BuildingBlocks.Web;
using Figgle;
using FluentValidation;
using Hellang.Middleware.ProblemDetails;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Prometheus;
using Serilog;
var builder = WebApplication.CreateBuilder(args);

View File

@ -1,16 +1,4 @@
namespace Booking.Booking.Dtos;
public record BookingResponseDto
{
public long Id { get; init; }
public string Name { get; init; }
public string FlightNumber { get; init; }
public long AircraftId { get; init; }
public decimal Price { get; init; }
public DateTime FlightDate { get; init; }
public string SeatNumber { get; init; }
public long DepartureAirportId { get; init; }
public long ArriveAirportId { get; init; }
public string Description { get; init; }
}
public record BookingResponseDto(long Id, string Name, string FlightNumber, long AircraftId, decimal Price,
DateTime FlightDate, string SeatNumber, long DepartureAirportId, long ArriveAirportId, string Description);

View File

@ -1,6 +1,6 @@
using Booking.Booking.Dtos;
using Booking.Booking.Models.Reads;
using BuildingBlocks.IdsGenerator;
using Booking.Booking.Features.CreateBooking.Commands.V1;
using Booking.Booking.Features.CreateBooking.Dtos.V1;
using Mapster;
namespace Booking.Booking.Features;
@ -12,15 +12,12 @@ public class BookingMappings : IRegister
config.Default.NameMatchingStrategy(NameMatchingStrategy.Flexible);
config.NewConfig<Models.Booking, BookingResponseDto>()
.Map(d => d.Name, s => s.PassengerInfo.Name)
.Map(d => d.Description, s => s.Trip.Description)
.Map(d => d.DepartureAirportId, s => s.Trip.DepartureAirportId)
.Map(d => d.ArriveAirportId, s => s.Trip.ArriveAirportId)
.Map(d => d.FlightNumber, s => s.Trip.FlightNumber)
.Map(d => d.FlightDate, s => s.Trip.FlightDate)
.Map(d => d.Price, s => s.Trip.Price)
.Map(d => d.SeatNumber, s => s.Trip.SeatNumber)
.Map(d => d.AircraftId, s => s.Trip.AircraftId);
.ConstructUsing(x => new BookingResponseDto(x.Id, x.PassengerInfo.Name, x.Trip.FlightNumber,
x.Trip.AircraftId, x.Trip.Price, x.Trip.FlightDate, x.Trip.SeatNumber, x.Trip.DepartureAirportId, x.Trip.ArriveAirportId,
x.Trip.Description));
config.NewConfig<CreateBookingRequestDto, CreateBookingCommand>()
.ConstructUsing(x => new CreateBookingCommand(x.PassengerId, x.FlightId, x.Description));
}
}

View File

@ -0,0 +1,3 @@
namespace Booking.Booking.Features.CreateBooking.Dtos.V1;
public record CreateBookingRequestDto(long PassengerId, long FlightId, string Description);

View File

@ -1,5 +1,7 @@
using Booking.Booking.Features.CreateBooking.Commands.V1;
using Booking.Booking.Features.CreateBooking.Dtos.V1;
using BuildingBlocks.Web;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
@ -9,6 +11,7 @@ using Microsoft.AspNetCore.Routing;
using Swashbuckle.AspNetCore.Annotations;
namespace Booking.Booking.Features.CreateBooking.Endpoints.V1;
public class CreateBookingEndpoint : IMinimalEndpoint
{
public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints)
@ -27,8 +30,11 @@ public class CreateBookingEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CreateBooking(CreateBookingCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CreateBooking(CreateBookingRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<CreateBookingCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -1,8 +1,6 @@
using Booking.Booking.Features.CreateBooking.Events.Domain.V1;
using Booking.Booking.Models.ValueObjects;
using BuildingBlocks.EventStoreDB.Events;
using BuildingBlocks.Utils;
using Microsoft.AspNetCore.Http;
namespace Booking.Booking.Models;

View File

@ -92,13 +92,12 @@ public static class InfrastructureExtensions
var env = app.Environment;
var appOptions = app.GetOptions<AppOptions>("AppOptions");
app.UseProblemDetails();
app.UseSerilogRequestLogging();
app.UseCorrelationId();
app.UseRouting();
app.UseHttpMetrics();
app.UseHttpsRedirection();
app.UseProblemDetails();
app.UseCustomHealthCheck();
app.MapMetrics();
app.MapGet("/", x => x.Response.WriteAsync(appOptions.Name));

View File

@ -10,8 +10,8 @@ public static class MediatRExtensions
public static IServiceCollection AddCustomMediatR(this IServiceCollection services)
{
services.AddMediatR(typeof(BookingRoot).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
return services;
}

View File

@ -1,9 +1,3 @@
namespace Flight.Aircrafts.Dtos;
public record AircraftResponseDto
{
public long Id { get; set; }
public string Name { get; init; }
public string Model { get; init; }
public int ManufacturingYear { get; init; }
}
public record AircraftResponseDto(long Id, string Name, string Model, int ManufacturingYear);

View File

@ -1,7 +1,10 @@
using BuildingBlocks.IdsGenerator;
using Flight.Aircrafts.Features.CreateAircraft.Commands.V1;
using Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads;
using Flight.Aircrafts.Features.CreateAircraft.Dtos.V1;
using Flight.Aircrafts.Models;
using Flight.Aircrafts.Models.Reads;
using Flight.Airports.Features.CreateAirport.Commands.V1;
using Mapster;
namespace Flight.Aircrafts.Features;
@ -17,5 +20,8 @@ public class AircraftMappings : IRegister
config.NewConfig<Aircraft, AircraftReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.AircraftId, s => s.Id);
config.NewConfig<CreateAircraftRequestDto, CreateAircraftCommand>()
.ConstructUsing(x => new CreateAircraftCommand(x.Name, x.Model, x.ManufacturingYear));
}
}

View File

@ -2,21 +2,4 @@
namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads;
public class CreateAircraftMongoCommand : InternalCommand
{
public CreateAircraftMongoCommand(long id, string name, string model, int manufacturingYear, bool isDeleted)
{
Id = id;
Name = name;
Model = model;
ManufacturingYear = manufacturingYear;
IsDeleted = isDeleted;
}
public long Id { get; }
public string Name { get; }
public string Model { get; }
public int ManufacturingYear { get; }
public bool IsDeleted { get; }
}
public record CreateAircraftMongoCommand(long Id, string Name, string Model, int ManufacturingYear, bool IsDeleted) : InternalCommand;

View File

@ -32,7 +32,7 @@ public class CreateAircraftMongoCommandHandler : ICommandHandler<CreateAircraftM
var aircraftReadModel = _mapper.Map<AircraftReadModel>(command);
var aircraft = await _flightReadDbContext.Aircraft.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == aircraftReadModel.Id, cancellationToken);
.FirstOrDefaultAsync(x => x.AircraftId == aircraftReadModel.AircraftId, cancellationToken);
if (aircraft is not null)
throw new AircraftAlreadyExistException();

View File

@ -0,0 +1,4 @@
namespace Flight.Aircrafts.Features.CreateAircraft.Dtos.V1;
public record CreateAircraftRequestDto(string Name, string Model, int ManufacturingYear);

View File

@ -3,6 +3,8 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Aircrafts.Dtos;
using Flight.Aircrafts.Features.CreateAircraft.Commands.V1;
using Flight.Aircrafts.Features.CreateAircraft.Dtos.V1;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -29,8 +31,11 @@ public class CreateAircraftEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CreateAircraft(CreateAircraftCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CreateAircraft(CreateAircraftRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<CreateAircraftCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -6,10 +6,6 @@ namespace Flight.Aircrafts.Models;
public record Aircraft : Aggregate<long>
{
public Aircraft()
{
}
public string Name { get; private set; }
public string Model { get; private set; }
public int ManufacturingYear { get; private set; }

View File

@ -1,5 +1,7 @@
using BuildingBlocks.IdsGenerator;
using Flight.Airports.Features.CreateAirport.Commands.V1;
using Flight.Airports.Features.CreateAirport.Commands.V1.Reads;
using Flight.Airports.Features.CreateAirport.Dtos.V1;
using Flight.Airports.Models;
using Flight.Airports.Models.Reads;
using Mapster;
@ -17,5 +19,8 @@ public class AirportMappings : IRegister
config.NewConfig<Airport, AirportReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.AirportId, s => s.Id);
config.NewConfig<CreateAirportRequestDto, CreateAirportCommand>()
.ConstructUsing(x => new CreateAirportCommand(x.Name, x.Address, x.Code));
}
}

View File

@ -1,8 +1,3 @@
namespace Flight.Airports.Dtos;
public record AirportResponseDto
{
public long Id { get; set; }
public string Name { get; init; }
public string Address { get; init; }
public string Code { get; init; }
}
public record AirportResponseDto(long Id, string Name, string Address, string Code);

View File

@ -2,19 +2,4 @@
namespace Flight.Airports.Features.CreateAirport.Commands.V1.Reads;
public class CreateAirportMongoCommand : InternalCommand
{
public CreateAirportMongoCommand(long id, string name, string address, string code, bool isDeleted)
{
Id = id;
Name = name;
Address = address;
Code = code;
IsDeleted = isDeleted;
}
public string Name { get; }
public string Address { get; }
public string Code { get; }
public bool IsDeleted { get; }
}
public record CreateAirportMongoCommand(long Id, string Name, string Address, string Code, bool IsDeleted) : InternalCommand;

View File

@ -32,7 +32,7 @@ public class CreateAirportMongoCommandHandler : ICommandHandler<CreateAirportMon
var airportReadModel = _mapper.Map<AirportReadModel>(command);
var aircraft = await _flightReadDbContext.Airport.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == airportReadModel.Id, cancellationToken);
.FirstOrDefaultAsync(x => x.AirportId == airportReadModel.AirportId, cancellationToken);
if (aircraft is not null)
throw new AirportAlreadyExistException();

View File

@ -0,0 +1,3 @@
namespace Flight.Airports.Features.CreateAirport.Dtos.V1;
public record CreateAirportRequestDto(string Name, string Address, string Code);

View File

@ -3,6 +3,8 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Airports.Dtos;
using Flight.Airports.Features.CreateAirport.Commands.V1;
using Flight.Airports.Features.CreateAirport.Dtos.V1;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -29,8 +31,11 @@ public class CreateAirportEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CreateAirport(CreateAirportCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CreateAirport(CreateAirportRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<CreateAirportCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -6,10 +6,6 @@ namespace Flight.Airports.Models;
public record Airport : Aggregate<long>
{
public Airport()
{
}
public string Name { get; private set; }
public string Address { get; private set; }
public string Code { get; private set; }

View File

@ -7,5 +7,5 @@ public class AirportReadModel
public string Name { get; init; }
public string Address { get; init; }
public string Code { get; init; }
public bool IsDeleted { get; set; }
public bool IsDeleted { get; init; }
}

View File

@ -90,8 +90,6 @@ public static class InfrastructureExtensions
SnowFlakIdGenerator.Configure(1);
builder.Services.AddCachingRequest(new List<Assembly> {typeof(FlightRoot).Assembly});
builder.Services.AddEasyCaching(options => { options.UseInMemory(configuration, "mem"); });
return builder;
@ -103,11 +101,11 @@ public static class InfrastructureExtensions
var env = app.Environment;
var appOptions = app.GetOptions<AppOptions>("AppOptions");
app.UseProblemDetails();
app.UseSerilogRequestLogging();
app.UseCorrelationId();
app.UseHttpMetrics();
app.UseMigration<FlightDbContext>(env);
app.UseProblemDetails();
app.UseHttpsRedirection();
app.MapMetrics();
app.UseCustomHealthCheck();

View File

@ -12,10 +12,11 @@ public static class MediatRExtensions
public static IServiceCollection AddCustomMediatR(this IServiceCollection services)
{
services.AddMediatR(typeof(FlightRoot).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(CachingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(CachingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(InvalidateCachingBehavior<,>));
return services;
}

View File

@ -2,18 +2,7 @@ using System;
using Flight.Flights.Models;
namespace Flight.Flights.Dtos;
public record FlightResponseDto
{
public long Id { get; init; }
public string FlightNumber { get; init; }
public long FlightId { get; set; }
public long AircraftId { get; init; }
public long DepartureAirportId { get; init; }
public DateTime DepartureDate { get; init; }
public DateTime ArriveDate { get; init; }
public long ArriveAirportId { get; init; }
public decimal DurationMinutes { get; init; }
public DateTime FlightDate { get; init; }
public Enums.FlightStatus Status { get; init; }
public decimal Price { get; init; }
}
public record FlightResponseDto(long Id, string FlightNumber, long AircraftId, long DepartureAirportId,
DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate,
Enums.FlightStatus Status, decimal Price);

View File

@ -40,6 +40,8 @@ public class CreateFlightCommandHandler : ICommandHandler<CreateFlightCommand, F
var newFlight = await _flightDbContext.Flights.AddAsync(flightEntity, cancellationToken);
return _mapper.Map<FlightResponseDto>(newFlight.Entity);
var f = _mapper.Map<FlightResponseDto>(newFlight.Entity);
return f;
}
}

View File

@ -3,36 +3,6 @@ using BuildingBlocks.Core.Event;
namespace Flight.Flights.Features.CreateFlight.Commands.V1.Reads;
public class CreateFlightMongoCommand : InternalCommand
{
public CreateFlightMongoCommand(long id, string flightNumber, long aircraftId, DateTime departureDate,
long departureAirportId,
DateTime arriveDate, long arriveAirportId, decimal durationMinutes, DateTime flightDate, Enums.FlightStatus status,
decimal price, bool isDeleted)
{
Id = id;
FlightNumber = flightNumber;
AircraftId = aircraftId;
DepartureDate = departureDate;
DepartureAirportId = departureAirportId;
ArriveDate = arriveDate;
ArriveAirportId = arriveAirportId;
DurationMinutes = durationMinutes;
FlightDate = flightDate;
Status = status;
Price = price;
IsDeleted = isDeleted;
}
public string FlightNumber { get; }
public long AircraftId { get; }
public DateTime DepartureDate { get; }
public long DepartureAirportId { get; }
public DateTime ArriveDate { get; }
public long ArriveAirportId { get; }
public decimal DurationMinutes { get; }
public DateTime FlightDate { get; }
public Enums.FlightStatus Status { get; }
public decimal Price { get; }
public bool IsDeleted { get; }
}
public record CreateFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate,
long DepartureAirportId, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate,
Enums.FlightStatus Status, decimal Price, bool IsDeleted) : InternalCommand;

View File

@ -33,7 +33,7 @@ public class CreateFlightMongoCommandHandler : ICommandHandler<CreateFlightMongo
var flightReadModel = _mapper.Map<FlightReadModel>(command);
var flight = await _flightReadDbContext.Flight.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == flightReadModel.Id && !x.IsDeleted, cancellationToken);
.FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken);
if (flight is not null)
throw new FlightAlreadyExistException();

View File

@ -0,0 +1,7 @@
using System;
namespace Flight.Flights.Features.CreateFlight.Dtos.V1;
public record CreateFlightRequestDto(string FlightNumber, long AircraftId, long DepartureAirportId,
DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId,
decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price);

View File

@ -3,6 +3,9 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Flights.Dtos;
using Flight.Flights.Features.CreateFlight.Commands.V1;
using Flight.Flights.Features.CreateFlight.Dtos.V1;
using Mapster;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -29,8 +32,11 @@ public class CreateFlightEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CreateFlight(CreateFlightCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CreateFlight(CreateFlightRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<CreateFlightCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -3,36 +3,6 @@ using BuildingBlocks.Core.Event;
namespace Flight.Flights.Features.DeleteFlight.Commands.V1.Reads;
public class DeleteFlightMongoCommand : InternalCommand
{
public DeleteFlightMongoCommand(long id, string flightNumber, long aircraftId, DateTime departureDate,
long departureAirportId,
DateTime arriveDate, long arriveAirportId, decimal durationMinutes, DateTime flightDate, Enums.FlightStatus status,
decimal price, bool isDeleted)
{
Id = id;
FlightNumber = flightNumber;
AircraftId = aircraftId;
DepartureDate = departureDate;
DepartureAirportId = departureAirportId;
ArriveDate = arriveDate;
ArriveAirportId = arriveAirportId;
DurationMinutes = durationMinutes;
FlightDate = flightDate;
Status = status;
Price = price;
IsDeleted = isDeleted;
}
public string FlightNumber { get; }
public long AircraftId { get; }
public DateTime DepartureDate { get; }
public long DepartureAirportId { get; }
public DateTime ArriveDate { get; }
public long ArriveAirportId { get; }
public decimal DurationMinutes { get; }
public DateTime FlightDate { get; }
public Enums.FlightStatus Status { get; }
public decimal Price { get; }
public bool IsDeleted { get; }
}
public record DeleteFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate,
long DepartureAirportId, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate,
Enums.FlightStatus Status, decimal Price, bool IsDeleted) : InternalCommand;

View File

@ -1,9 +1,13 @@
using AutoMapper;
using BuildingBlocks.IdsGenerator;
using Flight.Flights.Dtos;
using Flight.Flights.Features.CreateFlight.Commands.V1;
using Flight.Flights.Features.CreateFlight.Commands.V1.Reads;
using Flight.Flights.Features.CreateFlight.Dtos.V1;
using Flight.Flights.Features.DeleteFlight.Commands.V1.Reads;
using Flight.Flights.Features.UpdateFlight.Commands.V1;
using Flight.Flights.Features.UpdateFlight.Commands.V1.Reads;
using Flight.Flights.Features.UpdateFlight.Dtos;
using Flight.Flights.Models.Reads;
using Mapster;
@ -14,16 +18,30 @@ public class FlightMappings : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<Models.Flight, FlightResponseDto>()
.Map(d => d.FlightId, s => s.Id);
.ConstructUsing(x => new FlightResponseDto(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate,
x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.Price));
config.NewConfig<CreateFlightMongoCommand, FlightReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<Models.Flight, FlightReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<UpdateFlightMongoCommand, FlightReadModel>()
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<DeleteFlightMongoCommand, FlightReadModel>()
.Map(d => d.FlightId, s => s.Id);
config.NewConfig<CreateFlightRequestDto, CreateFlightCommand>()
.ConstructUsing(x => new CreateFlightCommand(x.FlightNumber, x.AircraftId, x.DepartureAirportId,
x.DepartureDate, x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.Price));
config.NewConfig<UpdateFlightRequestDto, UpdateFlightCommand>()
.ConstructUsing(x => new UpdateFlightCommand(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate,
x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.IsDeleted, x.Price));
}
}

View File

@ -36,4 +36,4 @@ public class GetAvailableFlightsEndpoint : IMinimalEndpoint
return Results.Ok(result);
}
}
}

View File

@ -1,29 +1,3 @@
// using System.Threading;
// using System.Threading.Tasks;
// using BuildingBlocks.Web;
// using Flight.Flights.Features.GetFlightById.Queries.V1;
// using Microsoft.AspNetCore.Authorization;
// using Microsoft.AspNetCore.Http;
// using Microsoft.AspNetCore.Mvc;
// using Swashbuckle.AspNetCore.Annotations;
//
// namespace Flight.Flights.Features.GetFlightById.Endpoints.V1;
//
// [Route(BaseApiPath + "/flight")]
// public class GetFlightByIdEndpoint : BaseController
// {
// [Authorize]
// [HttpGet("{id}")]
// [ProducesResponseType(StatusCodes.Status200OK)]
// [ProducesResponseType(StatusCodes.Status400BadRequest)]
// [SwaggerOperation(Summary = "Get flight by id", Description = "Get flight by id")]
// public async Task<ActionResult> GetById([FromRoute] GetFlightByIdQuery query, CancellationToken cancellationToken)
// {
// var result = await Mediator.Send(query, cancellationToken);
// return Ok(result);
// }
// }
using System.Threading;
using System.Threading.Tasks;
using BuildingBlocks.Web;
@ -61,4 +35,4 @@ public class GetFlightByIdEndpoint : IMinimalEndpoint
return Results.Ok(result);
}
}
}

View File

@ -3,36 +3,6 @@ using BuildingBlocks.Core.Event;
namespace Flight.Flights.Features.UpdateFlight.Commands.V1.Reads;
public class UpdateFlightMongoCommand : InternalCommand
{
public UpdateFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate,
long DepartureAirportId,
DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status,
decimal Price, bool IsDeleted)
{
this.Id = Id;
this.FlightNumber = FlightNumber;
this.AircraftId = AircraftId;
this.DepartureDate = DepartureDate;
this.DepartureAirportId = DepartureAirportId;
this.ArriveDate = ArriveDate;
this.ArriveAirportId = ArriveAirportId;
this.DurationMinutes = DurationMinutes;
this.FlightDate = FlightDate;
this.Status = Status;
this.Price = Price;
this.IsDeleted = IsDeleted;
}
public string FlightNumber { get; }
public long AircraftId { get; }
public DateTime DepartureDate { get; }
public long DepartureAirportId { get; }
public DateTime ArriveDate { get; }
public long ArriveAirportId { get; }
public decimal DurationMinutes { get; }
public DateTime FlightDate { get; }
public Enums.FlightStatus Status { get; }
public decimal Price { get; }
public bool IsDeleted { get; }
}
public record UpdateFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate,
long DepartureAirportId, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate,
Enums.FlightStatus Status, decimal Price, bool IsDeleted) : InternalCommand;

View File

@ -6,21 +6,9 @@ using Flight.Flights.Dtos;
namespace Flight.Flights.Features.UpdateFlight.Commands.V1;
public record UpdateFlightCommand : ICommand<FlightResponseDto>, IInvalidateCacheRequest, IInternalCommand
public record UpdateFlightCommand(long Id, string FlightNumber, long AircraftId, long DepartureAirportId,
DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate,
Enums.FlightStatus Status, bool IsDeleted, decimal Price) : ICommand<FlightResponseDto>, IInternalCommand, IInvalidateCacheRequest
{
public long Id { get; init; }
public string FlightNumber { get; init; }
public long AircraftId { get; init; }
public long DepartureAirportId { get; init; }
public DateTime DepartureDate { get; init; }
public DateTime ArriveDate { get; init; }
public long ArriveAirportId { get; init; }
public decimal DurationMinutes { get; init; }
public DateTime FlightDate { get; init; }
public Enums.FlightStatus Status { get; init; }
public bool IsDeleted { get; init; } = false;
public decimal Price { get; init; }
public string CacheKey => "GetAvailableFlightsQuery";
}

View File

@ -0,0 +1,6 @@
using System;
namespace Flight.Flights.Features.UpdateFlight.Dtos;
public record UpdateFlightRequestDto(long Id, string FlightNumber, long AircraftId, long DepartureAirportId, DateTime DepartureDate, DateTime ArriveDate,
long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price, bool IsDeleted);

View File

@ -3,6 +3,8 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Flights.Dtos;
using Flight.Flights.Features.UpdateFlight.Commands.V1;
using Flight.Flights.Features.UpdateFlight.Dtos;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -29,10 +31,12 @@ public class UpdateFlightEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> UpdateFlight(UpdateFlightCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> UpdateFlight(UpdateFlightRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken)
{
var command = mapper.Map<UpdateFlightCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);
}
}
}

View File

@ -1,6 +1,4 @@
using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Flight.Flights.Models.Reads;

View File

@ -1,12 +1,3 @@
using Flight.Seats.Models;
namespace Flight.Seats.Dtos;
public record SeatResponseDto
{
public long Id { get; set; }
public string SeatNumber { get; init; }
public Enums.SeatType Type { get; init; }
public Enums.SeatClass Class { get; init; }
public long FlightId { get; init; }
}
public record SeatResponseDto(long Id, string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId);

View File

@ -2,23 +2,5 @@
namespace Flight.Seats.Features.CreateSeat.Commands.V1.Reads;
public class CreateSeatMongoCommand : InternalCommand
{
public CreateSeatMongoCommand(long id, string seatNumber, Enums.SeatType type, Enums.SeatClass @class,
long flightId, bool isDeleted)
{
Id = id;
SeatNumber = seatNumber;
Type = type;
Class = @class;
FlightId = flightId;
IsDeleted = isDeleted;
}
public long Id { get; }
public string SeatNumber { get; }
public Enums.SeatType Type { get; }
public Enums.SeatClass Class { get; }
public long FlightId { get; }
public bool IsDeleted { get; }
}
public record CreateSeatMongoCommand(long Id, string SeatNumber, Enums.SeatType Type,
Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand;

View File

@ -32,7 +32,7 @@ public class CreateSeatMongoCommandHandler : ICommandHandler<CreateSeatMongoComm
var seatReadModel = _mapper.Map<SeatReadModel>(command);
var seat = await _flightReadDbContext.Seat.AsQueryable()
.FirstOrDefaultAsync(x => x.Id == seatReadModel.Id, cancellationToken);
.FirstOrDefaultAsync(x => x.SeatId == seatReadModel.SeatId, cancellationToken);
if (seat is not null)
throw new SeatAlreadyExistException();

View File

@ -0,0 +1,3 @@
namespace Flight.Seats.Features.CreateSeat.Dtos.V1;
public record CreateSeatRequestDto(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId);

View File

@ -1,34 +1,10 @@
// using System.Threading;
// using System.Threading.Tasks;
// using BuildingBlocks.Web;
// using Flight.Seats.Features.CreateSeat.Commands.V1;
// using Microsoft.AspNetCore.Http;
// using Microsoft.AspNetCore.Mvc;
// using Swashbuckle.AspNetCore.Annotations;
//
// namespace Flight.Seats.Features.CreateSeat.Endpoints.V1;
//
// [Route(BaseApiPath + "/flight/seat")]
// public class CreateSeatEndpoint : BaseController
// {
// [HttpPost]
// [ProducesResponseType(StatusCodes.Status201Created)]
// [ProducesResponseType(StatusCodes.Status400BadRequest)]
// [SwaggerOperation(Summary = "Create new seat", Description = "Create new seat")]
// public async Task<ActionResult> Create(CreateSeatCommand command, CancellationToken cancellationToken)
// {
// var result = await Mediator.Send(command, cancellationToken);
//
// return Ok(result);
// }
// }
using System.Threading;
using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Seats.Dtos;
using Flight.Seats.Features.CreateSeat.Commands.V1;
using Flight.Seats.Features.CreateSeat.Dtos.V1;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -55,10 +31,13 @@ public class CreateSeatEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CreateSeat(CreateSeatCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CreateSeat(CreateSeatRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<CreateSeatCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);
}
}
}

View File

@ -2,22 +2,5 @@
namespace Flight.Seats.Features.ReserveSeat.Commands.V1.Reads;
public class ReserveSeatMongoCommand : InternalCommand
{
public ReserveSeatMongoCommand(long id, string seatNumber, Enums.SeatType type, Enums.SeatClass @class, long flightId,
bool isDeleted)
{
Id = id;
SeatNumber = seatNumber;
Type = type;
Class = @class;
FlightId = flightId;
IsDeleted = isDeleted;
}
public string SeatNumber { get; }
public Enums.SeatType Type { get; }
public Enums.SeatClass Class { get; }
public long FlightId { get; }
public bool IsDeleted { get; }
}
public record ReserveSeatMongoCommand(long Id, string SeatNumber, Enums.SeatType Type,
Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand;

View File

@ -0,0 +1,4 @@
namespace Flight.Seats.Features.ReserveSeat.Dtos.V1;
public record ReserveSeatRequestDto(long FlightId, string SeatNumber);

View File

@ -3,6 +3,8 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Flight.Seats.Dtos;
using Flight.Seats.Features.ReserveSeat.Commands.V1;
using Flight.Seats.Features.ReserveSeat.Dtos.V1;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -29,10 +31,12 @@ public class ReserveSeatEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> ReserveSeat(ReserveSeatCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> ReserveSeat(ReserveSeatRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken)
{
var command = mapper.Map<ReserveSeatCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);
}
}
}

View File

@ -1,7 +1,11 @@
using BuildingBlocks.IdsGenerator;
using Flight.Seats.Dtos;
using Flight.Seats.Features.CreateSeat.Commands.V1;
using Flight.Seats.Features.CreateSeat.Commands.V1.Reads;
using Flight.Seats.Features.CreateSeat.Dtos.V1;
using Flight.Seats.Features.ReserveSeat.Commands.V1;
using Flight.Seats.Features.ReserveSeat.Commands.V1.Reads;
using Flight.Seats.Features.ReserveSeat.Dtos.V1;
using Flight.Seats.Models;
using Flight.Seats.Models.Reads;
using Mapster;
@ -12,14 +16,24 @@ public class SeatMappings : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<Seat, SeatResponseDto>();
config.NewConfig<Seat, SeatResponseDto>()
.ConstructUsing(x => new SeatResponseDto(x.Id, x.SeatNumber, x.Type, x.Class, x.FlightId));
config.NewConfig<CreateSeatMongoCommand, SeatReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.SeatId, s => s.Id);
config.NewConfig<Seat, SeatReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.SeatId, s => s.Id);
config.NewConfig<ReserveSeatMongoCommand, SeatReadModel>()
.Map(d => d.SeatId, s => s.Id);
config.NewConfig<CreateSeatRequestDto, CreateSeatCommand>()
.ConstructUsing(x => new CreateSeatCommand(x.SeatNumber, x.Type, x.Class, x.FlightId));
config.NewConfig<ReserveSeatRequestDto, ReserveSeatCommand>()
.ConstructUsing(x => new ReserveSeatCommand(x.FlightId, x.SeatNumber));
}
}

View File

@ -1,5 +1,4 @@
using Flight.Flights.Features.CreateFlight;
using Flight.Flights.Features.CreateFlight.Commands.V1;
using Flight.Flights.Features.CreateFlight.Commands.V1;
namespace Integration.Test.Fakes;

View File

@ -39,7 +39,7 @@ public class GetFlightByIdTests : IntegrationTestBase<Program, FlightDbContext,
// Assert
response.Should().NotBeNull();
response?.FlightId.Should().Be(command.Id);
response?.Id.Should().Be(command.Id);
}
[Fact]

View File

@ -84,6 +84,7 @@ public static class InfrastructureExtensions
var env = app.Environment;
var appOptions = app.GetOptions<AppOptions>("AppOptions");
app.UseProblemDetails();
app.UseSerilogRequestLogging();
app.UseMigration<IdentityContext>(env);
app.UseCorrelationId();

View File

@ -10,8 +10,8 @@ public static class MediatRExtensions
public static IServiceCollection AddCustomMediatR(this IServiceCollection services)
{
services.AddMediatR(typeof(IdentityRoot).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
return services;
}

View File

@ -1,13 +1,3 @@
using System;
namespace Identity.Identity.Dtos;
public record RegisterNewUserResponseDto
{
public long Id { get; init; }
public string FirstName { get; init; }
public string LastName { get; init; }
public string Username { get; init; }
public string PassportNumber { get; set; }
}
public record RegisterNewUserResponseDto(long Id, string FirstName, string LastName, string Username, string PassportNumber);

View File

@ -0,0 +1,15 @@
using Identity.Identity.Features.RegisterNewUser.Commands.V1;
using Identity.Identity.Features.RegisterNewUser.Dtos.V1;
using Mapster;
namespace Identity.Identity.Features;
public class IdentityMappings : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<RegisterNewUserRequestDto, RegisterNewUserCommand>()
.ConstructUsing(x => new RegisterNewUserCommand(x.FirstName, x.LastName, x.Username, x.Email,
x.Password, x.ConfirmPassword, x.PassportNumber));
}
}

View File

@ -29,7 +29,7 @@ public class RegisterNewUserCommandHandler : ICommandHandler<RegisterNewUserComm
{
Guard.Against.Null(command, nameof(command));
var applicationUser = new ApplicationUser
var applicationUser = new ApplicationUser()
{
FirstName = command.FirstName,
LastName = command.LastName,
@ -51,13 +51,7 @@ public class RegisterNewUserCommandHandler : ICommandHandler<RegisterNewUserComm
await _eventDispatcher.SendAsync(new UserCreated(applicationUser.Id, applicationUser.FirstName + " " + applicationUser.LastName,
applicationUser.PassPortNumber),cancellationToken: cancellationToken);
return new RegisterNewUserResponseDto
{
Id = applicationUser.Id,
FirstName = applicationUser.FirstName,
LastName = applicationUser.LastName,
Username = applicationUser.UserName,
PassportNumber = applicationUser.PassPortNumber
};
return new RegisterNewUserResponseDto(applicationUser.Id, applicationUser.FirstName, applicationUser.LastName,
applicationUser.UserName, applicationUser.PassPortNumber);
}
}

View File

@ -0,0 +1,4 @@
namespace Identity.Identity.Features.RegisterNewUser.Dtos.V1;
public record RegisterNewUserRequestDto(string FirstName, string LastName, string Username, string Email,
string Password, string ConfirmPassword, string PassportNumber);

View File

@ -3,6 +3,8 @@ using System.Threading.Tasks;
using BuildingBlocks.Web;
using Identity.Identity.Dtos;
using Identity.Identity.Features.RegisterNewUser.Commands.V1;
using Identity.Identity.Features.RegisterNewUser.Dtos.V1;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@ -28,8 +30,11 @@ public class RegisterNewUserEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> RegisterNewUser(RegisterNewUserCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> RegisterNewUser(RegisterNewUserRequestDto request, IMediator mediator, IMapper mapper,
CancellationToken cancellationToken)
{
var command = mapper.Map<RegisterNewUserCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -4,7 +4,7 @@ namespace Identity.Identity.Models;
public class ApplicationUser : IdentityUser<long>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string PassPortNumber { get; set; }
public string FirstName { get; init; }
public string LastName { get; init; }
public string PassPortNumber { get; init; }
}

View File

@ -1,27 +1,5 @@
using BuildingBlocks.EFCore;
using BuildingBlocks.Exception;
using BuildingBlocks.HealthCheck;
using BuildingBlocks.IdsGenerator;
using BuildingBlocks.Jwt;
using BuildingBlocks.Logging;
using BuildingBlocks.Mapster;
using BuildingBlocks.MassTransit;
using BuildingBlocks.Mongo;
using BuildingBlocks.OpenTelemetry;
using BuildingBlocks.PersistMessageProcessor;
using BuildingBlocks.Swagger;
using BuildingBlocks.Web;
using Figgle;
using FluentValidation;
using Hellang.Middleware.ProblemDetails;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Passenger;
using Passenger.Data;
using Passenger.Extensions;
using Passenger.Extensions.Infrastructure;
using Passenger.GrpcServer.Services;
using Prometheus;
using Serilog;
var builder = WebApplication.CreateBuilder(args);

View File

@ -91,11 +91,11 @@ public static class InfrastructureExtensions
var env = app.Environment;
var appOptions = app.GetOptions<AppOptions>("AppOptions");
app.UseProblemDetails();
app.UseSerilogRequestLogging();
app.UseMigration<PassengerDbContext>(env);
app.UseCorrelationId();
app.UseHttpMetrics();
app.UseProblemDetails();
app.UseHttpsRedirection();
app.UseCustomHealthCheck();
app.MapMetrics();

View File

@ -11,9 +11,9 @@ public static class MediatRExtensions
public static IServiceCollection AddCustomMediatR(this IServiceCollection services)
{
services.AddMediatR(typeof(PassengerRoot).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>));
return services;
}

View File

@ -2,22 +2,5 @@
namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1.Reads;
public class CompleteRegisterPassengerMongoCommand : InternalCommand
{
public CompleteRegisterPassengerMongoCommand(long id, string passportNumber, string name,
Enums.PassengerType passengerType, int age, bool isDeleted)
{
Id = id;
PassportNumber = passportNumber;
Name = name;
PassengerType = passengerType;
Age = age;
IsDeleted = isDeleted;
}
public string PassportNumber { get; }
public string Name { get; }
public Enums.PassengerType PassengerType { get; }
public int Age { get; }
public bool IsDeleted { get; }
}
public record CompleteRegisterPassengerMongoCommand(long Id, string PassportNumber, string Name,
Enums.PassengerType PassengerType, int Age, bool IsDeleted) : InternalCommand;

View File

@ -29,7 +29,7 @@ public class CompleteRegisterPassengerMongoCommandHandler : ICommandHandler<Comp
var passengerReadModel = _mapper.Map<PassengerReadModel>(command);
var passenger = await _passengerReadDbContext.Passenger.AsQueryable()
.FirstOrDefaultAsync(x => x.PassengerId == command.Id && !x.IsDeleted, cancellationToken);
.FirstOrDefaultAsync(x => x.PassengerId == passengerReadModel.PassengerId && !x.IsDeleted, cancellationToken);
if (passenger is not null)
{

View File

@ -0,0 +1,3 @@
namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Dtos.V1;
public record CompleteRegisterPassengerRequestDto(string PassportNumber, Enums.PassengerType PassengerType, int Age);

View File

@ -1,12 +1,12 @@
using BuildingBlocks.Web;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Passenger.Passengers.Dtos;
using Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1;
using Passenger.Passengers.Features.CompleteRegisterPassenger.Dtos.V1;
using Swashbuckle.AspNetCore.Annotations;
namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Endpoints.V1;
@ -29,8 +29,11 @@ public class CompleteRegisterPassengerEndpoint : IMinimalEndpoint
return endpoints;
}
private async Task<IResult> CompleteRegisterPassenger(CompleteRegisterPassengerCommand command, IMediator mediator, CancellationToken cancellationToken)
private async Task<IResult> CompleteRegisterPassenger(CompleteRegisterPassengerRequestDto request, IMapper mapper,
IMediator mediator, CancellationToken cancellationToken)
{
var command = mapper.Map<CompleteRegisterPassengerCommand>(request);
var result = await mediator.Send(command, cancellationToken);
return Results.Ok(result);

View File

@ -3,7 +3,9 @@ using BuildingBlocks.Contracts.EventBus.Messages;
using BuildingBlocks.IdsGenerator;
using Mapster;
using Passenger.Passengers.Dtos;
using Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1;
using Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1.Reads;
using Passenger.Passengers.Features.CompleteRegisterPassenger.Dtos.V1;
using Passenger.Passengers.Models.Reads;
namespace Passenger.Passengers.Features;
@ -15,5 +17,8 @@ public class PassengerMappings : IRegister
config.NewConfig<CompleteRegisterPassengerMongoCommand, PassengerReadModel>()
.Map(d => d.Id, s => SnowFlakIdGenerator.NewId())
.Map(d => d.PassengerId, s => s.Id);
config.NewConfig<CompleteRegisterPassengerRequestDto, CompleteRegisterPassengerCommand>()
.ConstructUsing(x => new CompleteRegisterPassengerCommand(x.PassportNumber, x.PassengerType, x.Age));
}
}

View File

@ -4,9 +4,9 @@ public class PassengerReadModel
{
public long Id { get; init; }
public long PassengerId { get; init; }
public string PassportNumber { get; private set; }
public string Name { get; private set; }
public Enums.PassengerType PassengerType { get; private set; }
public int Age { get; private set; }
public string PassportNumber { get; init; }
public string Name { get; init; }
public Enums.PassengerType PassengerType { get; init; }
public int Age { get; init; }
public bool IsDeleted { get; init; }
}