Esempio n. 1
0
        public async Task ProcessConfirmation(Data.Booking.Booking booking, EdoContracts.Accommodations.Booking bookingResponse)
        {
            await GetBookingInfo(booking.ReferenceCode, booking.LanguageCode)
            .Tap(Confirm)
            .Tap(NotifyBookingFinalization)
            .Bind(SendInvoice)
            .OnFailure(WriteFailureLog);

            Task <Result <AccommodationBookingInfo> > GetBookingInfo(string referenceCode, string languageCode) => _bookingRecordsManager
            .GetAccommodationBookingInfo(referenceCode, languageCode);


            Task Confirm(AccommodationBookingInfo bookingInfo) => _bookingRecordsManager.Confirm(bookingResponse, booking);


            Task NotifyBookingFinalization(AccommodationBookingInfo bookingInfo) => _bookingMailingService
            .NotifyBookingFinalized(bookingInfo);


            Task <Result> SendInvoice(AccommodationBookingInfo bookingInfo) => _bookingMailingService
            .SendInvoice(bookingInfo.BookingId, bookingInfo.AgentInformation.AgentEmail, booking.AgentId);


            void WriteFailureLog(string error) => _logger
            .LogBookingConfirmationFailure($"Booking '{booking.ReferenceCode} confirmation failed: '{error}");

            // TODO: Revert supplier order placing NIJO-1015
            // await SaveSupplierOrder();
            //
            // async Task SaveSupplierOrder()
            // {
            //     var supplierPrice = bookingResponse.RoomContractSet.Price.NetTotal;
            //     await _supplierOrderService.Add(bookingResponse.ReferenceCode, ServiceTypes.HTL, supplierPrice);
            // }
        }
Esempio n. 2
0
        public async Task ProcessResponse(Booking bookingResponse, Data.Booking.Booking booking)
        {
            await _bookingAuditLogService.Add(bookingResponse, booking);

            _logger.LogBookingResponseProcessStarted(
                $"Start the booking response processing with the reference code '{bookingResponse.ReferenceCode}'. Old status: {booking.Status}");

            if (bookingResponse.Status == BookingStatusCodes.NotFound)
            {
                await _bookingChangesProcessor.ProcessBookingNotFound(booking, bookingResponse);

                return;
            }

            if (bookingResponse.Status.ToInternalStatus() == booking.Status)
            {
                _logger.LogBookingResponseProcessSuccess(
                    $"The booking response with the reference code '{bookingResponse.ReferenceCode}' has been successfully processed. No changes applied");
                return;
            }

            await UpdateBookingDetails();

            switch (bookingResponse.Status)
            {
            case BookingStatusCodes.Confirmed:
                await _bookingChangesProcessor.ProcessConfirmation(booking, bookingResponse);

                break;

            case BookingStatusCodes.Cancelled:
                await _bookingChangesProcessor.ProcessCancellation(booking, UserInfo.InternalServiceAccount);

                break;
            }

            _logger.LogBookingResponseProcessSuccess(
                $"The booking response with the reference code '{bookingResponse.ReferenceCode}' has been successfully processed. " +
                $"New status: {bookingResponse.Status}");


            Task UpdateBookingDetails() => _bookingRecordsManager.UpdateBookingDetails(bookingResponse, booking);

            //TICKET https://happytravel.atlassian.net/browse/NIJO-315

            /*
             * async Task<Result> LogAppliedMarkups()
             * {
             *  long availabilityId = ??? ;
             *
             *  var (_, isGetAvailabilityFailure, responseWithMarkup, cachedAvailabilityError) = await _availabilityResultsCache.Get(availabilityId);
             *  if (isGetAvailabilityFailure)
             *      return Result.Fail(cachedAvailabilityError);
             *
             *  await _markupLogger.Write(bookingResponse.ReferenceCode, ServiceTypes.HTL, responseWithMarkup.AppliedPolicies);
             *  return Result.Success();
             * }
             */
        }
Esempio n. 3
0
 // TODO: Remove room information and contract description from booking NIJO-915
 static EdoContracts.Accommodations.Booking GetStubDetails(Data.Booking.Booking booking)
 => new EdoContracts.Accommodations.Booking(booking.ReferenceCode,
                                            // Will be set in the refresh step
                                            BookingStatusCodes.WaitingForResponse,
                                            booking.AccommodationId,
                                            booking.SupplierReferenceCode,
                                            booking.CheckInDate,
                                            booking.CheckOutDate,
                                            new List <SlimRoomOccupation>(0),
                                            BookingUpdateModes.Asynchronous);
Esempio n. 4
0
        public async Task ProcessBookingNotFound(Data.Booking.Booking booking, EdoContracts.Accommodations.Booking bookingResponse)
        {
            if (_dateTimeProvider.UtcNow() < booking.Created + BookingCheckTimeout)
            {
                _logger.LogBookingResponseProcessSuccess(
                    $"The booking response with the reference code '{bookingResponse.ReferenceCode}' has not been processed due to '{BookingStatusCodes.NotFound}' status.");
            }
            else
            {
                await _bookingRecordsManager.SetNeedsManualCorrectionStatus(booking);

                _logger.LogBookingResponseProcessSuccess(
                    $"The booking response with the reference code '{bookingResponse.ReferenceCode}' set as needed manual processing.");
            }
        }
Esempio n. 5
0
        public Task <Result> ProcessCancellation(Data.Booking.Booking booking, UserInfo user)
        {
            return(SendNotifications()
                   .Tap(CancelSupplierOrder)
                   .Bind(VoidMoney)
                   .Tap(SetBookingCancelled));


            async Task CancelSupplierOrder()
            {
                var referenceCode = booking.ReferenceCode;
                await _supplierOrderService.Cancel(referenceCode);
            }

            async Task <Result> SendNotifications()
            {
                var agent = await _context.Agents.SingleOrDefaultAsync(a => a.Id == booking.AgentId);

                if (agent == default)
                {
                    _logger.LogWarning("Booking cancellation notification: could not find agent with id '{0}' for the booking '{1}'",
                                       booking.AgentId, booking.ReferenceCode);

                    return(Result.Success());
                }

                var(_, _, bookingInfo, _) = await _bookingRecordsManager.GetAccommodationBookingInfo(booking.ReferenceCode, booking.LanguageCode);

                await _bookingMailingService.NotifyBookingCancelled(bookingInfo);

                return(Result.Success());
            }

            async Task <Result> VoidMoney()
            {
                if (booking.PaymentStatus == BookingPaymentStatuses.Authorized || booking.PaymentStatus == BookingPaymentStatuses.Captured)
                {
                    return(await _paymentService.VoidOrRefund(booking, user));
                }

                return(Result.Success());
            }

            Task SetBookingCancelled() => _bookingRecordsManager.ConfirmBookingCancellation(booking);
        }
Esempio n. 6
0
        private async Task <Result <VoidObject, ProblemDetails> > CancelBooking(Data.Booking.Booking booking, UserInfo user,
                                                                                bool requireProviderConfirmation = true)
        {
            if (booking.Status == BookingStatuses.Cancelled)
            {
                _logger.LogBookingAlreadyCancelled(
                    $"Skipping cancellation for a booking with reference code: '{booking.ReferenceCode}'. Already cancelled.");

                return(Result.Success <VoidObject, ProblemDetails>(VoidObject.Instance));
            }

            return(await SendCancellationRequest()
                   .Bind(ProcessCancellation)
                   .Finally(WriteLog));


            async Task <Result <Data.Booking.Booking, ProblemDetails> > SendCancellationRequest()
            {
                var(_, isCancelFailure, _, cancelError) = await _supplierConnectorManager.Get(booking.Supplier).CancelBooking(booking.ReferenceCode);

                return(isCancelFailure && requireProviderConfirmation
                    ? Result.Failure <Data.Booking.Booking, ProblemDetails>(cancelError)
                    : Result.Success <Data.Booking.Booking, ProblemDetails>(booking));
            }

            async Task <Result <VoidObject, ProblemDetails> > ProcessCancellation(Data.Booking.Booking b)
            {
                if (b.UpdateMode == BookingUpdateModes.Synchronous || !requireProviderConfirmation)
                {
                    return(await _bookingChangesProcessor.ProcessCancellation(b, user).ToResultWithProblemDetails());
                }

                return(VoidObject.Instance);
            }

            Result <T, ProblemDetails> WriteLog <T>(Result <T, ProblemDetails> result)
            => LoggerUtils.WriteLogByResult(result,
                                            () => _logger.LogBookingCancelSuccess($"Successfully cancelled a booking with reference code: '{booking.ReferenceCode}'"),
                                            () => _logger.LogBookingCancelFailure(
                                                $"Failed to cancel a booking with reference code: '{booking.ReferenceCode}'. Error: {result.Error.Detail}"));
        }
Esempio n. 7
0
        private async Task <Result <EdoContracts.Accommodations.Booking, ProblemDetails> > BookOnProvider(Data.Booking.Booking booking, string referenceCode, string languageCode)
        {
            // TODO: will be implemented in NIJO-31
            var bookingRequest = JsonConvert.DeserializeObject <AccommodationBookingRequest>(booking.BookingRequest);

            var features = new List <Feature>(); //bookingRequest.Features

            var roomDetails = bookingRequest.RoomDetails
                              .Select(d => new SlimRoomOccupation(d.Type, d.Passengers, string.Empty, d.IsExtraBedNeeded))
                              .ToList();

            var innerRequest = new BookingRequest(bookingRequest.AvailabilityId,
                                                  bookingRequest.RoomContractSetId,
                                                  booking.ReferenceCode,
                                                  roomDetails,
                                                  features,
                                                  bookingRequest.RejectIfUnavailable);

            try
            {
                var bookingResult = await _supplierConnectorManager
                                    .Get(booking.Supplier)
                                    .Book(innerRequest, languageCode);

                if (bookingResult.IsSuccess)
                {
                    return(bookingResult.Value);
                }

                // If result is failed this does not mean that booking failed. This means that we should check it later.
                _logger.LogBookingFinalizationFailure($"The booking finalization with the reference code: '{referenceCode}' has been failed");
                return(GetStubDetails(booking));
            }
            catch
            {
                var errorMessage = $"Failed to update booking data (refcode '{referenceCode}') after the request to the connector";

                var(_, isCancellationFailed, cancellationError) = await _supplierConnectorManager.Get(booking.Supplier).CancelBooking(booking.ReferenceCode);

                if (isCancellationFailed)
                {
                    errorMessage += Environment.NewLine + $"Booking cancellation has failed: {cancellationError}";
                }

                _logger.LogBookingFinalizationFailure(errorMessage);

                return(GetStubDetails(booking));
            }
Esempio n. 8
0
        private async Task <Result <EdoContracts.Accommodations.Booking, ProblemDetails> > SendReceipt(EdoContracts.Accommodations.Booking details, Data.Booking.Booking booking, AgentContext agentContext)
        {
            var(_, isReceiptFailure, receiptInfo, receiptError) = await _documentsService.GenerateReceipt(booking.Id, agentContext.AgentId);

            if (isReceiptFailure)
            {
                return(ProblemDetailsBuilder.Fail <EdoContracts.Accommodations.Booking>(receiptError));
            }

            await _notificationService.SendReceiptToCustomer(receiptInfo, agentContext.Email);

            return(Result.Success <EdoContracts.Accommodations.Booking, ProblemDetails>(details));
        }