donation = $donation; } /** * @since 4.16.8.1 Stop relying on a count taken once before the loop — EventTicketRepository::insert() now enforces remaining capacity itself, atomically with each insert, closing a race that let concurrent purchases jointly oversell a ticket type. * @since 4.6.0 Add support for currency conversion * @since 3.20.0 Add "amount" to the array of props * @since 3.6.0 */ public function __invoke(TicketPurchaseData $data) { $quantity = max(0, $data->quantity); for($i = 0; $i < $quantity; $i++) { $amount = $data->ticketType->price; if ($this->donation->amount->getCurrency() !== $data->ticketType->price->getCurrency()) { $amount = new Money($data->ticketType->price->multiply($this->donation->exchangeRate)->getAmount(), $this->donation->amount->getCurrency()); } try { EventTicket::create([ 'eventId' => $data->ticketType->eventId, 'ticketTypeId' => $data->ticketType->id, 'donationId' => $this->donation->id, 'amount' => $amount, ]); } catch (RuntimeException $exception) { break; } } } }