diff --git a/assets/vertical-slice-architecture.excalidraw b/assets/vertical-slice-architecture.excalidraw index 8737db9..b62827b 100644 --- a/assets/vertical-slice-architecture.excalidraw +++ b/assets/vertical-slice-architecture.excalidraw @@ -5,8 +5,8 @@ "elements": [ { "type": "rectangle", - "version": 240, - "versionNonce": 1959093945, + "version": 242, + "versionNonce": 1509780320, "isDeleted": false, "id": "80OGzNPG6Gk8NAvbV3XaF", "fillStyle": "solid", @@ -18,7 +18,7 @@ "x": 648, "y": 187, "strokeColor": "#000000", - "backgroundColor": "#41a7f5", + "backgroundColor": "#a8bffe", "width": 538, "height": 62, "seed": 246982778, @@ -32,14 +32,14 @@ "id": "46GLDhDwmnc8RGy3v8OK8" } ], - "updated": 1678375014228, + "updated": 1679316672934, "link": null, "locked": false }, { "type": "text", - "version": 136, - "versionNonce": 833895767, + "version": 137, + "versionNonce": 703919968, "isDeleted": false, "id": "46GLDhDwmnc8RGy3v8OK8", "fillStyle": "hachure", @@ -58,7 +58,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1678375014228, + "updated": 1679315949309, "link": null, "locked": false, "fontSize": 28, @@ -71,8 +71,8 @@ }, { "type": "rectangle", - "version": 350, - "versionNonce": 435319161, + "version": 358, + "versionNonce": 356515488, "isDeleted": false, "id": "nZuYK7wbLObwRvpRRLHay", "fillStyle": "solid", @@ -84,7 +84,7 @@ "x": 648, "y": 263, "strokeColor": "#000000", - "backgroundColor": "#ced4da", + "backgroundColor": "#fea8d5", "width": 538, "height": 62, "seed": 287502970, @@ -98,14 +98,14 @@ "id": "OALII-DXtatRPgn_EkHfp" } ], - "updated": 1678375286769, + "updated": 1679316735759, "link": null, "locked": false }, { "type": "text", - "version": 245, - "versionNonce": 63658455, + "version": 246, + "versionNonce": 1126108000, "isDeleted": false, "id": "OALII-DXtatRPgn_EkHfp", "fillStyle": "hachure", @@ -124,7 +124,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1678375018983, + "updated": 1679315949309, "link": null, "locked": false, "fontSize": 28, @@ -137,8 +137,8 @@ }, { "type": "rectangle", - "version": 276, - "versionNonce": 498715799, + "version": 282, + "versionNonce": 787808928, "isDeleted": false, "id": "za_4vz64MSfPF5TWmD7wj", "fillStyle": "solid", @@ -150,7 +150,7 @@ "x": 650, "y": 338, "strokeColor": "#000000", - "backgroundColor": "#fa5252", + "backgroundColor": "#f30358", "width": 538, "height": 62, "seed": 676018342, @@ -164,14 +164,14 @@ "id": "6CqYCSOKHqhqJ8nf4b-Sv" } ], - "updated": 1678375038578, + "updated": 1679316783390, "link": null, "locked": false }, { "type": "text", - "version": 188, - "versionNonce": 145052535, + "version": 189, + "versionNonce": 1441177440, "isDeleted": false, "id": "6CqYCSOKHqhqJ8nf4b-Sv", "fillStyle": "hachure", @@ -190,7 +190,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1678375033581, + "updated": 1679315949309, "link": null, "locked": false, "fontSize": 28, @@ -203,8 +203,8 @@ }, { "type": "rectangle", - "version": 324, - "versionNonce": 1540569401, + "version": 326, + "versionNonce": 1669046112, "isDeleted": false, "id": "t2sZwLLvmq3y2ndIbEomB", "fillStyle": "solid", @@ -216,7 +216,7 @@ "x": 648, "y": 413, "strokeColor": "#000000", - "backgroundColor": "#07da63", + "backgroundColor": "#9d9ca2", "width": 538, "height": 62, "seed": 1173221990, @@ -230,14 +230,14 @@ "id": "b3wdaWjaVmgHpzMD26uKD" } ], - "updated": 1678375048801, + "updated": 1679316844215, "link": null, "locked": false }, { "type": "text", - "version": 223, - "versionNonce": 1635337382, + "version": 224, + "versionNonce": 1385935712, "isDeleted": false, "id": "b3wdaWjaVmgHpzMD26uKD", "fillStyle": "hachure", @@ -256,7 +256,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1677440080893, + "updated": 1679315949310, "link": null, "locked": false, "fontSize": 28, @@ -269,20 +269,20 @@ }, { "type": "rectangle", - "version": 191, - "versionNonce": 502145367, + "version": 202, + "versionNonce": 1461187232, "isDeleted": false, "id": "FQZImjU2-VUOATU9Yeyly", "fillStyle": "solid", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, - "opacity": 90, + "opacity": 100, "angle": 0, "x": 678, "y": 154, "strokeColor": "#000000", - "backgroundColor": "#fff700 ", + "backgroundColor": "#fefda8", "width": 48, "height": 361, "seed": 1254939642, @@ -291,26 +291,26 @@ "type": 3 }, "boundElements": [], - "updated": 1678375337365, + "updated": 1679316609154, "link": null, "locked": false }, { "type": "rectangle", - "version": 231, - "versionNonce": 579313209, + "version": 249, + "versionNonce": 1540775776, "isDeleted": false, "id": "_Vw9EnXAyzxRDEzXCTfeL", "fillStyle": "solid", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, - "opacity": 90, + "opacity": 100, "angle": 0, - "x": 743, + "x": 742, "y": 153.5, "strokeColor": "#000000", - "backgroundColor": "#fff700 ", + "backgroundColor": "#fefda8", "width": 48, "height": 361, "seed": 523058342, @@ -319,21 +319,21 @@ "type": 3 }, "boundElements": [], - "updated": 1678375355851, + "updated": 1679316594766, "link": null, "locked": false }, { "type": "text", - "version": 245, - "versionNonce": 1220596518, + "version": 249, + "versionNonce": 871687840, "isDeleted": false, "id": "hyJiOwPt7LFndn5R0xgfL", "fillStyle": "solid", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, - "opacity": 70, + "opacity": 100, "angle": 4.707547804955119, "x": 637.1248451774691, "y": 317.9455509364301, @@ -345,7 +345,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1677440080893, + "updated": 1679315961675, "link": null, "locked": false, "fontSize": 28, @@ -358,15 +358,15 @@ }, { "type": "text", - "version": 179, - "versionNonce": 1053153850, + "version": 182, + "versionNonce": 1494113120, "isDeleted": false, "id": "7KOHd5JA_wVMmwXPVT1N3", "fillStyle": "solid", "strokeWidth": 1, "strokeStyle": "solid", "roughness": 1, - "opacity": 70, + "opacity": 80, "angle": 4.7123889803846915, "x": 695.6880416870117, "y": 313.20000000000005, @@ -378,7 +378,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1677440080893, + "updated": 1679315949310, "link": null, "locked": false, "fontSize": 28, @@ -391,8 +391,8 @@ }, { "type": "text", - "version": 162, - "versionNonce": 1556577894, + "version": 163, + "versionNonce": 1243581088, "isDeleted": false, "id": "SuFNrbzZGowiIybusnadN", "fillStyle": "solid", @@ -411,7 +411,7 @@ "groupIds": [], "roundness": null, "boundElements": [], - "updated": 1677440080893, + "updated": 1679315949310, "link": null, "locked": false, "fontSize": 28, diff --git a/assets/vertical-slice-architecture.png b/assets/vertical-slice-architecture.png index fe07eff..3137aac 100644 Binary files a/assets/vertical-slice-architecture.png and b/assets/vertical-slice-architecture.png differ diff --git a/src/Services/Booking/src/Booking/Booking.csproj b/src/Services/Booking/src/Booking/Booking.csproj index 856bc39..6f0239f 100644 --- a/src/Services/Booking/src/Booking/Booking.csproj +++ b/src/Services/Booking/src/Booking/Booking.csproj @@ -26,10 +26,14 @@ - - - + + + + <_Parameter1>Integration.Test + + + diff --git a/src/Services/Booking/src/Booking/Booking/Dtos/CreateReservationResponseDto.cs b/src/Services/Booking/src/Booking/Booking/Dtos/CreateReservation.cs similarity index 100% rename from src/Services/Booking/src/Booking/Booking/Dtos/CreateReservationResponseDto.cs rename to src/Services/Booking/src/Booking/Booking/Dtos/CreateReservation.cs diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/BookingAlreadyExistException.cs b/src/Services/Booking/src/Booking/Booking/Exceptions/BookingAlreadyExistException.cs similarity index 77% rename from src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/BookingAlreadyExistException.cs rename to src/Services/Booking/src/Booking/Booking/Exceptions/BookingAlreadyExistException.cs index ff9f3f9..0149537 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/BookingAlreadyExistException.cs +++ b/src/Services/Booking/src/Booking/Booking/Exceptions/BookingAlreadyExistException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Booking.Booking.Exceptions; -namespace Booking.Booking.Features.CreateBooking.Exceptions; +using BuildingBlocks.Exception; public class BookingAlreadyExistException : ConflictException { diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/FlightNotFoundException.cs b/src/Services/Booking/src/Booking/Booking/Exceptions/FlightNotFoundException.cs similarity index 74% rename from src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/FlightNotFoundException.cs rename to src/Services/Booking/src/Booking/Booking/Exceptions/FlightNotFoundException.cs index 124d7c3..af4b5e6 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Exceptions/FlightNotFoundException.cs +++ b/src/Services/Booking/src/Booking/Booking/Exceptions/FlightNotFoundException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Booking.Booking.Exceptions; -namespace Booking.Booking.Features.CreateBooking.Exceptions; +using BuildingBlocks.Exception; public class FlightNotFoundException : NotFoundException { diff --git a/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs b/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs index 42d454d..80f8443 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs @@ -1,10 +1,10 @@ using Booking.Booking.Dtos; -using Booking.Booking.Features.CreateBooking.Commands.V1; -using Booking.Booking.Features.CreateBooking.Dtos.V1; using Mapster; namespace Booking.Booking.Features; +using CreatingBook.Commands.V1; + public class BookingMappings : IRegister { public void Register(TypeAdapterConfig config) @@ -17,7 +17,7 @@ public class BookingMappings : IRegister x.Trip.Description)); - config.NewConfig() - .ConstructUsing(x => new CreateBookingCommand(x.PassengerId, x.FlightId, x.Description)); + config.NewConfig() + .ConstructUsing(x => new CreateBooking(x.PassengerId, x.FlightId, x.Description)); } } diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommand.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommand.cs deleted file mode 100644 index 441ad67..0000000 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; - -namespace Booking.Booking.Features.CreateBooking.Commands.V1; - -public record CreateBookingCommand(long PassengerId, long FlightId, string Description) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} - diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandValidator.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandValidator.cs deleted file mode 100644 index dd662bc..0000000 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandValidator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FluentValidation; - -namespace Booking.Booking.Features.CreateBooking.Commands.V1; - -public class CreateBookingCommandValidator : AbstractValidator -{ - public CreateBookingCommandValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.FlightId).NotNull().WithMessage("FlightId is required!"); - RuleFor(x => x.PassengerId).NotNull().WithMessage("PassengerId is required!"); - } -} diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Dtos/V1/CreateBookingRequestDto.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Dtos/V1/CreateBookingRequestDto.cs deleted file mode 100644 index 9fe7a91..0000000 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Dtos/V1/CreateBookingRequestDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Booking.Booking.Features.CreateBooking.Dtos.V1; - -public record CreateBookingRequestDto(long PassengerId, long FlightId, string Description); diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Events/Domain/V1/BookingCreatedDomainEvent.cs b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/BookingCreatedDomainEvent.cs similarity index 62% rename from src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Events/Domain/V1/BookingCreatedDomainEvent.cs rename to src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/BookingCreatedDomainEvent.cs index 2a13e14..e7ae19d 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Events/Domain/V1/BookingCreatedDomainEvent.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/BookingCreatedDomainEvent.cs @@ -1,7 +1,7 @@ -using Booking.Booking.Models.ValueObjects; +namespace Booking.Booking.Features.CreatingBook.Commands.V1; + using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Model; - -namespace Booking.Booking.Features.CreateBooking.Events.Domain.V1; +using Models.ValueObjects; public record BookingCreatedDomainEvent(long Id, PassengerInfo PassengerInfo, Trip Trip) : Audit, IDomainEvent; diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandHandler.cs b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBooking.cs similarity index 71% rename from src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandHandler.cs rename to src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBooking.cs index 87453e9..3376e2b 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Commands/V1/CreateBookingCommandHandler.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBooking.cs @@ -1,16 +1,33 @@ +namespace Booking.Booking.Features.CreatingBook.Commands.V1; + using Ardalis.GuardClauses; -using Booking.Booking.Features.CreateBooking.Exceptions; -using Booking.Booking.Models.ValueObjects; using BuildingBlocks.Core; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.EventStoreDB.Repository; +using BuildingBlocks.IdsGenerator; using BuildingBlocks.Web; +using Exceptions; using Flight; +using FluentValidation; +using Models.ValueObjects; using Passenger; -namespace Booking.Booking.Features.CreateBooking.Commands.V1; +public record CreateBooking(long PassengerId, long FlightId, string Description) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} -public class CreateBookingCommandHandler : ICommandHandler +internal class CreateBookingValidator : AbstractValidator +{ + public CreateBookingValidator() + { + RuleFor(x => x.FlightId).NotNull().WithMessage("FlightId is required!"); + RuleFor(x => x.PassengerId).NotNull().WithMessage("PassengerId is required!"); + } +} + +internal class CreateBookingCommandHandler : ICommandHandler { private readonly IEventStoreDBRepository _eventStoreDbRepository; private readonly ICurrentUserProvider _currentUserProvider; @@ -31,26 +48,30 @@ public class CreateBookingCommandHandler : ICommandHandler Handle(CreateBookingCommand command, CancellationToken cancellationToken) + public async Task Handle(CreateBooking command, CancellationToken cancellationToken) { Guard.Against.Null(command, nameof(command)); - var flight = await _flightGrpcServiceClient.GetByIdAsync(new Flight.GetByIdRequest {Id = command.FlightId}); + var flight = await _flightGrpcServiceClient.GetByIdAsync(new Flight.GetByIdRequest { Id = command.FlightId }); if (flight is null) + { throw new FlightNotFoundException(); + } var passenger = - await _passengerGrpcServiceClient.GetByIdAsync(new Passenger.GetByIdRequest {Id = command.PassengerId}); + await _passengerGrpcServiceClient.GetByIdAsync(new Passenger.GetByIdRequest { Id = command.PassengerId }); var emptySeat = (await _flightGrpcServiceClient - .GetAvailableSeatsAsync(new GetAvailableSeatsRequest {FlightId = command.FlightId}).ResponseAsync) + .GetAvailableSeatsAsync(new GetAvailableSeatsRequest { FlightId = command.FlightId }).ResponseAsync) ?.Items?.FirstOrDefault(); var reservation = await _eventStoreDbRepository.Find(command.Id, cancellationToken); if (reservation is not null && !reservation.IsDeleted) + { throw new BookingAlreadyExistException(); + } var aggrigate = Models.Booking.Create(command.Id, new PassengerInfo(passenger.Name), new Trip( flight.FlightNumber, flight.AircraftId, flight.DepartureAirportId, diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Endpoints/V1/CreateBookingEndpoint.cs b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBookingEndpoint.cs similarity index 74% rename from src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Endpoints/V1/CreateBookingEndpoint.cs rename to src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBookingEndpoint.cs index 5a4e85c..e7c3cc1 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/Endpoints/V1/CreateBookingEndpoint.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreatingBook/Commands/V1/CreateBookingEndpoint.cs @@ -1,29 +1,26 @@ -using Booking.Booking.Features.CreateBooking.Commands.V1; -using Booking.Booking.Features.CreateBooking.Dtos.V1; +namespace Booking.Booking.Features.CreatingBook.Commands.V1; + using BuildingBlocks.Web; +using Hellang.Middleware.ProblemDetails; 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 Swashbuckle.AspNetCore.Annotations; -namespace Booking.Booking.Features.CreateBooking.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record CreateBookingRequestDto(long PassengerId, long FlightId, string Description); public class CreateBookingEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/booking", CreateBooking) + builder.MapPost($"{EndpointConfig.BaseApiPath}/booking", CreateBooking) .RequireAuthorization() .WithTags("Booking") .WithName("CreateBooking") .WithMetadata(new SwaggerOperationAttribute("Create Booking", "Create Booking")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Booking").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Booking").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, @@ -41,13 +38,13 @@ public class CreateBookingEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task CreateBooking(CreateBookingRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Booking/src/Booking/Booking/Models/Booking.cs b/src/Services/Booking/src/Booking/Booking/Models/Booking.cs index 22e9ade..ce3bb66 100644 --- a/src/Services/Booking/src/Booking/Booking/Models/Booking.cs +++ b/src/Services/Booking/src/Booking/Booking/Models/Booking.cs @@ -1,9 +1,10 @@ -using Booking.Booking.Features.CreateBooking.Events.Domain.V1; using Booking.Booking.Models.ValueObjects; using BuildingBlocks.EventStoreDB.Events; namespace Booking.Booking.Models; +using Features.CreatingBook.Commands.V1; + public record Booking : AggregateEventSourcing { public Trip Trip { get; private set; } diff --git a/src/Services/Booking/src/Booking/BookingProjection.cs b/src/Services/Booking/src/Booking/BookingProjection.cs index 663c938..89b145a 100644 --- a/src/Services/Booking/src/Booking/BookingProjection.cs +++ b/src/Services/Booking/src/Booking/BookingProjection.cs @@ -1,4 +1,3 @@ -using Booking.Booking.Features.CreateBooking.Events.Domain.V1; using Booking.Booking.Models.Reads; using Booking.Data; using BuildingBlocks.EventStoreDB.Events; @@ -10,6 +9,8 @@ using MongoDB.Driver.Linq; namespace Booking; +using Booking.Features.CreatingBook.Commands.V1; + public class BookingProjection : IProjectionProcessor { private readonly BookingReadDbContext _bookingReadDbContext; diff --git a/src/Services/Booking/src/Booking/EventMapper.cs b/src/Services/Booking/src/Booking/EventMapper.cs index f8ee726..5cc4bd2 100644 --- a/src/Services/Booking/src/Booking/EventMapper.cs +++ b/src/Services/Booking/src/Booking/EventMapper.cs @@ -1,10 +1,11 @@ -using Booking.Booking.Features.CreateBooking.Events.Domain.V1; using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; using BuildingBlocks.Core.Event; namespace Booking; +using Booking.Features.CreatingBook.Commands.V1; + public sealed class EventMapper : IEventMapper { public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event) diff --git a/src/Services/Booking/tests/IntegrationTest/Fakes/FakeCreateBookingCommand.cs b/src/Services/Booking/tests/IntegrationTest/Fakes/FakeCreateBookingCommand.cs index 86bcfee..2abcce8 100644 --- a/src/Services/Booking/tests/IntegrationTest/Fakes/FakeCreateBookingCommand.cs +++ b/src/Services/Booking/tests/IntegrationTest/Fakes/FakeCreateBookingCommand.cs @@ -1,11 +1,11 @@ using AutoBogus; -using Booking.Booking.Features.CreateBooking; -using Booking.Booking.Features.CreateBooking.Commands.V1; using BuildingBlocks.IdsGenerator; namespace Integration.Test.Fakes; -public sealed class FakeCreateBookingCommand : AutoFaker +using global::Booking.Booking.Features.CreatingBook.Commands.V1; + +public sealed class FakeCreateBookingCommand : AutoFaker { public FakeCreateBookingCommand() { diff --git a/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftDto.cs b/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftDto.cs new file mode 100644 index 0000000..89aeed8 --- /dev/null +++ b/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftDto.cs @@ -0,0 +1,3 @@ +namespace Flight.Aircrafts.Dtos; + +public record AircraftDto(long Id, string Name, string Model, int ManufacturingYear); diff --git a/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftResponseDto.cs b/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftResponseDto.cs deleted file mode 100644 index 2781c2e..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Dtos/AircraftResponseDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Flight.Aircrafts.Dtos; - -public record AircraftResponseDto(long Id, string Name, string Model, int ManufacturingYear); diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Exceptions/AircraftAlreadyExistException.cs b/src/Services/Flight/src/Flight/Aircrafts/Exceptions/AircraftAlreadyExistException.cs similarity index 78% rename from src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Exceptions/AircraftAlreadyExistException.cs rename to src/Services/Flight/src/Flight/Aircrafts/Exceptions/AircraftAlreadyExistException.cs index f7901e4..241dcdb 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Exceptions/AircraftAlreadyExistException.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Exceptions/AircraftAlreadyExistException.cs @@ -1,8 +1,8 @@ +namespace Flight.Aircrafts.Exceptions; + using System.Net; using BuildingBlocks.Exception; -namespace Flight.Aircrafts.Features.CreateAircraft.Exceptions; - public class AircraftAlreadyExistException : AppException { public AircraftAlreadyExistException() : base("Aircraft already exist!", HttpStatusCode.Conflict) diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/AircraftMappings.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/AircraftMappings.cs index a1069e2..bef0168 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/AircraftMappings.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/AircraftMappings.cs @@ -1,19 +1,16 @@ 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; +using CreatingAircraft.V1; + public class AircraftMappings : IRegister { public void Register(TypeAdapterConfig config) { - config.NewConfig() + config.NewConfig() .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.AircraftId, s => s.Id); @@ -21,7 +18,7 @@ public class AircraftMappings : IRegister .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.AircraftId, s => s.Id); - config.NewConfig() - .ConstructUsing(x => new CreateAircraftCommand(x.Name, x.Model, x.ManufacturingYear)); + config.NewConfig() + .ConstructUsing(x => new CreatingAircraft.V1.CreateAircraft(x.Name, x.Model, x.ManufacturingYear)); } } diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommand.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommand.cs deleted file mode 100644 index df98fd5..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; -using Flight.Aircrafts.Dtos; - -namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1; - -public record CreateAircraftCommand(string Name, string Model, int ManufacturingYear) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandHandler.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandHandler.cs deleted file mode 100644 index 718c087..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using Flight.Aircrafts.Dtos; -using Flight.Aircrafts.Features.CreateAircraft.Exceptions; -using Flight.Aircrafts.Models; -using Flight.Data; -using MapsterMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1; - -public class CreateAircraftCommandHandler : IRequestHandler -{ - private readonly FlightDbContext _flightDbContext; - private readonly IMapper _mapper; - - public CreateAircraftCommandHandler(IMapper mapper, FlightDbContext flightDbContext) - { - _mapper = mapper; - _flightDbContext = flightDbContext; - } - - public async Task Handle(CreateAircraftCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var aircraft = await _flightDbContext.Aircraft.SingleOrDefaultAsync(x => x.Model == command.Model, cancellationToken); - - if (aircraft is not null) - throw new AircraftAlreadyExistException(); - - var aircraftEntity = Aircraft.Create(command.Id, command.Name, command.Model, command.ManufacturingYear); - - var newAircraft = await _flightDbContext.Aircraft.AddAsync(aircraftEntity, cancellationToken); - - await _flightDbContext.SaveChangesAsync(cancellationToken); - - return _mapper.Map(newAircraft.Entity); - } -} diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandValidator.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandValidator.cs deleted file mode 100644 index ced2729..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/CreateAircraftCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1; - -public class CreateAircraftCommandValidator : AbstractValidator -{ - public CreateAircraftCommandValidator() - { - RuleFor(x => x.Model).NotEmpty().WithMessage("Model is required"); - RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); - RuleFor(x => x.ManufacturingYear).NotEmpty().WithMessage("ManufacturingYear is required"); - } -} diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommand.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommand.cs deleted file mode 100644 index b032c85..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommand.cs +++ /dev/null @@ -1,5 +0,0 @@ -using BuildingBlocks.Core.Event; - -namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads; - -public record CreateAircraftMongoCommand(long Id, string Name, string Model, int ManufacturingYear, bool IsDeleted) : InternalCommand; diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Dtos/V1/CreateAircraftRequestDto.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Dtos/V1/CreateAircraftRequestDto.cs deleted file mode 100644 index c9ece02..0000000 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Dtos/V1/CreateAircraftRequestDto.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Flight.Aircrafts.Features.CreateAircraft.Dtos.V1; - -public record CreateAircraftRequestDto(string Name, string Model, int ManufacturingYear); - diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Events/Domain/V1/AircraftCreatedDomainEvent.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/AircraftCreatedDomainEvent.cs similarity index 70% rename from src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Events/Domain/V1/AircraftCreatedDomainEvent.cs rename to src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/AircraftCreatedDomainEvent.cs index fa70815..f9c7bac 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Events/Domain/V1/AircraftCreatedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/AircraftCreatedDomainEvent.cs @@ -1,5 +1,5 @@ +namespace Flight.Aircrafts.Features.CreatingAircraft.V1; + using BuildingBlocks.Core.Event; -namespace Flight.Aircrafts.Features.CreateAircraft.Events.Domain.V1; - public record AircraftCreatedDomainEvent(long Id, string Name, string Model, int ManufacturingYear, bool IsDeleted) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraft.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraft.cs new file mode 100644 index 0000000..126f4d3 --- /dev/null +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraft.cs @@ -0,0 +1,63 @@ +namespace Flight.Aircrafts.Features.CreatingAircraft.V1; + +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using Exceptions; +using Flight.Aircrafts.Dtos; +using Flight.Aircrafts.Models; +using Flight.Data; +using FluentValidation; +using MapsterMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +public record CreateAircraft(string Name, string Model, int ManufacturingYear) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} + +internal class CreateAircraftValidator : AbstractValidator +{ + public CreateAircraftValidator() + { + RuleFor(x => x.Model).NotEmpty().WithMessage("Model is required"); + RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); + RuleFor(x => x.ManufacturingYear).NotEmpty().WithMessage("ManufacturingYear is required"); + } +} + +internal class CreateAircraftHandler : IRequestHandler +{ + private readonly FlightDbContext _flightDbContext; + private readonly IMapper _mapper; + + public CreateAircraftHandler(IMapper mapper, FlightDbContext flightDbContext) + { + _mapper = mapper; + _flightDbContext = flightDbContext; + } + + public async Task Handle(CreateAircraft request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var aircraft = await _flightDbContext.Aircraft.SingleOrDefaultAsync(x => x.Model == request.Model, cancellationToken); + + if (aircraft is not null) + { + throw new AircraftAlreadyExistException(); + } + + var aircraftEntity = Aircraft.Create(request.Id, request.Name, request.Model, request.ManufacturingYear); + + var newAircraft = await _flightDbContext.Aircraft.AddAsync(aircraftEntity, cancellationToken); + + await _flightDbContext.SaveChangesAsync(cancellationToken); + + return _mapper.Map(newAircraft.Entity); + } +} diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Endpoints/V1/CreateAircraftEndpoint.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftEndpoint.cs similarity index 74% rename from src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Endpoints/V1/CreateAircraftEndpoint.cs rename to src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftEndpoint.cs index 168699a..9708a81 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Endpoints/V1/CreateAircraftEndpoint.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftEndpoint.cs @@ -1,9 +1,10 @@ +namespace Flight.Aircrafts.Features.CreatingAircraft.V1; + using System.Threading; 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 Dtos; +using Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,25 +12,23 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Aircrafts.Features.CreateAircraft.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record CreateAircraftRequestDto(string Name, string Model, int ManufacturingYear); public class CreateAircraftEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/flight/aircraft", CreateAircraft) + builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/aircraft", CreateAircraft) .RequireAuthorization() .WithTags("Flight") .WithName("CreateAircraft") .WithMetadata(new SwaggerOperationAttribute("Create Aircraft", "Create Aircraft")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "Aircraft Created", - typeof(AircraftResponseDto))) + typeof(AircraftDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -42,13 +41,13 @@ public class CreateAircraftEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task CreateAircraft(CreateAircraftRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftMongo.cs similarity index 57% rename from src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftMongo.cs index 80b0bbf..845bd75 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/Commands/V1/Reads/CreateAircraftMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/CreatingAircraft/V1/CreateAircraftMongo.cs @@ -1,23 +1,26 @@ -using System.Threading; +namespace Flight.Aircrafts.Features.CreatingAircraft.V1; + +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using Flight.Aircrafts.Features.CreateAircraft.Exceptions; -using Flight.Aircrafts.Models.Reads; +using BuildingBlocks.Core.Event; +using Exceptions; +using Flight.Aircrafts.Models; using Flight.Data; using MapsterMapper; using MediatR; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads; +public record CreateAircraftMongo(long Id, string Name, string Model, int ManufacturingYear, bool IsDeleted) : InternalCommand; -public class CreateAircraftMongoCommandHandler : ICommandHandler +public class CreateAircraftMongoHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; - public CreateAircraftMongoCommandHandler( + public CreateAircraftMongoHandler( FlightReadDbContext flightReadDbContext, IMapper mapper) { @@ -25,17 +28,19 @@ public class CreateAircraftMongoCommandHandler : ICommandHandler Handle(CreateAircraftMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(CreateAircraftMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var aircraftReadModel = _mapper.Map(command); + var aircraftReadModel = _mapper.Map(request); var aircraft = await _flightReadDbContext.Aircraft.AsQueryable() .FirstOrDefaultAsync(x => x.AircraftId == aircraftReadModel.AircraftId, cancellationToken); if (aircraft is not null) + { throw new AircraftAlreadyExistException(); + } await _flightReadDbContext.Aircraft.InsertOneAsync(aircraftReadModel, cancellationToken: cancellationToken); diff --git a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs index 7c37fb5..2608f0a 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs @@ -1,8 +1,9 @@ using BuildingBlocks.Core.Model; -using Flight.Aircrafts.Features.CreateAircraft.Events.Domain.V1; namespace Flight.Aircrafts.Models; +using Features.CreatingAircraft.V1; + public record Aircraft : Aggregate { public string Name { get; private set; } diff --git a/src/Services/Flight/src/Flight/Aircrafts/Models/Reads/AircraftReadModel.cs b/src/Services/Flight/src/Flight/Aircrafts/Models/AircraftReadModel.cs similarity index 86% rename from src/Services/Flight/src/Flight/Aircrafts/Models/Reads/AircraftReadModel.cs rename to src/Services/Flight/src/Flight/Aircrafts/Models/AircraftReadModel.cs index c444229..2f52435 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Models/Reads/AircraftReadModel.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Models/AircraftReadModel.cs @@ -1,4 +1,4 @@ -namespace Flight.Aircrafts.Models.Reads; +namespace Flight.Aircrafts.Models; public class AircraftReadModel { diff --git a/src/Services/Flight/src/Flight/Airports/AirportMappings.cs b/src/Services/Flight/src/Flight/Airports/AirportMappings.cs deleted file mode 100644 index 14c37e3..0000000 --- a/src/Services/Flight/src/Flight/Airports/AirportMappings.cs +++ /dev/null @@ -1,26 +0,0 @@ -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; - -namespace Flight.Airports; - -public class AirportMappings : IRegister -{ - public void Register(TypeAdapterConfig config) - { - config.NewConfig() - .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) - .Map(d => d.AirportId, s => s.Id); - - config.NewConfig() - .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) - .Map(d => d.AirportId, s => s.Id); - - config.NewConfig() - .ConstructUsing(x => new CreateAirportCommand(x.Name, x.Address, x.Code)); - } -} diff --git a/src/Services/Flight/src/Flight/Airports/Dtos/AirportDto.cs b/src/Services/Flight/src/Flight/Airports/Dtos/AirportDto.cs new file mode 100644 index 0000000..6ff8797 --- /dev/null +++ b/src/Services/Flight/src/Flight/Airports/Dtos/AirportDto.cs @@ -0,0 +1,3 @@ +namespace Flight.Airports.Dtos; + +public record AirportDto(long Id, string Name, string Address, string Code); diff --git a/src/Services/Flight/src/Flight/Airports/Dtos/AirportResponseDto.cs b/src/Services/Flight/src/Flight/Airports/Dtos/AirportResponseDto.cs deleted file mode 100644 index e5d4270..0000000 --- a/src/Services/Flight/src/Flight/Airports/Dtos/AirportResponseDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Flight.Airports.Dtos; - -public record AirportResponseDto(long Id, string Name, string Address, string Code); diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Exceptions/AirportAlreadyExistException.cs b/src/Services/Flight/src/Flight/Airports/Exceptions/AirportAlreadyExistException.cs similarity index 77% rename from src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Exceptions/AirportAlreadyExistException.cs rename to src/Services/Flight/src/Flight/Airports/Exceptions/AirportAlreadyExistException.cs index b4d32d2..55cdb27 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Exceptions/AirportAlreadyExistException.cs +++ b/src/Services/Flight/src/Flight/Airports/Exceptions/AirportAlreadyExistException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Flight.Airports.Exceptions; -namespace Flight.Airports.Features.CreateAirport.Exceptions; +using BuildingBlocks.Exception; public class AirportAlreadyExistException : ConflictException { diff --git a/src/Services/Flight/src/Flight/Airports/Features/AirportMappings.cs b/src/Services/Flight/src/Flight/Airports/Features/AirportMappings.cs new file mode 100644 index 0000000..fbd551c --- /dev/null +++ b/src/Services/Flight/src/Flight/Airports/Features/AirportMappings.cs @@ -0,0 +1,23 @@ +namespace Flight.Airports.Features; + +using BuildingBlocks.IdsGenerator; +using Flight.Airports.Features.CreatingAirport.V1; +using Flight.Airports.Models; +using Mapster; + +public class AirportMappings : IRegister +{ + public void Register(TypeAdapterConfig config) + { + config.NewConfig() + .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) + .Map(d => d.AirportId, s => s.Id); + + config.NewConfig() + .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) + .Map(d => d.AirportId, s => s.Id); + + config.NewConfig() + .ConstructUsing(x => new CreateAirport(x.Name, x.Address, x.Code)); + } +} diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommand.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommand.cs deleted file mode 100644 index 5a01136..0000000 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; -using Flight.Airports.Dtos; - -namespace Flight.Airports.Features.CreateAirport.Commands.V1; - -public record CreateAirportCommand(string Name, string Address, string Code) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandHandler.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandHandler.cs deleted file mode 100644 index 77dab54..0000000 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandHandler.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using Flight.Airports.Dtos; -using Flight.Airports.Features.CreateAirport.Exceptions; -using Flight.Data; -using MapsterMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace Flight.Airports.Features.CreateAirport.Commands.V1; - -public class CreateAirportCommandHandler : IRequestHandler -{ - private readonly FlightDbContext _flightDbContext; - private readonly IMapper _mapper; - - public CreateAirportCommandHandler(IMapper mapper, FlightDbContext flightDbContext) - { - _mapper = mapper; - _flightDbContext = flightDbContext; - } - - public async Task Handle(CreateAirportCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var airport = await _flightDbContext.Airports.SingleOrDefaultAsync(x => x.Code == command.Code, cancellationToken); - - if (airport is not null) - throw new AirportAlreadyExistException(); - - var airportEntity = Models.Airport.Create(command.Id, command.Name, command.Code, command.Address); - - var newAirport = await _flightDbContext.Airports.AddAsync(airportEntity, cancellationToken); - - await _flightDbContext.SaveChangesAsync(cancellationToken); - - return _mapper.Map(newAirport.Entity); - } -} diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandValidator.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandValidator.cs deleted file mode 100644 index eb1ac55..0000000 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/CreateAirportCommandValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace Flight.Airports.Features.CreateAirport.Commands.V1; - -public class CreateAirportCommandValidator : AbstractValidator -{ - public CreateAirportCommandValidator() - { - RuleFor(x => x.Code).NotEmpty().WithMessage("Code is required"); - RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); - RuleFor(x => x.Address).NotEmpty().WithMessage("Address is required"); - } -} diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommand.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommand.cs deleted file mode 100644 index 61323d5..0000000 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommand.cs +++ /dev/null @@ -1,5 +0,0 @@ -using BuildingBlocks.Core.Event; - -namespace Flight.Airports.Features.CreateAirport.Commands.V1.Reads; - -public record CreateAirportMongoCommand(long Id, string Name, string Address, string Code, bool IsDeleted) : InternalCommand; diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Dtos/V1/CreateAirportRequestDto.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Dtos/V1/CreateAirportRequestDto.cs deleted file mode 100644 index 0a9ea0e..0000000 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Dtos/V1/CreateAirportRequestDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Flight.Airports.Features.CreateAirport.Dtos.V1; - -public record CreateAirportRequestDto(string Name, string Address, string Code); diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Events/Domain/V1/AirportCreatedDomainEvent.cs b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/AirportCreatedDomainEvent.cs similarity index 70% rename from src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Events/Domain/V1/AirportCreatedDomainEvent.cs rename to src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/AirportCreatedDomainEvent.cs index 6f1536b..315a5b1 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Events/Domain/V1/AirportCreatedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/AirportCreatedDomainEvent.cs @@ -1,5 +1,5 @@ +namespace Flight.Airports.Features.CreatingAirport.V1; + using BuildingBlocks.Core.Event; -namespace Flight.Airports.Features.CreateAirport.Events.Domain.V1; - public record AirportCreatedDomainEvent(long Id, string Name, string Address, string Code, bool IsDeleted) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirport.cs b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirport.cs new file mode 100644 index 0000000..82ff1d8 --- /dev/null +++ b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirport.cs @@ -0,0 +1,63 @@ +namespace Flight.Airports.Features.CreatingAirport.V1; + +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using Dtos; +using Exceptions; +using Data; +using FluentValidation; +using MapsterMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +public record CreateAirport(string Name, string Address, string Code) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} + +internal class CreateAirportValidator : AbstractValidator +{ + public CreateAirportValidator() + { + RuleFor(x => x.Code).NotEmpty().WithMessage("Code is required"); + RuleFor(x => x.Name).NotEmpty().WithMessage("Name is required"); + RuleFor(x => x.Address).NotEmpty().WithMessage("Address is required"); + } +} + + +internal class CreateAirportHandler : IRequestHandler +{ + private readonly FlightDbContext _flightDbContext; + private readonly IMapper _mapper; + + public CreateAirportHandler(IMapper mapper, FlightDbContext flightDbContext) + { + _mapper = mapper; + _flightDbContext = flightDbContext; + } + + public async Task Handle(CreateAirport request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var airport = await _flightDbContext.Airports.SingleOrDefaultAsync(x => x.Code == request.Code, cancellationToken); + + if (airport is not null) + { + throw new AirportAlreadyExistException(); + } + + var airportEntity = Models.Airport.Create(request.Id, request.Name, request.Code, request.Address); + + var newAirport = await _flightDbContext.Airports.AddAsync(airportEntity, cancellationToken); + + await _flightDbContext.SaveChangesAsync(cancellationToken); + + return _mapper.Map(newAirport.Entity); + } +} diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Endpoints/V1/CreateAirportEndpoint.cs b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportEndpoint.cs similarity index 74% rename from src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Endpoints/V1/CreateAirportEndpoint.cs rename to src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportEndpoint.cs index 779fca8..4f6c8f2 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Endpoints/V1/CreateAirportEndpoint.cs +++ b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportEndpoint.cs @@ -1,9 +1,10 @@ +namespace Flight.Airports.Features.CreatingAirport.V1; + using System.Threading; 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 Dtos; +using Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,25 +12,23 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Airports.Features.CreateAirport.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record CreateAirportRequestDto(string Name, string Address, string Code); public class CreateAirportEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/flight/airport", CreateAirport) + builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/airport", CreateAirport) .RequireAuthorization() .WithTags("Flight") .WithName("CreateAirport") .WithMetadata(new SwaggerOperationAttribute("Create Airport", "Create Airport")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "Airport Created", - typeof(AirportResponseDto))) + typeof(AirportDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -42,13 +41,13 @@ public class CreateAirportEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task CreateAirport(CreateAirportRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportMongo.cs similarity index 57% rename from src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportMongo.cs index 42dd920..c46fc72 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Commands/V1/Reads/CreateAirportMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Airports/Features/CreatingAirport/V1/CreateAirportMongo.cs @@ -1,23 +1,26 @@ -using System.Threading; +namespace Flight.Airports.Features.CreatingAirport.V1; + +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using Flight.Airports.Features.CreateAirport.Exceptions; -using Flight.Airports.Models.Reads; -using Flight.Data; +using BuildingBlocks.Core.Event; +using Exceptions; +using Models; +using Data; using MapsterMapper; using MediatR; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Airports.Features.CreateAirport.Commands.V1.Reads; +public record CreateAirportMongo(long Id, string Name, string Address, string Code, bool IsDeleted) : InternalCommand; -public class CreateAirportMongoCommandHandler : ICommandHandler +internal class CreateAirportMongoHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; - public CreateAirportMongoCommandHandler( + public CreateAirportMongoHandler( FlightReadDbContext flightReadDbContext, IMapper mapper) { @@ -25,17 +28,19 @@ public class CreateAirportMongoCommandHandler : ICommandHandler Handle(CreateAirportMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(CreateAirportMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var airportReadModel = _mapper.Map(command); + var airportReadModel = _mapper.Map(request); var aircraft = await _flightReadDbContext.Airport.AsQueryable() .FirstOrDefaultAsync(x => x.AirportId == airportReadModel.AirportId, cancellationToken); if (aircraft is not null) + { throw new AirportAlreadyExistException(); + } await _flightReadDbContext.Airport.InsertOneAsync(airportReadModel, cancellationToken: cancellationToken); diff --git a/src/Services/Flight/src/Flight/Airports/Models/Airport.cs b/src/Services/Flight/src/Flight/Airports/Models/Airport.cs index 493bf52..655f692 100644 --- a/src/Services/Flight/src/Flight/Airports/Models/Airport.cs +++ b/src/Services/Flight/src/Flight/Airports/Models/Airport.cs @@ -1,9 +1,10 @@ using BuildingBlocks.Core.Model; using BuildingBlocks.IdsGenerator; -using Flight.Airports.Features.CreateAirport.Events.Domain.V1; namespace Flight.Airports.Models; +using Features.CreatingAirport.V1; + public record Airport : Aggregate { public string Name { get; private set; } diff --git a/src/Services/Flight/src/Flight/Airports/Models/Reads/AirportReadModel.cs b/src/Services/Flight/src/Flight/Airports/Models/AirportReadModel.cs similarity index 86% rename from src/Services/Flight/src/Flight/Airports/Models/Reads/AirportReadModel.cs rename to src/Services/Flight/src/Flight/Airports/Models/AirportReadModel.cs index 515c836..5cc384d 100644 --- a/src/Services/Flight/src/Flight/Airports/Models/Reads/AirportReadModel.cs +++ b/src/Services/Flight/src/Flight/Airports/Models/AirportReadModel.cs @@ -1,4 +1,4 @@ -namespace Flight.Airports.Models.Reads; +namespace Flight.Airports.Models; public class AirportReadModel { diff --git a/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs b/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs index d5c4d40..0c63e27 100644 --- a/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs +++ b/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs @@ -1,14 +1,15 @@ using BuildingBlocks.Mongo; -using Flight.Aircrafts.Models.Reads; -using Flight.Airports.Models.Reads; -using Flight.Flights.Models.Reads; -using Flight.Seats.Models.Reads; using Humanizer; using Microsoft.Extensions.Options; using MongoDB.Driver; namespace Flight.Data; +using Aircrafts.Models; +using Airports.Models; +using Flights.Models; +using Seats.Models; + public class FlightReadDbContext : MongoDbContext { public FlightReadDbContext(IOptions options) : base(options) diff --git a/src/Services/Flight/src/Flight/Data/Seed/FlightDataSeeder.cs b/src/Services/Flight/src/Flight/Data/Seed/FlightDataSeeder.cs index 8c64322..fb66552 100644 --- a/src/Services/Flight/src/Flight/Data/Seed/FlightDataSeeder.cs +++ b/src/Services/Flight/src/Flight/Data/Seed/FlightDataSeeder.cs @@ -3,12 +3,8 @@ using System.Collections.Generic; using System.Threading.Tasks; using BuildingBlocks.EFCore; using Flight.Aircrafts.Models; -using Flight.Aircrafts.Models.Reads; using Flight.Airports.Models; -using Flight.Airports.Models.Reads; -using Flight.Flights.Models.Reads; using Flight.Seats.Models; -using Flight.Seats.Models.Reads; using MapsterMapper; using Microsoft.EntityFrameworkCore; using MongoDB.Driver; @@ -16,6 +12,8 @@ using MongoDB.Driver.Linq; namespace Flight.Data.Seed; +using Flights.Models; + public class FlightDataSeeder : IDataSeeder { private readonly FlightDbContext _flightDbContext; diff --git a/src/Services/Flight/src/Flight/EventMapper.cs b/src/Services/Flight/src/Flight/EventMapper.cs index 32e0d36..d367bb6 100644 --- a/src/Services/Flight/src/Flight/EventMapper.cs +++ b/src/Services/Flight/src/Flight/EventMapper.cs @@ -1,23 +1,17 @@ using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; using BuildingBlocks.Core.Event; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads; -using Flight.Aircrafts.Features.CreateAircraft.Events.Domain.V1; -using Flight.Airports.Features.CreateAirport.Commands.V1.Reads; -using Flight.Airports.Features.CreateAirport.Events.Domain.V1; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; -using Flight.Flights.Features.CreateFlight.Events.Domain.V1; -using Flight.Flights.Features.DeleteFlight.Commands.V1.Reads; -using Flight.Flights.Features.DeleteFlight.Events.Domain.V1; -using Flight.Flights.Features.UpdateFlight.Commands.V1.Reads; -using Flight.Flights.Features.UpdateFlight.Events.V1; -using Flight.Seats.Features.CreateSeat.Commands.V1.Reads; -using Flight.Seats.Features.CreateSeat.Events.Domain.V1; -using Flight.Seats.Features.ReserveSeat.Commands.V1.Reads; -using Flight.Seats.Features.ReserveSeat.Events.Domain.V1; namespace Flight; +using Aircrafts.Features.CreatingAircraft.V1; +using Airports.Features.CreatingAirport.V1; +using Flights.Features.CreatingFlight.V1; +using Flights.Features.DeletingFlight.V1; +using Flights.Features.UpdatingFlight.V1; +using Seats.Features.CreatingSeat.V1; +using Seats.Features.ReservingSeat.Commands.V1; + // ref: https://www.ledjonbehluli.com/posts/domain_to_integration_event/ public sealed class EventMapper : IEventMapper { @@ -40,16 +34,16 @@ public sealed class EventMapper : IEventMapper { return @event switch { - FlightCreatedDomainEvent e => new CreateFlightMongoCommand(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, + FlightCreatedDomainEvent e => new CreateFlightMongo(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, e.ArriveDate, e.ArriveAirportId, e.DurationMinutes, e.FlightDate, e.Status, e.Price, e.IsDeleted), - FlightUpdatedDomainEvent e => new UpdateFlightMongoCommand(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, + FlightUpdatedDomainEvent e => new UpdateFlightMongo(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, e.ArriveDate, e.ArriveAirportId, e.DurationMinutes, e.FlightDate, e.Status, e.Price, e.IsDeleted), - FlightDeletedDomainEvent e => new DeleteFlightMongoCommand(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, + FlightDeletedDomainEvent e => new DeleteFlightMongo(e.Id, e.FlightNumber, e.AircraftId, e.DepartureDate, e.DepartureAirportId, e.ArriveDate, e.ArriveAirportId, e.DurationMinutes, e.FlightDate, e.Status, e.Price, e.IsDeleted), - AircraftCreatedDomainEvent e => new CreateAircraftMongoCommand(e.Id, e.Name, e.Model, e.ManufacturingYear, e.IsDeleted), - AirportCreatedDomainEvent e => new CreateAirportMongoCommand(e.Id, e.Name, e.Address, e.Code, e.IsDeleted), - SeatCreatedDomainEvent e => new CreateSeatMongoCommand(e.Id, e.SeatNumber, e.Type, e.Class, e.FlightId, e.IsDeleted), - SeatReservedDomainEvent e => new ReserveSeatMongoCommand(e.Id, e.SeatNumber, e.Type, e.Class, e.FlightId, e.IsDeleted), + AircraftCreatedDomainEvent e => new CreateAircraftMongo(e.Id, e.Name, e.Model, e.ManufacturingYear, e.IsDeleted), + AirportCreatedDomainEvent e => new CreateAirportMongo(e.Id, e.Name, e.Address, e.Code, e.IsDeleted), + SeatCreatedDomainEvent e => new CreateSeatMongo(e.Id, e.SeatNumber, e.Type, e.Class, e.FlightId, e.IsDeleted), + SeatReservedDomainEvent e => new ReserveSeatMongo(e.Id, e.SeatNumber, e.Type, e.Class, e.FlightId, e.IsDeleted), _ => null }; } diff --git a/src/Services/Flight/src/Flight/Flight.csproj b/src/Services/Flight/src/Flight/Flight.csproj index 7523afd..b8d25fe 100644 --- a/src/Services/Flight/src/Flight/Flight.csproj +++ b/src/Services/Flight/src/Flight/Flight.csproj @@ -19,7 +19,6 @@ - @@ -30,4 +29,20 @@ + + + <_Parameter1>Unit.Test + + + + + <_Parameter1>Integration.Test + + + + + <_Parameter1>EndToEnd.Test + + + diff --git a/src/Services/Flight/src/Flight/Flights/Dtos/FlightResponseDto.cs b/src/Services/Flight/src/Flight/Flights/Dtos/FlightDto.cs similarity index 69% rename from src/Services/Flight/src/Flight/Flights/Dtos/FlightResponseDto.cs rename to src/Services/Flight/src/Flight/Flights/Dtos/FlightDto.cs index 0630de8..5864b5b 100644 --- a/src/Services/Flight/src/Flight/Flights/Dtos/FlightResponseDto.cs +++ b/src/Services/Flight/src/Flight/Flights/Dtos/FlightDto.cs @@ -3,6 +3,6 @@ using Flight.Flights.Models; namespace Flight.Flights.Dtos; -public record FlightResponseDto(long Id, string FlightNumber, long AircraftId, long DepartureAirportId, +public record FlightDto(long Id, string FlightNumber, long AircraftId, long DepartureAirportId, DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price); diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Exceptions/FlightAlreadyExistException.cs b/src/Services/Flight/src/Flight/Flights/Exceptions/FlightAlreadyExistException.cs similarity index 77% rename from src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Exceptions/FlightAlreadyExistException.cs rename to src/Services/Flight/src/Flight/Flights/Exceptions/FlightAlreadyExistException.cs index e179bd8..a3622ef 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Exceptions/FlightAlreadyExistException.cs +++ b/src/Services/Flight/src/Flight/Flights/Exceptions/FlightAlreadyExistException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Flight.Flights.Exceptions; -namespace Flight.Flights.Features.CreateFlight.Exceptions; +using BuildingBlocks.Exception; public class FlightAlreadyExistException : ConflictException { diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommand.cs deleted file mode 100644 index 9e816ab..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; -using Flight.Flights.Dtos; - -namespace Flight.Flights.Features.CreateFlight.Commands.V1; - -public record CreateFlightCommand(string FlightNumber, long AircraftId, long DepartureAirportId, - DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, - decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandHandler.cs deleted file mode 100644 index c176dfe..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandHandler.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Dtos; -using Flight.Flights.Exceptions; -using Flight.Flights.Features.CreateFlight.Exceptions; -using MapsterMapper; -using Microsoft.EntityFrameworkCore; - -namespace Flight.Flights.Features.CreateFlight.Commands.V1; - -public class CreateFlightCommandHandler : ICommandHandler -{ - private readonly FlightDbContext _flightDbContext; - private readonly IMapper _mapper; - - public CreateFlightCommandHandler(IMapper mapper, - FlightDbContext flightDbContext) - { - _mapper = mapper; - _flightDbContext = flightDbContext; - } - - public async Task Handle(CreateFlightCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == command.Id, - cancellationToken); - - if (flight is not null) - throw new FlightAlreadyExistException(); - - var flightEntity = Models.Flight.Create(command.Id, command.FlightNumber, command.AircraftId, - command.DepartureAirportId, command.DepartureDate, - command.ArriveDate, command.ArriveAirportId, command.DurationMinutes, command.FlightDate, command.Status, - command.Price); - - var newFlight = await _flightDbContext.Flights.AddAsync(flightEntity, cancellationToken); - - return _mapper.Map(newFlight.Entity); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandValidator.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandValidator.cs deleted file mode 100644 index 482a741..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/CreateFlightCommandValidator.cs +++ /dev/null @@ -1,24 +0,0 @@ -using FluentValidation; - -namespace Flight.Flights.Features.CreateFlight.Commands.V1; - -public class CreateFlightCommandValidator : AbstractValidator -{ - public CreateFlightCommandValidator() - { - RuleFor(x => x.Price).GreaterThan(0).WithMessage("Price must be greater than 0"); - - RuleFor(x => x.Status).Must(p => (p.GetType().IsEnum && - p == Enums.FlightStatus.Flying) || - p == Enums.FlightStatus.Canceled || - p == Enums.FlightStatus.Delay || - p == Enums.FlightStatus.Completed) - .WithMessage("Status must be Flying, Delay, Canceled or Completed"); - - RuleFor(x => x.AircraftId).NotEmpty().WithMessage("AircraftId must be not empty"); - RuleFor(x => x.DepartureAirportId).NotEmpty().WithMessage("DepartureAirportId must be not empty"); - RuleFor(x => x.ArriveAirportId).NotEmpty().WithMessage("ArriveAirportId must be not empty"); - RuleFor(x => x.DurationMinutes).GreaterThan(0).WithMessage("DurationMinutes must be greater than 0"); - RuleFor(x => x.FlightDate).NotEmpty().WithMessage("FlightDate must be not empty"); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommand.cs deleted file mode 100644 index 4f84f12..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; -using BuildingBlocks.Core.Event; - -namespace Flight.Flights.Features.CreateFlight.Commands.V1.Reads; - -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; diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Dtos/V1/CreateFlightRequestDto.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Dtos/V1/CreateFlightRequestDto.cs deleted file mode 100644 index b343e36..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Dtos/V1/CreateFlightRequestDto.cs +++ /dev/null @@ -1,7 +0,0 @@ -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); diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlight.cs b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlight.cs new file mode 100644 index 0000000..095828e --- /dev/null +++ b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlight.cs @@ -0,0 +1,78 @@ +namespace Flight.Flights.Features.CreatingFlight.V1; + +using System; +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using Data; +using Dtos; +using Exceptions; +using FluentValidation; +using MapsterMapper; +using Microsoft.EntityFrameworkCore; + +public record CreateFlight(string FlightNumber, long AircraftId, long DepartureAirportId, + DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, + decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} + +internal class CreateFlightValidator : AbstractValidator +{ + public CreateFlightValidator() + { + RuleFor(x => x.Price).GreaterThan(0).WithMessage("Price must be greater than 0"); + + RuleFor(x => x.Status).Must(p => (p.GetType().IsEnum && + p == Enums.FlightStatus.Flying) || + p == Enums.FlightStatus.Canceled || + p == Enums.FlightStatus.Delay || + p == Enums.FlightStatus.Completed) + .WithMessage("Status must be Flying, Delay, Canceled or Completed"); + + RuleFor(x => x.AircraftId).NotEmpty().WithMessage("AircraftId must be not empty"); + RuleFor(x => x.DepartureAirportId).NotEmpty().WithMessage("DepartureAirportId must be not empty"); + RuleFor(x => x.ArriveAirportId).NotEmpty().WithMessage("ArriveAirportId must be not empty"); + RuleFor(x => x.DurationMinutes).GreaterThan(0).WithMessage("DurationMinutes must be greater than 0"); + RuleFor(x => x.FlightDate).NotEmpty().WithMessage("FlightDate must be not empty"); + } +} + +internal class CreateFlightHandler : ICommandHandler +{ + private readonly FlightDbContext _flightDbContext; + private readonly IMapper _mapper; + + public CreateFlightHandler(IMapper mapper, + FlightDbContext flightDbContext) + { + _mapper = mapper; + _flightDbContext = flightDbContext; + } + + public async Task Handle(CreateFlight request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == request.Id, + cancellationToken); + + if (flight is not null) + { + throw new FlightAlreadyExistException(); + } + + var flightEntity = Models.Flight.Create(request.Id, request.FlightNumber, request.AircraftId, + request.DepartureAirportId, request.DepartureDate, + request.ArriveDate, request.ArriveAirportId, request.DurationMinutes, request.FlightDate, request.Status, + request.Price); + + var newFlight = await _flightDbContext.Flights.AddAsync(flightEntity, cancellationToken); + + return _mapper.Map(newFlight.Entity); + } +} diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Endpoints/V1/CreateFlightEndpoint.cs b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightEndpoint.cs similarity index 72% rename from src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Endpoints/V1/CreateFlightEndpoint.cs rename to src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightEndpoint.cs index ef1b517..8768224 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Endpoints/V1/CreateFlightEndpoint.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightEndpoint.cs @@ -1,10 +1,11 @@ +namespace Flight.Flights.Features.CreatingFlight.V1; + +using System; using System.Threading; 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 Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -12,25 +13,25 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Flights.Features.CreateFlight.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record CreateFlightRequestDto(string FlightNumber, long AircraftId, long DepartureAirportId, + DateTime DepartureDate, DateTime ArriveDate, long ArriveAirportId, + decimal DurationMinutes, DateTime FlightDate, Enums.FlightStatus Status, decimal Price); public class CreateFlightEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/flight", CreateFlight) + builder.MapPost($"{EndpointConfig.BaseApiPath}/flight", CreateFlight) .RequireAuthorization() .WithTags("Flight") .WithName("CreateFlight") .WithMetadata(new SwaggerOperationAttribute("Create Flight", "Create Flight")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status201Created, "Flight Created", - typeof(FlightResponseDto))) + typeof(FlightDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -43,13 +44,13 @@ public class CreateFlightEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task CreateFlight(CreateFlightRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightMongo.cs similarity index 53% rename from src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightMongo.cs index 4321e88..feef219 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Commands/V1/Reads/CreateFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/CreateFlightMongo.cs @@ -1,24 +1,29 @@ -using System.Threading; +namespace Flight.Flights.Features.CreatingFlight.V1; + +using System; +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Data; using Flight.Flights.Exceptions; -using Flight.Flights.Features.CreateFlight.Exceptions; -using Flight.Flights.Models.Reads; using MapsterMapper; using MediatR; +using Models; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Flights.Features.CreateFlight.Commands.V1.Reads; +public record CreateFlightMongo(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; -public class CreateFlightMongoCommandHandler : ICommandHandler +internal class CreateFlightMongoHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; - public CreateFlightMongoCommandHandler( + public CreateFlightMongoHandler( FlightReadDbContext flightReadDbContext, IMapper mapper) { @@ -26,17 +31,19 @@ public class CreateFlightMongoCommandHandler : ICommandHandler Handle(CreateFlightMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(CreateFlightMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var flightReadModel = _mapper.Map(command); + var flightReadModel = _mapper.Map(request); var flight = await _flightReadDbContext.Flight.AsQueryable() .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken); if (flight is not null) + { throw new FlightAlreadyExistException(); + } await _flightReadDbContext.Flight.InsertOneAsync(flightReadModel, cancellationToken: cancellationToken); diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Events/Domain/V1/FlightCreatedDomainEvent.cs b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/FlightCreatedDomainEvent.cs similarity index 84% rename from src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Events/Domain/V1/FlightCreatedDomainEvent.cs rename to src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/FlightCreatedDomainEvent.cs index 8b52a9a..aaa3123 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Events/Domain/V1/FlightCreatedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreatingFlight/V1/FlightCreatedDomainEvent.cs @@ -1,8 +1,8 @@ +namespace Flight.Flights.Features.CreatingFlight.V1; + using System; using BuildingBlocks.Core.Event; -namespace Flight.Flights.Features.CreateFlight.Events.Domain.V1; - public record FlightCreatedDomainEvent(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) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommand.cs deleted file mode 100644 index b6c8268..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using Flight.Flights.Dtos; - -namespace Flight.Flights.Features.DeleteFlight.Commands.V1; - -public record DeleteFlightCommand(long Id) : ICommand, IInternalCommand; diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandValidator.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandValidator.cs deleted file mode 100644 index fb9a709..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandValidator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FluentValidation; - -namespace Flight.Flights.Features.DeleteFlight.Commands.V1; - -public class DeleteFlightCommandValidator : AbstractValidator -{ - public DeleteFlightCommandValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.Id).NotEmpty(); - } -} - diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommand.cs deleted file mode 100644 index 8dfca0b..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; -using BuildingBlocks.Core.Event; - -namespace Flight.Flights.Features.DeleteFlight.Commands.V1.Reads; - -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; diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlight.cs similarity index 51% rename from src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandHandler.cs rename to src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlight.cs index 6875395..9278eda 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/DeleteFlightCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlight.cs @@ -1,35 +1,48 @@ -using System.Threading; +namespace Flight.Flights.Features.DeletingFlight.V1; + +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Dtos; -using Flight.Flights.Exceptions; +using BuildingBlocks.Core.Event; +using Data; +using Dtos; +using Exceptions; +using FluentValidation; using MapsterMapper; using Microsoft.EntityFrameworkCore; -namespace Flight.Flights.Features.DeleteFlight.Commands.V1; +public record DeleteFlight(long Id) : ICommand, IInternalCommand; -public class DeleteFlightCommandHandler : ICommandHandler +internal class DeleteFlightValidator : AbstractValidator +{ + public DeleteFlightValidator() + { + RuleFor(x => x.Id).NotEmpty(); + } +} + +internal class DeleteFlightHandler : ICommandHandler { private readonly FlightDbContext _flightDbContext; private readonly IMapper _mapper; - public DeleteFlightCommandHandler(IMapper mapper, FlightDbContext flightDbContext) + public DeleteFlightHandler(IMapper mapper, FlightDbContext flightDbContext) { _mapper = mapper; _flightDbContext = flightDbContext; } - public async Task Handle(DeleteFlightCommand command, CancellationToken cancellationToken) + public async Task Handle(DeleteFlight request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == command.Id, cancellationToken); + var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken); if (flight is null) + { throw new FlightNotFountException(); - + } var deleteFlight = _flightDbContext.Flights.Remove(flight).Entity; @@ -37,6 +50,6 @@ public class DeleteFlightCommandHandler : ICommandHandler(deleteFlight); + return _mapper.Map(deleteFlight); } } diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Endpoints/V1/DeleteFlightEndpoint.cs b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightEndpoint.cs similarity index 74% rename from src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Endpoints/V1/DeleteFlightEndpoint.cs rename to src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightEndpoint.cs index 62cce91..cacc85a 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Endpoints/V1/DeleteFlightEndpoint.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightEndpoint.cs @@ -1,33 +1,31 @@ -using System.Threading; +namespace Flight.Flights.Features.DeletingFlight.V1; + +using System.Threading; using System.Threading.Tasks; using BuildingBlocks.Web; using Flight.Flights.Dtos; -using Flight.Flights.Features.DeleteFlight.Commands.V1; +using Hellang.Middleware.ProblemDetails; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Flights.Features.DeleteFlight.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; - public class DeleteFlightEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapDelete($"{EndpointConfig.BaseApiPath}/flight/{{id}}", DeleteFlight) + builder.MapDelete($"{EndpointConfig.BaseApiPath}/flight/{{id}}", DeleteFlight) .RequireAuthorization() .WithTags("Flight") .WithName("DeleteFlight") .WithMetadata(new SwaggerOperationAttribute("Delete Flight", "Delete Flight")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status204NoContent, "Flight Deleted", - typeof(FlightResponseDto))) + typeof(FlightDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -40,12 +38,12 @@ public class DeleteFlightEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task DeleteFlight(long id, IMediator mediator, CancellationToken cancellationToken) { - var result = await mediator.Send(new DeleteFlightCommand(id), cancellationToken); + var result = await mediator.Send(new DeleteFlight(id), cancellationToken); return Results.NoContent(); } diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightMongo.cs similarity index 57% rename from src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightMongo.cs index edb6385..2879e5c 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Commands/V1/Reads/DeleteFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/DeleteFlightMongo.cs @@ -1,18 +1,24 @@ -using System.Threading; +namespace Flight.Flights.Features.DeletingFlight.V1; + +using System; +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Exceptions; -using Flight.Flights.Models.Reads; +using BuildingBlocks.Core.Event; +using Data; +using Exceptions; using MapsterMapper; using MediatR; +using Models; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Flights.Features.DeleteFlight.Commands.V1.Reads; +public record DeleteFlightMongo(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; -public class DeleteFlightMongoCommandHandler : ICommandHandler +internal class DeleteFlightMongoCommandHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; @@ -25,17 +31,19 @@ public class DeleteFlightMongoCommandHandler : ICommandHandler Handle(DeleteFlightMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(DeleteFlightMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var flightReadModel = _mapper.Map(command); + var flightReadModel = _mapper.Map(request); var flight = await _flightReadDbContext.Flight.AsQueryable() .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken); if (flight is null) + { throw new FlightNotFountException(); + } await _flightReadDbContext.Flight.UpdateOneAsync( x => x.FlightId == flightReadModel.FlightId, diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Events/Domain/V1/FlightDeletedDomainEvent.cs b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/FlightDeletedDomainEvent.cs similarity index 80% rename from src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Events/Domain/V1/FlightDeletedDomainEvent.cs rename to src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/FlightDeletedDomainEvent.cs index a73bad9..a6813b7 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Events/Domain/V1/FlightDeletedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeletingFlight/V1/FlightDeletedDomainEvent.cs @@ -1,7 +1,7 @@ -using System; -using BuildingBlocks.Core.Event; +namespace Flight.Flights.Features.DeletingFlight.V1; -namespace Flight.Flights.Features.DeleteFlight.Events.Domain.V1; +using System; +using BuildingBlocks.Core.Event; public record FlightDeletedDomainEvent(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate, long DepartureAirportId, DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, diff --git a/src/Services/Flight/src/Flight/Flights/Features/FlightMappings.cs b/src/Services/Flight/src/Flight/Flights/Features/FlightMappings.cs index 9d04ce3..a125e4a 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/FlightMappings.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/FlightMappings.cs @@ -1,27 +1,23 @@ -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; namespace Flight.Flights.Features; +using CreatingFlight.V1; +using DeletingFlight.V1; +using Models; +using UpdatingFlight.V1; + public class FlightMappings : IRegister { public void Register(TypeAdapterConfig config) { - config.NewConfig() - .ConstructUsing(x => new FlightResponseDto(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate, + config.NewConfig() + .ConstructUsing(x => new FlightDto(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate, x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.Price)); - config.NewConfig() + config.NewConfig() .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.FlightId, s => s.Id); @@ -29,21 +25,21 @@ public class FlightMappings : IRegister .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.FlightId, s => s.Id); - config.NewConfig() + config.NewConfig() .Map(d => d.Id, s => s.FlightId); - config.NewConfig() + config.NewConfig() .Map(d => d.FlightId, s => s.Id); - config.NewConfig() + config.NewConfig() .Map(d => d.FlightId, s => s.Id); - config.NewConfig() - .ConstructUsing(x => new CreateFlightCommand(x.FlightNumber, x.AircraftId, x.DepartureAirportId, + config.NewConfig() + .ConstructUsing(x => new CreateFlight(x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate, x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.Price)); - config.NewConfig() - .ConstructUsing(x => new UpdateFlightCommand(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate, + config.NewConfig() + .ConstructUsing(x => new UpdateFlight(x.Id, x.FlightNumber, x.AircraftId, x.DepartureAirportId, x.DepartureDate, x.ArriveDate, x.ArriveAirportId, x.DurationMinutes, x.FlightDate, x.Status, x.IsDeleted, x.Price)); } diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQuery.cs b/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQuery.cs deleted file mode 100644 index 64a6fd3..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQuery.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using BuildingBlocks.Caching; -using BuildingBlocks.Core.CQRS; -using Flight.Flights.Dtos; - -namespace Flight.Flights.Features.GetAvailableFlights.Queries.V1; - -public record GetAvailableFlightsQuery : IQuery>, ICacheRequest -{ - public string CacheKey => "GetAvailableFlightsQuery"; - public DateTime? AbsoluteExpirationRelativeToNow => DateTime.Now.AddHours(1); -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryHandler.cs deleted file mode 100644 index 305b1cf..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryHandler.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Dtos; -using Flight.Flights.Exceptions; -using MapsterMapper; -using MongoDB.Driver; - -namespace Flight.Flights.Features.GetAvailableFlights.Queries.V1; - -public class GetAvailableFlightsQueryHandler : IQueryHandler> -{ - private readonly IMapper _mapper; - private readonly FlightReadDbContext _flightReadDbContext; - - public GetAvailableFlightsQueryHandler(IMapper mapper, FlightReadDbContext flightReadDbContext) - { - _mapper = mapper; - _flightReadDbContext = flightReadDbContext; - } - - public async Task> Handle(GetAvailableFlightsQuery query, - CancellationToken cancellationToken) - { - Guard.Against.Null(query, nameof(query)); - - var flight = (await _flightReadDbContext.Flight.AsQueryable().ToListAsync(cancellationToken)) - .Where(x => !x.IsDeleted); - - if (!flight.Any()) - throw new FlightNotFountException(); - - return _mapper.Map>(flight); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryValidator.cs b/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryValidator.cs deleted file mode 100644 index d4e95c6..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Queries/V1/GetAvailableFlightsQueryValidator.cs +++ /dev/null @@ -1,7 +0,0 @@ -using FluentValidation; - -namespace Flight.Flights.Features.GetAvailableFlights.Queries.V1; - -public class GetAvailableFlightsQueryValidator : AbstractValidator -{ -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQuery.cs b/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQuery.cs deleted file mode 100644 index 18f6cdd..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQuery.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using Flight.Flights.Dtos; - -namespace Flight.Flights.Features.GetFlightById.Queries.V1; - -public record GetFlightByIdQuery(long Id) : IQuery; diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryHandler.cs deleted file mode 100644 index 4af6560..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Dtos; -using Flight.Flights.Exceptions; -using MapsterMapper; -using MongoDB.Driver; -using MongoDB.Driver.Linq; - -namespace Flight.Flights.Features.GetFlightById.Queries.V1; - -public class GetFlightByIdQueryHandler : IQueryHandler -{ - private readonly IMapper _mapper; - private readonly FlightReadDbContext _flightReadDbContext; - - public GetFlightByIdQueryHandler(IMapper mapper, FlightReadDbContext flightReadDbContext) - { - _mapper = mapper; - _flightReadDbContext = flightReadDbContext; - } - - public async Task Handle(GetFlightByIdQuery query, CancellationToken cancellationToken) - { - Guard.Against.Null(query, nameof(query)); - - var flight = - await _flightReadDbContext.Flight.AsQueryable().SingleOrDefaultAsync(x => x.FlightId == query.Id && - !x.IsDeleted, cancellationToken); - - if (flight is null) - throw new FlightNotFountException(); - - return _mapper.Map(flight); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryValidator.cs b/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryValidator.cs deleted file mode 100644 index 5a30758..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Queries/V1/GetFlightByIdQueryValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace Flight.Flights.Features.GetFlightById.Queries.V1; - -public class GetFlightByIdQueryValidator : AbstractValidator -{ - public GetFlightByIdQueryValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.Id).NotNull().WithMessage("Id is required!"); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlights.cs b/src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlights.cs new file mode 100644 index 0000000..8fee6ce --- /dev/null +++ b/src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlights.cs @@ -0,0 +1,54 @@ +namespace Flight.Flights.Features.GettingAvailableFlights.V1; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Caching; +using BuildingBlocks.Core.CQRS; +using Data; +using Dtos; +using Exceptions; +using FluentValidation; +using MapsterMapper; +using MongoDB.Driver; + +public record GetAvailableFlights : IQuery>, ICacheRequest +{ + public string CacheKey => "GetAvailableFlights"; + public DateTime? AbsoluteExpirationRelativeToNow => DateTime.Now.AddHours(1); +} + +internal class GetAvailableFlightsValidator : AbstractValidator +{ +} + +internal class GetAvailableFlightsHandler : IQueryHandler> +{ + private readonly IMapper _mapper; + private readonly FlightReadDbContext _flightReadDbContext; + + public GetAvailableFlightsHandler(IMapper mapper, FlightReadDbContext flightReadDbContext) + { + _mapper = mapper; + _flightReadDbContext = flightReadDbContext; + } + + public async Task> Handle(GetAvailableFlights request, + CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var flight = (await _flightReadDbContext.Flight.AsQueryable().ToListAsync(cancellationToken)) + .Where(x => !x.IsDeleted); + + if (!flight.Any()) + { + throw new FlightNotFountException(); + } + + return _mapper.Map>(flight); + } +} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Endpoints/V1/GetAvailableFlightsEndpoint.cs b/src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlightsEndpoint.cs similarity index 77% rename from src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Endpoints/V1/GetAvailableFlightsEndpoint.cs rename to src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlightsEndpoint.cs index 904e4c4..d822f55 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/GetAvailableFlights/Endpoints/V1/GetAvailableFlightsEndpoint.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/GettingAvailableFlights/V1/GetAvailableFlightsEndpoint.cs @@ -1,34 +1,32 @@ +namespace Flight.Flights.Features.GettingAvailableFlights.V1; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using BuildingBlocks.Web; using Flight.Flights.Dtos; -using Flight.Flights.Features.GetAvailableFlights.Queries.V1; +using Hellang.Middleware.ProblemDetails; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Flights.Features.GetAvailableFlights.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; - public class GetAvailableFlightsEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-flights", GetAvailableFlights) + builder.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-flights", GetAvailableFlights) .RequireAuthorization() .WithTags("Flight") .WithName("GetAvailableFlights") .WithMetadata(new SwaggerOperationAttribute("Get Available Flights", "Get Available Flights")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "GetAvailableFlights", - typeof(IEnumerable))) + typeof(IEnumerable))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -41,12 +39,12 @@ public class GetAvailableFlightsEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task GetAvailableFlights(IMediator mediator, CancellationToken cancellationToken) { - var result = await mediator.Send(new GetAvailableFlightsQuery(), cancellationToken); + var result = await mediator.Send(new GetAvailableFlights(), cancellationToken); return Results.Ok(result); } diff --git a/src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightById.cs b/src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightById.cs new file mode 100644 index 0000000..3bacfc2 --- /dev/null +++ b/src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightById.cs @@ -0,0 +1,51 @@ +namespace Flight.Flights.Features.GettingFlightById.V1; + +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using Data; +using Dtos; +using Exceptions; +using FluentValidation; +using MapsterMapper; +using MongoDB.Driver; +using MongoDB.Driver.Linq; + +public record GetFlightById(long Id) : IQuery; + +internal class GetFlightByIdValidator : AbstractValidator +{ + public GetFlightByIdValidator() + { + RuleFor(x => x.Id).NotNull().WithMessage("Id is required!"); + } +} + +internal class GetFlightByIdHandler : IQueryHandler +{ + private readonly IMapper _mapper; + private readonly FlightReadDbContext _flightReadDbContext; + + public GetFlightByIdHandler(IMapper mapper, FlightReadDbContext flightReadDbContext) + { + _mapper = mapper; + _flightReadDbContext = flightReadDbContext; + } + + public async Task Handle(GetFlightById request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var flight = + await _flightReadDbContext.Flight.AsQueryable().SingleOrDefaultAsync(x => x.FlightId == request.Id && + !x.IsDeleted, cancellationToken); + + if (flight is null) + { + throw new FlightNotFountException(); + } + + return _mapper.Map(flight); + } +} diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Endpoints/V1/GetFlightByIdEndpoint.cs b/src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightByIdEndpoint.cs similarity index 74% rename from src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Endpoints/V1/GetFlightByIdEndpoint.cs rename to src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightByIdEndpoint.cs index b0b075e..795a7c0 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/Endpoints/V1/GetFlightByIdEndpoint.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/GettingFlightById/V1/GetFlightByIdEndpoint.cs @@ -1,36 +1,34 @@ +namespace Flight.Flights.Features.GettingFlightById.V1; + using System.Threading; using System.Threading.Tasks; using BuildingBlocks.Web; -using Flight.Flights.Dtos; -using Flight.Flights.Features.GetFlightById.Queries.V1; +using Dtos; +using Hellang.Middleware.ProblemDetails; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Flights.Features.GetFlightById.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; - public class GetFlightByIdEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapGet($"{EndpointConfig.BaseApiPath}/flight/{{id}}", GetById) + builder.MapGet($"{EndpointConfig.BaseApiPath}/flight/{{id}}", GetById) .RequireAuthorization() .WithTags("Flight") .WithName("GetFlightById") .WithMetadata(new SwaggerOperationAttribute("Get Flight By Id", "Get Flight By Id")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) - .Produces() + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) + .Produces() .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status400BadRequest) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "GetFlightById", - typeof(FlightResponseDto))) + typeof(FlightDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -43,12 +41,12 @@ public class GetFlightByIdEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task GetById(long id, IMediator mediator, CancellationToken cancellationToken) { - var result = await mediator.Send(new GetFlightByIdQuery(id), cancellationToken); + var result = await mediator.Send(new GetFlightById(id), cancellationToken); return Results.Ok(result); } diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommand.cs deleted file mode 100644 index 2d43110..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommand.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; -using BuildingBlocks.Core.Event; - -namespace Flight.Flights.Features.UpdateFlight.Commands.V1.Reads; - -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; diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommand.cs deleted file mode 100644 index f62daef..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using BuildingBlocks.Caching; -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using Flight.Flights.Dtos; - -namespace Flight.Flights.Features.UpdateFlight.Commands.V1; - -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, IInternalCommand, IInvalidateCacheRequest -{ - public string CacheKey => "GetAvailableFlightsQuery"; -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandHandler.cs deleted file mode 100644 index 011575f..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandHandler.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Dtos; -using Flight.Flights.Exceptions; -using MapsterMapper; -using Microsoft.EntityFrameworkCore; - -namespace Flight.Flights.Features.UpdateFlight.Commands.V1; - -public class UpdateFlightCommandHandler : ICommandHandler -{ - private readonly FlightDbContext _flightDbContext; - private readonly IMapper _mapper; - - public UpdateFlightCommandHandler(IMapper mapper, FlightDbContext flightDbContext) - { - _mapper = mapper; - _flightDbContext = flightDbContext; - } - - public async Task Handle(UpdateFlightCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == command.Id, - cancellationToken); - - if (flight is null) - throw new FlightNotFountException(); - - - flight.Update(command.Id, command.FlightNumber, command.AircraftId, command.DepartureAirportId, command.DepartureDate, - command.ArriveDate, command.ArriveAirportId, command.DurationMinutes, command.FlightDate, command.Status, command.Price, command.IsDeleted); - - var updateFlight = _flightDbContext.Flights.Update(flight); - - return _mapper.Map(updateFlight.Entity); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandValidator.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandValidator.cs deleted file mode 100644 index 8a859b6..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/UpdateFlightCommandValidator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Flight.Flights.Features.CreateFlight.Commands.V1; -using FluentValidation; - -namespace Flight.Flights.Features.UpdateFlight.Commands.V1; - -public class UpdateFlightCommandValidator : AbstractValidator -{ - public UpdateFlightCommandValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.Price).GreaterThan(0).WithMessage("Price must be greater than 0"); - - RuleFor(x => x.Status).Must(p => (p.GetType().IsEnum && - p == Enums.FlightStatus.Flying) || - p == Enums.FlightStatus.Canceled || - p == Enums.FlightStatus.Delay || - p == Enums.FlightStatus.Completed) - .WithMessage("Status must be Flying, Delay, Canceled or Completed"); - - RuleFor(x => x.AircraftId).NotEmpty().WithMessage("AircraftId must be not empty"); - RuleFor(x => x.DepartureAirportId).NotEmpty().WithMessage("DepartureAirportId must be not empty"); - RuleFor(x => x.ArriveAirportId).NotEmpty().WithMessage("ArriveAirportId must be not empty"); - RuleFor(x => x.DurationMinutes).GreaterThan(0).WithMessage("DurationMinutes must be greater than 0"); - RuleFor(x => x.FlightDate).NotEmpty().WithMessage("FlightDate must be not empty"); - } -} diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Dtos/UpdateFlightRequestDto.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Dtos/UpdateFlightRequestDto.cs deleted file mode 100644 index a4be2e2..0000000 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Dtos/UpdateFlightRequestDto.cs +++ /dev/null @@ -1,6 +0,0 @@ -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); diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Events/V1/FlightUpdatedDomainEvent.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/FlightUpdatedDomainEvent.cs similarity index 85% rename from src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Events/V1/FlightUpdatedDomainEvent.cs rename to src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/FlightUpdatedDomainEvent.cs index a81e410..0c08696 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Events/V1/FlightUpdatedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/FlightUpdatedDomainEvent.cs @@ -1,7 +1,8 @@ +namespace Flight.Flights.Features.UpdatingFlight.V1; + using System; using BuildingBlocks.Core.Event; -namespace Flight.Flights.Features.UpdateFlight.Events.V1; public record FlightUpdatedDomainEvent(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) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlight.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlight.cs new file mode 100644 index 0000000..dab020c --- /dev/null +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlight.cs @@ -0,0 +1,77 @@ +namespace Flight.Flights.Features.UpdatingFlight.V1; + +using System; +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Caching; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using Flight.Data; +using Flight.Flights.Dtos; +using Flight.Flights.Exceptions; +using Flight.Flights.Features.CreatingFlight.V1; +using FluentValidation; +using MapsterMapper; +using Microsoft.EntityFrameworkCore; + +public record UpdateFlight(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, IInternalCommand, IInvalidateCacheRequest +{ + public string CacheKey => "GetAvailableFlights"; +} + +internal class UpdateFlightValidator : AbstractValidator +{ + public UpdateFlightValidator() + { + RuleFor(x => x.Price).GreaterThan(0).WithMessage("Price must be greater than 0"); + + RuleFor(x => x.Status).Must(p => (p.GetType().IsEnum && + p == Enums.FlightStatus.Flying) || + p == Enums.FlightStatus.Canceled || + p == Enums.FlightStatus.Delay || + p == Enums.FlightStatus.Completed) + .WithMessage("Status must be Flying, Delay, Canceled or Completed"); + + RuleFor(x => x.AircraftId).NotEmpty().WithMessage("AircraftId must be not empty"); + RuleFor(x => x.DepartureAirportId).NotEmpty().WithMessage("DepartureAirportId must be not empty"); + RuleFor(x => x.ArriveAirportId).NotEmpty().WithMessage("ArriveAirportId must be not empty"); + RuleFor(x => x.DurationMinutes).GreaterThan(0).WithMessage("DurationMinutes must be greater than 0"); + RuleFor(x => x.FlightDate).NotEmpty().WithMessage("FlightDate must be not empty"); + } +} + +internal class UpdateFlightHandler : ICommandHandler +{ + private readonly FlightDbContext _flightDbContext; + private readonly IMapper _mapper; + + public UpdateFlightHandler(IMapper mapper, FlightDbContext flightDbContext) + { + _mapper = mapper; + _flightDbContext = flightDbContext; + } + + public async Task Handle(UpdateFlight request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == request.Id, + cancellationToken); + + if (flight is null) + { + throw new FlightNotFountException(); + } + + + flight.Update(request.Id, request.FlightNumber, request.AircraftId, request.DepartureAirportId, request.DepartureDate, + request.ArriveDate, request.ArriveAirportId, request.DurationMinutes, request.FlightDate, request.Status, request.Price, request.IsDeleted); + + var updateFlight = _flightDbContext.Flights.Update(flight); + + return _mapper.Map(updateFlight.Entity); + } +} diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Endpoints/V1/UpdateFlightEndpoint.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightEndpoint.cs similarity index 70% rename from src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Endpoints/V1/UpdateFlightEndpoint.cs rename to src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightEndpoint.cs index 505448c..9e51f4c 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Endpoints/V1/UpdateFlightEndpoint.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightEndpoint.cs @@ -1,9 +1,11 @@ +namespace Flight.Flights.Features.UpdatingFlight.V1; + +using System; using System.Threading; 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 Dtos; +using Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,28 +13,27 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Flights.Features.UpdateFlight.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +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); public class UpdateFlightEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPut($"{EndpointConfig.BaseApiPath}/flight", UpdateFlight) + builder.MapPut($"{EndpointConfig.BaseApiPath}/flight", UpdateFlight) .RequireAuthorization() .WithTags("Flight") .WithName("UpdateFlight") .WithMetadata(new SwaggerOperationAttribute("Update Flight", "Update Flight")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) - .Produces() + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) + .Produces() .Produces(StatusCodes.Status204NoContent) .Produces(StatusCodes.Status400BadRequest) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status204NoContent, "Flight Updated", - typeof(FlightResponseDto))) + typeof(FlightDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -45,12 +46,12 @@ public class UpdateFlightEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task UpdateFlight(UpdateFlightRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightMongo.cs similarity index 68% rename from src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightMongo.cs index f66ec87..d3eb683 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Commands/V1/Reads/UpdateFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdatingFlight/V1/UpdateFlightMongo.cs @@ -1,18 +1,25 @@ -using System.Threading; +namespace Flight.Flights.Features.UpdatingFlight.V1; + +using System; +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using Flight.Data; -using Flight.Flights.Exceptions; -using Flight.Flights.Models.Reads; +using BuildingBlocks.Core.Event; +using Data; +using Exceptions; using MapsterMapper; using MediatR; +using Models; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Flights.Features.UpdateFlight.Commands.V1.Reads; +public record UpdateFlightMongo(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; -public class UpdateFlightMongoCommandHandler : ICommandHandler + +internal class UpdateFlightMongoCommandHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; @@ -25,17 +32,19 @@ public class UpdateFlightMongoCommandHandler : ICommandHandler Handle(UpdateFlightMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(UpdateFlightMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var flightReadModel = _mapper.Map(command); + var flightReadModel = _mapper.Map(request); var flight = await _flightReadDbContext.Flight.AsQueryable() .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken); if (flight is null) + { throw new FlightNotFountException(); + } await _flightReadDbContext.Flight.UpdateOneAsync( x => x.FlightId == flightReadModel.FlightId, diff --git a/src/Services/Flight/src/Flight/Flights/Models/Flight.cs b/src/Services/Flight/src/Flight/Flights/Models/Flight.cs index 5b4bf29..d0b4fd5 100644 --- a/src/Services/Flight/src/Flight/Flights/Models/Flight.cs +++ b/src/Services/Flight/src/Flight/Flights/Models/Flight.cs @@ -1,11 +1,12 @@ using System; using BuildingBlocks.Core.Model; -using Flight.Flights.Features.CreateFlight.Events.Domain.V1; -using Flight.Flights.Features.DeleteFlight.Events.Domain.V1; -using Flight.Flights.Features.UpdateFlight.Events.V1; namespace Flight.Flights.Models; +using Features.CreatingFlight.V1; +using Features.DeletingFlight.V1; +using Features.UpdatingFlight.V1; + public record Flight : Aggregate { public string FlightNumber { get; private set; } diff --git a/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs b/src/Services/Flight/src/Flight/Flights/Models/FlightReadModel.cs similarity index 94% rename from src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs rename to src/Services/Flight/src/Flight/Flights/Models/FlightReadModel.cs index fb3fdcd..cd51d06 100644 --- a/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs +++ b/src/Services/Flight/src/Flight/Flights/Models/FlightReadModel.cs @@ -1,6 +1,6 @@ -using System; +namespace Flight.Flights.Models; -namespace Flight.Flights.Models.Reads; +using System; public class FlightReadModel { diff --git a/src/Services/Flight/src/Flight/GrpcServer/Services/FlightGrpcServices.cs b/src/Services/Flight/src/Flight/GrpcServer/Services/FlightGrpcServices.cs index 2fc625f..f6e72f2 100644 --- a/src/Services/Flight/src/Flight/GrpcServer/Services/FlightGrpcServices.cs +++ b/src/Services/Flight/src/Flight/GrpcServer/Services/FlightGrpcServices.cs @@ -1,16 +1,14 @@ using System.Threading.Tasks; -using Flight.Flights.Features.GetFlightById; -using Flight.Flights.Features.GetFlightById.Queries.V1; -using Flight.Seats.Features.GetAvailableSeats; -using Flight.Seats.Features.GetAvailableSeats.Queries.V1; -using Flight.Seats.Features.ReserveSeat; -using Flight.Seats.Features.ReserveSeat.Commands.V1; using Grpc.Core; using Mapster; using MediatR; namespace Flight.GrpcServer.Services; +using Flights.Features.GettingFlightById.V1; +using Seats.Features.GettingAvailableSeats.V1; +using Seats.Features.ReservingSeat.Commands.V1; + public class FlightGrpcServices : FlightGrpcService.FlightGrpcServiceBase { private readonly IMediator _mediator; @@ -22,13 +20,13 @@ public class FlightGrpcServices : FlightGrpcService.FlightGrpcServiceBase public override async Task GetById(GetByIdRequest request, ServerCallContext context) { - var result = await _mediator.Send(new GetFlightByIdQuery(request.Id)); + var result = await _mediator.Send(new GetFlightById(request.Id)); return result.Adapt(); } public override async Task ReserveSeat(ReserveSeatRequest request, ServerCallContext context) { - var result = await _mediator.Send(new ReserveSeatCommand(request.FlightId, request.SeatNumber)); + var result = await _mediator.Send(new ReserveSeat(request.FlightId, request.SeatNumber)); return result.Adapt(); } @@ -36,7 +34,7 @@ public class FlightGrpcServices : FlightGrpcService.FlightGrpcServiceBase { var result = new ListSeatsResponse(); - var availableSeats = await _mediator.Send(new GetAvailableSeatsQuery(request.FlightId)); + var availableSeats = await _mediator.Send(new GetAvailableSeats(request.FlightId)); foreach (var availableSeat in availableSeats) { diff --git a/src/Services/Flight/src/Flight/Seats/Dtos/SeatDto.cs b/src/Services/Flight/src/Flight/Seats/Dtos/SeatDto.cs new file mode 100644 index 0000000..9fcc68f --- /dev/null +++ b/src/Services/Flight/src/Flight/Seats/Dtos/SeatDto.cs @@ -0,0 +1,3 @@ +namespace Flight.Seats.Dtos; + +public record SeatDto(long Id, string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId); diff --git a/src/Services/Flight/src/Flight/Seats/Dtos/SeatResponseDto.cs b/src/Services/Flight/src/Flight/Seats/Dtos/SeatResponseDto.cs deleted file mode 100644 index 1fe3d49..0000000 --- a/src/Services/Flight/src/Flight/Seats/Dtos/SeatResponseDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Flight.Seats.Dtos; - -public record SeatResponseDto(long Id, string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId); diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Exceptions/AllSeatsFullException.cs b/src/Services/Flight/src/Flight/Seats/Exceptions/AllSeatsFullException.cs similarity index 73% rename from src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Exceptions/AllSeatsFullException.cs rename to src/Services/Flight/src/Flight/Seats/Exceptions/AllSeatsFullException.cs index 1f41e9f..bf58cf3 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Exceptions/AllSeatsFullException.cs +++ b/src/Services/Flight/src/Flight/Seats/Exceptions/AllSeatsFullException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Flight.Seats.Exceptions; -namespace Flight.Seats.Features.GetAvailableSeats.Exceptions; +using BuildingBlocks.Exception; public class AllSeatsFullException : BadRequestException { diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Exceptions/SeatAlreadyExistException.cs b/src/Services/Flight/src/Flight/Seats/Exceptions/SeatAlreadyExistException.cs similarity index 78% rename from src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Exceptions/SeatAlreadyExistException.cs rename to src/Services/Flight/src/Flight/Seats/Exceptions/SeatAlreadyExistException.cs index a40afe4..bdbd615 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Exceptions/SeatAlreadyExistException.cs +++ b/src/Services/Flight/src/Flight/Seats/Exceptions/SeatAlreadyExistException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Flight.Seats.Exceptions; -namespace Flight.Seats.Features.CreateSeat.Exceptions; +using BuildingBlocks.Exception; public class SeatAlreadyExistException : ConflictException { diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Exceptions/SeatNumberIncorrectException.cs b/src/Services/Flight/src/Flight/Seats/Exceptions/SeatNumberIncorrectException.cs similarity index 77% rename from src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Exceptions/SeatNumberIncorrectException.cs rename to src/Services/Flight/src/Flight/Seats/Exceptions/SeatNumberIncorrectException.cs index cf731ea..bc2fa5b 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Exceptions/SeatNumberIncorrectException.cs +++ b/src/Services/Flight/src/Flight/Seats/Exceptions/SeatNumberIncorrectException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Flight.Seats.Exceptions; -namespace Flight.Seats.Features.ReserveSeat.Exceptions; +using BuildingBlocks.Exception; public class SeatNumberIncorrectException : BadRequestException { diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommand.cs deleted file mode 100644 index 9793485..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; -using Flight.Seats.Dtos; - -namespace Flight.Seats.Features.CreateSeat.Commands.V1; - -public record CreateSeatCommand(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandHandler.cs deleted file mode 100644 index 757cb43..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandHandler.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using Flight.Data; -using Flight.Seats.Dtos; -using Flight.Seats.Features.CreateSeat.Exceptions; -using Flight.Seats.Models; -using MapsterMapper; -using MediatR; -using Microsoft.EntityFrameworkCore; - -namespace Flight.Seats.Features.CreateSeat.Commands.V1; - -public class CreateSeatCommandHandler : IRequestHandler -{ - private readonly FlightDbContext _flightDbContext; - private readonly IMapper _mapper; - - public CreateSeatCommandHandler(IMapper mapper, FlightDbContext flightDbContext) - { - _mapper = mapper; - _flightDbContext = flightDbContext; - } - - public async Task Handle(CreateSeatCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var seat = await _flightDbContext.Seats.SingleOrDefaultAsync(x => x.Id == command.Id, cancellationToken); - - if (seat is not null) - throw new SeatAlreadyExistException(); - - var seatEntity = Seat.Create(command.Id, command.SeatNumber, command.Type, command.Class, command.FlightId); - - var newSeat = await _flightDbContext.Seats.AddAsync(seatEntity, cancellationToken); - - return _mapper.Map(newSeat.Entity); - } -} diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandValidator.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandValidator.cs deleted file mode 100644 index 48bfa99..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/CreateSeatCommandValidator.cs +++ /dev/null @@ -1,17 +0,0 @@ -using FluentValidation; - -namespace Flight.Seats.Features.CreateSeat.Commands.V1; - -public class CreateSeatCommandValidator : AbstractValidator -{ - public CreateSeatCommandValidator() - { - RuleFor(x => x.SeatNumber).NotEmpty().WithMessage("SeatNumber is required"); - RuleFor(x => x.FlightId).NotEmpty().WithMessage("FlightId is required"); - RuleFor(x => x.Class).Must(p => (p.GetType().IsEnum && - p == Enums.SeatClass.FirstClass) || - p == Enums.SeatClass.Business || - p == Enums.SeatClass.Economy) - .WithMessage("Status must be FirstClass, Business or Economy"); - } -} diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommand.cs deleted file mode 100644 index df4cc59..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BuildingBlocks.Core.Event; - -namespace Flight.Seats.Features.CreateSeat.Commands.V1.Reads; - -public record CreateSeatMongoCommand(long Id, string SeatNumber, Enums.SeatType Type, - Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand; diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Dtos/V1/CreateSeatRequestDto.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Dtos/V1/CreateSeatRequestDto.cs deleted file mode 100644 index e176ddc..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Dtos/V1/CreateSeatRequestDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Flight.Seats.Features.CreateSeat.Dtos.V1; - -public record CreateSeatRequestDto(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId); diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeat.cs b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeat.cs new file mode 100644 index 0000000..f51c901 --- /dev/null +++ b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeat.cs @@ -0,0 +1,66 @@ +namespace Flight.Seats.Features.CreatingSeat.V1; + +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using Flight.Data; +using Flight.Seats.Dtos; +using Flight.Seats.Exceptions; +using Flight.Seats.Models; +using FluentValidation; +using MapsterMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +public record CreateSeat(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} + +internal class CreateSeatValidator : AbstractValidator +{ + public CreateSeatValidator() + { + RuleFor(x => x.SeatNumber).NotEmpty().WithMessage("SeatNumber is required"); + RuleFor(x => x.FlightId).NotEmpty().WithMessage("FlightId is required"); + RuleFor(x => x.Class).Must(p => (p.GetType().IsEnum && + p == Enums.SeatClass.FirstClass) || + p == Enums.SeatClass.Business || + p == Enums.SeatClass.Economy) + .WithMessage("Status must be FirstClass, Business or Economy"); + } +} + +internal class CreateSeatCommandHandler : IRequestHandler +{ + private readonly FlightDbContext _flightDbContext; + private readonly IMapper _mapper; + + public CreateSeatCommandHandler(IMapper mapper, FlightDbContext flightDbContext) + { + _mapper = mapper; + _flightDbContext = flightDbContext; + } + + public async Task Handle(CreateSeat command, CancellationToken cancellationToken) + { + Guard.Against.Null(command, nameof(command)); + + var seat = await _flightDbContext.Seats.SingleOrDefaultAsync(x => x.Id == command.Id, cancellationToken); + + if (seat is not null) + { + throw new SeatAlreadyExistException(); + } + + var seatEntity = Seat.Create(command.Id, command.SeatNumber, command.Type, command.Class, command.FlightId); + + var newSeat = await _flightDbContext.Seats.AddAsync(seatEntity, cancellationToken); + + return _mapper.Map(newSeat.Entity); + } +} + diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Endpoints/V1/CreateSeatEndpoint.cs b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatEndpoint.cs similarity index 86% rename from src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Endpoints/V1/CreateSeatEndpoint.cs rename to src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatEndpoint.cs index beddb94..25b6ffa 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Endpoints/V1/CreateSeatEndpoint.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatEndpoint.cs @@ -1,9 +1,10 @@ +namespace Flight.Seats.Features.CreatingSeat.V1; + 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 Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,9 +12,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Seats.Features.CreateSeat.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record CreateSeatRequestDto(string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId); public class CreateSeatEndpoint : IMinimalEndpoint { @@ -29,7 +28,7 @@ public class CreateSeatEndpoint : IMinimalEndpoint new SwaggerResponseAttribute( StatusCodes.Status200OK, "Seat Created", - typeof(SeatResponseDto))) + typeof(SeatDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -48,7 +47,7 @@ public class CreateSeatEndpoint : IMinimalEndpoint private async Task CreateSeat(CreateSeatRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatMongo.cs similarity index 56% rename from src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatMongo.cs index 66a7e7f..6d93f6d 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Commands/V1/Reads/CreateSeatMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/CreateSeatMongo.cs @@ -1,23 +1,27 @@ -using System.Threading; +namespace Flight.Seats.Features.CreatingSeat.V1; + +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Data; -using Flight.Seats.Features.CreateSeat.Exceptions; -using Flight.Seats.Models.Reads; +using Flight.Seats.Exceptions; +using Flight.Seats.Models; using MapsterMapper; using MediatR; using MongoDB.Driver; using MongoDB.Driver.Linq; -namespace Flight.Seats.Features.CreateSeat.Commands.V1.Reads; +public record CreateSeatMongo(long Id, string SeatNumber, Enums.SeatType Type, + Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand; -public class CreateSeatMongoCommandHandler : ICommandHandler +public class CreateSeatMongoHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; - public CreateSeatMongoCommandHandler( + public CreateSeatMongoHandler( FlightReadDbContext flightReadDbContext, IMapper mapper) { @@ -25,17 +29,19 @@ public class CreateSeatMongoCommandHandler : ICommandHandler Handle(CreateSeatMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(CreateSeatMongo request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var seatReadModel = _mapper.Map(command); + var seatReadModel = _mapper.Map(request); var seat = await _flightReadDbContext.Seat.AsQueryable() .FirstOrDefaultAsync(x => x.SeatId == seatReadModel.SeatId, cancellationToken); if (seat is not null) + { throw new SeatAlreadyExistException(); + } await _flightReadDbContext.Seat.InsertOneAsync(seatReadModel, cancellationToken: cancellationToken); diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Events/Domain/V1/SeatCreatedDomainEvent.cs b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/SeatCreatedDomainEvent.cs similarity index 75% rename from src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Events/Domain/V1/SeatCreatedDomainEvent.cs rename to src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/SeatCreatedDomainEvent.cs index c80ea00..3f80f56 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/Events/Domain/V1/SeatCreatedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/CreatingSeat/V1/SeatCreatedDomainEvent.cs @@ -1,5 +1,5 @@ +namespace Flight.Seats.Features.CreatingSeat.V1; + using BuildingBlocks.Core.Event; -namespace Flight.Seats.Features.CreateSeat.Events.Domain.V1; - public record SeatCreatedDomainEvent(long Id, string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId, bool IsDeleted) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQuery.cs b/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQuery.cs deleted file mode 100644 index 770f9eb..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQuery.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System.Collections.Generic; -using BuildingBlocks.Core.CQRS; -using Flight.Seats.Dtos; - -namespace Flight.Seats.Features.GetAvailableSeats.Queries.V1; - -public record GetAvailableSeatsQuery(long FlightId) : IQuery>; diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryValidator.cs b/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryValidator.cs deleted file mode 100644 index a3e486e..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace Flight.Seats.Features.GetAvailableSeats.Queries.V1; - -public class GetAvailableSeatsQueryValidator : AbstractValidator -{ - public GetAvailableSeatsQueryValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.FlightId).NotNull().WithMessage("FlightId is required!"); - } -} diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeats.cs similarity index 53% rename from src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryHandler.cs rename to src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeats.cs index c418b50..c6b4aa1 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Queries/V1/GetAvailableSeatsQueryHandler.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeats.cs @@ -1,18 +1,30 @@ +namespace Flight.Seats.Features.GettingAvailableSeats.V1; + using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; using Flight.Data; using Flight.Seats.Dtos; -using Flight.Seats.Features.GetAvailableSeats.Exceptions; +using Flight.Seats.Exceptions; +using FluentValidation; using MapsterMapper; using MediatR; using MongoDB.Driver; -namespace Flight.Seats.Features.GetAvailableSeats.Queries.V1; +public record GetAvailableSeats(long FlightId) : IQuery>; -public class GetAvailableSeatsQueryHandler : IRequestHandler> +internal class GetAvailableSeatsValidator : AbstractValidator +{ + public GetAvailableSeatsValidator() + { + RuleFor(x => x.FlightId).NotNull().WithMessage("FlightId is required!"); + } +} + +internal class GetAvailableSeatsQueryHandler : IRequestHandler> { private readonly IMapper _mapper; private readonly FlightReadDbContext _flightReadDbContext; @@ -24,7 +36,7 @@ public class GetAvailableSeatsQueryHandler : IRequestHandler> Handle(GetAvailableSeatsQuery query, CancellationToken cancellationToken) + public async Task> Handle(GetAvailableSeats query, CancellationToken cancellationToken) { Guard.Against.Null(query, nameof(query)); @@ -32,8 +44,10 @@ public class GetAvailableSeatsQueryHandler : IRequestHandler x.FlightId == query.FlightId && !x.IsDeleted); if (!seats.Any()) + { throw new AllSeatsFullException(); + } - return _mapper.Map>(seats); + return _mapper.Map>(seats); } } diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Endpoints/V1/GetAvailableSeatsEndpoint.cs b/src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeatsEndpoint.cs similarity index 74% rename from src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Endpoints/V1/GetAvailableSeatsEndpoint.cs rename to src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeatsEndpoint.cs index e569f8e..f0fd757 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/Endpoints/V1/GetAvailableSeatsEndpoint.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/GettingAvailableSeats/V1/GetAvailableSeatsEndpoint.cs @@ -1,34 +1,32 @@ +namespace Flight.Seats.Features.GettingAvailableSeats.V1; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using BuildingBlocks.Web; using Flight.Seats.Dtos; -using Flight.Seats.Features.GetAvailableSeats.Queries.V1; +using Hellang.Middleware.ProblemDetails; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Seats.Features.GetAvailableSeats.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; - public class GetAvailableSeatsEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-seats/{{id}}", GetAvailableSeats) + builder.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-seats/{{id}}", GetAvailableSeats) .RequireAuthorization() .WithTags("Flight") .WithName("GetAvailableSeats") .WithMetadata(new SwaggerOperationAttribute("Get Available Seats", "Get Available Seats")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "GetAvailableSeats", - typeof(IEnumerable))) + typeof(IEnumerable))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -41,12 +39,12 @@ public class GetAvailableSeatsEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task GetAvailableSeats(long id, IMediator mediator, CancellationToken cancellationToken) { - var result = await mediator.Send(new GetAvailableSeatsQuery(id), cancellationToken); + var result = await mediator.Send(new GetAvailableSeats(id), cancellationToken); return Results.Ok(result); } diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommand.cs deleted file mode 100644 index ebc6a4c..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BuildingBlocks.Core.Event; - -namespace Flight.Seats.Features.ReserveSeat.Commands.V1.Reads; - -public record ReserveSeatMongoCommand(long Id, string SeatNumber, Enums.SeatType Type, - Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand; diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommand.cs deleted file mode 100644 index dfba907..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using Flight.Seats.Dtos; - -namespace Flight.Seats.Features.ReserveSeat.Commands.V1; - -public record ReserveSeatCommand(long FlightId, string SeatNumber) : ICommand, IInternalCommand; diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandValidator.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandValidator.cs deleted file mode 100644 index 881d36a..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandValidator.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FluentValidation; - -namespace Flight.Seats.Features.ReserveSeat.Commands.V1; - -public class ReserveSeatCommandValidator : AbstractValidator -{ - public ReserveSeatCommandValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.FlightId).NotEmpty().WithMessage("FlightId must not be empty"); - RuleFor(x => x.SeatNumber).NotEmpty().WithMessage("SeatNumber must not be empty"); - } -} diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Dtos/V1/ReserveSeatRequestDto.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Dtos/V1/ReserveSeatRequestDto.cs deleted file mode 100644 index 7b3ec12..0000000 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Dtos/V1/ReserveSeatRequestDto.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Flight.Seats.Features.ReserveSeat.Dtos.V1; - - -public record ReserveSeatRequestDto(long FlightId, string SeatNumber); diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeat.cs similarity index 52% rename from src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandHandler.cs rename to src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeat.cs index 2b15fc1..64b6751 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/ReserveSeatCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeat.cs @@ -1,16 +1,30 @@ +namespace Flight.Seats.Features.ReservingSeat.Commands.V1; + using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Data; using Flight.Seats.Dtos; -using Flight.Seats.Features.ReserveSeat.Exceptions; +using Flight.Seats.Exceptions; +using FluentValidation; using MapsterMapper; using MediatR; using Microsoft.EntityFrameworkCore; -namespace Flight.Seats.Features.ReserveSeat.Commands.V1; +public record ReserveSeat(long FlightId, string SeatNumber) : ICommand, IInternalCommand; -public class ReserveSeatCommandHandler : IRequestHandler +internal class ReserveSeatValidator : AbstractValidator +{ + public ReserveSeatValidator() + { + RuleFor(x => x.FlightId).NotEmpty().WithMessage("FlightId must not be empty"); + RuleFor(x => x.SeatNumber).NotEmpty().WithMessage("SeatNumber must not be empty"); + } +} + +internal class ReserveSeatCommandHandler : IRequestHandler { private readonly FlightDbContext _flightDbContext; private readonly IMapper _mapper; @@ -21,19 +35,21 @@ public class ReserveSeatCommandHandler : IRequestHandler Handle(ReserveSeatCommand command, CancellationToken cancellationToken) + public async Task Handle(ReserveSeat command, CancellationToken cancellationToken) { Guard.Against.Null(command, nameof(command)); var seat = await _flightDbContext.Seats.SingleOrDefaultAsync(x => x.SeatNumber == command.SeatNumber && x.FlightId == command.FlightId, cancellationToken); if (seat is null) + { throw new SeatNumberIncorrectException(); + } var reserveSeat = await seat.ReserveSeat(seat); var updatedSeat = _flightDbContext.Seats.Update(reserveSeat); - return _mapper.Map(updatedSeat.Entity); + return _mapper.Map(updatedSeat.Entity); } } diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Endpoints/V1/ReserveSeatEndpoint.cs b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatEndpoint.cs similarity index 76% rename from src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Endpoints/V1/ReserveSeatEndpoint.cs rename to src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatEndpoint.cs index 32ccf2c..1a94891 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Endpoints/V1/ReserveSeatEndpoint.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatEndpoint.cs @@ -1,9 +1,10 @@ +namespace Flight.Seats.Features.ReservingSeat.Commands.V1; + using System.Threading; 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 Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,25 +12,23 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Flight.Seats.Features.ReserveSeat.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record ReserveSeatRequestDto(long FlightId, string SeatNumber); public class ReserveSeatEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/flight/reserve-seat", ReserveSeat) + builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/reserve-seat", ReserveSeat) .RequireAuthorization() .WithTags("Flight") .WithName("ReserveSeat") .WithMetadata(new SwaggerOperationAttribute("Reserve Seat", "Reserve Seat")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Flight").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "ReserveSeat", - typeof(SeatResponseDto))) + typeof(SeatDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -42,12 +41,12 @@ public class ReserveSeatEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task ReserveSeat(ReserveSeatRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatMongo.cs similarity index 62% rename from src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommandHandler.cs rename to src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatMongo.cs index a37f7b7..6377e72 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Commands/V1/Reads/ReserveSeatMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/ReserveSeatMongo.cs @@ -1,21 +1,25 @@ -using System.Threading; +namespace Flight.Seats.Features.ReservingSeat.Commands.V1; + +using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Data; -using Flight.Seats.Models.Reads; +using Flight.Seats.Models; using MapsterMapper; using MediatR; using MongoDB.Driver; -namespace Flight.Seats.Features.ReserveSeat.Commands.V1.Reads; +public record ReserveSeatMongo(long Id, string SeatNumber, Enums.SeatType Type, + Enums.SeatClass Class, long FlightId, bool IsDeleted) : InternalCommand; -public class ReserveSeatMongoCommandHandler : ICommandHandler +internal class ReserveSeatMongoHandler : ICommandHandler { private readonly FlightReadDbContext _flightReadDbContext; private readonly IMapper _mapper; - public ReserveSeatMongoCommandHandler( + public ReserveSeatMongoHandler( FlightReadDbContext flightReadDbContext, IMapper mapper) { @@ -23,7 +27,7 @@ public class ReserveSeatMongoCommandHandler : ICommandHandler Handle(ReserveSeatMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(ReserveSeatMongo command, CancellationToken cancellationToken) { Guard.Against.Null(command, nameof(command)); diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Events/Domain/V1/SeatReservedDomainEvent.cs b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/SeatReservedDomainEvent.cs similarity index 61% rename from src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Events/Domain/V1/SeatReservedDomainEvent.cs rename to src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/SeatReservedDomainEvent.cs index 45655ee..1ccc1a7 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Events/Domain/V1/SeatReservedDomainEvent.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReservingSeat/Commands/V1/SeatReservedDomainEvent.cs @@ -1,5 +1,5 @@ -using BuildingBlocks.Core.Event; +namespace Flight.Seats.Features.ReservingSeat.Commands.V1; -namespace Flight.Seats.Features.ReserveSeat.Events.Domain.V1; +using BuildingBlocks.Core.Event; public record SeatReservedDomainEvent(long Id, string SeatNumber, Enums.SeatType Type, Enums.SeatClass Class, long FlightId, bool IsDeleted) : IDomainEvent; diff --git a/src/Services/Flight/src/Flight/Seats/Features/SeatMappings.cs b/src/Services/Flight/src/Flight/Seats/Features/SeatMappings.cs index 11443d3..3a80879 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/SeatMappings.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/SeatMappings.cs @@ -1,25 +1,21 @@ 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; namespace Flight.Seats.Features; +using CreatingSeat.V1; +using ReservingSeat.Commands.V1; + public class SeatMappings : IRegister { public void Register(TypeAdapterConfig config) { - config.NewConfig() - .ConstructUsing(x => new SeatResponseDto(x.Id, x.SeatNumber, x.Type, x.Class, x.FlightId)); + config.NewConfig() + .ConstructUsing(x => new SeatDto(x.Id, x.SeatNumber, x.Type, x.Class, x.FlightId)); - config.NewConfig() + config.NewConfig() .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.SeatId, s => s.Id); @@ -27,13 +23,13 @@ public class SeatMappings : IRegister .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.SeatId, s => s.Id); - config.NewConfig() + config.NewConfig() .Map(d => d.SeatId, s => s.Id); - config.NewConfig() - .ConstructUsing(x => new CreateSeatCommand(x.SeatNumber, x.Type, x.Class, x.FlightId)); + config.NewConfig() + .ConstructUsing(x => new CreateSeat(x.SeatNumber, x.Type, x.Class, x.FlightId)); - config.NewConfig() - .ConstructUsing(x => new ReserveSeatCommand(x.FlightId, x.SeatNumber)); + config.NewConfig() + .ConstructUsing(x => new ReserveSeat(x.FlightId, x.SeatNumber)); } } diff --git a/src/Services/Flight/src/Flight/Seats/Models/Seat.cs b/src/Services/Flight/src/Flight/Seats/Models/Seat.cs index f4c4f2e..fb74d9f 100644 --- a/src/Services/Flight/src/Flight/Seats/Models/Seat.cs +++ b/src/Services/Flight/src/Flight/Seats/Models/Seat.cs @@ -1,11 +1,12 @@ using System; using System.Threading.Tasks; using BuildingBlocks.Core.Model; -using Flight.Seats.Features.CreateSeat.Events.Domain.V1; -using Flight.Seats.Features.ReserveSeat.Events.Domain.V1; namespace Flight.Seats.Models; +using Features.CreatingSeat.V1; +using Features.ReservingSeat.Commands.V1; + public record Seat : Aggregate { public static Seat Create(long id, string seatNumber, Enums.SeatType type, Enums.SeatClass @class, long flightId, diff --git a/src/Services/Flight/src/Flight/Seats/Models/Reads/SeatReadModel.cs b/src/Services/Flight/src/Flight/Seats/Models/SeatReadModel.cs similarity index 88% rename from src/Services/Flight/src/Flight/Seats/Models/Reads/SeatReadModel.cs rename to src/Services/Flight/src/Flight/Seats/Models/SeatReadModel.cs index e4719a7..8662267 100644 --- a/src/Services/Flight/src/Flight/Seats/Models/Reads/SeatReadModel.cs +++ b/src/Services/Flight/src/Flight/Seats/Models/SeatReadModel.cs @@ -1,4 +1,4 @@ -namespace Flight.Seats.Models.Reads; +namespace Flight.Seats.Models; public class SeatReadModel { diff --git a/src/Services/Flight/tests/EndToEndTest/Fakes/FakeCreateFlightCommand.cs b/src/Services/Flight/tests/EndToEndTest/Fakes/FakeCreateFlightCommand.cs index a82842a..f2875f5 100644 --- a/src/Services/Flight/tests/EndToEndTest/Fakes/FakeCreateFlightCommand.cs +++ b/src/Services/Flight/tests/EndToEndTest/Fakes/FakeCreateFlightCommand.cs @@ -1,11 +1,12 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; using Flight.Flights.Enums; -using Flight.Flights.Features.CreateFlight.Commands.V1; namespace EndToEnd.Test.Fakes; -public sealed class FakeCreateFlightCommand : AutoFaker +using global::Flight.Flights.Features.CreatingFlight.V1; + +public sealed class FakeCreateFlightCommand : AutoFaker { public FakeCreateFlightCommand() { diff --git a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs index 21daea4..a7b7d64 100644 --- a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs +++ b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs @@ -4,13 +4,12 @@ using EndToEnd.Test.Fakes; using EndToEnd.Test.Routes; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; using FluentAssertions; using Xunit; namespace EndToEnd.Test.Flight.Features; -using BuildingBlocks.Contracts.EventBus.Messages; +using global::Flight.Flights.Features.CreatingFlight.V1; public class GetFlightByIdTests: FlightEndToEndTestBase { @@ -25,7 +24,7 @@ public class GetFlightByIdTests: FlightEndToEndTestBase //Arrange var command = new FakeCreateFlightCommand().Generate(); await Fixture.SendAsync(command); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); // Act var route = ApiRoutes.Flight.GetFlightById.Replace(ApiRoutes.Flight.Id, command.Id.ToString()); diff --git a/src/Services/Flight/tests/EndToEndTest/Routes/ApiRoutes.cs b/src/Services/Flight/tests/EndToEndTest/Routes/ApiRoutes.cs index 523e47e..4bbf880 100644 --- a/src/Services/Flight/tests/EndToEndTest/Routes/ApiRoutes.cs +++ b/src/Services/Flight/tests/EndToEndTest/Routes/ApiRoutes.cs @@ -1,8 +1,8 @@ namespace EndToEnd.Test.Routes; -public class ApiRoutes +public static class ApiRoutes { - public const string BaseApiPath = "api/v1.0"; + private const string BaseApiPath = "api/v1.0"; public static class Flight { diff --git a/src/Services/Flight/tests/IntegrationTest/Aircraft/Features/CreateAircraftTests.cs b/src/Services/Flight/tests/IntegrationTest/Aircraft/Features/CreateAircraftTests.cs index 3295692..9a4039e 100644 --- a/src/Services/Flight/tests/IntegrationTest/Aircraft/Features/CreateAircraftTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Aircraft/Features/CreateAircraftTests.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.TestBase; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1.Reads; using Flight.Api; using Flight.Data; using FluentAssertions; @@ -10,6 +9,8 @@ using Xunit; namespace Integration.Test.Aircraft.Features; +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + public class CreateAircraftTests : FlightIntegrationTestBase { public CreateAircraftTests( @@ -32,6 +33,6 @@ public class CreateAircraftTests : FlightIntegrationTestBase (await Fixture.WaitForPublishing()).Should().Be(true); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Airport/Features/CreateAirportTests.cs b/src/Services/Flight/tests/IntegrationTest/Airport/Features/CreateAirportTests.cs index 20c00bd..56c9727 100644 --- a/src/Services/Flight/tests/IntegrationTest/Airport/Features/CreateAirportTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Airport/Features/CreateAirportTests.cs @@ -1,7 +1,6 @@ using System.Threading.Tasks; using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.TestBase; -using Flight.Airports.Features.CreateAirport.Commands.V1.Reads; using Flight.Api; using Flight.Data; using FluentAssertions; @@ -10,6 +9,8 @@ using Xunit; namespace Integration.Test.Airport.Features; +using global::Flight.Airports.Features.CreatingAirport.V1; + public class CreateAirportTests : FlightIntegrationTestBase { public CreateAirportTests( @@ -32,6 +33,6 @@ public class CreateAirportTests : FlightIntegrationTestBase (await Fixture.WaitForPublishing()).Should().Be(true); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAircraftCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAircraftCommand.cs index 6c01631..9afddac 100644 --- a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAircraftCommand.cs +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAircraftCommand.cs @@ -1,10 +1,11 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1; namespace Integration.Test.Fakes; -public class FakeCreateAircraftCommand : AutoFaker +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + +public class FakeCreateAircraftCommand : AutoFaker { public FakeCreateAircraftCommand() { diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAirportCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAirportCommand.cs index d6a0544..5d3827e 100644 --- a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAirportCommand.cs +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateAirportCommand.cs @@ -1,10 +1,11 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; -using Flight.Airports.Features.CreateAirport.Commands.V1; namespace Integration.Test.Fakes; -public class FakeCreateAirportCommand : AutoFaker +using global::Flight.Airports.Features.CreatingAirport.V1; + +public class FakeCreateAirportCommand : AutoFaker { public FakeCreateAirportCommand() { diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateFlightCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateFlightCommand.cs index d3d93b7..7a7248d 100644 --- a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateFlightCommand.cs +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateFlightCommand.cs @@ -1,11 +1,12 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; using Flight.Flights.Enums; -using Flight.Flights.Features.CreateFlight.Commands.V1; namespace Integration.Test.Fakes; -public sealed class FakeCreateFlightCommand : AutoFaker +using global::Flight.Flights.Features.CreatingFlight.V1; + +public sealed class FakeCreateFlightCommand : AutoFaker { public FakeCreateFlightCommand() { diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs index 262853a..dbccc27 100644 --- a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeCreateSeatCommand.cs @@ -1,11 +1,12 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; using Flight.Seats.Enums; -using Flight.Seats.Features.CreateSeat.Commands.V1; namespace Integration.Test.Fakes; -public class FakeCreateSeatCommand : AutoFaker +using global::Flight.Seats.Features.CreatingSeat.V1; + +public class FakeCreateSeatCommand : AutoFaker { public FakeCreateSeatCommand(long flightId) { diff --git a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeUpdateFlightCommand.cs b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeUpdateFlightCommand.cs index b07f68d..28e54a6 100644 --- a/src/Services/Flight/tests/IntegrationTest/Fakes/FakeUpdateFlightCommand.cs +++ b/src/Services/Flight/tests/IntegrationTest/Fakes/FakeUpdateFlightCommand.cs @@ -1,10 +1,10 @@ using AutoBogus; -using Flight.Flights.Features.UpdateFlight; -using Flight.Flights.Features.UpdateFlight.Commands.V1; namespace Integration.Test.Fakes; -public class FakeUpdateFlightCommand : AutoFaker +using global::Flight.Flights.Features.UpdatingFlight.V1; + +public class FakeUpdateFlightCommand : AutoFaker { public FakeUpdateFlightCommand(global::Flight.Flights.Models.Flight flight) { diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/CreateFlightTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/CreateFlightTests.cs index 979dd01..de26ae4 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/CreateFlightTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/CreateFlightTests.cs @@ -3,13 +3,14 @@ using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.TestBase; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Flight.Features; +using global::Flight.Flights.Features.CreatingFlight.V1; + public class CreateFlightTests : FlightIntegrationTestBase { public CreateFlightTests( @@ -33,6 +34,6 @@ public class CreateFlightTests : FlightIntegrationTestBase (await Fixture.WaitForPublishing()).Should().Be(true); (await Fixture.WaitForConsuming()).Should().Be(true); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/DeleteFlightTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/DeleteFlightTests.cs index 5410371..675d8ec 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/DeleteFlightTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/DeleteFlightTests.cs @@ -4,14 +4,14 @@ using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.TestBase; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.DeleteFlight.Commands.V1; -using Flight.Flights.Features.DeleteFlight.Commands.V1.Reads; using FluentAssertions; using Microsoft.EntityFrameworkCore; using Xunit; namespace Integration.Test.Flight.Features; +using global::Flight.Flights.Features.DeletingFlight.V1; + public class DeleteFlightTests : FlightIntegrationTestBase { public DeleteFlightTests( @@ -24,7 +24,7 @@ public class DeleteFlightTests : FlightIntegrationTestBase { // Arrange var flightEntity = await Fixture.FindAsync(1); - var command = new DeleteFlightCommand(flightEntity.Id); + var command = new DeleteFlight(flightEntity.Id); // Act await Fixture.SendAsync(command); @@ -39,6 +39,6 @@ public class DeleteFlightTests : FlightIntegrationTestBase (await Fixture.WaitForPublishing()).Should().Be(true); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs index f45f610..9a31d6a 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetAvailableFlightsTests.cs @@ -3,14 +3,15 @@ using System.Threading.Tasks; using BuildingBlocks.TestBase; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; -using Flight.Flights.Features.GetAvailableFlights.Queries.V1; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Flight.Features; +using global::Flight.Flights.Features.CreatingFlight.V1; +using global::Flight.Flights.Features.GettingAvailableFlights.V1; + public class GetAvailableFlightsTests : FlightIntegrationTestBase { public GetAvailableFlightsTests( @@ -26,9 +27,9 @@ public class GetAvailableFlightsTests : FlightIntegrationTestBase await Fixture.SendAsync(flightCommand); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); - var query = new GetAvailableFlightsQuery(); + var query = new GetAvailableFlights(); // Act var response = (await Fixture.SendAsync(query))?.ToList(); diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs index bbdf616..5f0243c 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs @@ -3,14 +3,15 @@ using BuildingBlocks.TestBase; using Flight; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; -using Flight.Flights.Features.GetFlightById.Queries.V1; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Flight.Features; +using global::Flight.Flights.Features.CreatingFlight.V1; +using global::Flight.Flights.Features.GettingFlightById.V1; + public class GetFlightByIdTests : FlightIntegrationTestBase { public GetFlightByIdTests( @@ -25,9 +26,9 @@ public class GetFlightByIdTests : FlightIntegrationTestBase var command = new FakeCreateFlightCommand().Generate(); await Fixture.SendAsync(command); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); - var query = new GetFlightByIdQuery(command.Id); + var query = new GetFlightById(command.Id); // Act var response = await Fixture.SendAsync(query); @@ -44,7 +45,7 @@ public class GetFlightByIdTests : FlightIntegrationTestBase var command = new FakeCreateFlightCommand().Generate(); await Fixture.SendAsync(command); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); var flightGrpcClient = new FlightGrpcService.FlightGrpcServiceClient(Fixture.Channel); diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/UpdateFlightTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/UpdateFlightTests.cs index e625e00..2975c73 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/UpdateFlightTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/UpdateFlightTests.cs @@ -3,13 +3,14 @@ using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.TestBase; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.UpdateFlight.Commands.V1.Reads; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Flight.Features; +using global::Flight.Flights.Features.UpdatingFlight.V1; + public class UpdateFlightTests : FlightIntegrationTestBase { public UpdateFlightTests( @@ -34,6 +35,6 @@ public class UpdateFlightTests : FlightIntegrationTestBase (await Fixture.WaitForPublishing()).Should().Be(true); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); } } diff --git a/src/Services/Flight/tests/IntegrationTest/Seat/Features/GetAvailableSeatsTests.cs b/src/Services/Flight/tests/IntegrationTest/Seat/Features/GetAvailableSeatsTests.cs index a7d90b1..fd61e11 100644 --- a/src/Services/Flight/tests/IntegrationTest/Seat/Features/GetAvailableSeatsTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Seat/Features/GetAvailableSeatsTests.cs @@ -3,14 +3,15 @@ using BuildingBlocks.TestBase; using Flight; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; -using Flight.Seats.Features.CreateSeat.Commands.V1.Reads; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Seat.Features; +using global::Flight.Flights.Features.CreatingFlight.V1; +using global::Flight.Seats.Features.CreatingSeat.V1; + public class GetAvailableSeatsTests : FlightIntegrationTestBase { public GetAvailableSeatsTests( @@ -26,13 +27,13 @@ public class GetAvailableSeatsTests : FlightIntegrationTestBase await Fixture.SendAsync(flightCommand); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); var seatCommand = new FakeCreateSeatCommand(flightCommand.Id).Generate(); await Fixture.SendAsync(seatCommand); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); var flightGrpcClient = new FlightGrpcService.FlightGrpcServiceClient(Fixture.Channel); diff --git a/src/Services/Flight/tests/IntegrationTest/Seat/Features/ReserveSeatTests.cs b/src/Services/Flight/tests/IntegrationTest/Seat/Features/ReserveSeatTests.cs index f3b7658..76ddf55 100644 --- a/src/Services/Flight/tests/IntegrationTest/Seat/Features/ReserveSeatTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Seat/Features/ReserveSeatTests.cs @@ -3,14 +3,15 @@ using BuildingBlocks.TestBase; using Flight; using Flight.Api; using Flight.Data; -using Flight.Flights.Features.CreateFlight.Commands.V1.Reads; -using Flight.Seats.Features.CreateSeat.Commands.V1.Reads; using FluentAssertions; using Integration.Test.Fakes; using Xunit; namespace Integration.Test.Seat.Features; +using global::Flight.Flights.Features.CreatingFlight.V1; +using global::Flight.Seats.Features.CreatingSeat.V1; + public class ReserveSeatTests : FlightIntegrationTestBase { public ReserveSeatTests( @@ -26,13 +27,13 @@ public class ReserveSeatTests : FlightIntegrationTestBase await Fixture.SendAsync(flightCommand); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); var seatCommand = new FakeCreateSeatCommand(flightCommand.Id).Generate(); await Fixture.SendAsync(seatCommand); - (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); + (await Fixture.ShouldProcessedPersistInternalCommand()).Should().Be(true); var flightGrpcClient = new FlightGrpcService.FlightGrpcServiceClient(Fixture.Channel); diff --git a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs index eefbd98..8fbf5eb 100644 --- a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs @@ -1,30 +1,29 @@ using System; using System.Threading; using System.Threading.Tasks; -using Flight.Aircrafts.Dtos; -using Flight.Aircrafts.Features.CreateAircraft; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1; using FluentAssertions; -using Microsoft.EntityFrameworkCore; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; namespace Unit.Test.Aircraft.Features.CreateAircraftTests; +using global::Flight.Aircrafts.Dtos; +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + [Collection(nameof(UnitTestFixture))] public class CreateAircraftCommandHandlerTests { private readonly UnitTestFixture _fixture; - private readonly CreateAircraftCommandHandler _handler; + private readonly CreateAircraftHandler _handler; - public Task Act(CreateAircraftCommand command, CancellationToken cancellationToken) => + public Task Act(CreateAircraft command, CancellationToken cancellationToken) => _handler.Handle(command, cancellationToken); public CreateAircraftCommandHandlerTests(UnitTestFixture fixture) { _fixture = fixture; - _handler = new CreateAircraftCommandHandler(_fixture.Mapper, _fixture.DbContext); + _handler = new CreateAircraftHandler(_fixture.Mapper, _fixture.DbContext); } [Fact] @@ -47,7 +46,7 @@ public class CreateAircraftCommandHandlerTests public async Task handler_with_null_command_should_throw_argument_exception() { // Arrange - CreateAircraftCommand command = null; + CreateAircraft command = null; // Act Func act = async () => { await Act(command, CancellationToken.None); }; diff --git a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandValidatorTests.cs b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandValidatorTests.cs index dea9e32..8937533 100644 --- a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandValidatorTests.cs +++ b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandValidatorTests.cs @@ -1,6 +1,4 @@ -using Flight.Aircrafts.Features.CreateAircraft; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1; -using FluentAssertions; +using FluentAssertions; using FluentValidation.TestHelper; using Unit.Test.Common; using Unit.Test.Fakes; @@ -8,6 +6,8 @@ using Xunit; namespace Unit.Test.Aircraft.Features.CreateAircraftTests; +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + [Collection(nameof(UnitTestFixture))] public class CreateAircraftCommandValidatorTests { @@ -16,7 +16,7 @@ public class CreateAircraftCommandValidatorTests { // Arrange var command = new FakeValidateCreateAircraftCommand().Generate(); - var validator = new CreateAircraftCommandValidator(); + var validator = new CreateAircraftValidator(); // Act var result = validator.TestValidate(command); diff --git a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs index 5a8a991..ee73127 100644 --- a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs @@ -1,31 +1,30 @@ using System; using System.Threading; using System.Threading.Tasks; -using Flight.Airports.Dtos; -using Flight.Airports.Features.CreateAirport; -using Flight.Airports.Features.CreateAirport.Commands.V1; using FluentAssertions; -using Microsoft.EntityFrameworkCore; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; namespace Unit.Test.Airport.Features.CreateAirportTests; +using global::Flight.Airports.Dtos; +using global::Flight.Airports.Features.CreatingAirport.V1; + [Collection(nameof(UnitTestFixture))] public class CreateAirportCommandHandlerTests { private readonly UnitTestFixture _fixture; - private readonly CreateAirportCommandHandler _handler; + private readonly CreateAirportHandler _handler; public CreateAirportCommandHandlerTests(UnitTestFixture fixture) { _fixture = fixture; - _handler = new CreateAirportCommandHandler(_fixture.Mapper, _fixture.DbContext); + _handler = new CreateAirportHandler(_fixture.Mapper, _fixture.DbContext); } - public Task Act(CreateAirportCommand command, CancellationToken cancellationToken) => + public Task Act(CreateAirport command, CancellationToken cancellationToken) => _handler.Handle(command, cancellationToken); [Fact] @@ -48,7 +47,7 @@ public class CreateAirportCommandHandlerTests public async Task handler_with_null_command_should_throw_argument_exception() { // Arrange - CreateAirportCommand command = null; + CreateAirport command = null; // Act var act = async () => { await Act(command, CancellationToken.None); }; diff --git a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandValidatorTests.cs b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandValidatorTests.cs index eb0b650..3d62eaf 100644 --- a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandValidatorTests.cs +++ b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandValidatorTests.cs @@ -1,6 +1,4 @@ -using Flight.Airports.Features.CreateAirport; -using Flight.Airports.Features.CreateAirport.Commands.V1; -using FluentAssertions; +using FluentAssertions; using FluentValidation.TestHelper; using Unit.Test.Common; using Unit.Test.Fakes; @@ -8,6 +6,8 @@ using Xunit; namespace Unit.Test.Airport.Features.CreateAirportTests; +using global::Flight.Airports.Features.CreatingAirport.V1; + [Collection(nameof(UnitTestFixture))] public class CreateAirportCommandValidatorTests { @@ -16,7 +16,7 @@ public class CreateAirportCommandValidatorTests { // Arrange var command = new FakeValidateCreateAirportCommand().Generate(); - var validator = new CreateAirportCommandValidator(); + var validator = new CreateAirportValidator(); // Act var result = validator.TestValidate(command); diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAircraftCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAircraftCommand.cs index 818b22f..7111fff 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAircraftCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAircraftCommand.cs @@ -1,11 +1,11 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; -using Flight.Aircrafts.Features.CreateAircraft; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1; namespace Unit.Test.Fakes; -public class FakeCreateAircraftCommand : AutoFaker +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + +public class FakeCreateAircraftCommand : AutoFaker { public FakeCreateAircraftCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAirportCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAirportCommand.cs index b3ef3ef..d9a079b 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAirportCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateAirportCommand.cs @@ -1,11 +1,11 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; -using Flight.Airports.Features.CreateAirport; -using Flight.Airports.Features.CreateAirport.Commands.V1; namespace Unit.Test.Fakes; -public class FakeCreateAirportCommand : AutoFaker +using global::Flight.Airports.Features.CreatingAirport.V1; + +public class FakeCreateAirportCommand : AutoFaker { public FakeCreateAirportCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateFlightCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateFlightCommand.cs index 3dc75bf..ad03ce9 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateFlightCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateFlightCommand.cs @@ -1,11 +1,11 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; -using Flight.Flights.Features.CreateFlight; -using Flight.Flights.Features.CreateFlight.Commands.V1; namespace Unit.Test.Fakes; -public sealed class FakeCreateFlightCommand : AutoFaker +using global::Flight.Flights.Features.CreatingFlight.V1; + +public sealed class FakeCreateFlightCommand : AutoFaker { public FakeCreateFlightCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateSeatCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateSeatCommand.cs index 6986011..6276482 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateSeatCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeCreateSeatCommand.cs @@ -1,13 +1,12 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; using Flight.Seats.Enums; -using Flight.Seats.Features.CreateSeat; -using Flight.Seats.Features.CreateSeat.Commands.V1; -using Flight.Seats.Models; namespace Unit.Test.Fakes; -public class FakeCreateSeatCommand : AutoFaker +using global::Flight.Seats.Features.CreatingSeat.V1; + +public class FakeCreateSeatCommand : AutoFaker { public FakeCreateSeatCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAircraftCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAircraftCommand.cs index 6b3d292..3e4cf55 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAircraftCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAircraftCommand.cs @@ -1,10 +1,10 @@ using AutoBogus; -using Flight.Aircrafts.Features.CreateAircraft; -using Flight.Aircrafts.Features.CreateAircraft.Commands.V1; namespace Unit.Test.Fakes; -public class FakeValidateCreateAircraftCommand : AutoFaker +using global::Flight.Aircrafts.Features.CreatingAircraft.V1; + +public class FakeValidateCreateAircraftCommand : AutoFaker { public FakeValidateCreateAircraftCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAirportCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAirportCommand.cs index 1e188f1..59003af 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAirportCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateAirportCommand.cs @@ -1,10 +1,10 @@ using AutoBogus; -using Flight.Airports.Features.CreateAirport; -using Flight.Airports.Features.CreateAirport.Commands.V1; namespace Unit.Test.Fakes; -public class FakeValidateCreateAirportCommand : AutoFaker +using global::Flight.Airports.Features.CreatingAirport.V1; + +public class FakeValidateCreateAirportCommand : AutoFaker { public FakeValidateCreateAirportCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateFlightCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateFlightCommand.cs index c2379be..b869c6d 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateFlightCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateFlightCommand.cs @@ -1,13 +1,12 @@ using System; using AutoBogus; using Flight.Flights.Enums; -using Flight.Flights.Features.CreateFlight; -using Flight.Flights.Features.CreateFlight.Commands.V1; -using Flight.Flights.Models; namespace Unit.Test.Fakes; -public class FakeValidateCreateFlightCommand : AutoFaker +using global::Flight.Flights.Features.CreatingFlight.V1; + +public class FakeValidateCreateFlightCommand : AutoFaker { public FakeValidateCreateFlightCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateSeatCommand.cs b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateSeatCommand.cs index 6d17c53..7fd41f1 100644 --- a/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateSeatCommand.cs +++ b/src/Services/Flight/tests/UnitTest/Fakes/FakeValidateCreateSeatCommand.cs @@ -1,12 +1,11 @@ using AutoBogus; using Flight.Seats.Enums; -using Flight.Seats.Features.CreateSeat; -using Flight.Seats.Features.CreateSeat.Commands.V1; -using Flight.Seats.Models; namespace Unit.Test.Fakes; -public class FakeValidateCreateSeatCommand : AutoFaker +using global::Flight.Seats.Features.CreatingSeat.V1; + +public class FakeValidateCreateSeatCommand : AutoFaker { public FakeValidateCreateSeatCommand() { diff --git a/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandHandlerTests.cs index 90e10bf..92e3105 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandHandlerTests.cs @@ -5,24 +5,24 @@ using System.Threading; using System.Threading.Tasks; using FluentAssertions; using global::Flight.Flights.Dtos; -using global::Flight.Flights.Features.CreateFlight.Commands.V1; -using Unit.Test.Common; -using Unit.Test.Fakes; +using global::Flight.Flights.Features.CreatingFlight.V1; +using Common; +using Fakes; using Xunit; [Collection(nameof(UnitTestFixture))] public class CreateFlightCommandHandlerTests { private readonly UnitTestFixture _fixture; - private readonly CreateFlightCommandHandler _handler; + private readonly CreateFlightHandler _handler; - public Task Act(CreateFlightCommand command, CancellationToken cancellationToken) => + public Task Act(CreateFlight command, CancellationToken cancellationToken) => _handler.Handle(command, cancellationToken); public CreateFlightCommandHandlerTests(UnitTestFixture fixture) { _fixture = fixture; - _handler = new CreateFlightCommandHandler(fixture.Mapper, fixture.DbContext); + _handler = new CreateFlightHandler(fixture.Mapper, fixture.DbContext); } [Fact] @@ -46,7 +46,7 @@ public class CreateFlightCommandHandlerTests public async Task handler_with_null_command_should_throw_argument_exception() { // Arrange - CreateFlightCommand command = null; + CreateFlight command = null; // Act Func act = async () => { await Act(command, CancellationToken.None); }; diff --git a/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandValidatorTests.cs b/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandValidatorTests.cs index 043f0ca..50de43f 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandValidatorTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/Features/Commands/CreateFlight/CreateFlightCommandValidatorTests.cs @@ -2,7 +2,7 @@ using FluentAssertions; using FluentValidation.TestHelper; -using global::Flight.Flights.Features.CreateFlight.Commands.V1; +using global::Flight.Flights.Features.CreatingFlight.V1; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; @@ -15,7 +15,7 @@ public class CreateFlightCommandValidatorTests { // Arrange var command = new FakeValidateCreateFlightCommand().Generate(); - var validator = new CreateFlightCommandValidator(); + var validator = new CreateFlightValidator(); // Act var result = validator.TestValidate(command); diff --git a/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/CreateFlightTests.cs b/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/CreateFlightTests.cs index 2dd003e..0729bf9 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/CreateFlightTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/CreateFlightTests.cs @@ -2,7 +2,7 @@ { using System.Linq; using FluentAssertions; - using global::Flight.Flights.Features.CreateFlight.Events.Domain.V1; + using global::Flight.Flights.Features.CreatingFlight.V1; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; diff --git a/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/UpdateFlightTests.cs b/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/UpdateFlightTests.cs index 9b79329..de5b5bc 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/UpdateFlightTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/Features/Domain/UpdateFlightTests.cs @@ -2,7 +2,7 @@ using System.Linq; using FluentAssertions; -using global::Flight.Flights.Features.UpdateFlight.Events.V1; +using global::Flight.Flights.Features.UpdatingFlight.V1; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; diff --git a/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs b/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs index d132e05..495ec0b 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs @@ -25,7 +25,7 @@ public class FlightMappingTests yield return new object[] { // these types will instantiate with reflection in the future - typeof(global::Flight.Flights.Models.Flight), typeof(FlightResponseDto) + typeof(global::Flight.Flights.Models.Flight), typeof(FlightDto) }; } } diff --git a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs index f5acd26..4ad9119 100644 --- a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs @@ -2,16 +2,15 @@ using System.Threading; using System.Threading.Tasks; using Flight.Seats.Dtos; -using Flight.Seats.Features.CreateSeat; -using Flight.Seats.Features.CreateSeat.Commands.V1; using FluentAssertions; -using Microsoft.EntityFrameworkCore; using Unit.Test.Common; using Unit.Test.Fakes; using Xunit; namespace Unit.Test.Seat.Features; +using global::Flight.Seats.Features.CreatingSeat.V1; + [Collection(nameof(UnitTestFixture))] public class CreateSeatCommandHandlerTests { @@ -25,7 +24,7 @@ public class CreateSeatCommandHandlerTests _handler = new CreateSeatCommandHandler(_fixture.Mapper, _fixture.DbContext); } - public Task Act(CreateSeatCommand command, CancellationToken cancellationToken) + public Task Act(CreateSeat command, CancellationToken cancellationToken) { return _handler.Handle(command, cancellationToken); } @@ -50,7 +49,7 @@ public class CreateSeatCommandHandlerTests public async Task handler_with_null_command_should_throw_argument_exception() { // Arrange - CreateSeatCommand command = null; + CreateSeat command = null; // Act var act = async () => { await Act(command, CancellationToken.None); }; diff --git a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandValidatorTests.cs b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandValidatorTests.cs index d61637d..3296670 100644 --- a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandValidatorTests.cs +++ b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandValidatorTests.cs @@ -1,6 +1,4 @@ -using Flight.Seats.Features.CreateSeat; -using Flight.Seats.Features.CreateSeat.Commands.V1; -using FluentAssertions; +using FluentAssertions; using FluentValidation.TestHelper; using Unit.Test.Common; using Unit.Test.Fakes; @@ -8,6 +6,8 @@ using Xunit; namespace Unit.Test.Seat.Features; +using global::Flight.Seats.Features.CreatingSeat.V1; + [Collection(nameof(UnitTestFixture))] public class CreateSeatCommandValidatorTests { @@ -16,7 +16,7 @@ public class CreateSeatCommandValidatorTests { // Arrange var command = new FakeValidateCreateSeatCommand().Generate(); - var validator = new CreateSeatCommandValidator(); + var validator = new CreateSeatValidator(); // Act var result = validator.TestValidate(command); diff --git a/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs b/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs index 43f4aba..04bdfd6 100644 --- a/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs +++ b/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs @@ -25,7 +25,7 @@ public class SeatMappingTests yield return new object[] { // these types will instantiate with reflection in the future - typeof(global::Flight.Seats.Models.Seat), typeof(SeatResponseDto) + typeof(global::Flight.Seats.Models.Seat), typeof(SeatDto) }; } } diff --git a/src/Services/Flight/tests/UnitTest/Unit.Test.csproj b/src/Services/Flight/tests/UnitTest/Unit.Test.csproj index 144c97b..7ebb982 100644 --- a/src/Services/Flight/tests/UnitTest/Unit.Test.csproj +++ b/src/Services/Flight/tests/UnitTest/Unit.Test.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Services/Identity/src/Identity/Identity.csproj b/src/Services/Identity/src/Identity/Identity.csproj index 57491c9..26628df 100644 --- a/src/Services/Identity/src/Identity/Identity.csproj +++ b/src/Services/Identity/src/Identity/Identity.csproj @@ -19,4 +19,10 @@ + + + <_Parameter1>Integration.Test + + + diff --git a/src/Services/Identity/src/Identity/Identity/Dtos/RegisterNewUserResponseDto.cs b/src/Services/Identity/src/Identity/Identity/Dtos/RegisterNewUserDto.cs similarity index 100% rename from src/Services/Identity/src/Identity/Identity/Dtos/RegisterNewUserResponseDto.cs rename to src/Services/Identity/src/Identity/Identity/Dtos/RegisterNewUserDto.cs diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Exceptions/RegisterIdentityUserException.cs b/src/Services/Identity/src/Identity/Identity/Exceptions/RegisterIdentityUserException.cs similarity index 73% rename from src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Exceptions/RegisterIdentityUserException.cs rename to src/Services/Identity/src/Identity/Identity/Exceptions/RegisterIdentityUserException.cs index 562aeb3..632290e 100644 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Exceptions/RegisterIdentityUserException.cs +++ b/src/Services/Identity/src/Identity/Identity/Exceptions/RegisterIdentityUserException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Identity.Identity.Exceptions; -namespace Identity.Identity.Features.RegisterNewUser.Exceptions; +using BuildingBlocks.Exception; public class RegisterIdentityUserException : AppException { diff --git a/src/Services/Identity/src/Identity/Identity/Features/IdentityMappings.cs b/src/Services/Identity/src/Identity/Identity/Features/IdentityMappings.cs index 903ebb3..166ccac 100644 --- a/src/Services/Identity/src/Identity/Identity/Features/IdentityMappings.cs +++ b/src/Services/Identity/src/Identity/Identity/Features/IdentityMappings.cs @@ -1,15 +1,15 @@ -using Identity.Identity.Features.RegisterNewUser.Commands.V1; -using Identity.Identity.Features.RegisterNewUser.Dtos.V1; -using Mapster; +using Mapster; namespace Identity.Identity.Features; +using RegisteringNewUser.V1; + public class IdentityMappings : IRegister { public void Register(TypeAdapterConfig config) { - config.NewConfig() - .ConstructUsing(x => new RegisterNewUserCommand(x.FirstName, x.LastName, x.Username, x.Email, + config.NewConfig() + .ConstructUsing(x => new RegisterNewUser(x.FirstName, x.LastName, x.Username, x.Email, x.Password, x.ConfirmPassword, x.PassportNumber)); } } diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommand.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommand.cs deleted file mode 100644 index 2df81d8..0000000 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommand.cs +++ /dev/null @@ -1,7 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using Identity.Identity.Dtos; - -namespace Identity.Identity.Features.RegisterNewUser.Commands.V1; - -public record RegisterNewUserCommand(string FirstName, string LastName, string Username, string Email, - string Password, string ConfirmPassword, string PassportNumber) : ICommand; diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommandHandler.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommandHandler.cs deleted file mode 100644 index ff585fa..0000000 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserCommandHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Ardalis.GuardClauses; -using BuildingBlocks.Contracts.EventBus.Messages; -using BuildingBlocks.Core; -using BuildingBlocks.Core.CQRS; -using Identity.Identity.Dtos; -using Identity.Identity.Features.RegisterNewUser.Exceptions; -using Identity.Identity.Models; -using Microsoft.AspNetCore.Identity; - -namespace Identity.Identity.Features.RegisterNewUser.Commands.V1; - -public class RegisterNewUserCommandHandler : ICommandHandler -{ - private readonly IEventDispatcher _eventDispatcher; - private readonly UserManager _userManager; - - public RegisterNewUserCommandHandler(UserManager userManager, - IEventDispatcher eventDispatcher) - { - _userManager = userManager; - _eventDispatcher = eventDispatcher; - } - - public async Task Handle(RegisterNewUserCommand command, - CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var applicationUser = new User() - { - FirstName = command.FirstName, - LastName = command.LastName, - UserName = command.Username, - Email = command.Email, - PasswordHash = command.Password, - PassPortNumber = command.PassportNumber - }; - - var identityResult = await _userManager.CreateAsync(applicationUser, command.Password); - var roleResult = await _userManager.AddToRoleAsync(applicationUser, Constants.Constants.Role.User); - - if (identityResult.Succeeded == false) - throw new RegisterIdentityUserException(string.Join(',', identityResult.Errors.Select(e => e.Description))); - - if (roleResult.Succeeded == false) - throw new RegisterIdentityUserException(string.Join(',', roleResult.Errors.Select(e => e.Description))); - - await _eventDispatcher.SendAsync(new UserCreated(applicationUser.Id, applicationUser.FirstName + " " + applicationUser.LastName, - applicationUser.PassPortNumber),cancellationToken: cancellationToken); - - return new RegisterNewUserResponseDto(applicationUser.Id, applicationUser.FirstName, applicationUser.LastName, - applicationUser.UserName, applicationUser.PassPortNumber); - } -} diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserValidator.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserValidator.cs deleted file mode 100644 index 23fb9bc..0000000 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Commands/V1/RegisterNewUserValidator.cs +++ /dev/null @@ -1,28 +0,0 @@ -using FluentValidation; - -namespace Identity.Identity.Features.RegisterNewUser.Commands.V1; - -public class RegisterNewUserValidator : AbstractValidator -{ - public RegisterNewUserValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.Password).NotEmpty().WithMessage("Please enter the password"); - RuleFor(x => x.ConfirmPassword).NotEmpty().WithMessage("Please enter the confirmation password"); - - RuleFor(x => x).Custom((x, context) => - { - if (x.Password != x.ConfirmPassword) - { - context.AddFailure(nameof(x.Password), "Passwords should match"); - } - }); - - RuleFor(x => x.Username).NotEmpty().WithMessage("Please enter the username"); - RuleFor(x => x.FirstName).NotEmpty().WithMessage("Please enter the first name"); - RuleFor(x => x.LastName).NotEmpty().WithMessage("Please enter the last name"); - RuleFor(x => x.Email).NotEmpty().WithMessage("Please enter the last email") - .EmailAddress().WithMessage("A valid email is required"); - } -} diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Dtos/V1/RegisterNewUserRequestDto.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Dtos/V1/RegisterNewUserRequestDto.cs deleted file mode 100644 index d1efe05..0000000 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Dtos/V1/RegisterNewUserRequestDto.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Identity.Identity.Features.RegisterNewUser.Dtos.V1; - -public record RegisterNewUserRequestDto(string FirstName, string LastName, string Username, string Email, - string Password, string ConfirmPassword, string PassportNumber); diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUser.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUser.cs new file mode 100644 index 0000000..2500df2 --- /dev/null +++ b/src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUser.cs @@ -0,0 +1,88 @@ +namespace Identity.Identity.Features.RegisteringNewUser.V1; + +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Ardalis.GuardClauses; +using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.Core; +using BuildingBlocks.Core.CQRS; +using Dtos; +using Exceptions; +using FluentValidation; +using Microsoft.AspNetCore.Identity; +using Models; + +public record RegisterNewUser(string FirstName, string LastName, string Username, string Email, + string Password, string ConfirmPassword, string PassportNumber) : ICommand; + +internal class RegisterNewUserValidator : AbstractValidator +{ + public RegisterNewUserValidator() + { + RuleFor(x => x.Password).NotEmpty().WithMessage("Please enter the password"); + RuleFor(x => x.ConfirmPassword).NotEmpty().WithMessage("Please enter the confirmation password"); + + RuleFor(x => x).Custom((x, context) => + { + if (x.Password != x.ConfirmPassword) + { + context.AddFailure(nameof(x.Password), "Passwords should match"); + } + }); + + RuleFor(x => x.Username).NotEmpty().WithMessage("Please enter the username"); + RuleFor(x => x.FirstName).NotEmpty().WithMessage("Please enter the first name"); + RuleFor(x => x.LastName).NotEmpty().WithMessage("Please enter the last name"); + RuleFor(x => x.Email).NotEmpty().WithMessage("Please enter the last email") + .EmailAddress().WithMessage("A valid email is required"); + } +} + +internal class RegisterNewUserHandler : ICommandHandler +{ + private readonly IEventDispatcher _eventDispatcher; + private readonly UserManager _userManager; + + public RegisterNewUserHandler(UserManager userManager, + IEventDispatcher eventDispatcher) + { + _userManager = userManager; + _eventDispatcher = eventDispatcher; + } + + public async Task Handle(RegisterNewUser request, + CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var applicationUser = new User() + { + FirstName = request.FirstName, + LastName = request.LastName, + UserName = request.Username, + Email = request.Email, + PasswordHash = request.Password, + PassPortNumber = request.PassportNumber + }; + + var identityResult = await _userManager.CreateAsync(applicationUser, request.Password); + var roleResult = await _userManager.AddToRoleAsync(applicationUser, Constants.Constants.Role.User); + + if (identityResult.Succeeded == false) + { + throw new RegisterIdentityUserException(string.Join(',', identityResult.Errors.Select(e => e.Description))); + } + + if (roleResult.Succeeded == false) + { + throw new RegisterIdentityUserException(string.Join(',', roleResult.Errors.Select(e => e.Description))); + } + + await _eventDispatcher.SendAsync(new UserCreated(applicationUser.Id, applicationUser.FirstName + " " + applicationUser.LastName, + applicationUser.PassPortNumber),cancellationToken: cancellationToken); + + return new RegisterNewUserResponseDto(applicationUser.Id, applicationUser.FirstName, applicationUser.LastName, + applicationUser.UserName, applicationUser.PassPortNumber); + } +} diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Endpoints/V1/RegisterNewUserEndpoint.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUserEndpoint.cs similarity index 72% rename from src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Endpoints/V1/RegisterNewUserEndpoint.cs rename to src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUserEndpoint.cs index 5b6c215..de4e612 100644 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/Endpoints/V1/RegisterNewUserEndpoint.cs +++ b/src/Services/Identity/src/Identity/Identity/Features/RegisteringNewUser/V1/RegisterNewUserEndpoint.cs @@ -1,9 +1,10 @@ +namespace Identity.Identity.Features.RegisteringNewUser.V1; + using System.Threading; 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 Dtos; +using Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; @@ -11,19 +12,18 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Swashbuckle.AspNetCore.Annotations; -namespace Identity.Identity.Features.RegisterNewUser.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; +public record RegisterNewUserRequestDto(string FirstName, string LastName, string Username, string Email, + string Password, string ConfirmPassword, string PassportNumber); public class RegisterNewUserEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/identity/register-user", RegisterNewUser) + builder.MapPost($"{EndpointConfig.BaseApiPath}/identity/register-user", RegisterNewUser) .WithTags("Identity") .WithName("RegisterUser") .WithMetadata(new SwaggerOperationAttribute("Register User", "Register User")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Identity").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Identity").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, @@ -36,13 +36,13 @@ public class RegisterNewUserEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task RegisterNewUser(RegisterNewUserRequestDto request, IMediator mediator, IMapper mapper, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs b/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs index 5582dde..beb1e9f 100644 --- a/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs +++ b/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs @@ -1,9 +1,10 @@ using AutoBogus; -using Identity.Identity.Features.RegisterNewUser.Commands.V1; namespace Integration.Test.Fakes; -public class FakeRegisterNewUserCommand : AutoFaker +using global::Identity.Identity.Features.RegisteringNewUser.V1; + +public class FakeRegisterNewUserCommand : AutoFaker { public FakeRegisterNewUserCommand() { diff --git a/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs b/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs index 6991084..62aa107 100644 --- a/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs +++ b/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs @@ -2,10 +2,11 @@ using Humanizer; using Microsoft.Extensions.Options; using MongoDB.Driver; -using Passenger.Passengers.Models.Reads; namespace Passenger.Data; +using Passengers.Models; + public class PassengerReadDbContext : MongoDbContext { public PassengerReadDbContext(IOptions options) : base(options) diff --git a/src/Services/Passenger/src/Passenger/EventMapper.cs b/src/Services/Passenger/src/Passenger/EventMapper.cs index 5fdcfed..86263a2 100644 --- a/src/Services/Passenger/src/Passenger/EventMapper.cs +++ b/src/Services/Passenger/src/Passenger/EventMapper.cs @@ -1,12 +1,12 @@ using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; using BuildingBlocks.Core.Event; -using Passenger.Identity.Consumers.RegisterNewUser.Events.Domain.V1; -using Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1.Reads; -using Passenger.Passengers.Features.CompleteRegisterPassenger.Events.Domain.V1; namespace Passenger; +using Identity.Consumers.RegisteringNewUser.V1; +using Passengers.Features.CompletingRegisterPassenger.V1; + public sealed class EventMapper : IEventMapper { public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event) diff --git a/src/Services/Passenger/src/Passenger/GrpcServer/Services/PassengerGrpcServices.cs b/src/Services/Passenger/src/Passenger/GrpcServer/Services/PassengerGrpcServices.cs index b2c15e1..693db94 100644 --- a/src/Services/Passenger/src/Passenger/GrpcServer/Services/PassengerGrpcServices.cs +++ b/src/Services/Passenger/src/Passenger/GrpcServer/Services/PassengerGrpcServices.cs @@ -1,11 +1,11 @@ using Grpc.Core; using Mapster; using MediatR; -using Passenger.Passengers.Features.GetPassengerById; -using Passenger.Passengers.Features.GetPassengerById.Queries.V1; namespace Passenger.GrpcServer.Services; +using Passengers.Features.GettingPassengerById.Queries.V1; + public class PassengerGrpcServices : PassengerGrpcService.PassengerGrpcServiceBase { private readonly IMediator _mediator; @@ -17,7 +17,7 @@ public class PassengerGrpcServices : PassengerGrpcService.PassengerGrpcServiceBa public override async Task GetById(GetByIdRequest request, ServerCallContext context) { - var result = await _mediator.Send(new GetPassengerQueryById(request.Id)); + var result = await _mediator.Send(new GetPassengerById(request.Id)); return result.Adapt(); } } diff --git a/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Events/Domain/V1/PassengerCreatedDomainEvent.cs b/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/PassengerCreatedDomainEvent.cs similarity index 54% rename from src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Events/Domain/V1/PassengerCreatedDomainEvent.cs rename to src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/PassengerCreatedDomainEvent.cs index 3aaa1c8..78ec968 100644 --- a/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Events/Domain/V1/PassengerCreatedDomainEvent.cs +++ b/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/PassengerCreatedDomainEvent.cs @@ -1,5 +1,5 @@ -using BuildingBlocks.Core.Event; +namespace Passenger.Identity.Consumers.RegisteringNewUser.V1; -namespace Passenger.Identity.Consumers.RegisterNewUser.Events.Domain.V1; +using BuildingBlocks.Core.Event; public record PassengerCreatedDomainEvent(long Id, string Name, string PassportNumber, bool IsDeleted = false) : IDomainEvent; diff --git a/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Consumes/V1/RegisterNewUserConsumerHandler.cs b/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/RegisterNewUser.cs similarity index 80% rename from src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Consumes/V1/RegisterNewUserConsumerHandler.cs rename to src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/RegisterNewUser.cs index 48c1071..590dd5f 100644 --- a/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisterNewUser/Consumes/V1/RegisterNewUserConsumerHandler.cs +++ b/src/Services/Passenger/src/Passenger/Identity/Consumers/RegisteringNewUser/V1/RegisterNewUser.cs @@ -1,3 +1,5 @@ +namespace Passenger.Identity.Consumers.RegisteringNewUser.V1; + using Ardalis.GuardClauses; using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; @@ -10,20 +12,17 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Passenger.Data; -using Passenger.Identity.Consumers.RegisterNewUser.Events.Domain.V1; -namespace Passenger.Identity.Consumers.RegisterNewUser.Consumes.V1; - -public class RegisterNewUserConsumerHandler : IConsumer +public class RegisterNewUserHandler : IConsumer { private readonly PassengerDbContext _passengerDbContext; private readonly IEventDispatcher _eventDispatcher; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly AppOptions _options; - public RegisterNewUserConsumerHandler(PassengerDbContext passengerDbContext, + public RegisterNewUserHandler(PassengerDbContext passengerDbContext, IEventDispatcher eventDispatcher, - ILogger logger, + ILogger logger, IOptions options) { _passengerDbContext = passengerDbContext; @@ -42,7 +41,9 @@ public class RegisterNewUserConsumerHandler : IConsumer await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber == context.Message.PassportNumber); if (passengerExist) + { return; + } var passenger = Passengers.Models.Passenger.Create(SnowFlakIdGenerator.NewId(), context.Message.Name, context.Message.PassportNumber); diff --git a/src/Services/Passenger/src/Passenger/Passenger.csproj b/src/Services/Passenger/src/Passenger/Passenger.csproj index 8e10d56..afe0565 100644 --- a/src/Services/Passenger/src/Passenger/Passenger.csproj +++ b/src/Services/Passenger/src/Passenger/Passenger.csproj @@ -26,4 +26,10 @@ + + + <_Parameter1>Integration.Test + + + diff --git a/src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerResponseDto.cs b/src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerDto.cs similarity index 87% rename from src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerResponseDto.cs rename to src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerDto.cs index df22ffc..e534d2f 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerResponseDto.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Dtos/PassengerDto.cs @@ -1,6 +1,6 @@ namespace Passenger.Passengers.Dtos; -public record PassengerResponseDto +public record PassengerDto { public long Id { get; init; } public string Name { get; init; } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Exceptions/PassengerAlreadyExist.cs b/src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerAlreadyExist.cs similarity index 70% rename from src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Exceptions/PassengerAlreadyExist.cs rename to src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerAlreadyExist.cs index 9584f8d..62a46a2 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Exceptions/PassengerAlreadyExist.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerAlreadyExist.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Passenger.Passengers.Exceptions; -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Exceptions; +using BuildingBlocks.Exception; public class PassengerNotExist : BadRequestException { diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Exceptions/PassengerNotFoundException.cs b/src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerNotFoundException.cs similarity index 74% rename from src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Exceptions/PassengerNotFoundException.cs rename to src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerNotFoundException.cs index ff3faaf..845d876 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Exceptions/PassengerNotFoundException.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Exceptions/PassengerNotFoundException.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Exception; +namespace Passenger.Passengers.Exceptions; -namespace Passenger.Passengers.Features.GetPassengerById.Exceptions; +using BuildingBlocks.Exception; public class PassengerNotFoundException: NotFoundException { diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommand.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommand.cs deleted file mode 100644 index 6eee73f..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommand.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using BuildingBlocks.Core.Event; -using BuildingBlocks.IdsGenerator; -using Passenger.Passengers.Dtos; - -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1; - -public record CompleteRegisterPassengerCommand(string PassportNumber, Enums.PassengerType PassengerType, int Age) : ICommand, IInternalCommand -{ - public long Id { get; init; } = SnowFlakIdGenerator.NewId(); -} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandHandler.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandHandler.cs deleted file mode 100644 index 299fae5..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using MapsterMapper; -using Microsoft.EntityFrameworkCore; -using Passenger.Data; -using Passenger.Passengers.Dtos; -using Passenger.Passengers.Features.CompleteRegisterPassenger.Exceptions; - -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1; - -public class CompleteRegisterPassengerCommandHandler : ICommandHandler -{ - private readonly IMapper _mapper; - private readonly PassengerDbContext _passengerDbContext; - - public CompleteRegisterPassengerCommandHandler(IMapper mapper, PassengerDbContext passengerDbContext) - { - _mapper = mapper; - _passengerDbContext = passengerDbContext; - } - - public async Task Handle(CompleteRegisterPassengerCommand command, CancellationToken cancellationToken) - { - Guard.Against.Null(command, nameof(command)); - - var passenger = await _passengerDbContext.Passengers.AsNoTracking().SingleOrDefaultAsync( - x => x.PassportNumber == command.PassportNumber, cancellationToken); - - if (passenger is null) - throw new PassengerNotExist(); - - var passengerEntity = passenger.CompleteRegistrationPassenger(passenger.Id, passenger.Name, passenger.PassportNumber, command.PassengerType, command.Age); - - var updatePassenger = _passengerDbContext.Passengers.Update(passengerEntity); - - return _mapper.Map(updatePassenger.Entity); - } -} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandValidator.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandValidator.cs deleted file mode 100644 index 4ae3cf9..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/CompleteRegisterPassengerCommandValidator.cs +++ /dev/null @@ -1,20 +0,0 @@ -using FluentValidation; - -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1; - -public class CompleteRegisterPassengerCommandValidator : AbstractValidator -{ - public CompleteRegisterPassengerCommandValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.PassportNumber).NotNull().WithMessage("The PassportNumber is required!"); - RuleFor(x => x.Age).GreaterThan(0).WithMessage("The Age must be greater than 0!"); - RuleFor(x => x.PassengerType).Must(p => p.GetType().IsEnum && - p == Enums.PassengerType.Baby || - p == Enums.PassengerType.Female || - p == Enums.PassengerType.Male || - p == Enums.PassengerType.Unknown) - .WithMessage("PassengerType must be Male, Female, Baby or Unknown"); - } -} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommand.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommand.cs deleted file mode 100644 index bca3943..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommand.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BuildingBlocks.Core.Event; - -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1.Reads; - -public record CompleteRegisterPassengerMongoCommand(long Id, string PassportNumber, string Name, - Enums.PassengerType PassengerType, int Age, bool IsDeleted) : InternalCommand; diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Dtos/V1/CompleteRegisterPassengerRequestDto.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Dtos/V1/CompleteRegisterPassengerRequestDto.cs deleted file mode 100644 index 6b7b227..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Dtos/V1/CompleteRegisterPassengerRequestDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Dtos.V1; - -public record CompleteRegisterPassengerRequestDto(string PassportNumber, Enums.PassengerType PassengerType, int Age); diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassenger.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassenger.cs new file mode 100644 index 0000000..39740a9 --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassenger.cs @@ -0,0 +1,65 @@ +namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1; + +using Ardalis.GuardClauses; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using Exceptions; +using FluentValidation; +using MapsterMapper; +using Microsoft.EntityFrameworkCore; +using Passenger.Data; +using Passenger.Passengers.Dtos; + +public record CompleteRegisterPassenger + (string PassportNumber, Enums.PassengerType PassengerType, int Age) : ICommand, IInternalCommand +{ + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); +} + +internal class CompleteRegisterPassengerValidator : AbstractValidator +{ + public CompleteRegisterPassengerValidator() + { + RuleFor(x => x.PassportNumber).NotNull().WithMessage("The PassportNumber is required!"); + RuleFor(x => x.Age).GreaterThan(0).WithMessage("The Age must be greater than 0!"); + RuleFor(x => x.PassengerType).Must(p => p.GetType().IsEnum && + p == Enums.PassengerType.Baby || + p == Enums.PassengerType.Female || + p == Enums.PassengerType.Male || + p == Enums.PassengerType.Unknown) + .WithMessage("PassengerType must be Male, Female, Baby or Unknown"); + } +} + +internal class CompleteRegisterPassengerCommandHandler : ICommandHandler +{ + private readonly IMapper _mapper; + private readonly PassengerDbContext _passengerDbContext; + + public CompleteRegisterPassengerCommandHandler(IMapper mapper, PassengerDbContext passengerDbContext) + { + _mapper = mapper; + _passengerDbContext = passengerDbContext; + } + + public async Task Handle(CompleteRegisterPassenger request, CancellationToken cancellationToken) + { + Guard.Against.Null(request, nameof(request)); + + var passenger = await _passengerDbContext.Passengers.AsNoTracking().SingleOrDefaultAsync( + x => x.PassportNumber == request.PassportNumber, cancellationToken); + + if (passenger is null) + { + throw new PassengerNotExist(); + } + + var passengerEntity = passenger.CompleteRegistrationPassenger(passenger.Id, passenger.Name, + passenger.PassportNumber, request.PassengerType, request.Age); + + var updatePassenger = _passengerDbContext.Passengers.Update(passengerEntity); + + return _mapper.Map(updatePassenger.Entity); + } +} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Endpoints/V1/CompleteRegisterPassengerEndpoint.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerEndpoint.cs similarity index 73% rename from src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Endpoints/V1/CompleteRegisterPassengerEndpoint.cs rename to src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerEndpoint.cs index 9b02ae4..834a8de 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Endpoints/V1/CompleteRegisterPassengerEndpoint.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerEndpoint.cs @@ -1,33 +1,32 @@ +namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1; + using BuildingBlocks.Web; +using Hellang.Middleware.ProblemDetails; using MapsterMapper; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; 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; - -using Hellang.Middleware.ProblemDetails; +public record CompleteRegisterPassengerRequestDto(string PassportNumber, Enums.PassengerType PassengerType, int Age); public class CompleteRegisterPassengerEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapPost($"{EndpointConfig.BaseApiPath}/passenger/complete-registration", CompleteRegisterPassenger) + builder.MapPost($"{EndpointConfig.BaseApiPath}/passenger/complete-registration", CompleteRegisterPassenger) .RequireAuthorization() .WithTags("Passenger") .WithName("CompleteRegisterPassenger") .WithMetadata(new SwaggerOperationAttribute("Complete Register Passenger", "Complete Register Passenger")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Passenger").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "Register Passenger Completed", - typeof(PassengerResponseDto))) + typeof(PassengerDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -40,13 +39,13 @@ public class CompleteRegisterPassengerEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task CompleteRegisterPassenger(CompleteRegisterPassengerRequestDto request, IMapper mapper, IMediator mediator, CancellationToken cancellationToken) { - var command = mapper.Map(request); + var command = mapper.Map(request); var result = await mediator.Send(command, cancellationToken); diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommandHandler.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerMongo.cs similarity index 73% rename from src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommandHandler.cs rename to src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerMongo.cs index a19ec74..a7a0b9a 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Commands/V1/Reads/CompleteRegisterPassengerMongoCommandHandler.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/CompleteRegisterPassengerMongo.cs @@ -1,20 +1,25 @@ -using Ardalis.GuardClauses; +namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1; + +using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using MapsterMapper; using MediatR; +using Models; using MongoDB.Driver; using MongoDB.Driver.Linq; using Passenger.Data; -using Passenger.Passengers.Models.Reads; -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1.Reads; +public record CompleteRegisterPassengerMongoCommand(long Id, string PassportNumber, string Name, + Enums.PassengerType PassengerType, int Age, bool IsDeleted) : InternalCommand; -public class CompleteRegisterPassengerMongoCommandHandler : ICommandHandler + +internal class CompleteRegisterPassengerMongoHandler : ICommandHandler { private readonly PassengerReadDbContext _passengerReadDbContext; private readonly IMapper _mapper; - public CompleteRegisterPassengerMongoCommandHandler( + public CompleteRegisterPassengerMongoHandler( PassengerReadDbContext passengerReadDbContext, IMapper mapper) { @@ -22,11 +27,11 @@ public class CompleteRegisterPassengerMongoCommandHandler : ICommandHandler Handle(CompleteRegisterPassengerMongoCommand command, CancellationToken cancellationToken) + public async Task Handle(CompleteRegisterPassengerMongoCommand request, CancellationToken cancellationToken) { - Guard.Against.Null(command, nameof(command)); + Guard.Against.Null(request, nameof(request)); - var passengerReadModel = _mapper.Map(command); + var passengerReadModel = _mapper.Map(request); var passenger = await _passengerReadDbContext.Passenger.AsQueryable() .FirstOrDefaultAsync(x => x.PassengerId == passengerReadModel.PassengerId && !x.IsDeleted, cancellationToken); diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Events/Domain/V1/PassengerRegistrationCompletedDomainEvent.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/PassengerRegistrationCompletedDomainEvent.cs similarity index 72% rename from src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Events/Domain/V1/PassengerRegistrationCompletedDomainEvent.cs rename to src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/PassengerRegistrationCompletedDomainEvent.cs index 885224e..1adee6f 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Events/Domain/V1/PassengerRegistrationCompletedDomainEvent.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompletingRegisterPassenger/V1/PassengerRegistrationCompletedDomainEvent.cs @@ -1,6 +1,6 @@ -using BuildingBlocks.Core.Event; +namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1; -namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Events.Domain.V1; +using BuildingBlocks.Core.Event; public record PassengerRegistrationCompletedDomainEvent(long Id, string Name, string PassportNumber, Enums.PassengerType PassengerType, int Age, bool IsDeleted = false) : IDomainEvent; diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryById.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryById.cs deleted file mode 100644 index c53712e..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryById.cs +++ /dev/null @@ -1,6 +0,0 @@ -using BuildingBlocks.Core.CQRS; -using Passenger.Passengers.Dtos; - -namespace Passenger.Passengers.Features.GetPassengerById.Queries.V1; - -public record GetPassengerQueryById(long Id) : IQuery; diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdHandler.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdHandler.cs deleted file mode 100644 index 320b7e0..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdHandler.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Ardalis.GuardClauses; -using BuildingBlocks.Core.CQRS; -using MapsterMapper; -using Microsoft.EntityFrameworkCore; -using Passenger.Data; -using Passenger.Passengers.Dtos; -using Passenger.Passengers.Features.GetPassengerById.Exceptions; - -namespace Passenger.Passengers.Features.GetPassengerById.Queries.V1; - -public class GetPassengerQueryByIdHandler : IQueryHandler -{ - private readonly PassengerDbContext _passengerDbContext; - private readonly IMapper _mapper; - - public GetPassengerQueryByIdHandler(IMapper mapper, PassengerDbContext passengerDbContext) - { - _mapper = mapper; - _passengerDbContext = passengerDbContext; - } - - public async Task Handle(GetPassengerQueryById query, CancellationToken cancellationToken) - { - Guard.Against.Null(query, nameof(query)); - - var passenger = - await _passengerDbContext.Passengers.SingleOrDefaultAsync(x => x.Id == query.Id, cancellationToken); - - if (passenger is null) - throw new PassengerNotFoundException(); - - return _mapper.Map(passenger!); - } -} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdValidator.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdValidator.cs deleted file mode 100644 index 48d9f26..0000000 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Queries/V1/GetPassengerQueryByIdValidator.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentValidation; - -namespace Passenger.Passengers.Features.GetPassengerById.Queries.V1; - -public class GetPassengerQueryByIdValidator: AbstractValidator -{ - public GetPassengerQueryByIdValidator() - { - CascadeMode = CascadeMode.Stop; - - RuleFor(x => x.Id).NotNull().WithMessage("Id is required!"); - } -} \ No newline at end of file diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerById.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerById.cs new file mode 100644 index 0000000..db6986e --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerById.cs @@ -0,0 +1,47 @@ +namespace Passenger.Passengers.Features.GettingPassengerById.Queries.V1; + +using BuildingBlocks.Core.CQRS; +using Data; +using Dtos; +using FluentValidation; +using MapsterMapper; +using Microsoft.EntityFrameworkCore; +using Ardalis.GuardClauses; +using Exceptions; + +public record GetPassengerById(long Id) : IQuery; + +internal class GetPassengerByIdValidator: AbstractValidator +{ + public GetPassengerByIdValidator() + { + RuleFor(x => x.Id).NotNull().WithMessage("Id is required!"); + } +} + +internal class GetPassengerByIdHandler : IQueryHandler +{ + private readonly PassengerDbContext _passengerDbContext; + private readonly IMapper _mapper; + + public GetPassengerByIdHandler(IMapper mapper, PassengerDbContext passengerDbContext) + { + _mapper = mapper; + _passengerDbContext = passengerDbContext; + } + + public async Task Handle(GetPassengerById query, CancellationToken cancellationToken) + { + Guard.Against.Null(query, nameof(query)); + + var passenger = + await _passengerDbContext.Passengers.SingleOrDefaultAsync(x => x.Id == query.Id, cancellationToken); + + if (passenger is null) + { + throw new PassengerNotFoundException(); + } + + return _mapper.Map(passenger!); + } +} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Endpoints/V1/GetPassengerByIdEndpoint.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerByIdEndpoint.cs similarity index 71% rename from src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Endpoints/V1/GetPassengerByIdEndpoint.cs rename to src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerByIdEndpoint.cs index ddbee17..986d153 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/GetPassengerById/Endpoints/V1/GetPassengerByIdEndpoint.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/GettingPassengerById/Queries/V1/GetPassengerByIdEndpoint.cs @@ -1,33 +1,29 @@ +namespace Passenger.Passengers.Features.GettingPassengerById.Queries.V1; + using BuildingBlocks.Web; +using Hellang.Middleware.ProblemDetails; 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.GetPassengerById.Queries.V1; using Swashbuckle.AspNetCore.Annotations; -namespace Passenger.Passengers.Features.GetPassengerById.Endpoints.V1; - -using Hellang.Middleware.ProblemDetails; - public class GetPassengerByIdEndpoint : IMinimalEndpoint { - public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder endpoints) + public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) { - endpoints.MapGet($"{EndpointConfig.BaseApiPath}/passenger/{{id}}", GetById) + builder.MapGet($"{EndpointConfig.BaseApiPath}/passenger/{{id}}", GetById) .RequireAuthorization() .WithTags("Passenger") .WithName("GetPassengerById") .WithMetadata(new SwaggerOperationAttribute("Get Passenger By Id", "Get Passenger By Id")) - .WithApiVersionSet(endpoints.NewApiVersionSet("Passenger").Build()) + .WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build()) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status200OK, "GetPassengerById", - typeof(PassengerResponseDto))) + typeof(PassengerDto))) .WithMetadata( new SwaggerResponseAttribute( StatusCodes.Status400BadRequest, @@ -40,12 +36,12 @@ public class GetPassengerByIdEndpoint : IMinimalEndpoint typeof(StatusCodeProblemDetails))) .HasApiVersion(1.0); - return endpoints; + return builder; } private async Task GetById(long id, IMediator mediator, CancellationToken cancellationToken) { - var result = await mediator.Send(new GetPassengerQueryById(id), cancellationToken); + var result = await mediator.Send(new GetPassengerById(id), cancellationToken); return Results.Ok(result); } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs index 59dcd9b..501183c 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs @@ -1,15 +1,11 @@ -using AutoMapper; -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; +using CompletingRegisterPassenger.V1; +using Models; + public class PassengerMappings : IRegister { public void Register(TypeAdapterConfig config) @@ -18,7 +14,7 @@ public class PassengerMappings : IRegister .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) .Map(d => d.PassengerId, s => s.Id); - config.NewConfig() - .ConstructUsing(x => new CompleteRegisterPassengerCommand(x.PassportNumber, x.PassengerType, x.Age)); + config.NewConfig() + .ConstructUsing(x => new CompleteRegisterPassenger(x.PassportNumber, x.PassengerType, x.Age)); } } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs b/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs index 70913ad..79258dd 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs @@ -1,9 +1,10 @@ using BuildingBlocks.Core.Model; -using Passenger.Identity.Consumers.RegisterNewUser.Events.Domain.V1; -using Passenger.Passengers.Features.CompleteRegisterPassenger.Events.Domain.V1; namespace Passenger.Passengers.Models; +using Features.CompletingRegisterPassenger.V1; +using Identity.Consumers.RegisteringNewUser.V1; + public record Passenger : Aggregate { public Passenger CompleteRegistrationPassenger(long id, string name, string passportNumber, Enums.PassengerType passengerType, int age, bool isDeleted = false) diff --git a/src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs b/src/Services/Passenger/src/Passenger/Passengers/Models/PassengerReadModel.cs similarity index 87% rename from src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs rename to src/Services/Passenger/src/Passenger/Passengers/Models/PassengerReadModel.cs index 37f71ab..a9f24a2 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Models/PassengerReadModel.cs @@ -1,4 +1,4 @@ -namespace Passenger.Passengers.Models.Reads; +namespace Passenger.Passengers.Models; public class PassengerReadModel { diff --git a/src/Services/Passenger/tests/IntegrationTest/Fakes/FakeCompleteRegisterPassengerCommand.cs b/src/Services/Passenger/tests/IntegrationTest/Fakes/FakeCompleteRegisterPassengerCommand.cs index 7ee8600..4840817 100644 --- a/src/Services/Passenger/tests/IntegrationTest/Fakes/FakeCompleteRegisterPassengerCommand.cs +++ b/src/Services/Passenger/tests/IntegrationTest/Fakes/FakeCompleteRegisterPassengerCommand.cs @@ -1,13 +1,12 @@ using AutoBogus; using BuildingBlocks.IdsGenerator; using Passenger.Passengers.Enums; -using Passenger.Passengers.Features.CompleteRegisterPassenger; -using Passenger.Passengers.Features.CompleteRegisterPassenger.Commands.V1; -using Passenger.Passengers.Models; namespace Integration.Test.Fakes; -public sealed class FakeCompleteRegisterPassengerCommand : AutoFaker +using global::Passenger.Passengers.Features.CompletingRegisterPassenger.V1; + +public sealed class FakeCompleteRegisterPassengerCommand : AutoFaker { public FakeCompleteRegisterPassengerCommand(string passportNumber) { diff --git a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs index 71a168d..b41513d 100644 --- a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs +++ b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs @@ -5,11 +5,12 @@ using Integration.Test.Fakes; using Passenger; using Passenger.Api; using Passenger.Data; -using Passenger.Passengers.Features.GetPassengerById.Queries.V1; using Xunit; namespace Integration.Test.Passenger.Features; +using global::Passenger.Passengers.Features.GettingPassengerById.Queries.V1; + public class GetPassengerByIdTests : PassengerIntegrationTestBase { public GetPassengerByIdTests( @@ -26,7 +27,7 @@ public class GetPassengerByIdTests : PassengerIntegrationTestBase var passengerEntity = FakePassengerCreated.Generate(userCreated); await Fixture.InsertAsync(passengerEntity); - var query = new GetPassengerQueryById(passengerEntity.Id); + var query = new GetPassengerById(passengerEntity.Id); // Act var response = await Fixture.SendAsync(query);