PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Commands / Booking / Appointment / GetAppointmentCommandHandler.php
ameliabooking / src / Application / Commands / Booking / Appointment Last commit date
AddAppointmentCommand.php 1 year ago AddAppointmentCommandHandler.php 6 days ago AddBookingCommand.php 1 year ago AddBookingCommandHandler.php 6 days ago ApproveBookingRemotelyCommand.php 1 year ago ApproveBookingRemotelyCommandHandler.php 3 months ago CancelBookingCommand.php 1 year ago CancelBookingCommandHandler.php 6 days ago CancelBookingRemotelyCommand.php 1 year ago CancelBookingRemotelyCommandHandler.php 2 months ago DeleteAppointmentCommand.php 1 year ago DeleteAppointmentCommandHandler.php 1 year ago DeleteBookingCommand.php 1 year ago DeleteBookingCommandHandler.php 11 months ago DeleteBookingRemotelyCommand.php 11 months ago DeleteBookingRemotelyCommandHandler.php 7 months ago GetAppointmentBookingsCommand.php 7 months ago GetAppointmentBookingsCommandHandler.php 6 days ago GetAppointmentCommand.php 7 years ago GetAppointmentCommandHandler.php 6 days ago GetAppointmentsCommand.php 1 year ago GetAppointmentsCommandHandler.php 6 days ago GetIcsCommand.php 7 months ago GetIcsCommandHandler.php 4 years ago GetTimeSlotsCommand.php 1 year ago GetTimeSlotsCommandHandler.php 3 weeks ago ReassignBookingCommand.php 1 year ago ReassignBookingCommandHandler.php 6 days ago RejectBookingRemotelyCommand.php 1 year ago RejectBookingRemotelyCommandHandler.php 6 months ago SuccessfulBookingCommand.php 1 year ago SuccessfulBookingCommandHandler.php 1 year ago UpdateAppointmentCommand.php 1 year ago UpdateAppointmentCommandHandler.php 6 days ago UpdateAppointmentNoteCommand.php 4 months ago UpdateAppointmentNoteCommandHandler.php 6 days ago UpdateAppointmentStatusCommand.php 1 year ago UpdateAppointmentStatusCommandHandler.php 6 days ago UpdateAppointmentTimeCommand.php 1 year ago UpdateAppointmentTimeCommandHandler.php 6 days ago UpdateBookingStatusCommand.php 1 year ago UpdateBookingStatusCommandHandler.php 6 months ago
GetAppointmentCommandHandler.php
404 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Commands\Booking\Appointment;
4
5 use AmeliaBooking\Application\Commands\CommandHandler;
6 use AmeliaBooking\Application\Commands\CommandResult;
7 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
8 use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService;
9 use AmeliaBooking\Application\Services\CustomField\AbstractCustomFieldApplicationService;
10 use AmeliaBooking\Application\Services\Payment\PaymentApplicationService;
11 use AmeliaBooking\Application\Services\Reservation\AppointmentReservationService;
12 use AmeliaBooking\Application\Services\User\CustomerApplicationService;
13 use AmeliaBooking\Application\Services\User\ProviderApplicationService;
14 use AmeliaBooking\Application\Services\User\UserApplicationService;
15 use AmeliaBooking\Domain\Collection\Collection;
16 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
17 use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment;
18 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
19 use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer;
20 use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService;
21 use AmeliaBooking\Domain\Entity\Entities;
22 use AmeliaBooking\Domain\Entity\Payment\Payment;
23 use AmeliaBooking\Domain\Entity\User\AbstractUser;
24 use AmeliaBooking\Domain\Services\Settings\SettingsService;
25 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
26 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
27 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
28 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository;
29 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository;
30 use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldRepository;
31 use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository;
32 use AmeliaBooking\Infrastructure\Services\LessonSpace\AbstractLessonSpaceService;
33 use AmeliaBooking\Infrastructure\WP\Integrations\IvyForms\IvyFormsService;
34 use DateTimeZone;
35
36 /**
37 * Class GetAppointmentCommandHandler
38 *
39 * @package AmeliaBooking\Application\Commands\Booking\Appointment
40 */
41 class GetAppointmentCommandHandler extends CommandHandler
42 {
43 /**
44 * @param GetAppointmentCommand $command
45 *
46 * @return CommandResult
47 * @throws AccessDeniedException
48 * @throws QueryExecutionException
49 * @throws InvalidArgumentException
50 * @throws NotFoundException
51 */
52 public function handle(GetAppointmentCommand $command)
53 {
54 /** @var AbstractUser $user */
55 $user = $command->authorize();
56
57 $result = new CommandResult();
58
59 /** @var UserApplicationService $userAS */
60 $userAS = $this->container->get('application.user.service');
61
62 /** @var AbstractCustomFieldApplicationService $customFieldService */
63 $customFieldService = $this->container->get('application.customField.service');
64
65 /** @var AppointmentApplicationService $appointmentAS */
66 $appointmentAS = $this->container->get('application.booking.appointment.service');
67
68 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
69 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
70
71 /** @var AppointmentRepository $appointmentRepo */
72 $appointmentRepo = $this->container->get('domain.booking.appointment.repository');
73
74 /** @var ServiceRepository $serviceRepository */
75 $serviceRepository = $this->container->get('domain.bookable.service.repository');
76
77 /** @var CustomerApplicationService $customerAS */
78 $customerAS = $this->container->get('application.user.customer.service');
79
80 /** @var ProviderApplicationService $providerAS */
81 $providerAS = $this->container->get('application.user.provider.service');
82
83 /** @var CustomFieldRepository $customFieldRepository */
84 $customFieldRepository = $this->container->get('domain.customField.repository');
85
86 /** @var Appointment $appointment */
87 $appointment = $appointmentRepo->getById((int)$command->getField('id'));
88
89 if ($userAS->isProvider($user) && $user->getId()->getValue() !== $appointment->getProviderId()->getValue()) {
90 throw new AccessDeniedException('You are not allowed to read appointment');
91 }
92
93 // TODO: Redesign - check if could be removed, if every appointment call needs the same data returned
94 $getDrawerInfo = !empty($command->getField('params')['drawer']);
95
96 if ($userAS->isCustomer($user) && !$customerAS->hasCustomerBooking($appointment->getBookings(), $user)) {
97 throw new AccessDeniedException('You are not allowed to read appointment');
98 }
99
100 /** @var PaymentRepository $paymentRepository */
101 $paymentRepository = $this->container->get('domain.payment.repository');
102
103 $bookingIds = [];
104
105 $customerAS->removeBookingsForOtherCustomers($user, new Collection([$appointment]));
106
107 $timeZone = !empty($command->getField('params')['timeZone'])
108 ? $command->getField('params')['timeZone']
109 : ($user && $user->getType() === Entities::PROVIDER ? $providerAS->getTimeZone($user) : null);
110
111 if ($timeZone) {
112 $appointment->getBookingStart()->getValue()->setTimezone(new DateTimeZone($timeZone));
113
114 $appointment->getBookingEnd()->getValue()->setTimezone(new DateTimeZone($timeZone));
115 }
116
117 /** @var SettingsService $settingsDS */
118 $settingsDS = $this->container->get('domain.settings.service');
119
120 $badges = $settingsDS->isFeatureEnabled('employeeBadge')
121 ? $settingsDS->getSetting('roles', 'providerBadges')
122 : [];
123
124 $badge = !empty($badges['badges']) && $appointment->getProvider()->getBadgeId() ?
125 array_filter(
126 $badges['badges'],
127 function ($badge) use ($appointment) {
128 return $badge['id'] === $appointment->getProvider()->getBadgeId()->getValue();
129 }
130 )
131 : null;
132
133 $bookingsPrice = 0;
134 $paidPrice = 0;
135 $bookedSpots = 0;
136 $bookings = [];
137
138 /** @var PaymentApplicationService $paymentAS */
139 $paymentAS = $this->container->get('application.payment.service');
140
141 /** @var AppointmentReservationService $reservationService */
142 $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT);
143
144 /** @var Collection $customFieldsCollection */
145 $customFieldsCollection = $customFieldRepository->getAll([], false);
146
147 /** @var CustomerBooking $booking */
148 foreach ($appointment->getBookings()->getItems() as $booking) {
149 /** @var Payment $payment */
150 foreach ($booking->getPayments()->getItems() as $payment) {
151 if ($payment->getParentId() && $payment->getParentId()->getValue()) {
152 try {
153 /** @var Payment $parentPayment */
154 $parentPayment = $paymentRepository->getById($payment->getParentId()->getValue());
155
156 $bookingIds[] = $parentPayment->getCustomerBookingId()->getValue();
157 } catch (\Exception $e) {
158 }
159 }
160
161 /** @var Collection $relatedPayments */
162 $relatedPayments = $paymentRepository->getByEntityId(
163 $payment->getParentId() ? $payment->getParentId()->getValue() : $payment->getId()->getValue(),
164 'parentId'
165 );
166
167 /** @var Payment $relatedPayment */
168 foreach ($relatedPayments->getItems() as $relatedPayment) {
169 $bookingIds[] = $relatedPayment->getCustomerBookingId()->getValue();
170 }
171 }
172 }
173
174 /** @var Collection $recurringAppointments */
175 $recurringAppointments = $bookingIds ? $appointmentRepo->getFiltered(
176 [
177 'bookingIds' => array_unique($bookingIds),
178 'customerId' => !empty($command->getField('params')['customerId']) ? $command->getField('params')['customerId'] : null
179 ]
180 ) : $appointmentRepo->getFiltered(
181 [
182 'parentId' => $appointment->getParentId() ?
183 $appointment->getParentId()->getValue() : $appointment->getId()->getValue()
184 ]
185 );
186
187 if ($recurringAppointments->keyExists($appointment->getId()->getValue())) {
188 $recurringAppointments->deleteItem($appointment->getId()->getValue());
189 }
190
191 $appointmentArray = $appointment->toArray();
192 if (!empty($appointmentArray['lessonSpace'])) {
193 /** @var SettingsService $settingsDS */
194 $settingsDS = $this->container->get('domain.settings.service');
195
196 $lessonSpaceApiKey = $settingsDS->getSetting('lessonSpace', 'apiKey');
197 $lessonSpaceEnabled = $settingsDS->getSetting('lessonSpace', 'enabled');
198 $lessonSpaceCompanyId = $settingsDS->getSetting('lessonSpace', 'companyId');
199 if ($lessonSpaceEnabled && $lessonSpaceApiKey && $lessonSpaceCompanyId) {
200 /** @var AbstractLessonSpaceService $lessonSpaceService */
201 $lessonSpaceService = $this->container->get('infrastructure.lesson.space.service');
202 $spaceId = explode("https://www.thelessonspace.com/space/", $appointmentArray['lessonSpace']);
203 if ($spaceId && count($spaceId) > 1) {
204 $appointmentArray['lessonSpaceDetails'] = $lessonSpaceService->getSpace($lessonSpaceApiKey, $lessonSpaceCompanyId, $spaceId[1]);
205 }
206 }
207 }
208
209 if (isset($appointmentArray['notifyParticipants'])) {
210 $appointmentArray['notifyParticipants'] = intval($appointmentArray['notifyParticipants']);
211 }
212 if (isset($appointmentArray['createPaymentLinks'])) {
213 $appointmentArray['createPaymentLinks'] = intval($appointmentArray['createPaymentLinks']);
214 }
215
216 $service = $serviceRepository->getByCriteria(
217 ['services' => [$appointment->getServiceId()->getValue()]]
218 )->getItem($appointment->getServiceId()->getValue());
219
220 if ($getDrawerInfo) {
221 $wcTax = 0;
222 $wcDiscount = 0;
223
224 /** @var CustomerBooking $booking */
225 foreach ($appointment->getBookings()->getItems() as $booking) {
226 $ivyEntryId = $booking->getIvyEntryId() ? $booking->getIvyEntryId()->getValue() : null;
227
228 if ($booking->getPackageCustomerService()) {
229 /** @var Collection $packageCustomerServices */
230 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(
231 [
232 'ids' => [$booking->getPackageCustomerService()->getId()->getValue()],
233 ]
234 );
235
236 /** @var PackageCustomerService $packageCustomerService */
237 foreach ($packageCustomerServices->getItems() as $packageCustomerService) {
238 /** @var PackageCustomer $packageCustomer */
239 $packageCustomer = $packageCustomerService->getPackageCustomer();
240
241 $ivyEntryId = $packageCustomer && $packageCustomer->getIvyEntryId()
242 ? $packageCustomer->getIvyEntryId()->getValue()
243 : null;
244 }
245 }
246
247 $customFields = [];
248 $bookingPrice = $paymentAS->calculateAppointmentPrice($booking->toArray(), 'appointment');
249 $bookingsPrice += $bookingPrice;
250
251 $bookedSpots += $booking->getPersons()->getValue();
252
253 // Create bookable with extras to properly calculate payment amount
254 $bookableWithExtras = $paymentAS->createBookableWithExtras($booking->toArray(), 'appointment');
255 $bookingPaymentAmount = $reservationService->getPaymentAmount($booking, $bookableWithExtras, true);
256
257 $bookingPaidPrice = 0;
258 $paymentMethods = [];
259 $wcOrderUrls = [];
260 foreach ($booking->getPayments()->toArray() as $paymentItem) {
261 $paymentMethods[] = $paymentItem['gateway'];
262 if ($paymentItem['status'] === 'paid' || $paymentItem['status'] === 'partiallyPaid') {
263 $bookingPaidPrice += $paymentItem['amount'];
264 }
265
266 $paymentAS->addWcFields($paymentItem);
267
268 $wcTax += !empty($paymentItem['wcItemTaxValue']) ? $paymentItem['wcItemTaxValue'] : 0;
269
270 $wcDiscount += !empty($paymentItem['wcItemCouponValue']) ? $paymentItem['wcItemCouponValue'] : 0;
271
272 if (!empty($paymentItem['wcOrderId'])) {
273 $wcOrderUrls[$paymentItem['wcOrderId']] = $paymentItem['wcOrderUrl'];
274 }
275 }
276
277 $paidPrice += $bookingPaidPrice;
278
279 $customerBirthday = $booking->getCustomer() && $booking->getCustomer()->getBirthday() ?
280 $booking->getCustomer()->getBirthday()->getValue()->format('Y-m-d') :
281 null;
282
283 if ($booking->getCustomFields() && $booking->getCustomFields()->getValue()) {
284 $customFields = $customFieldService->reformatCustomField($booking, $customFields, $customFieldsCollection);
285 }
286
287 $total = $bookingPaymentAmount['subtotal']
288 + $bookingPaymentAmount['total_tax']
289 + $wcTax
290 - $bookingPaymentAmount['discount']
291 - $bookingPaymentAmount['deduction']
292 - $wcDiscount;
293
294 $bookings[] = [
295 'id' => $booking->getId()->getValue(),
296 'customer' => $booking->getCustomer() ? array_merge($booking->getCustomer()->toArray(), ['birthday' => $customerBirthday]) : null,
297 'status' => $booking->getStatus()->getValue(),
298 'isPackageBooking' => !!$booking->getPackageCustomerService(),
299 'payment' => [
300 'paymentMethods' => $paymentMethods,
301 'wcOrderUrls' => $wcOrderUrls,
302 'status' => $paymentAS->getFullStatus($booking->toArray(), 'appointment'),
303 'total' => $total,
304 'tax' => $bookingPaymentAmount['total_tax'],
305 'wcTax' => $wcTax,
306 'discount' => $bookingPaymentAmount['discount'] + $bookingPaymentAmount['deduction'],
307 'wcDiscount' => $wcDiscount,
308 'service' => $bookingPaymentAmount['bookable'],
309 'extras' => $bookingPaymentAmount['subtotal'] - $bookingPaymentAmount['bookable'],
310 'subtotal' => $bookingPaymentAmount['subtotal'],
311 'paid' => $bookingPaidPrice,
312 'due' => max($total - $bookingPaidPrice, 0),
313 'id' => $booking->getPayments()->length() > 0 ? $booking->getPayments()->toArray()[0]['id'] : null,
314 ],
315 'bookedSpots' => $booking->getPersons()->getValue(),
316 'customFields' => $customFields,
317 'extras' => $booking->getExtras() ? array_map(
318 function ($extra) use ($service) {
319 $serviceExtra = $service->getExtras()->getItem($extra['extraId']);
320 return array_merge(
321 $extra,
322 ['name' => $serviceExtra ? $serviceExtra->getName()->getValue() : null]
323 );
324 },
325 $booking->getExtras()->toArray()
326 ) : null,
327 'duration' => $booking->getDuration()
328 ? $booking->getDuration()->getValue()
329 : $service->getDuration()->getValue(),
330 'ivyEntryId' => $ivyEntryId,
331 'ivyEntryFields' => $ivyEntryId ? IvyFormsService::getEntryFields($ivyEntryId) : [],
332 ];
333 }
334
335 $serviceSettingsRaw = $service->getSettings() ? $service->getSettings()->getValue() : null;
336 $waitingListEnabled = false;
337 if (!empty($serviceSettingsRaw)) {
338 $serviceSettings = json_decode($serviceSettingsRaw, true);
339 if (isset($serviceSettings['waitingList']['enabled'])) {
340 $waitingListEnabled = (bool)$serviceSettings['waitingList']['enabled'];
341 }
342 }
343
344 $appointmentArray = [
345 'id' => $appointment->getId()->getValue(),
346 'employee' => $appointment->getProvider() ? [
347 'id' => $appointment->getProvider()->getId()->getValue(),
348 'firstName' => $appointment->getProvider()->getFirstName()->getValue(),
349 'lastName' => $appointment->getProvider()->getLastName() ? $appointment->getProvider()->getLastName()->getValue() : null,
350 'picture' => $appointment->getProvider()->getPicture() ? $appointment->getProvider()->getPicture()->getThumbPath() : null,
351 'badge' => !empty($badge) ? array_values($badge)[0] : null,
352 ] : null,
353 'location' => $appointment->getLocation() ? [
354 'id' => $appointment->getLocation()->getId()->getValue(),
355 'name' => $appointment->getLocation()->getName() ? $appointment->getLocation()->getName()->getValue() : null
356 ] : null,
357 'service' => $appointment->getService() ? [
358 'id' => $appointment->getService()->getId()->getValue(),
359 'name' => $appointment->getService()->getName()->getValue(),
360 'color' => $appointment->getService()->getColor() ? $appointment->getService()->getColor()->getValue() : null,
361 'pictureThumbPath' => $appointment->getService()->getPicture() ? $appointment->getService()->getPicture()->getThumbPath() : null,
362 'settings' => [
363 'waitingListEnabled' => $waitingListEnabled,
364 ],
365 ] : null,
366 'bookingStartDateTime' => $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'),
367 'bookingEndDateTime' => $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s'),
368 'recurringCount' => $recurringAppointments->length(),
369 'googleMeetLink' => $appointment->getGoogleMeetUrl(),
370 'zoomHostLink' => $appointment->getZoomMeeting() ? $appointment->getZoomMeeting()->getStartUrl()->getValue() : null,
371 'zoomJoinLink' => $appointment->getZoomMeeting() ? $appointment->getZoomMeeting()->getJoinUrl()->getValue() : null,
372 'lessonSpace' => $appointment->getLessonSpace() ? $appointment->getLessonSpace() : null,
373 'microsoftTeamsLink' => $appointment->getMicrosoftTeamsUrl() ? $appointment->getMicrosoftTeamsUrl() : null,
374 'note' => $appointment->getInternalNotes() ? $appointment->getInternalNotes()->getValue() : null,
375 'status' => $appointment->getStatus()->getValue(),
376 'bookings' => $bookings,
377 'price' => [
378 'total' => $bookingsPrice
379 ],
380 'paidPrice' => $paidPrice,
381 'bookedSpots' => $bookedSpots,
382 'cancelable' => $appointmentAS->isCancelable($appointment, $service, $user),
383 'reschedulable' => $appointmentAS->isReschedulable($appointment, $service, $user),
384 ];
385 }
386
387 $appointmentArray = apply_filters('amelia_get_appointment_filter', $appointmentArray);
388
389 do_action('amelia_get_appointment', $appointmentArray);
390
391
392 $result->setResult(CommandResult::RESULT_SUCCESS);
393 $result->setMessage('Successfully retrieved appointment');
394 $result->setData(
395 [
396 Entities::APPOINTMENT => $appointmentArray,
397 'recurring' => $recurringAppointments->toArray()
398 ]
399 );
400
401 return $result;
402 }
403 }
404