PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.3
Booking for Appointments and Events Calendar – Amelia v2.3
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 2 months ago AppointmentReservationService.php 2 months ago EventReservationService.php 3 months ago ReservationService.php 2 years ago
EventReservationService.php
1413 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 $reservedTicketsSpots = [];
774
775 /** @var EventTicket $ticket */
776 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
777 $availableTicketsSpots[$ticket->getId()->getValue()] = $ticket->getSpots()->getValue();
778
779 if (!$reservation->getBookings()->length()) {
780 $reservedTicketsSpots[$ticket->getId()->getValue()] = $ticket->getSold() ? $ticket->getSold()->getValue() : 0;
781 }
782 }
783
784 /** @var CustomerBooking $booking */
785 foreach ($reservation->getBookings()->getItems() as $booking) {
786 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
787 /** @var CustomerBookingEventTicket $bookingTicket */
788 foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) {
789 $eventTicketId = $bookingTicket->getEventTicketId()->getValue();
790
791 if (!array_key_exists($eventTicketId, $reservedTicketsSpots)) {
792 $reservedTicketsSpots[$eventTicketId] = 0;
793 }
794
795 $reservedTicketsSpots[$eventTicketId] += $bookingTicket->getPersons()->getValue();
796 }
797 }
798 }
799
800 if ($newBooking) {
801 /** @var CustomerBookingEventTicket $newBookingTicket */
802 foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) {
803 $eventTicketId = $newBookingTicket->getEventTicketId()->getValue();
804
805 if (empty($reservedTicketsSpots[$eventTicketId])) {
806 $reservedTicketsSpots[$eventTicketId] = 0;
807 }
808
809 $reservedTicketsSpots[$eventTicketId] +=
810 $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0;
811 }
812 }
813
814 $hasTicketCapacity = [];
815
816 foreach ($availableTicketsSpots as $eventTicketId => $availablePersons) {
817 $hasTicketCapacity[$eventTicketId] = !array_key_exists($eventTicketId, $reservedTicketsSpots) ||
818 (
819 $newBooking
820 ? $reservedTicketsSpots[$eventTicketId] <= $availablePersons
821 : $reservedTicketsSpots[$eventTicketId] < $availablePersons
822 );
823 }
824
825 $hasCapacity = false;
826
827 foreach ($hasTicketCapacity as $ticketId => $ticketCapacity) {
828 if ($newBooking) {
829 $hasCapacity = true;
830
831 /** @var EventTicket $ticket */
832 $ticket = $reservation->getCustomTickets()->getItem($ticketId);
833
834 /** @var CustomerBookingEventTicket $ticketBooking */
835 foreach ($newBooking->getTicketsBooking()->getItems() as $ticketBooking) {
836 if (
837 $ticketBooking->getEventTicketId()->getValue() === $ticketId &&
838 $ticketBooking->getPersons() &&
839 $ticketBooking->getPersons()->getValue() &&
840 (!$ticketCapacity || !$ticket->getEnabled()->getValue())
841 ) {
842 $hasCapacity = false;
843
844 break 2;
845 }
846 }
847 } else {
848 $hasCapacity = $hasCapacity || $ticketCapacity;
849 }
850 }
851 } elseif ($reservation->getMaxCustomCapacity()) {
852 $availableTicketsSpots = $reservation->getMaxCustomCapacity()->getValue();
853
854 $reservedTicketsSpots = 0;
855
856 if (!$reservation->getBookings()->length()) {
857 /** @var EventTicket $ticket */
858 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
859 $reservedTicketsSpots += $ticket->getSold() ? $ticket->getSold()->getValue() : 0;
860 }
861 }
862
863 /** @var CustomerBooking $booking */
864 foreach ($reservation->getBookings()->getItems() as $booking) {
865 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
866 /** @var CustomerBookingEventTicket $bookingTicket */
867 foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) {
868 $reservedTicketsSpots += $bookingTicket->getPersons()->getValue();
869 }
870 }
871 }
872
873 if ($newBooking) {
874 /** @var CustomerBookingEventTicket $newBookingTicket */
875 foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) {
876 $reservedTicketsSpots += $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0;
877 }
878 }
879
880 $hasCapacity = ($newBooking ? $reservedTicketsSpots <= $availableTicketsSpots : $reservedTicketsSpots < $availableTicketsSpots);
881 } else {
882 $persons = !$reservation->getBookings()->length() && $reservation->getSpotsSold()
883 ? $reservation->getSpotsSold()->getValue()
884 : 0;
885
886 /** @var CustomerBooking $booking */
887 foreach ($reservation->getBookings()->getItems() as $booking) {
888 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) {
889 $persons += $booking->getPersons()->getValue();
890 }
891 }
892
893 if ($newBooking) {
894 $hasCapacity = ($reservation->getMaxCapacity()->getValue() - $persons - $newBooking->getPersons()->getValue()) >= 0;
895 } else {
896 $hasCapacity = $reservation->getMaxCapacity()->getValue() - $persons > 0;
897 }
898 }
899
900 $bookingCloses = $reservation->getBookingCloses() ?
901 $reservation->getBookingCloses()->getValue() :
902 $reservation->getPeriods()->getItem(0)->getPeriodStart()->getValue();
903
904 $bookingOpens = $reservation->getBookingOpens() ?
905 $reservation->getBookingOpens()->getValue() :
906 $reservation->getCreated()->getValue();
907
908 $hasWaitingList = false;
909 $eventSettings = $reservation->getSettings() ? json_decode($reservation->getSettings()->getValue(), true) : null;
910
911 /** @var SettingsService $settingsDS */
912 $settingsDS = $this->container->get('domain.settings.service');
913
914 if (
915 $settingsDS->isFeatureEnabled('waitingList') && $eventSettings && !empty($eventSettings['waitingList']) &&
916 $eventSettings['waitingList']['enabled']
917 ) {
918 $waitingCustomers = 0;
919
920 if (!$reservation->getBookings()->length()) {
921 if ($reservation->getCustomPricing()->getValue()) {
922 /** @var EventTicket $ticket */
923 foreach ($reservation->getCustomTickets()->getItems() as $ticket) {
924 $waitingCustomers += $ticket->getWaiting() ? $ticket->getWaiting()->getValue() : 0;
925 }
926 } else {
927 $waitingCustomers += $reservation->getSpotsWaiting() ? $reservation->getSpotsWaiting()->getValue() : 0;
928 }
929 }
930
931 /** @var CustomerBooking $booking */
932 foreach ($reservation->getBookings()->getItems() as $booking) {
933 if ($booking->getStatus()->getValue() === BookingStatus::WAITING) {
934 if ($reservation->getCustomPricing()->getValue()) {
935 foreach ($booking->getTicketsBooking()->getItems() as $item) {
936 $waitingCustomers += $item->getPersons()->getValue();
937 }
938 } else {
939 $waitingCustomers += $booking->getPersons()->getValue();
940 }
941 }
942 }
943
944 if ($newBooking && $reservation->getCustomPricing() && $reservation->getCustomPricing()->getValue()) {
945 foreach ($newBooking->getTicketsBooking()->getItems() as $item) {
946 if (!$reservation->getMaxCustomCapacity()) {
947 $ticketData = $reservation->getCustomTickets()->getItem($item->getId()->getValue());
948
949 $waitingListSpots = $ticketData->getWaitingListSpots() ? $ticketData->getWaitingListSpots()->getValue() : 0;
950
951 $personsValue = $item->getPersons() ? $item->getPersons()->getValue() : 0;
952 $waitingValue = $ticketData->getWaiting() ? $ticketData->getWaiting()->getValue() : 0;
953
954 $hasWaitingList = $waitingListSpots >= ($personsValue + $waitingValue);
955 }
956 }
957
958 if ($reservation->getMaxCustomCapacity()) {
959 $hasWaitingList = $eventSettings['waitingList']['maxCapacity'] > $waitingCustomers;
960 }
961 } else {
962 $hasWaitingList = $eventSettings['waitingList']['maxCapacity'] > $waitingCustomers;
963 }
964
965 $eventSettings['waitingList']['peopleWaiting'] = $waitingCustomers;
966
967 $reservation->setSettings(new Json(json_encode($eventSettings)));
968 }
969
970 return $dateTime > $bookingOpens &&
971 $dateTime < $bookingCloses &&
972 ($hasCapacity || ($hasWaitingList && $newBooking && $newBooking->getStatus()->getValue() === BookingStatus::WAITING)) &&
973 in_array($reservation->getStatus()->getValue(), [BookingStatus::APPROVED, BookingStatus::PENDING], true);
974 }
975
976 /**
977 * @param CustomerBooking $booking
978 * @param Event $bookable
979 * @param bool $invoice
980 *
981 * @return array
982 *
983 * @throws InvalidArgumentException
984 */
985 public function getPaymentAmount($booking, $bookable, $invoice = false)
986 {
987 /** @var TaxApplicationService $taxApplicationService */
988 $taxApplicationService = $this->container->get('application.tax.service');
989
990 /** @var Tax $eventTax */
991 $eventTax = $this->getTax($booking->getTax());
992
993 $persons = $booking->getPersons()->getValue();
994
995 $unitPrice = (float)$bookable->getPrice()->getValue();
996
997 $price = $unitPrice * ($this->isAggregatedPrice($bookable) ? $persons : 1);
998
999 $taxAmount = 0;
1000
1001 $ticketsTax = [];
1002
1003 if (
1004 $booking->getTicketsBooking() &&
1005 $booking->getTicketsBooking()->length() &&
1006 $bookable->getCustomPricing() &&
1007 $bookable->getCustomPricing()->getValue()
1008 ) {
1009 /** @var EventApplicationService $eventApplicationService */
1010 $eventApplicationService = $this->container->get('application.booking.event.service');
1011
1012 $bookable->setCustomTickets(
1013 $eventApplicationService->getTicketsPriceByDateRange($bookable->getCustomTickets())
1014 );
1015
1016 $ticketSumPrice = 0;
1017
1018 /** @var CustomerBookingEventTicket $bookingToEventTicket */
1019 foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) {
1020 /** @var EventTicket $ticket */
1021 $ticket = $bookable->getCustomTickets()->getItem($bookingToEventTicket->getEventTicketId()->getValue());
1022
1023 $ticketPrice = $ticket->getDateRangePrice() ?
1024 $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue();
1025
1026 $ticketPersons = $bookingToEventTicket->getPersons() ?
1027 ($booking->getAggregatedPrice()->getValue() ? $bookingToEventTicket->getPersons()->getValue() : 1)
1028 : 0;
1029
1030 $ticketSubtotal = $ticketPersons * $ticketPrice;
1031
1032 $ticketSumPrice += $ticketSubtotal;
1033
1034 if ($bookingToEventTicket->getId()) {
1035 if ($eventTax && $eventTax->getExcluded()->getValue()) {
1036 $ticketsTax[$bookingToEventTicket->getId()->getValue()] = $this->getTaxAmount($eventTax, $ticketSubtotal);
1037 } elseif ($eventTax && !$eventTax->getExcluded()->getValue()) {
1038 $ticketsTax[$bookingToEventTicket->getId()->getValue()] =
1039 $this->getTaxAmount($eventTax, $taxApplicationService->getBasePrice($ticketSubtotal, $eventTax));
1040 } else {
1041 $ticketsTax[$bookingToEventTicket->getId()->getValue()] = 0;
1042 }
1043 }
1044 }
1045
1046 $price = $ticketSumPrice;
1047 }
1048
1049 if ($eventTax && !$eventTax->getExcluded()->getValue() && ($booking->getCoupon() || $invoice)) {
1050 $price = $taxApplicationService->getBasePrice($price, $eventTax);
1051 }
1052
1053 $priceWithoutCoupon = $price;
1054
1055 $subtotalPrice = round($price, 4);
1056
1057 $subtraction = 0;
1058
1059 $reductionAmount = [
1060 'deduction' => 0,
1061 'discount' => 0,
1062 ];
1063
1064 if ($booking->getCoupon()) {
1065 $reductionAmount['discount'] = $price / 100 * ($booking->getCoupon()->getDiscount()->getValue() ?: 0);
1066
1067 $reductionAmount['deduction'] = $booking->getCoupon()->getDeduction()->getValue();
1068
1069 $subtraction = $reductionAmount['discount'] + $reductionAmount['deduction'];
1070
1071 $price = max($price - $subtraction, 0);
1072 }
1073
1074 if ($eventTax && ($eventTax->getExcluded()->getValue() || $subtraction || $invoice)) {
1075 $taxAmount = $this->getTaxAmount($eventTax, $price);
1076 $price += $taxAmount;
1077 $priceWithoutCoupon += $taxAmount;
1078 }
1079
1080 $price = (float)max(round($price, 2), 0);
1081
1082 if (!$price) {
1083 foreach ($ticketsTax as $ticketId => $ticketTax) {
1084 $ticketsTax[$ticketId] = 0;
1085 }
1086 }
1087
1088 return [
1089 'price' => apply_filters('amelia_modify_payment_amount', $price, $booking),
1090 'discount' => $reductionAmount['discount'],
1091 'deduction' => $reductionAmount['deduction'],
1092 'total' => $priceWithoutCoupon,
1093 'unit_price' => $unitPrice,
1094 'qty' => $this->isAggregatedPrice($bookable) ? $persons : 1,
1095 'bookable' => $subtotalPrice,
1096 'subtotal' => $subtotalPrice,
1097 'tax' => $eventTax ? $this->getTaxAmount($eventTax, $subtotalPrice) : 0,
1098 'total_tax' => $taxAmount,
1099 'tax_rate' => $eventTax ? $this->getTaxRate($eventTax) : '',
1100 'tax_type' => $eventTax ? $eventTax->getType()->getValue() : '',
1101 'tax_excluded' => $eventTax ? $eventTax->getExcluded()->getValue() : false,
1102 'tickets_tax' => $ticketsTax,
1103 'full_discount' =>
1104 $this->getCouponDiscountAmount($booking->getCoupon(), $priceWithoutCoupon) +
1105 ($booking->getCoupon() && $booking->getCoupon()->getDeduction() ? (float)$booking->getCoupon()->getDeduction()->getValue() : 0)
1106 ];
1107 }
1108
1109 /**
1110 * @param Reservation $reservation
1111 *
1112 * @return float
1113 *
1114 * @throws InvalidArgumentException
1115 */
1116 public function getReservationPaymentAmount($reservation)
1117 {
1118 /** @var AbstractDepositApplicationService $depositAS */
1119 $depositAS = $this->container->get('application.deposit.service');
1120
1121 /** @var Event $bookable */
1122 $bookable = $reservation->getBookable();
1123
1124 $paymentAmount = $this->getPaymentAmount($reservation->getBooking(), $bookable)['price'];
1125
1126 if ($reservation->getApplyDeposit()->getValue()) {
1127 $personsCount = $reservation->getBooking()->getPersons()->getValue();
1128
1129 if ($reservation->getBooking()->getTicketsBooking() && $bookable->getCustomPricing()->getValue()) {
1130 $personsCount = 0;
1131
1132 /** @var CustomerBookingEventTicket $bookingToEventTicket */
1133 foreach ($reservation->getBooking()->getTicketsBooking()->getItems() as $bookingToEventTicket) {
1134 $personsCount += ($bookingToEventTicket->getPersons() ?
1135 $bookingToEventTicket->getPersons()->getValue() : 0);
1136 }
1137 }
1138
1139 $paymentAmount = $depositAS->calculateDepositAmount(
1140 $paymentAmount,
1141 $bookable,
1142 $personsCount
1143 );
1144 }
1145
1146 return $paymentAmount;
1147 }
1148
1149 /**
1150 * @param Reservation $reservation
1151 * @param bool $usePayment
1152 *
1153 * @return array
1154 *
1155 * @throws InvalidArgumentException
1156 */
1157 public function getProvidersPaymentAmount($reservation, $usePayment = true)
1158 {
1159 $amountData = [];
1160
1161 /** @var Payment $payment */
1162 $payment = $usePayment ? $reservation->getBooking()->getPayments()->getItem(0) : null;
1163
1164 /** @var Event $event */
1165 $event = $reservation->getBookable();
1166
1167 /** @var Provider $provider */
1168 foreach ($event->getProviders()->getItems() as $provider) {
1169 $amountData[$provider->getId()->getValue()][] = [
1170 'paymentId' => $payment ? $payment->getId()->getValue() : null,
1171 'amount' => $this->getReservationPaymentAmount($reservation),
1172 ];
1173 }
1174
1175 return $amountData;
1176 }
1177
1178 /**
1179 * @param Payment $payment
1180 * @param boolean $fromLink
1181 *
1182 * @return CommandResult
1183 * @throws InvalidArgumentException
1184 * @throws Exception
1185 */
1186 public function getReservationByPayment($payment, $fromLink = false)
1187 {
1188 $result = new CommandResult();
1189
1190 /** @var CustomerRepository $customerRepository */
1191 $customerRepository = $this->container->get('domain.users.customers.repository');
1192
1193 /** @var LocationRepository $locationRepository */
1194 $locationRepository = $this->container->get('domain.locations.repository');
1195
1196 /** @var ReservationServiceInterface $reservationService */
1197 $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT);
1198
1199 /** @var Event $event */
1200 $event = $reservationService->getReservationByBookingId(
1201 $payment->getCustomerBookingId()->getValue()
1202 );
1203
1204 if ($event->getLocationId()) {
1205 /** @var Location $location */
1206 $location = $locationRepository->getById($event->getLocationId()->getValue());
1207
1208 $event->setLocation($location);
1209 }
1210
1211 /** @var CustomerBooking $booking */
1212 $booking = $event->getBookings()->getItem($payment->getCustomerBookingId()->getValue());
1213
1214 $booking->setChangedStatus(new BooleanValueObject(true));
1215
1216 $this->setToken($booking);
1217
1218 /** @var AbstractUser $customer */
1219 $customer = $customerRepository->getById($booking->getCustomerId()->getValue());
1220
1221 $result->setData(
1222 [
1223 'type' => Entities::EVENT,
1224 Entities::EVENT => $event->toArray(),
1225 Entities::BOOKING => $booking->toArray(),
1226 'appointmentStatusChanged' => false,
1227 'customer' => $customer->toArray(),
1228 'packageId' => 0,
1229 'recurring' => [],
1230 'utcTime' => $reservationService->getBookingPeriods(
1231 $event,
1232 $booking,
1233 $event
1234 ),
1235 'isRetry' => !$fromLink,
1236 'fromLink' => $fromLink,
1237 'paymentId' => $payment->getId()->getValue(),
1238 'packageCustomerId' => null,
1239 'payment' => [
1240 'id' => $payment->getId()->getValue(),
1241 'amount' => $payment->getAmount()->getValue(),
1242 'gateway' => $payment->getGateway()->getName()->getValue(),
1243 'gatewayTitle' => $payment->getGatewayTitle() ? $payment->getGatewayTitle()->getValue() : '',
1244 'invoiceNumber' => $payment->getInvoiceNumber() ? $payment->getInvoiceNumber()->getValue() : '',
1245 ],
1246 ]
1247 );
1248
1249 return $result;
1250 }
1251
1252 /**
1253 * @param int $bookingId
1254 *
1255 * @return CommandResult
1256 * @throws InvalidArgumentException
1257 * @throws Exception
1258 */
1259 public function getBookingResultByBookingId($bookingId)
1260 {
1261 $result = new CommandResult();
1262
1263 /** @var CustomerRepository $customerRepository */
1264 $customerRepository = $this->container->get('domain.users.customers.repository');
1265
1266 /** @var LocationRepository $locationRepository */
1267 $locationRepository = $this->container->get('domain.locations.repository');
1268
1269 /** @var ReservationServiceInterface $reservationService */
1270 $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT);
1271
1272 /** @var Event $event */
1273 $event = $reservationService->getReservationByBookingId(
1274 $bookingId
1275 );
1276
1277 if ($event->getLocationId()) {
1278 /** @var Location $location */
1279 $location = $locationRepository->getById($event->getLocationId()->getValue());
1280
1281 $event->setLocation($location);
1282 }
1283
1284 /** @var CustomerBooking $booking */
1285 $booking = $event->getBookings()->getItem($bookingId);
1286
1287 $booking->setChangedStatus(new BooleanValueObject(true));
1288
1289 $this->setToken($booking);
1290
1291 /** @var AbstractUser $customer */
1292 $customer = $customerRepository->getById($booking->getCustomerId()->getValue());
1293
1294 $result->setData(
1295 [
1296 'type' => Entities::EVENT,
1297 Entities::EVENT => $event->toArray(),
1298 Entities::BOOKING => $booking->toArray(),
1299 'appointmentStatusChanged' => false,
1300 'customer' => $customer->toArray(),
1301 'packageId' => 0,
1302 'recurring' => [],
1303 'utcTime' => $reservationService->getBookingPeriods(
1304 $event,
1305 $booking,
1306 $event
1307 ),
1308 'isRetry' => true,
1309 'paymentId' => null,
1310 'packageCustomerId' => null,
1311 'payment' => null,
1312 ]
1313 );
1314
1315 return $result;
1316 }
1317
1318 /**
1319 * @param array $data
1320 *
1321 * @return void
1322 * @throws QueryExecutionException
1323 */
1324 public function manageTaxes(&$data)
1325 {
1326 /** @var TaxApplicationService $taxAS */
1327 $taxAS = $this->container->get('application.tax.service');
1328
1329 /** @var SettingsService $settingsService */
1330 $settingsService = $this->container->get('domain.settings.service');
1331
1332 if ($settingsService->isFeatureEnabled('tax')) {
1333 /** @var Collection $taxes */
1334 $taxes = $taxAS->getAll();
1335
1336 $data['bookings'][0]['tax'] = $taxAS->getTaxData(
1337 $data['eventId'],
1338 Entities::EVENT,
1339 $taxes
1340 );
1341 }
1342 }
1343
1344 /**
1345 * @param int $bookingId
1346 *
1347 * @return array
1348 *
1349 * @throws AccessDeniedException
1350 * @throws InvalidArgumentException
1351 * @throws QueryExecutionException
1352 */
1353 public function deleteBooking($bookingId)
1354 {
1355 /** @var CustomerBookingRepository $customerBookingRepository */
1356 $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository');
1357
1358 /** @var EventApplicationService $eventApplicationService */
1359 $eventApplicationService = $this->container->get('application.booking.event.service');
1360
1361 /** @var CustomerBooking $customerBooking */
1362 $customerBooking = $customerBookingRepository->getById((int)$bookingId);
1363
1364 if (!$customerBooking) {
1365 throw new \Exception('Booking not found');
1366 }
1367
1368 $customerBookingRepository->beginTransaction();
1369
1370 if (!$eventApplicationService->deleteEventBooking($customerBooking)) {
1371 $customerBookingRepository->rollback();
1372 throw new \Exception('Could not delete booking');
1373 }
1374
1375 $customerBookingRepository->commit();
1376
1377 return [];
1378 }
1379
1380 /**
1381 * @param array $data
1382 * @param bool $invoices
1383 *
1384 * @return array
1385 * @throws InvalidArgumentException
1386 */
1387 public function getPaymentSummary($data, $invoices)
1388 {
1389 /** @var Event $bookable */
1390 $bookable = EventFactory::create(
1391 [
1392 'price' => $data['bookedPrice'] * ($data['aggregatedPrice'] ? $data['persons'] : 1),
1393 'aggregatedPrice' => $data['aggregatedPrice'],
1394 'customPricing' => false,
1395 'customTickets' => [],
1396 ]
1397 );
1398
1399 /** @var CustomerBooking $booking */
1400 $booking = CustomerBookingFactory::create(
1401 [
1402 'persons' => 1,
1403 'aggregatedPrice' => $data['aggregatedPrice'],
1404 'ticketsData' => null,
1405 'coupon' => $data['coupon'],
1406 'tax' => $data['bookedTax'],
1407 ]
1408 );
1409
1410 return $this->getCommonPaymentSummary($booking, $bookable, $data, $invoices);
1411 }
1412 }
1413