PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Services / Reservation / EventReservationService.php
ameliabooking / src / Application / Services / Reservation Last commit date
AbstractReservationService.php 6 days ago AppointmentReservationService.php 6 days ago EventReservationService.php 6 days ago ReservationService.php 2 years ago
EventReservationService.php
1400 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Services\Reservation;
4
5 use AmeliaBooking\Application\Commands\CommandResult;
6 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
7 use AmeliaBooking\Application\Services\Booking\EventApplicationService;
8 use AmeliaBooking\Application\Services\Coupon\CouponApplicationService;
9 use AmeliaBooking\Application\Services\Deposit\AbstractDepositApplicationService;
10 use AmeliaBooking\Application\Services\QrCode\QrCodeApplicationService;
11 use AmeliaBooking\Application\Services\Tax\TaxApplicationService;
12 use AmeliaBooking\Domain\Collection\Collection;
13 use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException;
14 use AmeliaBooking\Domain\Common\Exceptions\BookingsLimitReachedException;
15 use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException;
16 use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException;
17 use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException;
18 use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException;
19 use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException;
20 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
21 use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable;
22 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
23 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBookingExtra;
24 use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventPeriod;
25 use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket;
26 use AmeliaBooking\Domain\Entity\Booking\Event\Event;
27 use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod;
28 use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket;
29 use AmeliaBooking\Domain\Entity\Booking\Reservation;
30 use AmeliaBooking\Domain\Entity\Coupon\Coupon;
31 use AmeliaBooking\Domain\Entity\Entities;
32 use AmeliaBooking\Domain\Entity\Location\Location;
33 use AmeliaBooking\Domain\Entity\Payment\Payment;
34 use AmeliaBooking\Domain\Entity\Tax\Tax;
35 use AmeliaBooking\Domain\Entity\User\AbstractUser;
36 use AmeliaBooking\Domain\Entity\User\Provider;
37 use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory;
38 use AmeliaBooking\Domain\Factory\Booking\Event\CustomerBookingEventPeriodFactory;
39 use AmeliaBooking\Domain\Factory\Booking\Event\CustomerBookingEventTicketFactory;
40 use AmeliaBooking\Domain\Factory\Booking\Event\EventFactory;
41 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
42 use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface;
43 use AmeliaBooking\Domain\Services\Settings\SettingsService;
44 use AmeliaBooking\Domain\ValueObjects\BooleanValueObject;
45 use AmeliaBooking\Domain\ValueObjects\Number\Float\Price;
46 use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id;
47 use AmeliaBooking\Domain\ValueObjects\Number\Integer\IntegerValue;
48 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
49 use AmeliaBooking\Domain\ValueObjects\String\PaymentType;
50 use AmeliaBooking\Domain\ValueObjects\String\Token;
51 use AmeliaBooking\Domain\ValueObjects\Json;
52 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
53 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository;
54 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
55 use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventPeriodRepository;
56 use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository;
57 use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository;
58 use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository;
59 use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository;
60 use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings;
61 use DateTime;
62 use Exception;
63
64 /**
65 * Class EventReservationService
66 *
67 * @package AmeliaBooking\Application\Services\Reservation
68 */
69 class EventReservationService extends AbstractReservationService
70 {
71 /**
72 * @return string
73 */
74 public function getType()
75 {
76 return Entities::EVENT;
77 }
78
79 /**
80 * @param array $eventData
81 * @param Reservation $reservation
82 * @param bool $save
83 *
84 * @return void
85 *
86 * @throws CouponExpiredException
87 * @throws CouponInvalidException
88 * @throws CouponUnknownException
89 * @throws BookingUnavailableException
90 * @throws InvalidArgumentException
91 * @throws QueryExecutionException
92 * @throws Exception
93 */
94 public function book($eventData, $reservation, $save)
95 {
96 /** @var LocationRepository $locationRepository */
97 $locationRepository = $this->container->get('domain.locations.repository');
98
99 /** @var EventApplicationService $eventApplicationService */
100 $eventApplicationService = $this->container->get('application.booking.event.service');
101
102 /** @var CouponApplicationService $couponAS */
103 $couponAS = $this->container->get('application.coupon.service');
104
105 /** @var AbstractDepositApplicationService $depositAS */
106 $depositAS = $this->container->get('application.deposit.service');
107
108 $this->manageTaxes($eventData);
109
110 /** @var Coupon $coupon */
111 $coupon = !empty($eventData['couponCode']) ? $couponAS->processCoupon(
112 $eventData['couponCode'],
113 [$eventData['eventId']],
114 Entities::EVENT,
115 $eventData['bookings'][0]['customerId'],
116 $reservation->hasCouponValidation()->getValue()
117 ) : null;
118
119 if ($coupon) {
120 $eventData['bookings'][0]['coupon'] = $coupon->toArray();
121
122 $eventData['bookings'][0]['couponId'] = $coupon->getId()->getValue();
123 }
124
125 /** @var Event $event */
126 $event = $eventApplicationService->getEventById(
127 $eventData['eventId'],
128 [
129 'fetchEventsPeriods' => true,
130 'fetchEventsTickets' => true,
131 'fetchApprovedBookings' => true,
132 'fetchBookings' => true,
133 'fetchBookingsTickets' => true,
134 'fetchEventsProviders' => true,
135 ]
136 );
137
138 if ($event->getCustomPricing()->getValue()) {
139 $event->setCustomTickets($eventApplicationService->getTicketsPriceByDateRange($event->getCustomTickets()));
140 }
141
142 $bookingArray = array_merge(
143 $eventData['bookings'][0],
144 empty($eventData['bookings'][0]['status']) ?
145 ['status' => BookingStatus::APPROVED] : ['status' => $eventData['bookings'][0]['status']]
146 );
147
148 $bookingArray = apply_filters('amelia_before_event_booking_saved_filter', $bookingArray, $event ? $event->toArray() : null);
149
150 do_action('amelia_before_event_booking_saved', $bookingArray, $event ? $event->toArray() : null);
151
152 $booking = CustomerBookingFactory::create($bookingArray);
153
154 if ($event->getCustomPricing()->getValue()) {
155 $booking->setPersons(new IntegerValue(0));
156 }
157
158 $bookingStatus = empty($eventData['bookings'][0]['status']) ? BookingStatus::APPROVED : $eventData['bookings'][0]['status'];
159
160 if (!empty($eventData['payment']['gateway'])) {
161 $bookingStatus = in_array($eventData['payment']['gateway'], [PaymentType::MOLLIE, PaymentType::BARION]) ?
162 BookingStatus::PENDING : (empty($eventData['bookings'][0]['status']) ? BookingStatus::APPROVED : $eventData['bookings'][0]['status']);
163
164 if (!empty($eventData['payment']['orderStatus'])) {
165 $bookingStatus = $this->getWcStatus(
166 Entities::EVENT,
167 $eventData['payment']['orderStatus'],
168 'booking',
169 false
170 ) ?: $bookingStatus;
171 }
172 }
173
174 $booking->setStatus(new BookingStatus($bookingStatus));
175
176 $personsCount = 0;
177
178 /** @var CustomerBooking $customerBooking */
179 foreach ($event->getBookings()->getItems() as $customerBooking) {
180 if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED) {
181 $personsCount += $customerBooking->getPersons()->getValue();
182 }
183 if (
184 $customerBooking->getStatus()->getValue() !== BookingStatus::CANCELED &&
185 !$event->getBookMultipleTimes()->getValue() &&
186 $booking->getCustomerId() &&
187 $booking->getCustomerId()->getValue() === $customerBooking->getCustomerId()->getValue()
188 ) {
189 throw new CustomerBookedException(
190 FrontendStrings::getCommonStrings()['customer_already_booked_ev']
191 );
192 }
193 }
194
195 /** @var SettingsService $settingsDS */
196 $settingsDS = $this->container->get('domain.settings.service');
197
198 $limitPerCustomerEvents = $settingsDS->getSetting('roles', 'limitPerCustomerEvent');
199
200 if (
201 !empty($limitPerCustomerEvents) &&
202 $limitPerCustomerEvents['enabled'] &&
203 empty($eventData['isBackendOrCabinet'])
204 ) {
205 /** @var EventRepository $eventRepository */
206 $eventRepository = $this->container->get('domain.booking.event.repository');
207
208 $count = $eventRepository->getRelevantBookingsCount(
209 $event,
210 $booking->toArray(),
211 $limitPerCustomerEvents
212 );
213
214 if ($count >= $limitPerCustomerEvents['numberOfApp']) {
215 throw new BookingsLimitReachedException(
216 FrontendStrings::getCommonStrings()['bookings_limit_reached']
217 );
218 }
219 }
220
221 /** @var AbstractUser $currentUser */
222 $currentUser = $this->container->get('logged.in.user');
223
224 $isCustomer = (!$currentUser || ($currentUser->getType() === AbstractUser::USER_ROLE_CUSTOMER));
225
226 if (
227 $reservation->hasAvailabilityValidation()->getValue() &&
228 $isCustomer &&
229 !$this->isBookable($event, $booking, DateTimeService::getNowDateTimeObject())
230 ) {
231 throw new BookingUnavailableException(
232 FrontendStrings::getCommonStrings()['time_slot_unavailable']
233 );
234 }
235
236
237 $booking->setAggregatedPrice(new BooleanValueObject($event->getAggregatedPrice() ? $event->getAggregatedPrice()->getValue() : true));
238
239 $paymentAmount = $this->getPaymentAmount($booking, $event)['price'];
240
241 $applyDeposit =
242 !empty($eventData['bookings'][0]['deposit']) && $eventData['payment']['gateway'] !== PaymentType::ON_SITE;
243
244 if ($applyDeposit) {
245 $personsCount = $booking->getPersons()->getValue();
246
247 if ($booking->getTicketsBooking() && $event->getCustomPricing()->getValue()) {
248 $personsCount = 0;
249
250 /** @var CustomerBookingEventTicket $bookingToEventTicket */
251 foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) {
252 $personsCount += ($bookingToEventTicket->getPersons() ?
253 $bookingToEventTicket->getPersons()->getValue() : 0);
254 }
255 }
256
257 $paymentDeposit = $depositAS->calculateDepositAmount(
258 $paymentAmount,
259 $event,
260 $personsCount
261 );
262
263 $eventData['payment']['deposit'] = $paymentAmount !== $paymentDeposit;
264
265 $paymentAmount = $paymentDeposit;
266 }
267
268 if ($save) {
269 /** @var CustomerBookingRepository $bookingRepository */
270 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
271
272 /** @var CustomerBookingExtraRepository $bookingExtraRepository */
273 $bookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository');
274
275 /** @var CustomerBookingEventPeriodRepository $bookingEventPeriodRepository */
276 $bookingEventPeriodRepository =
277 $this->container->get('domain.booking.customerBookingEventPeriod.repository');
278
279 /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */
280 $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository');
281
282 $booking->setPrice(new Price($event->getPrice()->getValue()));
283 $booking->setToken(new Token());
284
285 if ($booking->getTicketsBooking() && $event->getCustomPricing()->getValue()) {
286 $ticketSumPrice = 0;
287
288 /** @var CustomerBookingEventTicket $bookingToEventTicket */
289 foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) {
290 /** @var EventTicket $ticket */
291 $ticket = $event->getCustomTickets()->getItem(
292 $bookingToEventTicket->getEventTicketId()->getValue()
293 );
294
295 $ticketPrice = $ticket->getDateRangePrice() ?
296 $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue();
297
298 $ticketSumPrice += $bookingToEventTicket->getPersons() ?
299 ($booking->getAggregatedPrice()->getValue() ? $bookingToEventTicket->getPersons()->getValue() : 1)
300 * $ticketPrice : 0;
301 }
302
303 $booking->setPrice(new Price($ticketSumPrice));
304 }
305
306 $booking->setActionsCompleted(new BooleanValueObject(!empty($eventData['payment']['isBackendBooking'])));
307
308 $bookingId = $bookingRepository->add($booking);
309
310 /** @var CustomerBookingExtra $bookingExtra */
311 foreach ($booking->getExtras()->getItems() as $bookingExtra) {
312 $bookingExtra->setCustomerBookingId(new Id($bookingId));
313 $bookingExtraId = $bookingExtraRepository->add($bookingExtra);
314 $bookingExtra->setId(new Id($bookingExtraId));
315 }
316
317 $booking->setId(new Id($bookingId));
318
319 // BEGIN QR Codes generation for event booking
320 if ($settingsDS->isFeatureEnabled('eTickets')) {
321 /** @var QrCodeApplicationService $qrCodeApplicationService */
322 $qrCodeApplicationService = $this->container->get('application.qrcode.service');
323
324 $qrCodes = $qrCodeApplicationService->createQrCodeEventData($event, $booking);
325
326
327 if (!empty($qrCodes)) {
328 $booking->setQrCodes(new Json(json_encode($qrCodes)));
329 $bookingRepository->update($bookingId, $booking);
330 }
331 }
332 // END QR Codes generation
333
334 /** @var Payment $payment */
335 $payment = $this->addPayment(
336 $booking->getId()->getValue(),
337 null,
338 $eventData['payment'],
339 $paymentAmount,
340 $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(),
341 Entities::EVENT
342 );
343
344 /** @var Collection $payments */
345 $payments = new Collection();
346
347 $payments->addItem($payment);
348
349 $booking->setPayments($payments);
350
351 /** @var EventPeriod $eventPeriod */
352 foreach ($event->getPeriods()->getItems() as $eventPeriod) {
353 /** @var CustomerBookingEventPeriod $bookingEventPeriod */
354 $bookingEventPeriod = CustomerBookingEventPeriodFactory::create(
355 [
356 'eventPeriodId' => $eventPeriod->getId()->getValue(),
357 'customerBookingId' => $bookingId
358 ]
359 );
360
361 $bookingEventPeriodRepository->add($bookingEventPeriod);
362 }
363
364 /** @var CustomerBookingEventTicket $eventTicket */
365 foreach ($booking->getTicketsBooking()->getItems() as $eventTicket) {
366 if ($eventTicket->getPersons()) {
367 /** @var EventTicket $ticket */
368 $ticket = $event->getCustomTickets()->getItem($eventTicket->getEventTicketId()->getValue());
369
370 $ticketPrice = $ticket->getDateRangePrice() ?
371 $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue();
372
373 /** @var CustomerBookingEventTicket $bookingEventTicket */
374 $bookingEventTicket = CustomerBookingEventTicketFactory::create(
375 [
376 'eventTicketId' => $eventTicket->getEventTicketId()->getValue(),
377 'customerBookingId' => $bookingId,
378 'persons' => $eventTicket->getPersons()->getValue(),
379 'price' => $ticketPrice,
380 ]
381 );
382
383 $bookingEventTicketRepository->add($bookingEventTicket);
384 }
385 }
386
387 $event->getBookings()->addItem($booking, $booking->getId()->getValue());
388
389 do_action('amelia_after_event_booking_saved', $booking ? $booking->toArray() : null, $event ? $event->toArray() : null);
390 }
391
392 if ($event->getLocationId()) {
393 /** @var Location $location */
394 $location = $locationRepository->getById($event->getLocationId()->getValue());
395
396 $event->setLocation($location);
397 }
398
399 $reservation->setApplyDeposit(new BooleanValueObject($applyDeposit));
400 if ($booking->getCustomer()) {
401 $reservation->setCustomer($booking->getCustomer());
402 }
403
404 /** @var Collection $bookings */
405 $bookings = new Collection();
406
407 $bookings->addItem($booking);
408
409 $event->setBookings($bookings);
410
411 $reservation->setBookable($event);
412 $reservation->setBooking($booking);
413 $reservation->setReservation($event);
414 $reservation->setRecurring(new Collection());
415 $reservation->setPackageReservations(new Collection());
416 $reservation->setIsStatusChanged(new BooleanValueObject(false));
417 }
418
419 /**
420 * @param CustomerBooking $booking
421 * @param string $requestedStatus
422 * @param bool $inspectCancellationTime
423 *
424 * @return array
425 *
426 * @throws InvalidArgumentException
427 * @throws QueryExecutionException
428 * @throws BookingCancellationException
429 */
430 public function updateStatus($booking, $requestedStatus, $inspectCancellationTime = true)
431 {
432 /** @var CustomerBookingRepository $bookingRepository */
433 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
434 /** @var SettingsService $settingsDS */
435 $settingsDS = $this->container->get('domain.settings.service');
436
437 /** @var Event $event */
438 $event = $this->getReservationByBookingId($booking->getId()->getValue());
439
440 if ($requestedStatus === BookingStatus::CANCELED && $inspectCancellationTime) {
441 $minimumCancelTimeInSeconds = $settingsDS
442 ->getEntitySettings($event->getSettings())
443 ->getGeneralSettings()
444 ->getMinimumTimeRequirementPriorToCanceling();
445
446 $this->inspectMinimumCancellationTime(
447 $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(),
448 $minimumCancelTimeInSeconds
449 );
450 }
451
452 $booking->setStatus(new BookingStatus($requestedStatus));
453
454 $bookingRepository->update($booking->getId()->getValue(), $booking);
455
456 return [
457 Entities::EVENT => $event->toArray(),
458 'appointmentStatusChanged' => false,
459 Entities::BOOKING => $booking->toArray()
460 ];
461 }
462
463 /**
464 * @param Event $reservation
465 * @param CustomerBooking $booking
466 * @param AbstractBookable $bookable
467 *
468 * @return array
469 */
470 public function getBookingPeriods($reservation, $booking, $bookable)
471 {
472 $dates = [];
473
474 /** @var EventPeriod $period */
475 foreach ($reservation->getPeriods()->getItems() as $period) {
476 $dates[] = [
477 'start' => DateTimeService::getCustomDateTimeInUtc(
478 $period->getPeriodStart()->getValue()->format('Y-m-d H:i:s')
479 ),
480 'end' => DateTimeService::getCustomDateTimeInUtc(
481 $period->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')
482 )
483 ];
484 }
485
486 return $dates;
487 }
488
489 /**
490 * @param array $data
491 *
492 * @return AbstractBookable
493 *
494 * @throws QueryExecutionException
495 * @throws InvalidArgumentException
496 */
497 public function getBookableEntity($data)
498 {
499 /** @var EventRepository $eventRepository */
500 $eventRepository = $this->container->get('domain.booking.event.repository');
501
502 return $eventRepository->getById($data['eventId']);
503 }
504
505 /**
506 * @param Event $bookable
507 *
508 * @return boolean
509 */
510 public function isAggregatedPrice($bookable)
511 {
512 return $bookable->getAggregatedPrice()->getValue();
513 }
514
515 /**
516 * @param BooleanValueObject $bookableAggregatedPrice
517 * @param BooleanValueObject $extraAggregatedPrice
518 *
519 * @return boolean
520 */
521 public function isExtraAggregatedPrice($extraAggregatedPrice, $bookableAggregatedPrice)
522 {
523 return true;
524 }
525
526 /**
527 * @param Reservation $reservation
528 * @param string $paymentGateway
529 * @param array $requestData
530 *
531 * @return array
532 *
533 * @throws InvalidArgumentException
534 */
535 public function getWooCommerceData($reservation, $paymentGateway, $requestData)
536 {
537 /** @var Event $event */
538 $event = $reservation->getBookable();
539
540 /** @var AbstractUser $customer */
541 $customer = $reservation->getCustomer();
542
543 /** @var CustomerBooking $booking */
544 $booking = $reservation->getBooking();
545
546 $dateTimeValues = [];
547
548 /** @var EventPeriod $period */
549 foreach ($event->getPeriods()->getItems() as $period) {
550 $dateTimeValues[] = [
551 'start' => $period->getPeriodStart()->getValue()->format('Y-m-d H:i'),
552 'end' => $period->getPeriodEnd()->getValue()->format('Y-m-d H:i')
553 ];
554 }
555
556 $info = [
557 'type' => Entities::EVENT,
558 'eventId' => $event->getId()->getValue(),
559 'name' => $event->getName()->getValue(),
560 'couponId' => $booking->getCoupon() ? $booking->getCoupon()->getId()->getValue() : '',
561 'couponCode' => $booking->getCoupon() ? $booking->getCoupon()->getCode()->getValue() : '',
562 'dateTimeValues' => $dateTimeValues,
563 'bookings' => [
564 [
565 'customerId' => $customer->getId() ? $customer->getId()->getValue() : null,
566 'customer' => [
567 'email' => $customer->getEmail()->getValue(),
568 'externalId' => $customer->getExternalId() ? $customer->getExternalId()->getValue() : null,
569 'firstName' => $customer->getFirstName()->getValue(),
570 'id' => $customer->getId() ? $customer->getId()->getValue() : null,
571 'lastName' => $customer->getLastName()->getValue(),
572 'phone' => $customer->getPhone()->getValue(),
573 'countryPhoneIso' => $customer->getCountryPhoneIso() ?
574 $customer->getCountryPhoneIso()->getValue() : null,
575 'customFields' => $customer->getCustomFields() ?
576 json_decode($customer->getCustomFields()->getValue(), true) : null,
577 ],
578 'info' => $booking->getInfo()->getValue(),
579 'persons' => $booking->getPersons()->getValue(),
580 'extras' => [],
581 'utcOffset' => $booking->getUtcOffset() ? $booking->getUtcOffset()->getValue() : null,
582 'customFields' => $booking->getCustomFields() ?
583 json_decode($booking->getCustomFields()->getValue(), true) : null,
584 'deposit' => $reservation->getApplyDeposit()->getValue(),
585 'ticketsData' => $requestData['bookings'][0]['ticketsData'],
586 ]
587 ],
588 'payment' => [
589 'gateway' => $paymentGateway
590 ],
591 'locale' => $reservation->getLocale()->getValue(),
592 'timeZone' => $reservation->getTimeZone()->getValue(),
593 'recurring' => [],
594 'package' => [],
595 'ivy' => !empty($requestData['ivy']) ? $requestData['ivy'] : null,
596 ];
597
598 foreach ($booking->getExtras()->keys() as $extraKey) {
599 /** @var CustomerBookingExtra $bookingExtra */
600 $bookingExtra = $booking->getExtras()->getItem($extraKey);
601
602 $info['bookings'][0]['extras'][] = [
603 'extraId' => $bookingExtra->getExtraId()->getValue(),
604 'quantity' => $bookingExtra->getQuantity()->getValue()
605 ];
606 }
607
608 return $info;
609 }
610
611
612 /**
613 * @param array $reservation
614 *
615 * @return array
616 *
617 * @throws InvalidArgumentException
618 */
619 public function getWooCommerceDataFromArray($reservation, $index)
620 {
621 /** @var array $event */
622 $event = $reservation['bookable'];
623
624 /** @var array $customer */
625 $customer = !empty($reservation['customer'])
626 ? $reservation['customer']
627 : (!empty($reservation['booking']['customer']) ? $reservation['booking']['customer'] : null);
628
629 /** @var array $booking */
630 $booking = $reservation['booking'];
631
632 if (!empty($booking['ticketsData'])) {
633 foreach ($booking['ticketsData'] as &$ticket) {
634 $customTicketIndex = array_search(
635 $ticket['eventTicketId'],
636 array_column($reservation['event']['customTickets'], 'id')
637 );
638 if ($customTicketIndex !== false) {
639 $ticket['name'] = $reservation['event']['customTickets'][$customTicketIndex]['name'];
640 }
641 }
642 }
643
644 $dateTimeValues = [];
645
646 $customerInfo = !empty($booking['info']) ? json_decode($booking['info'], true) : null;
647
648 foreach ($event['periods'] as $period) {
649 $dateTimeValues[] = [
650 'start' => $period['periodStart'],
651 'end' => $period['periodEnd']
652 ];
653 }
654
655 $info = [
656 'type' => Entities::EVENT,
657 'eventId' => $event['id'],
658 'name' => $event['name'],
659 'couponId' => $booking['coupon'] ? $booking['coupon']['id'] : '',
660 'couponCode' => $booking['coupon'] ? $booking['coupon']['code'] : '',
661 'dateTimeValues' => $dateTimeValues,
662 'bookings' => [
663 [
664 'customerId' => $customer['id'],
665 'customer' => [
666 'email' => $customer['email'],
667 'externalId' => $customer['externalId'],
668 'firstName' => $customer['firstName'],
669 'id' => $customer['id'],
670 'lastName' => $customer['lastName'],
671 'phone' => $customer['phone'],
672 'countryPhoneIso' => $customer['countryPhoneIso']
673 ],
674 'info' => $booking['info'],
675 'persons' => $booking['persons'],
676 'extras' => [],
677 'utcOffset' => $booking['utcOffset'],
678 'customFields' => $booking['customFields'] ?
679 json_decode($booking['customFields'], true) : null,
680 'deposit' => $booking['price'] > $booking['payments'][0]['amount'],
681 'ticketsData' => $booking['ticketsData'],
682 ]
683 ],
684 'payment' => [
685 'gateway' => $booking['payments'][0]['gateway']
686 ],
687 'locale' => $customerInfo ? $customerInfo['locale'] : null,
688 'timeZone' => $customerInfo ? $customerInfo['timeZone'] : null,
689 'recurring' => [],
690 'package' => [],
691 ];
692
693 foreach ($booking['extras'] as $extra) {
694 $info['bookings'][0]['extras'][] = [
695 'extraId' => $extra['id'],
696 'quantity' => $extra['quantity']
697 ];
698 }
699
700 return $info;
701 }
702
703 /**
704 * @param int $id
705 *
706 * @return Event
707 *
708 * @throws QueryExecutionException
709 * @throws InvalidArgumentException
710 */
711 public function getReservationByBookingId($id)
712 {
713 /** @var EventRepository $eventRepository */
714 $eventRepository = $this->container->get('domain.booking.event.repository');
715
716 /** @var Event $event */
717 $event = $eventRepository->getByBookingId(
718 $id,
719 [
720 'fetchEventsTickets' => true,
721 'fetchEventsTags' => true,
722 'fetchEventsProviders' => true,
723 'fetchEventsImages' => true,
724 ]
725 );
726
727 /** @var Collection $eventsBookings */
728 $eventsBookings = $eventRepository->getBookingsByCriteria(
729 [
730 'ids' => [$event->getId()->getValue()],
731 'fetchBookings' => true,
732 'fetchBookingsTickets' => true,
733 'fetchBookingsUsers' => true,
734 'fetchBookingsPayments' => true,
735 ]
736 );
737
738 if ($eventsBookings->keyExists($event->getId()->getValue())) {
739 $event->setBookings($eventsBookings->getItem($event->getId()->getValue()));
740 }
741
742 return $event;
743 }
744
745 /**
746 * @param Event $reservation
747 * @param CustomerBooking $newBooking
748 * @param DateTime $dateTime
749 *
750 * @return boolean
751 *
752 * @throws InvalidArgumentException
753 */
754 public function isBookable($reservation, $newBooking, $dateTime)
755 {
756 if ($reservation->getCustomPricing() && $reservation->getCustomPricing()->getValue() && !$reservation->getMaxCustomCapacity()) {
757 $availableTicketsSpots = [];
758
759 $reservedTicketsSpots = [];
760
761 /** @var EventTicket $ticket */
762 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
763 $availableTicketsSpots[$ticket->getId()->getValue()] = $ticket->getSpots()->getValue();
764
765 if (!$reservation->getBookings()->length()) {
766 $reservedTicketsSpots[$ticket->getId()->getValue()] = $ticket->getSold() ? $ticket->getSold()->getValue() : 0;
767 }
768 }
769
770 /** @var CustomerBooking $booking */
771 foreach ($reservation->getBookings()->getItems() as $booking) {
772 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
773 /** @var CustomerBookingEventTicket $bookingTicket */
774 foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) {
775 $eventTicketId = $bookingTicket->getEventTicketId()->getValue();
776
777 if (!array_key_exists($eventTicketId, $reservedTicketsSpots)) {
778 $reservedTicketsSpots[$eventTicketId] = 0;
779 }
780
781 $reservedTicketsSpots[$eventTicketId] += $bookingTicket->getPersons()->getValue();
782 }
783 }
784 }
785
786 if ($newBooking) {
787 /** @var CustomerBookingEventTicket $newBookingTicket */
788 foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) {
789 $eventTicketId = $newBookingTicket->getEventTicketId()->getValue();
790
791 if (empty($reservedTicketsSpots[$eventTicketId])) {
792 $reservedTicketsSpots[$eventTicketId] = 0;
793 }
794
795 $reservedTicketsSpots[$eventTicketId] +=
796 $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0;
797 }
798 }
799
800 $hasTicketCapacity = [];
801
802 foreach ($availableTicketsSpots as $eventTicketId => $availablePersons) {
803 $hasTicketCapacity[$eventTicketId] = !array_key_exists($eventTicketId, $reservedTicketsSpots) ||
804 (
805 $newBooking
806 ? $reservedTicketsSpots[$eventTicketId] <= $availablePersons
807 : $reservedTicketsSpots[$eventTicketId] < $availablePersons
808 );
809 }
810
811 $hasCapacity = false;
812
813 foreach ($hasTicketCapacity as $ticketId => $ticketCapacity) {
814 if ($newBooking) {
815 $hasCapacity = true;
816
817 /** @var EventTicket $ticket */
818 $ticket = $reservation->getCustomTickets()->getItem($ticketId);
819
820 /** @var CustomerBookingEventTicket $ticketBooking */
821 foreach ($newBooking->getTicketsBooking()->getItems() as $ticketBooking) {
822 if (
823 $ticketBooking->getEventTicketId()->getValue() === $ticketId &&
824 $ticketBooking->getPersons() &&
825 $ticketBooking->getPersons()->getValue() &&
826 (!$ticketCapacity || !$ticket->getEnabled()->getValue())
827 ) {
828 $hasCapacity = false;
829
830 break 2;
831 }
832 }
833 } else {
834 $hasCapacity = $hasCapacity || $ticketCapacity;
835 }
836 }
837 } elseif ($reservation->getMaxCustomCapacity()) {
838 $availableTicketsSpots = $reservation->getMaxCustomCapacity()->getValue();
839
840 $reservedTicketsSpots = 0;
841
842 if (!$reservation->getBookings()->length()) {
843 /** @var EventTicket $ticket */
844 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
845 $reservedTicketsSpots += $ticket->getSold() ? $ticket->getSold()->getValue() : 0;
846 }
847 }
848
849 /** @var CustomerBooking $booking */
850 foreach ($reservation->getBookings()->getItems() as $booking) {
851 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
852 /** @var CustomerBookingEventTicket $bookingTicket */
853 foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) {
854 $reservedTicketsSpots += $bookingTicket->getPersons()->getValue();
855 }
856 }
857 }
858
859 if ($newBooking) {
860 /** @var CustomerBookingEventTicket $newBookingTicket */
861 foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) {
862 $reservedTicketsSpots += $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0;
863 }
864 }
865
866 $hasCapacity = ($newBooking ? $reservedTicketsSpots <= $availableTicketsSpots : $reservedTicketsSpots < $availableTicketsSpots);
867 } else {
868 $persons = !$reservation->getBookings()->length() && $reservation->getSpotsSold()
869 ? $reservation->getSpotsSold()->getValue()
870 : 0;
871
872 /** @var CustomerBooking $booking */
873 foreach ($reservation->getBookings()->getItems() as $booking) {
874 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
875 $persons += $booking->getPersons()->getValue();
876 }
877 }
878
879 if ($newBooking) {
880 $hasCapacity = ($reservation->getMaxCapacity()->getValue() - $persons - $newBooking->getPersons()->getValue()) >= 0;
881 } else {
882 $hasCapacity = $reservation->getMaxCapacity()->getValue() - $persons > 0;
883 }
884 }
885
886 $bookingCloses = $reservation->getBookingCloses() ?
887 $reservation->getBookingCloses()->getValue() :
888 $reservation->getPeriods()->getItem(0)->getPeriodStart()->getValue();
889
890 $bookingOpens = $reservation->getBookingOpens() ?
891 $reservation->getBookingOpens()->getValue() :
892 $reservation->getCreated()->getValue();
893
894 $hasWaitingList = false;
895 $eventSettings = $reservation->getSettings() ? json_decode($reservation->getSettings()->getValue(), true) : null;
896
897 /** @var SettingsService $settingsDS */
898 $settingsDS = $this->container->get('domain.settings.service');
899
900 if (
901 $settingsDS->isFeatureEnabled('waitingList') && $eventSettings && !empty($eventSettings['waitingList']) &&
902 $eventSettings['waitingList']['enabled']
903 ) {
904 $waitingCustomers = 0;
905
906 if (!$reservation->getBookings()->length()) {
907 if ($reservation->getCustomPricing()->getValue()) {
908 /** @var EventTicket $ticket */
909 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
910 $waitingCustomers += $ticket->getWaiting() ? $ticket->getWaiting()->getValue() : 0;
911 }
912 } else {
913 $waitingCustomers += $reservation->getSpotsWaiting() ? $reservation->getSpotsWaiting()->getValue() : 0;
914 }
915 }
916
917 /** @var CustomerBooking $booking */
918 foreach ($reservation->getBookings()->getItems() as $booking) {
919 if ($booking->getStatus()->getValue() === BookingStatus::WAITING) {
920 if ($reservation->getCustomPricing()->getValue()) {
921 foreach ($booking->getTicketsBooking()->getItems() as $item) {
922 $waitingCustomers += $item->getPersons()->getValue();
923 }
924 } else {
925 $waitingCustomers += $booking->getPersons()->getValue();
926 }
927 }
928 }
929
930 if ($newBooking && $reservation->getCustomPricing() && $reservation->getCustomPricing()->getValue()) {
931 foreach ($newBooking->getTicketsBooking()->getItems() as $item) {
932 if (!$reservation->getMaxCustomCapacity()) {
933 $ticketData = $reservation->getCustomTickets()->getItem($item->getId()->getValue());
934
935 $waitingListSpots = $ticketData->getWaitingListSpots() ? $ticketData->getWaitingListSpots()->getValue() : 0;
936
937 $personsValue = $item->getPersons() ? $item->getPersons()->getValue() : 0;
938 $waitingValue = $ticketData->getWaiting() ? $ticketData->getWaiting()->getValue() : 0;
939
940 $hasWaitingList = $waitingListSpots >= ($personsValue + $waitingValue);
941 }
942 }
943
944 if ($reservation->getMaxCustomCapacity()) {
945 $hasWaitingList = $eventSettings['waitingList']['maxCapacity'] > $waitingCustomers;
946 }
947 } else {
948 $hasWaitingList = $eventSettings['waitingList']['maxCapacity'] > $waitingCustomers;
949 }
950
951 $eventSettings['waitingList']['peopleWaiting'] = $waitingCustomers;
952
953 $reservation->setSettings(new Json(json_encode($eventSettings)));
954 }
955
956 return $dateTime > $bookingOpens &&
957 $dateTime < $bookingCloses &&
958 ($hasCapacity || ($hasWaitingList && $newBooking && $newBooking->getStatus()->getValue() === BookingStatus::WAITING)) &&
959 in_array($reservation->getStatus()->getValue(), [BookingStatus::APPROVED, BookingStatus::PENDING], true);
960 }
961
962 /**
963 * @param CustomerBooking $booking
964 * @param Event $bookable
965 * @param bool $invoice
966 *
967 * @return array
968 *
969 * @throws InvalidArgumentException
970 */
971 public function getPaymentAmount($booking, $bookable, $invoice = false)
972 {
973 /** @var TaxApplicationService $taxApplicationService */
974 $taxApplicationService = $this->container->get('application.tax.service');
975
976 /** @var Tax $eventTax */
977 $eventTax = $this->getTax($booking->getTax());
978
979 $persons = $booking->getPersons()->getValue();
980
981 $unitPrice = (float)$bookable->getPrice()->getValue();
982
983 $price = $unitPrice * ($this->isAggregatedPrice($bookable) ? $persons : 1);
984
985 $taxAmount = 0;
986
987 $ticketsTax = [];
988
989 if (
990 $booking->getTicketsBooking() &&
991 $booking->getTicketsBooking()->length() &&
992 $bookable->getCustomPricing() &&
993 $bookable->getCustomPricing()->getValue()
994 ) {
995 /** @var EventApplicationService $eventApplicationService */
996 $eventApplicationService = $this->container->get('application.booking.event.service');
997
998 $bookable->setCustomTickets(
999 $eventApplicationService->getTicketsPriceByDateRange($bookable->getCustomTickets())
1000 );
1001
1002 $ticketSumPrice = 0;
1003
1004 /** @var CustomerBookingEventTicket $bookingToEventTicket */
1005 foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) {
1006 /** @var EventTicket $ticket */
1007 $ticket = $bookable->getCustomTickets()->getItem($bookingToEventTicket->getEventTicketId()->getValue());
1008
1009 $ticketPrice = $ticket->getDateRangePrice() ?
1010 $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue();
1011
1012 $ticketPersons = $bookingToEventTicket->getPersons() ?
1013 ($booking->getAggregatedPrice()->getValue() ? $bookingToEventTicket->getPersons()->getValue() : 1)
1014 : 0;
1015
1016 $ticketSubtotal = $ticketPersons * $ticketPrice;
1017
1018 $ticketSumPrice += $ticketSubtotal;
1019
1020 if ($bookingToEventTicket->getId()) {
1021 if ($eventTax && $eventTax->getExcluded()->getValue()) {
1022 $ticketsTax[$bookingToEventTicket->getId()->getValue()] = $this->getTaxAmount($eventTax, $ticketSubtotal);
1023 } elseif ($eventTax && !$eventTax->getExcluded()->getValue()) {
1024 $ticketsTax[$bookingToEventTicket->getId()->getValue()] =
1025 $this->getTaxAmount($eventTax, $taxApplicationService->getBasePrice($ticketSubtotal, $eventTax));
1026 } else {
1027 $ticketsTax[$bookingToEventTicket->getId()->getValue()] = 0;
1028 }
1029 }
1030 }
1031
1032 $price = $ticketSumPrice;
1033 }
1034
1035 if ($eventTax && !$eventTax->getExcluded()->getValue() && ($booking->getCoupon() || $invoice)) {
1036 $price = $taxApplicationService->getBasePrice($price, $eventTax);
1037 }
1038
1039 $priceWithoutCoupon = $price;
1040
1041 $subtotalPrice = round($price, 4);
1042
1043 $subtraction = 0;
1044
1045 $reductionAmount = [
1046 'deduction' => 0,
1047 'discount' => 0,
1048 ];
1049
1050 if ($booking->getCoupon()) {
1051 $reductionAmount['discount'] = $price / 100 * ($booking->getCoupon()->getDiscount()->getValue() ?: 0);
1052
1053 $reductionAmount['deduction'] = $booking->getCoupon()->getDeduction()->getValue();
1054
1055 $subtraction = $reductionAmount['discount'] + $reductionAmount['deduction'];
1056
1057 $price = max($price - $subtraction, 0);
1058 }
1059
1060 if ($eventTax && ($eventTax->getExcluded()->getValue() || $subtraction || $invoice)) {
1061 $taxAmount = $this->getTaxAmount($eventTax, $price);
1062 $price += $taxAmount;
1063 $priceWithoutCoupon += $taxAmount;
1064 }
1065
1066 $price = (float)max(round($price, 2), 0);
1067
1068 if (!$price) {
1069 foreach ($ticketsTax as $ticketId => $ticketTax) {
1070 $ticketsTax[$ticketId] = 0;
1071 }
1072 }
1073
1074 return [
1075 'price' => apply_filters('amelia_modify_payment_amount', $price, $booking),
1076 'discount' => $reductionAmount['discount'],
1077 'deduction' => $reductionAmount['deduction'],
1078 'total' => $priceWithoutCoupon,
1079 'unit_price' => $unitPrice,
1080 'qty' => $this->isAggregatedPrice($bookable) ? $persons : 1,
1081 'bookable' => $subtotalPrice,
1082 'subtotal' => $subtotalPrice,
1083 'tax' => $eventTax ? $this->getTaxAmount($eventTax, $subtotalPrice) : 0,
1084 'total_tax' => $taxAmount,
1085 'tax_rate' => $eventTax ? $this->getTaxRate($eventTax) : '',
1086 'tax_type' => $eventTax ? $eventTax->getType()->getValue() : '',
1087 'tax_excluded' => $eventTax ? $eventTax->getExcluded()->getValue() : false,
1088 'tickets_tax' => $ticketsTax,
1089 'full_discount' =>
1090 $this->getCouponDiscountAmount($booking->getCoupon(), $priceWithoutCoupon) +
1091 ($booking->getCoupon() && $booking->getCoupon()->getDeduction() ? (float)$booking->getCoupon()->getDeduction()->getValue() : 0)
1092 ];
1093 }
1094
1095 /**
1096 * @param Reservation $reservation
1097 *
1098 * @return float
1099 *
1100 * @throws InvalidArgumentException
1101 */
1102 public function getReservationPaymentAmount($reservation)
1103 {
1104 /** @var AbstractDepositApplicationService $depositAS */
1105 $depositAS = $this->container->get('application.deposit.service');
1106
1107 /** @var Event $bookable */
1108 $bookable = $reservation->getBookable();
1109
1110 $paymentAmount = $this->getPaymentAmount($reservation->getBooking(), $bookable)['price'];
1111
1112 if ($reservation->getApplyDeposit()->getValue()) {
1113 $personsCount = $reservation->getBooking()->getPersons()->getValue();
1114
1115 if ($reservation->getBooking()->getTicketsBooking() && $bookable->getCustomPricing()->getValue()) {
1116 $personsCount = 0;
1117
1118 /** @var CustomerBookingEventTicket $bookingToEventTicket */
1119 foreach ($reservation->getBooking()->getTicketsBooking()->getItems() as $bookingToEventTicket) {
1120 $personsCount += ($bookingToEventTicket->getPersons() ?
1121 $bookingToEventTicket->getPersons()->getValue() : 0);
1122 }
1123 }
1124
1125 $paymentAmount = $depositAS->calculateDepositAmount(
1126 $paymentAmount,
1127 $bookable,
1128 $personsCount
1129 );
1130 }
1131
1132 return $paymentAmount;
1133 }
1134
1135 /**
1136 * @param Reservation $reservation
1137 * @param bool $usePayment
1138 *
1139 * @return array
1140 *
1141 * @throws InvalidArgumentException
1142 */
1143 public function getProvidersPaymentAmount($reservation, $usePayment = true)
1144 {
1145 $amountData = [];
1146
1147 /** @var Payment $payment */
1148 $payment = $usePayment ? $reservation->getBooking()->getPayments()->getItem(0) : null;
1149
1150 /** @var Event $event */
1151 $event = $reservation->getBookable();
1152
1153 /** @var Provider $provider */
1154 foreach ($event->getProviders()->getItems() as $provider) {
1155 $amountData[$provider->getId()->getValue()][] = [
1156 'paymentId' => $payment ? $payment->getId()->getValue() : null,
1157 'amount' => $this->getReservationPaymentAmount($reservation),
1158 ];
1159 }
1160
1161 return $amountData;
1162 }
1163
1164 /**
1165 * @param Payment $payment
1166 * @param boolean $fromLink
1167 *
1168 * @return CommandResult
1169 * @throws InvalidArgumentException
1170 * @throws Exception
1171 */
1172 public function getReservationByPayment($payment, $fromLink = false)
1173 {
1174 $result = new CommandResult();
1175
1176 /** @var CustomerRepository $customerRepository */
1177 $customerRepository = $this->container->get('domain.users.customers.repository');
1178
1179 /** @var LocationRepository $locationRepository */
1180 $locationRepository = $this->container->get('domain.locations.repository');
1181
1182 /** @var ReservationServiceInterface $reservationService */
1183 $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT);
1184
1185 /** @var Event $event */
1186 $event = $reservationService->getReservationByBookingId(
1187 $payment->getCustomerBookingId()->getValue()
1188 );
1189
1190 if ($event->getLocationId()) {
1191 /** @var Location $location */
1192 $location = $locationRepository->getById($event->getLocationId()->getValue());
1193
1194 $event->setLocation($location);
1195 }
1196
1197 /** @var CustomerBooking $booking */
1198 $booking = $event->getBookings()->getItem($payment->getCustomerBookingId()->getValue());
1199
1200 $booking->setChangedStatus(new BooleanValueObject(true));
1201
1202 $this->setToken($booking);
1203
1204 /** @var AbstractUser $customer */
1205 $customer = $customerRepository->getById($booking->getCustomerId()->getValue());
1206
1207 $result->setData(
1208 [
1209 'type' => Entities::EVENT,
1210 Entities::EVENT => $event->toArray(),
1211 Entities::BOOKING => $booking->toArray(),
1212 'appointmentStatusChanged' => false,
1213 'customer' => $customer->toArray(),
1214 'packageId' => 0,
1215 'recurring' => [],
1216 'utcTime' => $reservationService->getBookingPeriods(
1217 $event,
1218 $booking,
1219 $event
1220 ),
1221 'bookable' => $event->toArray(),
1222 'isRetry' => !$fromLink,
1223 'fromLink' => $fromLink,
1224 'paymentId' => $payment->getId()->getValue(),
1225 'packageCustomerId' => null,
1226 'payment' => [
1227 'id' => $payment->getId()->getValue(),
1228 'amount' => $payment->getAmount()->getValue(),
1229 'gateway' => $payment->getGateway()->getName()->getValue(),
1230 'gatewayTitle' => $payment->getGatewayTitle() ? $payment->getGatewayTitle()->getValue() : '',
1231 'invoiceNumber' => $payment->getInvoiceNumber() ? $payment->getInvoiceNumber()->getValue() : '',
1232 ],
1233 ]
1234 );
1235
1236 return $result;
1237 }
1238
1239 /**
1240 * @param int $bookingId
1241 *
1242 * @return CommandResult
1243 * @throws InvalidArgumentException
1244 * @throws Exception
1245 */
1246 public function getBookingResultByBookingId($bookingId)
1247 {
1248 $result = new CommandResult();
1249
1250 /** @var CustomerRepository $customerRepository */
1251 $customerRepository = $this->container->get('domain.users.customers.repository');
1252
1253 /** @var LocationRepository $locationRepository */
1254 $locationRepository = $this->container->get('domain.locations.repository');
1255
1256 /** @var ReservationServiceInterface $reservationService */
1257 $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT);
1258
1259 /** @var Event $event */
1260 $event = $reservationService->getReservationByBookingId(
1261 $bookingId
1262 );
1263
1264 if ($event->getLocationId()) {
1265 /** @var Location $location */
1266 $location = $locationRepository->getById($event->getLocationId()->getValue());
1267
1268 $event->setLocation($location);
1269 }
1270
1271 /** @var CustomerBooking $booking */
1272 $booking = $event->getBookings()->getItem($bookingId);
1273
1274 $booking->setChangedStatus(new BooleanValueObject(true));
1275
1276 $this->setToken($booking);
1277
1278 /** @var AbstractUser $customer */
1279 $customer = $customerRepository->getById($booking->getCustomerId()->getValue());
1280
1281 $result->setData(
1282 [
1283 'type' => Entities::EVENT,
1284 Entities::EVENT => $event->toArray(),
1285 Entities::BOOKING => $booking->toArray(),
1286 'appointmentStatusChanged' => false,
1287 'customer' => $customer->toArray(),
1288 'packageId' => 0,
1289 'recurring' => [],
1290 'utcTime' => $reservationService->getBookingPeriods(
1291 $event,
1292 $booking,
1293 $event
1294 ),
1295 'isRetry' => true,
1296 'paymentId' => null,
1297 'packageCustomerId' => null,
1298 'payment' => null,
1299 ]
1300 );
1301
1302 return $result;
1303 }
1304
1305 /**
1306 * @param array $data
1307 *
1308 * @return void
1309 * @throws QueryExecutionException
1310 */
1311 public function manageTaxes(&$data)
1312 {
1313 /** @var TaxApplicationService $taxAS */
1314 $taxAS = $this->container->get('application.tax.service');
1315
1316 /** @var SettingsService $settingsService */
1317 $settingsService = $this->container->get('domain.settings.service');
1318
1319 if ($settingsService->isFeatureEnabled('tax')) {
1320 /** @var Collection $taxes */
1321 $taxes = $taxAS->getAll();
1322
1323 $data['bookings'][0]['tax'] = $taxAS->getTaxData(
1324 $data['eventId'],
1325 Entities::EVENT,
1326 $taxes
1327 );
1328 }
1329 }
1330
1331 /**
1332 * @param int $bookingId
1333 *
1334 * @return array
1335 *
1336 * @throws AccessDeniedException
1337 * @throws InvalidArgumentException
1338 * @throws QueryExecutionException
1339 */
1340 public function deleteBooking($bookingId)
1341 {
1342 /** @var CustomerBookingRepository $customerBookingRepository */
1343 $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository');
1344
1345 /** @var EventApplicationService $eventApplicationService */
1346 $eventApplicationService = $this->container->get('application.booking.event.service');
1347
1348 /** @var CustomerBooking $customerBooking */
1349 $customerBooking = $customerBookingRepository->getById((int)$bookingId);
1350
1351 if (!$customerBooking) {
1352 throw new \Exception('Booking not found');
1353 }
1354
1355 $customerBookingRepository->beginTransaction();
1356
1357 if (!$eventApplicationService->deleteEventBooking($customerBooking)) {
1358 $customerBookingRepository->rollback();
1359 throw new \Exception('Could not delete booking');
1360 }
1361
1362 $customerBookingRepository->commit();
1363
1364 return [];
1365 }
1366
1367 /**
1368 * @param array $data
1369 * @param bool $invoices
1370 *
1371 * @return array
1372 * @throws InvalidArgumentException
1373 */
1374 public function getPaymentSummary($data, $invoices)
1375 {
1376 /** @var Event $bookable */
1377 $bookable = EventFactory::create(
1378 [
1379 'price' => $data['bookedPrice'] * ($data['aggregatedPrice'] ? $data['persons'] : 1),
1380 'aggregatedPrice' => $data['aggregatedPrice'],
1381 'customPricing' => false,
1382 'customTickets' => [],
1383 ]
1384 );
1385
1386 /** @var CustomerBooking $booking */
1387 $booking = CustomerBookingFactory::create(
1388 [
1389 'persons' => 1,
1390 'aggregatedPrice' => $data['aggregatedPrice'],
1391 'ticketsData' => null,
1392 'coupon' => $data['coupon'],
1393 'tax' => $data['bookedTax'],
1394 ]
1395 );
1396
1397 return $this->getCommonPaymentSummary($booking, $bookable, $data, $invoices);
1398 }
1399 }
1400