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