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