public async Task PurchaseTicketsAsync()

in src/Relecloud.Web.CallCenter.Api/Controllers/TicketController.cs [86:186]


        public async Task<IActionResult> PurchaseTicketsAsync(PurchaseTicketsRequest purchaseTicketRequest)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest();
                }

                var errors = new List<string>();
                if (purchaseTicketRequest == null)
                {
                    errors.Add("Purchase ticket request must not be null");
                }
                else
                {
                    if (purchaseTicketRequest.PaymentDetails == null)
                    {
                        errors.Add("Missing required payment details");
                    }
                    if (purchaseTicketRequest.ConcertIdsAndTicketCounts == null)
                    {
                        errors.Add("Missing required concert ticket details");
                    }
                    if (string.IsNullOrEmpty(purchaseTicketRequest.UserId))
                    {
                        errors.Add("Missing required userId");
                    }
                }
                
                if (errors.Any())
                {
                    return BadRequest(PurchaseTicketsResult.ErrorResponse(errors));
                }

                await this.concertRepository.CreateOrUpdateUserAsync(new User{
                    Id = purchaseTicketRequest!.UserId ?? Guid.Empty.ToString(),
                    DisplayName = purchaseTicketRequest!.PaymentDetails!.Name
                });

                var orderTotal = await TotalInvoiceAmountAsync(purchaseTicketRequest);
                var preAuthRequest = new PreAuthPaymentRequest
                {
                    Amount = orderTotal,
                    PaymentDetails = purchaseTicketRequest.PaymentDetails!,
                    Tickets = purchaseTicketRequest.ConcertIdsAndTicketCounts
                };
                var preAuthResponse = await paymentGatewayService.PreAuthPaymentAsync(preAuthRequest);

                if (preAuthResponse.Status != PreAuthPaymentResultStatus.FundsOnHold)
                {
                    return BadRequest(PurchaseTicketsResult.ErrorResponse("We were unable to process this card. Please review your payment details."));
                }

                var customer = await this.concertRepository.GetCustomerByEmailAsync(purchaseTicketRequest.PaymentDetails!.Email);
                var customerId = customer?.Id ?? 0;
                if (customerId == 0)
                {
                    var createResult = await this.concertRepository.CreateCustomerAsync(new Customer
                    {
                        Name = purchaseTicketRequest.PaymentDetails.Name,
                        Email = purchaseTicketRequest.PaymentDetails.Email,
                        Phone = purchaseTicketRequest.PaymentDetails.Phone,
                    });
                    if (createResult.Success)
                    {
                        customerId = createResult.NewId;
                    }
                }

                foreach (var concertAndTickets in purchaseTicketRequest.ConcertIdsAndTicketCounts!)
                {
                    var reserveResult = await this.ticketService.ReserveTicketsAsync(concertAndTickets.Key, purchaseTicketRequest.UserId!, concertAndTickets.Value, customerId);

                    if (reserveResult.Status != ReserveTicketsResultStatus.Success)
                    {
                        return BadRequest(PurchaseTicketsResult.ErrorResponse($"{reserveResult.Status}: Tickets not successfully reserved"));
                    }
                }

                //built-in assumption: if generating a ticket throws an error then we should not reach this code
                // and the hold on the customer's card will automatically be released by the Payment Gateway
                var captureRequest = new CapturePaymentRequest
                {
                    HoldCode = preAuthResponse.HoldCode,
                    TotalPrice = orderTotal
                };

                await paymentGatewayService.CapturePaymentAsync(captureRequest);

                return Accepted(new PurchaseTicketsResult
                {
                    Status = PurchaseTicketsResultStatus.Success
                });
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Unhandled exception from TicketController.PurchaseTicketsAsync");
                return Problem("Unable to Create the ticket");
            }
        }