From a0baae2e08c5d4a781a651000926c480bcd77b4f Mon Sep 17 00:00:00 2001 From: paula_rodriguezslash <paula.rodriguez@slashmobility.com> Date: Sun, 7 Apr 2024 12:55:06 +0100 Subject: [PATCH] first try updated the vals to ask flight service --- .../Data/DTO/BookingDTO.cs | 4 ++ .../Data/DTO/FlightCapacityDTO.cs | 7 +++ .../FlightBooking.Service/Data/Enums.cs | 8 ++++ .../Data/Models/Booking.cs | 1 + .../FlightBooking.Service.csproj | 1 + .../Services/BookingOrderService.cs | 44 ++++++++++++++++++- .../Services/FlightService.cs | 21 ++++++++- .../Services/Interfaces/IFlightService.cs | 1 + .../FlightBooking.Service/Startup.cs | 3 ++ 9 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 BookingService/FlightBooking.Service/Data/DTO/FlightCapacityDTO.cs diff --git a/BookingService/FlightBooking.Service/Data/DTO/BookingDTO.cs b/BookingService/FlightBooking.Service/Data/DTO/BookingDTO.cs index 8a93333..eaea2ea 100644 --- a/BookingService/FlightBooking.Service/Data/DTO/BookingDTO.cs +++ b/BookingService/FlightBooking.Service/Data/DTO/BookingDTO.cs @@ -1,4 +1,6 @@ using System.ComponentModel.DataAnnotations; +using FlightBooking.Service.Data; + namespace FlightBooking.Service.Data.DTO { @@ -52,5 +54,7 @@ namespace FlightBooking.Service.Data.DTO public int OutboundFareId { get; set; } //We are keeping Fare per booking to allow flexibility e.g Adult in Economy and Child in Business class public int? ReturnFareId { get; set; } + + public ClassType ClassType { get; set; } } } \ No newline at end of file diff --git a/BookingService/FlightBooking.Service/Data/DTO/FlightCapacityDTO.cs b/BookingService/FlightBooking.Service/Data/DTO/FlightCapacityDTO.cs new file mode 100644 index 0000000..8de7630 --- /dev/null +++ b/BookingService/FlightBooking.Service/Data/DTO/FlightCapacityDTO.cs @@ -0,0 +1,7 @@ +namespace FlightBooking.Service.Data.DTO{ + public class FlightCapacityDTO + { + public int EconomyCapacity { get; set; } + public int BusinessCapacity { get; set; } + } +} diff --git a/BookingService/FlightBooking.Service/Data/Enums.cs b/BookingService/FlightBooking.Service/Data/Enums.cs index 15a8a62..3101df5 100644 --- a/BookingService/FlightBooking.Service/Data/Enums.cs +++ b/BookingService/FlightBooking.Service/Data/Enums.cs @@ -23,6 +23,7 @@ EntityExist, Unprocessable, Unauthorized, + FullCapacity } public enum SortOrder @@ -37,4 +38,11 @@ Confirmed, Paid } + + public enum ClassType + { + BUSINESS = 0, + ECONOMY = 1 + } + } \ No newline at end of file diff --git a/BookingService/FlightBooking.Service/Data/Models/Booking.cs b/BookingService/FlightBooking.Service/Data/Models/Booking.cs index 315ea18..085709f 100644 --- a/BookingService/FlightBooking.Service/Data/Models/Booking.cs +++ b/BookingService/FlightBooking.Service/Data/Models/Booking.cs @@ -32,5 +32,6 @@ namespace FlightBooking.Service.Data.Models //one to one to for seats. one booking at most one seat public ReservedSeat? ReservedSeat { get; set; } + public ClassType ClassType { get; set; } } } \ No newline at end of file diff --git a/BookingService/FlightBooking.Service/FlightBooking.Service.csproj b/BookingService/FlightBooking.Service/FlightBooking.Service.csproj index 217d79c..0f54507 100644 --- a/BookingService/FlightBooking.Service/FlightBooking.Service.csproj +++ b/BookingService/FlightBooking.Service/FlightBooking.Service.csproj @@ -27,6 +27,7 @@ </PackageReference> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.1" /> <PackageReference Include="MySqlConnector" Version="2.3.5" /> + <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="NLog.Web.AspNetCore" Version="5.3.8" /> <PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="7.3.1" /> diff --git a/BookingService/FlightBooking.Service/Services/BookingOrderService.cs b/BookingService/FlightBooking.Service/Services/BookingOrderService.cs index f1d70bd..57674c3 100644 --- a/BookingService/FlightBooking.Service/Services/BookingOrderService.cs +++ b/BookingService/FlightBooking.Service/Services/BookingOrderService.cs @@ -12,21 +12,25 @@ namespace FlightBooking.Service.Services { private readonly IGenericRepository<BookingOrder> _orderRepo; private readonly IGenericRepository<FlightInformation> _flightRepo; + private readonly IGenericRepository<Booking> _bookingRepo; private readonly IGenericRepository<FlightFare> _flightFareRepo; private readonly IStripeService _stripeService; + private readonly IFlightService _flightService; private readonly ILogger<BookingOrderService> _logger; private List<FlightFare> allFlightFares = new List<FlightFare>(); //declare once so we can use it throughout - public BookingOrderService(IGenericRepository<BookingOrder> orderRepo, IGenericRepository<FlightInformation> flightRepo, - IGenericRepository<FlightFare> flightFareRepo, IStripeService stripeService, ILogger<BookingOrderService> logger) + public BookingOrderService(IGenericRepository<BookingOrder> orderRepo, IGenericRepository<FlightInformation> flightRepo, IGenericRepository<Booking> bookingRepo, + IGenericRepository<FlightFare> flightFareRepo, IStripeService stripeService, ILogger<BookingOrderService> logger, IFlightService flightService) { _orderRepo = orderRepo; _flightRepo = flightRepo; + _bookingRepo = bookingRepo; _flightFareRepo = flightFareRepo; _stripeService = stripeService; _logger = logger; + _flightService = flightService; } public async Task<ServiceResponse<BookingResponseDTO?>> CreateBookingOrderAsync(BookingOrderDTO order) @@ -108,6 +112,42 @@ namespace FlightBooking.Service.Services return new ServiceResponse<BookingResponseDTO?>(null, InternalCode.Unprocessable, "The number of flights exceed number of available seats"); } + + // Retrieve flight information to get the flight ID for capacity check + var flightInfo = await _flightRepo.Query().FirstOrDefaultAsync(f => f.FlightNumber == order.OutboundFlightNumber); + if (flightInfo == null) + { + // Handle flight not found scenario + return new ServiceResponse<BookingResponseDTO?>(null, InternalCode.Unprocessable, "Flight not found."); + } + + // Retrieve flight capacity + var flightCapacity = await _flightService.GetFlightCapacityAsync(flightInfo.Id); + if (flightCapacity == null) + { + // Handle capacity fetch error + return new ServiceResponse<BookingResponseDTO?>(null, InternalCode.Unprocessable, "Unable to retrieve flight capacity."); + } + + // Calculate existing bookings for each class type + var existingBookings = await _bookingRepo.Query().Where(b => b.FlightId == flightInfo.Id).ToListAsync(); + int existingEconomyBookings = existingBookings.Count(b => b.ClassType == ClassType.ECONOMY); + int existingBusinessBookings = existingBookings.Count(b => b.ClassType == ClassType.BUSINESS); + + // Compare against capacity + foreach (var bookingRequest in order.Bookings) + { + if (bookingRequest.ClassType == ClassType.Economy && existingEconomyBookings >= flightCapacity.EconomyCapacity) + { + return new ServiceResponse<BookingResponseDTO?>(null, InternalCode.FullCapacity, "Economy class is fully booked."); + } + if (bookingRequest.ClassType == ClassType.Business && existingBusinessBookings >= flightCapacity.BusinessCapacity) + { + return new ServiceResponse<BookingResponseDTO?>(null, InternalCode.FullCapacity, "Business class is fully booked."); + } + } + + //if all checks passed, lets reduce number of available seats. //If Checks are passed, set status as InProgress and reduce available seats to avoid overbooking the flight //We hold a seat for N mins max(N is set in config). Use a background job to return UnbookedSeats back into the Pool diff --git a/BookingService/FlightBooking.Service/Services/FlightService.cs b/BookingService/FlightBooking.Service/Services/FlightService.cs index f7f4e13..d0f9e65 100644 --- a/BookingService/FlightBooking.Service/Services/FlightService.cs +++ b/BookingService/FlightBooking.Service/Services/FlightService.cs @@ -5,6 +5,8 @@ using FlightBooking.Service.Data.Models; using FlightBooking.Service.Data.Repository; using FlightBooking.Service.Services.Interfaces; using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; + namespace FlightBooking.Service.Services { @@ -13,11 +15,13 @@ namespace FlightBooking.Service.Services { private readonly IGenericRepository<FlightInformation> _flightRepo; private readonly IMapper _mapper; + private readonly HttpClient _httpClient; - public FlightService(IGenericRepository<FlightInformation> flightRepo, IMapper mapper) + public FlightService(IGenericRepository<FlightInformation> flightRepo, IMapper mapper, IHttpClientFactory httpClientFactory) { _mapper = mapper; _flightRepo = flightRepo; + _httpClient = httpClientFactory.CreateClient("FlightServiceClient"); } public async Task<ServiceResponse<FlightInformationDTO?>> GetFlightInformationAsync(string flightNumber) @@ -43,5 +47,20 @@ namespace FlightBooking.Service.Services return new ServiceResponse<string>(string.Empty, (InternalCode)result); } + public async Task<FlightCapacityDTO> GetFlightCapacityAsync(int flightId) + { + var response = await _httpClient.GetAsync($"api/Flight/{flightId}/capacity"); + response.EnsureSuccessStatusCode(); + + var content = await response.Content.ReadAsStringAsync(); + var capacity = JsonConvert.DeserializeObject<FlightCapacityDTO>(content); + + if (capacity == null) + { + throw new InvalidOperationException("The flight capacity data could not be retrieved."); + } + + return capacity; + } } } \ No newline at end of file diff --git a/BookingService/FlightBooking.Service/Services/Interfaces/IFlightService.cs b/BookingService/FlightBooking.Service/Services/Interfaces/IFlightService.cs index 290f5d2..5e54b08 100644 --- a/BookingService/FlightBooking.Service/Services/Interfaces/IFlightService.cs +++ b/BookingService/FlightBooking.Service/Services/Interfaces/IFlightService.cs @@ -10,6 +10,7 @@ namespace FlightBooking.Service.Services.Interfaces /// <param name="flightNumber"></param> /// <returns></returns> Task<ServiceResponse<FlightInformationDTO?>> GetFlightInformationAsync(string flightNumber); + Task<FlightCapacityDTO> GetFlightCapacityAsync(int flightId); /// <summary> /// Updates the flight capacity diff --git a/BookingService/FlightBooking.Service/Startup.cs b/BookingService/FlightBooking.Service/Startup.cs index 540cfff..68702c8 100644 --- a/BookingService/FlightBooking.Service/Startup.cs +++ b/BookingService/FlightBooking.Service/Startup.cs @@ -3,6 +3,7 @@ using FlightBooking.Service.Data.Configs; using FlightBooking.Service.Data.Repository; using FlightBooking.Service.Middleware; using FlightBooking.Service.Services; +using FlightBooking.Service.Services.Interfaces; // Adjust this to the correct namespace where IFlightService is located using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; @@ -93,6 +94,8 @@ namespace FlightBooking.Service //Add our custom services services.AddRepository(); services.AddServices(); + services.AddScoped<IFlightService, FlightService>(); + services.AddEndpointsApiExplorer(); services.AddSwaggerGen(options => -- GitLab