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