Exemple #1
0
        public Task <Result <BatchOperationResult> > Capture(List <int> bookingIds, ServiceAccount serviceAccount)
        {
            return(ExecuteBatchAction(bookingIds,
                                      IsBookingValidForCapturePredicate,
                                      Capture,
                                      serviceAccount));

            Task <Result <string> > Capture(Booking booking, ApiCaller serviceAcc)
            => _creditCardPaymentService.Capture(booking, serviceAccount.ToApiCaller());
        }
Exemple #2
0
        public Task <Result <BatchOperationResult> > Cancel(List <int> bookingIds, ServiceAccount serviceAccount)
        {
            return(ExecuteBatchAction(bookingIds,
                                      IsBookingValidForCancelPredicate,
                                      ProcessBooking,
                                      serviceAccount));


            Task <Result <string> > ProcessBooking(Booking booking, ApiCaller _)
            {
                return(_supplierBookingManagementService.Cancel(booking, serviceAccount.ToApiCaller(), BookingChangeEvents.Cancel)
                       .Finally(CreateResult));


                Result <string> CreateResult(Result result)
                => result.IsSuccess
                        ? Result.Success($"Booking '{booking.ReferenceCode}' was cancelled.")
                        : Result.Failure <string>($"Unable to cancel booking '{booking.ReferenceCode}'. Reason: {result.Error}");
            }
        }
Exemple #3
0
        public Task <Result <BatchOperationResult> > Charge(List <int> bookingIds, ServiceAccount serviceAccount)
        {
            return(ExecuteBatchAction(bookingIds,
                                      IsBookingValidForChargePredicate,
                                      Charge,
                                      serviceAccount));


            async Task <Result <string> > Charge(Booking booking, ApiCaller serviceAcc)
            {
                if (BookingStatusesNeededRefreshBeforePayment.Contains(booking.Status))
                {
                    var(_, isRefreshingFailure, refreshingError) = await _supplierBookingManagementService.RefreshStatus(booking, serviceAcc,
                                                                                                                         BookingChangeEvents.Charge);

                    if (isRefreshingFailure)
                    {
                        await _bookingRecordsUpdater.ChangeStatus(booking, BookingStatuses.ManualCorrectionNeeded, _dateTimeProvider.UtcNow(), serviceAcc, new BookingChangeReason
                        {
                            Source = BookingChangeSources.System,
                            Event  = BookingChangeEvents.Charge,
                            Reason = "Failure in refreshing booking status before payment"
                        });

                        return(Result.Failure <string>(refreshingError));
                    }

                    // Need to get fresh information about the booking
                    booking = await _context.Bookings.SingleOrDefaultAsync(b => b.ReferenceCode == booking.ReferenceCode);

                    if (BookingStatusesNeededRefreshBeforePayment.Contains(booking.Status))
                    {
                        await _bookingRecordsUpdater.ChangeStatus(booking, BookingStatuses.ManualCorrectionNeeded, _dateTimeProvider.UtcNow(), serviceAcc, new BookingChangeReason
                        {
                            Source = BookingChangeSources.System,
                            Event  = BookingChangeEvents.Charge,
                            Reason = "After refreshing the booking received a status requiring refreshing"
                        });

                        return(Result.Failure <string>($"Booking {booking.ReferenceCode} with status {booking.Status} cannot be charged"));
                    }
                }

                var chargeResult = await _accountPaymentService.Charge(booking, serviceAccount.ToApiCaller());

                if (chargeResult.IsFailure)
                {
                    var(_, isCancelFailure, error) = await _supplierBookingManagementService.Cancel(booking, serviceAccount.ToApiCaller(),
                                                                                                    BookingChangeEvents.Charge);

                    if (isCancelFailure)
                    {
                        await _bookingRecordsUpdater.ChangeStatus(booking, BookingStatuses.ManualCorrectionNeeded, _dateTimeProvider.UtcNow(), serviceAcc, new BookingChangeReason
                        {
                            Source = BookingChangeSources.System,
                            Event  = BookingChangeEvents.Charge,
                            Reason = "It is impossible to cancel the booking for which the error occurred during charge"
                        });

                        return(Result.Failure <string>(error));
                    }
                }

                return(chargeResult);
            }
        }
Exemple #4
0
        private async Task <Result <BatchOperationResult> > ExecuteBatchAction(List <int> bookingIds,
                                                                               Expression <Func <Booking, bool> > predicate,
                                                                               Func <Booking, ApiCaller, Task <Result <string> > > action,
                                                                               ServiceAccount serviceAccount)
        {
            var bookings = await GetBookings();

            return(await ValidateCount()
                   .Map(ProcessBookings));


            Task <List <Booking> > GetBookings()
            => _context.Bookings
            .Where(booking => bookingIds.Contains(booking.Id))
            .Where(predicate)
            .ToListAsync();


            Result ValidateCount()
            => bookings.Count != bookingIds.Count
                    ? Result.Failure("Invalid booking ids. Could not find some of requested bookings.")
                    : Result.Success();


            Task <BatchOperationResult> ProcessBookings() => Combine(bookings.Select(booking => action(booking, serviceAccount.ToApiCaller())));


            async Task <BatchOperationResult> Combine(IEnumerable <Task <Result <string> > > results)
            {
                var  builder   = new StringBuilder();
                bool hasErrors = false;

                foreach (var result in results)
                {
                    var(_, isFailure, value, error) = await result;
                    if (isFailure)
                    {
                        hasErrors = true;
                    }

                    builder.AppendLine(isFailure ? error : value);
                }

                return(new BatchOperationResult(builder.ToString(), hasErrors));
            }
        }