public async Task <Result <AccommodationBookingInfo> > Execute(AccommodationBookingRequest request, Func <Task <Result <AccommodationBookingInfo> > > bookingFunction, string languageCode) { return(await _functionExecutor.Execute(executingFunction : async() => await bookingFunction().Tap(SaveEvaluationTokenMapping), getResultFunction : () => GetBookingByEvaluationToken(request.EvaluationToken, languageCode), operationKey : request.EvaluationToken, maximumDuration : MaximumBookingDuration)); Task SaveEvaluationTokenMapping(AccommodationBookingInfo bookingInfo) { var key = GetEvaluationTokenKey(request.EvaluationToken); return(_flow.SetAsync(key, bookingInfo.BookingDetails.ReferenceCode, EvaluationTokenMappingLifeTime)); } async Task <Result <AccommodationBookingInfo> > GetBookingByEvaluationToken(string evaluationToken, string languageCode) { var key = GetEvaluationTokenKey(request.EvaluationToken); var referenceCode = await _flow.GetAsync <string>(key, EvaluationTokenMappingLifeTime); if (referenceCode is null) { return(Result.Failure <AccommodationBookingInfo>("Could not find booking reference code")); } return(await _bookingInfoService.GetAccommodationBookingInfo(referenceCode, languageCode)); } string GetEvaluationTokenKey(string evaluationToken) => _flow.BuildKey(nameof(IdempotentBookingExecutor), evaluationToken); }
public async Task <Result <Booking> > Register(AccommodationBookingRequest request, AgentContext agent, string languageCode) { return(await _validationService.Validate(request.ClientReferenceCode, agent) .Bind(GetCachedAvailability) .Bind(RegisterBooking)); async Task <Result <BookingAvailabilityInfo> > GetCachedAvailability() => await _bookingEvaluationStorage.Get(request.SearchId, request.AccommodationId, request.RoomContractSetId); async Task <Result <Booking> > RegisterBooking(BookingAvailabilityInfo availabilityInfo) { var booking = await _bookingRegistrationService.Register(bookingRequest : request.ToEdoModel(), availabilityInfo : availabilityInfo, paymentMethod : PaymentTypes.VirtualAccount, agentContext : agent, languageCode : languageCode); return(booking.IsSuccess ? booking.Value.FromEdoModels() : Result.Failure <Booking>(booking.Error)); } }
public Task <Result <AccommodationBookingInfo> > BookByAccount(AccommodationBookingRequest bookingRequest, AgentContext agentContext, string languageCode, string clientIp) { Baggage.AddSearchId(bookingRequest.SearchId); _logger.LogBookingByAccountStarted(bookingRequest.HtId); return(GetCachedAvailability(bookingRequest) .Ensure(IsPaymentTypeAllowed, "Payment type is not allowed") .Bind(RegisterBooking) .Check(GenerateInvoice) .CheckIf(IsDeadlinePassed, ChargeMoney) .Bind(SendSupplierRequest) .Bind(GetAccommodationBookingInfo) .Finally(WriteLog)); bool IsDeadlinePassed(Data.Bookings.Booking booking) => booking.GetPayDueDate() <= _dateTimeProvider.UtcToday(); async Task <Result <BookingAvailabilityInfo> > GetCachedAvailability(AccommodationBookingRequest bookingRequest) => await _bookingEvaluationStorage.Get(bookingRequest.SearchId, bookingRequest.HtId, bookingRequest.RoomContractSetId); bool IsPaymentTypeAllowed(BookingAvailabilityInfo availabilityInfo) => availabilityInfo.AvailablePaymentTypes.Contains(PaymentTypes.VirtualAccount); Task <Result <Data.Bookings.Booking> > RegisterBooking(BookingAvailabilityInfo bookingAvailability) => _registrationService.Register(bookingRequest, bookingAvailability, PaymentTypes.VirtualAccount, agentContext, languageCode); async Task <Result> ChargeMoney(Data.Bookings.Booking booking) => await _accountPaymentService.Charge(booking, agentContext.ToApiCaller()); Task <Result> GenerateInvoice(Data.Bookings.Booking booking) => _documentsService.GenerateInvoice(booking); async Task <Result <Booking> > SendSupplierRequest(Data.Bookings.Booking booking) { var refreshedBooking = await _recordManager.Get(booking.ReferenceCode); return(await _requestExecutor.Execute(refreshedBooking.Value, agentContext, languageCode)); } Task <Result <AccommodationBookingInfo> > GetAccommodationBookingInfo(EdoContracts.Accommodations.Booking details) => _bookingInfoService.GetAccommodationBookingInfo(details.ReferenceCode, languageCode); Result <AccommodationBookingInfo> WriteLog(Result <AccommodationBookingInfo> result) => LoggerUtils.WriteLogByResult(result, () => _logger.LogBookingByAccountSuccess(result.Value.BookingDetails.ReferenceCode), () => _logger.LogBookingByAccountFailure(bookingRequest.HtId, result.Error)); }
public Task <Result <AccommodationBookingInfo> > Book(AccommodationBookingRequest bookingRequest, AgentContext agentContext, string languageCode, string clientIp) { Baggage.AddSearchId(bookingRequest.SearchId); _logger.LogBookingByOfflinePaymentStarted(bookingRequest.HtId); return(GetCachedAvailability(bookingRequest) .Ensure(IsPaymentTypeAllowed, "Payment type is not allowed") .Ensure(IsDeadlineNotPassed, "Deadline already passed, can not book") .Bind(RegisterBooking) .Check(GenerateInvoice) .Bind(SendSupplierRequest) .Bind(GetAccommodationBookingInfo) .Finally(WriteLog)); bool IsDeadlineNotPassed(BookingAvailabilityInfo bookingAvailability) { var deadlineDate = bookingAvailability.RoomContractSet.Deadline.Date; var dueDate = deadlineDate == null || deadlineDate == DateTime.MinValue ? bookingAvailability.CheckInDate : deadlineDate.Value; return(_dateTimeProvider.UtcToday() < dueDate - BookingPaymentTypesHelper.OfflinePaymentAdditionalDays); } async Task <Result <BookingAvailabilityInfo> > GetCachedAvailability(AccommodationBookingRequest bookingRequest) => await _bookingEvaluationStorage.Get(bookingRequest.SearchId, bookingRequest.HtId, bookingRequest.RoomContractSetId); bool IsPaymentTypeAllowed(BookingAvailabilityInfo availabilityInfo) => availabilityInfo.AvailablePaymentTypes.Contains(PaymentTypes.Offline); Task <Result <Data.Bookings.Booking> > RegisterBooking(BookingAvailabilityInfo bookingAvailability) => _registrationService.Register(bookingRequest, bookingAvailability, PaymentTypes.Offline, agentContext, languageCode); Task <Result> GenerateInvoice(Data.Bookings.Booking booking) => _documentsService.GenerateInvoice(booking); async Task <Result <Booking> > SendSupplierRequest(Data.Bookings.Booking booking) { return(await _requestExecutor.Execute(booking, agentContext, languageCode)); } Task <Result <AccommodationBookingInfo> > GetAccommodationBookingInfo(EdoContracts.Accommodations.Booking details) => _bookingInfoService.GetAccommodationBookingInfo(details.ReferenceCode, languageCode); Result <AccommodationBookingInfo> WriteLog(Result <AccommodationBookingInfo> result) => LoggerUtils.WriteLogByResult(result, () => _logger.LogBookingByAccountSuccess(result.Value.BookingDetails.ReferenceCode), () => _logger.LogBookingByOfflinePaymentFailure(bookingRequest.HtId, result.Error)); }
public async Task <ActionResult <Booking> > Register([FromBody] AccommodationBookingRequest request) { var agent = await _agentContextService.GetAgent(); var(isSuccess, _, booking, error) = await _bookingCreationService.Register(request, agent, "en"); return(isSuccess ? Ok(booking) : BadRequest(ProblemDetailsBuilder.Build(error))); }
public async Task <IActionResult> RegisterBooking([FromBody] AccommodationBookingRequest request) { var(_, isFailure, refCode, error) = await _bookingRegistrationService.Register(request, await _agentContextService.GetAgent(), LanguageCode); if (isFailure) { return(BadRequest(error)); } return(Ok(refCode)); }
public async Task <IActionResult> RegisterBooking([FromBody] AccommodationBookingRequest request) { var(_, isFailure, refCode, error) = await _bankCreditCardBookingFlow.Register(request, await _agentContextService.GetAgent(), LanguageCode); if (isFailure) { return(BadRequest(ProblemDetailsBuilder.Build(error))); } return(Ok(refCode)); }
public Task Set(string referenceCode, AccommodationBookingRequest request, BookingAvailabilityInfo availabilityInfo) { var bookingRequest = new BookingRequest { ReferenceCode = referenceCode, RequestData = JsonConvert.SerializeObject(request), AvailabilityData = JsonConvert.SerializeObject(availabilityInfo), }; _edoContext.BookingRequests.Add(bookingRequest); return(_edoContext.SaveChangesAsync()); }
public async Task <IActionResult> Book([FromBody] AccommodationBookingRequest request) { var agentContext = await _agentContextService.GetAgent(); var(_, isFailure, bookingInfo, error) = await _idempotentBookingExecutor.Execute(request : request, bookingFunction : () => _financialAccountBookingFlow.BookByAccount(request, agentContext, LanguageCode, ClientIp), languageCode : LanguageCode); if (isFailure) { return(BadRequest(ProblemDetailsBuilder.Build(error))); } return(Ok(bookingInfo)); }
public static Edo.Api.Models.Bookings.AccommodationBookingRequest ToEdoModel(this AccommodationBookingRequest request) { return(new Edo.Api.Models.Bookings.AccommodationBookingRequest(itineraryNumber: string.Empty, clientReferenceCode: request.ClientReferenceCode, roomDetails: request.RoomDetails .Select(r => r.ToEdoModel()) .ToList(), features: new List <Api.Models.Accommodations.AccommodationFeature>(), searchId: request.SearchId, htId: request.AccommodationId, roomContractSetId: request.RoomContractSetId, mainPassengerName: GetMainPassengerName(request.RoomDetails), evaluationToken: null, rejectIfUnavailable: true)); }
public async Task <Result <string, ProblemDetails> > Register(AccommodationBookingRequest bookingRequest, AgentContext agentContext, string languageCode) { string availabilityId = default; var settings = await _accommodationBookingSettingsService.Get(agentContext); return(await GetCachedAvailability(bookingRequest, agentContext) .Ensure(AreAprSettingsSuitable, ProblemDetailsBuilder.Build("You can't book the restricted contract without explicit approval from a Happytravel.com officer.")) .Ensure(AreDeadlineSettingsSuitable, ProblemDetailsBuilder.Build("You can't book the contract within deadline without explicit approval from a Happytravel.com officer.")) .Tap(FillAvailabilityId) .Map(ExtractBookingAvailabilityInfo) .Map(Register) .Finally(WriteLog)); bool AreAprSettingsSuitable( (Suppliers, DataWithMarkup <RoomContractSetAvailability>) bookingData) => BookingRegistrationService.AreAprSettingsSuitable(bookingRequest, bookingData, settings); bool AreDeadlineSettingsSuitable( (Suppliers, DataWithMarkup <RoomContractSetAvailability>) bookingData) => this.AreDeadlineSettingsSuitable(bookingRequest, bookingData, settings); void FillAvailabilityId((Suppliers, DataWithMarkup <RoomContractSetAvailability> Result) responseWithMarkup) => availabilityId = responseWithMarkup.Result.Data.AvailabilityId; async Task <string> Register(BookingAvailabilityInfo bookingAvailability) { var bookingRequestWithAvailabilityId = new AccommodationBookingRequest(bookingRequest, availabilityId); return(await _bookingRecordsManager.Register(bookingRequestWithAvailabilityId, bookingAvailability, agentContext, languageCode)); } Result <string, ProblemDetails> WriteLog(Result <string, ProblemDetails> result) => LoggerUtils.WriteLogByResult(result, () => _logger.LogBookingRegistrationSuccess($"Successfully registered a booking with reference code: '{result.Value}'"), () => _logger.LogBookingRegistrationFailure($"Failed to register a booking. AvailabilityId: '{availabilityId}'. " + $"Itinerary number: {bookingRequest.ItineraryNumber}. Passenger name: {bookingRequest.MainPassengerName}. Error: {result.Error.Detail}")); }
public async Task <Result <string> > Register(AccommodationBookingRequest bookingRequest, AgentContext agentContext, string languageCode) { Baggage.AddSearchId(bookingRequest.SearchId); _logger.LogCreditCardBookingFlowStarted(bookingRequest.HtId); var(_, isFailure, booking, error) = await GetCachedAvailability(bookingRequest) .Ensure(IsPaymentTypeAllowed, "Payment type is not allowed") .Bind(Register) .Check(SendEmailToPropertyOwner) .Finally(WriteLog); if (isFailure) { return(Result.Failure <string>(error)); } return(booking.ReferenceCode); async Task <Result <BookingAvailabilityInfo> > GetCachedAvailability(AccommodationBookingRequest bookingRequest) => await _evaluationStorage.Get(bookingRequest.SearchId, bookingRequest.HtId, bookingRequest.RoomContractSetId); bool IsPaymentTypeAllowed(BookingAvailabilityInfo availabilityInfo) => availabilityInfo.AvailablePaymentTypes.Contains(PaymentTypes.CreditCard); Task <Result <Booking> > Register(BookingAvailabilityInfo bookingAvailability) => _registrationService.Register(bookingRequest, bookingAvailability, PaymentTypes.CreditCard, agentContext, languageCode); async Task <Result> SendEmailToPropertyOwner(Booking booking) => await _bookingConfirmationService.SendConfirmationEmail(booking); Result <Booking> WriteLog(Result <Booking> result) => LoggerUtils.WriteLogByResult(result, () => _logger.LogBookingRegistrationSuccess(result.Value.ReferenceCode), () => _logger.LogBookingRegistrationFailure(bookingRequest.HtId, bookingRequest.ItineraryNumber, bookingRequest.MainPassengerName, result.Error)); }
public async Task <Result <AccommodationBookingInfo, ProblemDetails> > BookByAccount(AccommodationBookingRequest bookingRequest, AgentContext agentContext, string languageCode, string clientIp) { string availabilityId = default; DateTime?availabilityDeadline = default; DateTime availabilityCheckIn = default; string referenceCode = default; var wasPaymentMade = false; var settings = await _accommodationBookingSettingsService.Get(agentContext); // TODO Remove lots of code duplication in account and card purchase booking var(_, isRegisterFailure, booking, registerError) = await GetCachedAvailability(bookingRequest, agentContext) .Ensure(AreAprSettingsSuitable, ProblemDetailsBuilder.Build("You can't book the restricted contract without explicit approval from a Happytravel.com officer.")) .Ensure(AreDeadlineSettingsSuitable, ProblemDetailsBuilder.Build("You can't book the contract within deadline without explicit approval from a Happytravel.com officer.")) .Tap(FillAvailabilityLocalVariables) .Map(ExtractBookingAvailabilityInfo) .BindWithTransaction(_context, info => Result.Success <BookingAvailabilityInfo, ProblemDetails>(info) .Map(RegisterBooking) .Bind(GetBooking) .Bind(PayUsingAccountIfDeadlinePassed)) .OnFailure(WriteLogFailure); if (isRegisterFailure) { return(Result.Failure <AccommodationBookingInfo, ProblemDetails>(registerError)); } return(await BookOnProvider(booking, booking.ReferenceCode, languageCode) .Tap(ProcessResponse) .OnFailure(VoidMoneyAndCancelBooking) .Bind(GenerateInvoice) .Bind(SendReceiptIfPaymentMade) .Bind(GetAccommodationBookingInfo) .Finally(WriteLog)); void FillAvailabilityLocalVariables((Suppliers, DataWithMarkup <RoomContractSetAvailability> Result) responseWithMarkup) { availabilityId = responseWithMarkup.Result.Data.AvailabilityId; availabilityDeadline = responseWithMarkup.Result.Data.RoomContractSet.Deadline.Date; availabilityCheckIn = responseWithMarkup.Result.Data.CheckInDate; } bool AreAprSettingsSuitable( (Suppliers, DataWithMarkup <RoomContractSetAvailability>) bookingData) => BookingRegistrationService.AreAprSettingsSuitable(bookingRequest, bookingData, settings); bool AreDeadlineSettingsSuitable( (Suppliers, DataWithMarkup <RoomContractSetAvailability>) bookingData) => this.AreDeadlineSettingsSuitable(bookingRequest, bookingData, settings); async Task <string> RegisterBooking(BookingAvailabilityInfo bookingAvailability) { var bookingRequestWithAvailabilityId = new AccommodationBookingRequest(bookingRequest, availabilityId); var registeredReferenceCode = await _bookingRecordsManager.Register(bookingRequestWithAvailabilityId, bookingAvailability, agentContext, languageCode); referenceCode = registeredReferenceCode; return(registeredReferenceCode); } async Task <Result <Data.Booking.Booking, ProblemDetails> > GetBooking(string referenceCode) => await _bookingRecordsManager.Get(referenceCode).ToResultWithProblemDetails(); async Task <Result <Data.Booking.Booking, ProblemDetails> > PayUsingAccountIfDeadlinePassed(Data.Booking.Booking bookingInPipeline) { var daysBeforeDeadline = Infrastructure.Constants.Common.DaysBeforeDeadlineWhenPayForBooking; var now = _dateTimeProvider.UtcNow(); var deadlinePassed = availabilityCheckIn <= now.AddDays(daysBeforeDeadline) || (availabilityDeadline.HasValue && availabilityDeadline <= now.AddDays(daysBeforeDeadline)); if (!deadlinePassed) { return(bookingInPipeline); } var(_, isPaymentFailure, _, paymentError) = await _accountPaymentService.Charge(bookingInPipeline, agentContext, clientIp); if (isPaymentFailure) { return(ProblemDetailsBuilder.Fail <Data.Booking.Booking>(paymentError)); } wasPaymentMade = true; return(bookingInPipeline); } Task ProcessResponse(EdoContracts.Accommodations.Booking bookingResponse) => _bookingResponseProcessor.ProcessResponse(bookingResponse, booking); Task VoidMoneyAndCancelBooking(ProblemDetails problemDetails) => this.VoidMoneyAndCancelBooking(booking, agentContext); Task <Result <EdoContracts.Accommodations.Booking, ProblemDetails> > GenerateInvoice(EdoContracts.Accommodations.Booking details) => this.GenerateInvoice(details, booking.ReferenceCode, agentContext); async Task <Result <EdoContracts.Accommodations.Booking, ProblemDetails> > SendReceiptIfPaymentMade(EdoContracts.Accommodations.Booking details) => wasPaymentMade ? await SendReceipt(details, booking, agentContext) : details; Task <Result <AccommodationBookingInfo, ProblemDetails> > GetAccommodationBookingInfo(EdoContracts.Accommodations.Booking details) => _bookingRecordsManager.GetAccommodationBookingInfo(details.ReferenceCode, languageCode) .ToResultWithProblemDetails(); void WriteLogFailure(ProblemDetails problemDetails) => _logger.LogBookingByAccountFailure($"Failed to book using account. Reference code: '{referenceCode}'. Error: {problemDetails.Detail}"); Result <T, ProblemDetails> WriteLog <T>(Result <T, ProblemDetails> result) => LoggerUtils.WriteLogByResult(result, () => _logger.LogBookingFinalizationSuccess($"Successfully booked using account. Reference code: '{referenceCode}'"), () => _logger.LogBookingFinalizationFailure( $"Failed to book using account. Reference code: '{referenceCode}'. Error: {result.Error.Detail}")); }
public async Task <string> Register(AccommodationBookingRequest bookingRequest, BookingAvailabilityInfo availabilityInfo, AgentContext agentContext, string languageCode) { var(_, _, booking, _) = await Result.Success() .Map(GetTags) .Map(Create); return(booking.ReferenceCode); async Task <(string itn, string referenceCode)> GetTags() { string itn; if (string.IsNullOrWhiteSpace(bookingRequest.ItineraryNumber)) { itn = await _tagProcessor.GenerateItn(); } else { // User can send reference code instead of itn if (!_tagProcessor.TryGetItnFromReferenceCode(bookingRequest.ItineraryNumber, out itn)) { itn = bookingRequest.ItineraryNumber; } if (!await AreExistBookingsForItn(itn, agentContext.AgentId)) { itn = await _tagProcessor.GenerateItn(); } } var referenceCode = await _tagProcessor.GenerateReferenceCode( ServiceTypes.HTL, availabilityInfo.CountryCode, itn); return(itn, referenceCode); } async Task <Data.Booking.Booking> Create((string itn, string referenceCode) tags) { var createdBooking = BookingFactory.Create( _dateTimeProvider.UtcNow(), agentContext, tags.itn, tags.referenceCode, availabilityInfo, bookingRequest.PaymentMethod, bookingRequest, languageCode, availabilityInfo.Supplier, availabilityInfo.RoomContractSet.Deadline.Date, availabilityInfo.CheckInDate, availabilityInfo.CheckOutDate); _context.Bookings.Add(createdBooking); await _context.SaveChangesAsync(); _context.Entry(createdBooking).State = EntityState.Detached; return(createdBooking); } }
public async Task <Result <Booking> > Register(AccommodationBookingRequest bookingRequest, BookingAvailabilityInfo availabilityInfo, PaymentTypes paymentMethod, AgentContext agentContext, string languageCode) { var(_, isFailure, booking, error) = await CheckRooms() .Map(GetTags) .Map(Create) .Tap(SaveRequestInfo) .Tap(LogBookingStatus) .Tap(SaveMarkups) .Tap(CreateSupplierOrder); if (isFailure) { return(Result.Failure <Booking>(error)); } _logger.LogBookingRegistrationSuccess(booking.ReferenceCode); return(booking); Result CheckRooms() { if (bookingRequest.RoomDetails.Count != availabilityInfo.AvailabilityRequest.RoomDetails.Count) { return(Result.Failure("Rooms does not correspond to search rooms")); } for (var i = 0; i < bookingRequest.RoomDetails.Count; i++) { var adultsCount = bookingRequest.RoomDetails[i].Passengers.Count(p => p.Age == null); var childrenCount = bookingRequest.RoomDetails[i].Passengers.Count(p => p.Age != null); if (availabilityInfo.AvailabilityRequest.RoomDetails[i].AdultsNumber != adultsCount || availabilityInfo.AvailabilityRequest.RoomDetails[i].ChildrenAges.Count != childrenCount) { return(Result.Failure("Rooms does not correspond to search rooms")); } } return(Result.Success()); } async Task <(string itn, string referenceCode)> GetTags() { string itn; if (string.IsNullOrWhiteSpace(bookingRequest.ItineraryNumber)) { itn = await _tagProcessor.GenerateItn(); } else { // User can send reference code instead of itn if (!_tagProcessor.TryGetItnFromReferenceCode(bookingRequest.ItineraryNumber, out itn)) { itn = bookingRequest.ItineraryNumber; } if (!await AreExistBookingsForItn(itn, agentContext.AgentId)) { itn = await _tagProcessor.GenerateItn(); } } var referenceCode = await _tagProcessor.GenerateReferenceCode( ServiceTypes.HTL, availabilityInfo.CountryCode, itn); return(itn, referenceCode); } async Task <Booking> Create((string itn, string referenceCode) tags) { var createdBooking = await CreateBooking( created : _dateTimeProvider.UtcNow(), agentContext : agentContext, itineraryNumber : tags.itn, referenceCode : tags.referenceCode, clientReferenceCode : bookingRequest.ClientReferenceCode, availabilityInfo : availabilityInfo, paymentMethod : paymentMethod, bookingRequest : bookingRequest, languageCode : languageCode); _context.Bookings.Add(createdBooking); await _context.SaveChangesAsync(); _context.Entry(createdBooking).State = EntityState.Detached; return(createdBooking); } Task SaveRequestInfo(Booking booking) => _requestStorage.Set(booking.ReferenceCode, bookingRequest, availabilityInfo); Task LogBookingStatus(Booking booking) { var changeReason = new BookingChangeReason { Event = BookingChangeEvents.Create, Source = BookingChangeSources.System }; return(_changeLogService.Write(booking, BookingStatuses.Created, booking.Created.DateTime, agentContext.ToApiCaller(), changeReason)); } Task SaveMarkups(Booking booking) => _appliedBookingMarkupRecordsManager.Create(booking.ReferenceCode, availabilityInfo.AppliedMarkups); Task CreateSupplierOrder(Booking booking) => _supplierOrderService.Add(referenceCode: booking.ReferenceCode, serviceType: ServiceTypes.HTL, convertedPrice: availabilityInfo.ConvertedSupplierPrice, supplierPrice: availabilityInfo.OriginalSupplierPrice, deadline: availabilityInfo.SupplierDeadline, supplier: (int)booking.Supplier, paymentType: availabilityInfo.CardRequirement is not null ? SupplierPaymentType.CreditCard : SupplierPaymentType.DirectPayment, paymentDate: availabilityInfo.RoomContractSet.IsAdvancePurchaseRate ? booking.Created.DateTime : booking.CheckOutDate.DateTime); }
private async Task <Booking> CreateBooking(DateTime created, AgentContext agentContext, string itineraryNumber, string referenceCode, string clientReferenceCode, BookingAvailabilityInfo availabilityInfo, PaymentTypes paymentMethod, AccommodationBookingRequest bookingRequest, string languageCode) { var booking = new Booking { Created = created, ItineraryNumber = itineraryNumber, ReferenceCode = referenceCode, ClientReferenceCode = clientReferenceCode, Status = BookingStatuses.Created, PaymentType = paymentMethod, LanguageCode = languageCode, Supplier = availabilityInfo.Supplier, PaymentStatus = BookingPaymentStatuses.NotPaid, DeadlineDate = availabilityInfo.RoomContractSet.Deadline.Date, CheckInDate = availabilityInfo.CheckInDate, CheckOutDate = availabilityInfo.CheckOutDate, HtId = availabilityInfo.HtId, Tags = availabilityInfo.RoomContractSet.Tags, IsDirectContract = availabilityInfo.RoomContractSet.IsDirectContract, CancellationPolicies = availabilityInfo.RoomContractSet.Deadline.Policies, IsAdvancePurchaseRate = availabilityInfo.RoomContractSet.IsAdvancePurchaseRate, IsPackage = availabilityInfo.RoomContractSet.IsPackageRate }; AddRequestInfo(bookingRequest); AddServiceDetails(); AddAgentInfo(); AddRooms(availabilityInfo.RoomContractSet.Rooms, bookingRequest.RoomDetails); booking = await AddStaticData(booking, availabilityInfo); return(booking); void AddRequestInfo(in AccommodationBookingRequest bookingRequestInternal) { booking.Nationality = availabilityInfo.AvailabilityRequest.Nationality.ToUpper(); booking.Residency = availabilityInfo.AvailabilityRequest.Residency.ToUpper(); booking.MainPassengerName = bookingRequestInternal.MainPassengerName.Trim(); } void AddServiceDetails() { var rate = availabilityInfo.RoomContractSet.Rate; booking.TotalPrice = rate.FinalPrice.Amount; booking.Currency = rate.Currency; } void AddAgentInfo() { booking.AgentId = agentContext.AgentId; booking.AgencyId = agentContext.AgencyId; } void AddRooms(List <RoomContract> roomContracts, List <BookingRoomDetails> bookingRequestRoomDetails) { booking.Rooms = roomContracts .Select((r, number) => new BookedRoom(r.Type, r.IsExtraBedNeeded, r.Rate.FinalPrice, r.BoardBasis, r.MealPlan, r.Deadline.Date, r.ContractDescription, r.Remarks, r.Deadline, GetCorrespondingPassengers(number), r.IsAdvancePurchaseRate, string.Empty)) .ToList(); List <Passenger> GetCorrespondingPassengers(int number) => bookingRequestRoomDetails[number].Passengers .Select(p => new Passenger(p.Title, p.LastName.Trim(), p.FirstName.Trim(), p.IsLeader, p.Age)) .ToList(); } }