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