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 / Commands / Booking / Appointment / UpdateAppointmentCommandHandler.php
ameliabooking / src / Application / Commands / Booking / Appointment Last commit date
AddAppointmentCommand.php 1 year ago AddAppointmentCommandHandler.php 1 year ago AddBookingCommand.php 1 year ago AddBookingCommandHandler.php 1 year ago ApproveBookingRemotelyCommand.php 1 year ago ApproveBookingRemotelyCommandHandler.php 1 year ago CancelBookingCommand.php 1 year ago CancelBookingCommandHandler.php 1 year ago CancelBookingRemotelyCommand.php 1 year ago CancelBookingRemotelyCommandHandler.php 2 years ago DeleteAppointmentCommand.php 1 year ago DeleteAppointmentCommandHandler.php 1 year ago DeleteBookingCommand.php 1 year ago DeleteBookingCommandHandler.php 1 year ago DeleteBookingRemotelyCommand.php 1 year ago DeleteBookingRemotelyCommandHandler.php 1 year ago GetAppointmentCommand.php 7 years ago GetAppointmentCommandHandler.php 1 year ago GetAppointmentsCommand.php 1 year ago GetAppointmentsCommandHandler.php 1 year ago GetIcsCommand.php 1 year ago GetIcsCommandHandler.php 4 years ago GetPackageAppointmentsCommand.php 1 year ago GetPackageAppointmentsCommandHandler.php 1 year ago GetTimeSlotsCommand.php 1 year ago GetTimeSlotsCommandHandler.php 1 year ago ReassignBookingCommand.php 1 year ago ReassignBookingCommandHandler.php 1 year ago RejectBookingRemotelyCommand.php 1 year ago RejectBookingRemotelyCommandHandler.php 1 year ago SuccessfulBookingCommand.php 1 year ago SuccessfulBookingCommandHandler.php 1 year ago UpdateAppointmentCommand.php 1 year ago UpdateAppointmentCommandHandler.php 1 year ago UpdateAppointmentStatusCommand.php 1 year ago UpdateAppointmentStatusCommandHandler.php 1 year ago UpdateAppointmentTimeCommand.php 1 year ago UpdateAppointmentTimeCommandHandler.php 1 year ago UpdateBookingStatusCommand.php 1 year ago UpdateBookingStatusCommandHandler.php 1 year ago
UpdateAppointmentCommandHandler.php
432 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\Bookable\BookableApplicationService;
9 use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService;
10 use AmeliaBooking\Application\Services\Booking\BookingApplicationService;
11 use AmeliaBooking\Application\Services\CustomField\AbstractCustomFieldApplicationService;
12 use AmeliaBooking\Application\Services\Entity\EntityApplicationService;
13 use AmeliaBooking\Application\Services\Payment\PaymentApplicationService;
14 use AmeliaBooking\Application\Services\Reservation\AppointmentReservationService;
15 use AmeliaBooking\Application\Services\User\UserApplicationService;
16 use AmeliaBooking\Application\Services\Zoom\AbstractZoomApplicationService;
17 use AmeliaBooking\Domain\Collection\Collection;
18 use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException;
19 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
20 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
21 use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment;
22 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
23 use AmeliaBooking\Domain\Entity\Entities;
24 use AmeliaBooking\Domain\Entity\User\AbstractUser;
25 use AmeliaBooking\Domain\Entity\User\Provider;
26 use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory;
27 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
28 use AmeliaBooking\Domain\Services\Settings\SettingsService;
29 use AmeliaBooking\Domain\ValueObjects\BooleanValueObject;
30 use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue;
31 use AmeliaBooking\Domain\ValueObjects\Number\Float\Price;
32 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
33 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
34 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
35 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository;
36 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
37 use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository;
38 use AmeliaBooking\Infrastructure\Repository\User\UserRepository;
39 use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings;
40 use Exception;
41 use Interop\Container\Exception\ContainerException;
42
43 /**
44 * Class UpdateAppointmentCommandHandler
45 *
46 * @package AmeliaBooking\Application\Commands\Booking\Appointment
47 */
48 class UpdateAppointmentCommandHandler extends CommandHandler
49 {
50 /**
51 * @var array
52 */
53 public $mandatoryFields = [
54 'bookings',
55 'bookingStart',
56 'notifyParticipants',
57 'serviceId',
58 'providerId',
59 'id'
60 ];
61
62 /**
63 * @param UpdateAppointmentCommand $command
64 *
65 * @return CommandResult
66 * @throws AccessDeniedException
67 * @throws InvalidArgumentException
68 * @throws QueryExecutionException
69 * @throws NotFoundException
70 * @throws ContainerException
71 * @throws Exception
72 */
73 public function handle(UpdateAppointmentCommand $command)
74 {
75 $result = new CommandResult();
76
77 $this->checkMandatoryFields($command);
78
79 /** @var AppointmentRepository $appointmentRepo */
80 $appointmentRepo = $this->container->get('domain.booking.appointment.repository');
81 /** @var AppointmentApplicationService $appointmentAS */
82 $appointmentAS = $this->container->get('application.booking.appointment.service');
83 /** @var BookingApplicationService $bookingAS */
84 $bookingAS = $this->container->get('application.booking.booking.service');
85 /** @var BookableApplicationService $bookableAS */
86 $bookableAS = $this->container->get('application.bookable.service');
87 /** @var AbstractCustomFieldApplicationService $customFieldService */
88 $customFieldService = $this->container->get('application.customField.service');
89 /** @var AbstractZoomApplicationService $zoomService */
90 $zoomService = $this->container->get('application.zoom.service');
91 /** @var UserApplicationService $userAS */
92 $userAS = $this->getContainer()->get('application.user.service');
93 /** @var SettingsService $settingsDS */
94 $settingsDS = $this->container->get('domain.settings.service');
95 /** @var ProviderRepository $providerRepository */
96 $providerRepository = $this->container->get('domain.users.providers.repository');
97 /** @var PaymentApplicationService $paymentAS */
98 $paymentAS = $this->container->get('application.payment.service');
99 /** @var AppointmentReservationService $reservationService */
100 $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT);
101
102 try {
103 /** @var AbstractUser $user */
104 $user = $command->getUserApplicationService()->authorization(
105 $command->getPage() === 'cabinet' ? $command->getToken() : null,
106 $command->getCabinetType()
107 );
108 } catch (AuthorizationException $e) {
109 $result->setResult(CommandResult::RESULT_ERROR);
110 $result->setData(
111 [
112 'reauthorize' => true
113 ]
114 );
115
116 return $result;
117 }
118
119 if ($userAS->isCustomer($user)) {
120 throw new AccessDeniedException('You are not allowed to update appointment');
121 }
122
123 if ($userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteAppointments')) {
124 throw new AccessDeniedException('You are not allowed to update appointment');
125 }
126
127 $appointmentData = $command->getFields();
128
129 /** @var EntityApplicationService $entityService */
130 $entityService = $this->container->get('application.entity.service');
131
132 $entityService->removeMissingEntityForAppointment($appointmentData);
133
134 /** @var Service $service */
135 $service = $bookableAS->getAppointmentService(
136 $command->getFields()['serviceId'],
137 $command->getFields()['providerId']
138 );
139
140 $appointmentAS->convertTime($appointmentData);
141
142 $reservationService->manageTaxes($appointmentData);
143
144 $removedBookingsData = $command->getField('removedBookings');
145
146 // added check for API call when removedBookings not sent
147 $removedBookingsData = empty($removedBookingsData) ? [] : $removedBookingsData;
148
149 $appointment = apply_filters('amelia_before_appointment_updated_filter', $appointmentData, $removedBookingsData, $service ? $service->toArray() : null);
150
151 do_action('amelia_before_appointment_updated', $appointment, $removedBookingsData, $service ? $service->toArray() : null);
152
153 /** @var Appointment $appointment */
154 $appointment = $appointmentAS->build($appointmentData, $service);
155
156 /** @var ProviderRepository $providerRepository */
157 $providerRepository = $this->container->get('domain.users.providers.repository');
158
159 /** @var Provider $provider */
160 $provider = $providerRepository->getById($appointmentData['providerId']);
161
162 $appointment->setProvider($provider);
163
164 /** @var Appointment $oldAppointment */
165 $oldAppointment = $appointmentRepo->getById($appointment->getId()->getValue());
166
167 $appointment->setInitialBookingStart(
168 new DateTimeValue(clone $oldAppointment->getBookingStart()->getValue())
169 );
170
171 $appointment->setInitialBookingEnd(
172 new DateTimeValue(clone $oldAppointment->getBookingEnd()->getValue())
173 );
174
175 /** @var CustomerBooking $newBooking */
176 foreach ($appointment->getBookings()->getItems() as $newBooking) {
177 /** @var CustomerBooking $oldBooking */
178 foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) {
179 if (
180 $newBooking->getId() &&
181 $newBooking->getId()->getValue() === $oldBooking->getId()->getValue()
182 ) {
183 if ($oldBooking->getUtcOffset()) {
184 $newBooking->setUtcOffset($oldBooking->getUtcOffset());
185 }
186
187 if ($oldBooking->getCreated()) {
188 $newBooking->setCreated($oldBooking->getCreated());
189 }
190
191 if ($oldBooking->getInfo()) {
192 $newBooking->setInfo($oldBooking->getInfo());
193 }
194
195 if ($oldBooking->getStatus()->getValue() === $newBooking->getStatus()->getValue()) {
196 $newBooking->setUpdated(
197 new BooleanValueObject(
198 $appointmentAS->appointmentDetailsChanged($appointment, $oldAppointment) ||
199 $appointmentAS->bookingDetailsChanged($newBooking, $oldBooking)
200 )
201 );
202 }
203 }
204 }
205 }
206
207 $appointment->setBookingEnd(
208 new DateTimeValue(
209 DateTimeService::getCustomDateTimeObject(
210 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
211 )->modify('+' . $appointmentAS->getAppointmentLengthTime($appointment, $service) . ' second')
212 )
213 );
214
215 $userConnectionChanges = $appointmentAS->getUserConnectionChanges(
216 $appointment->getProviderId()->getValue(),
217 $oldAppointment->getProviderId()->getValue()
218 );
219
220 if ($oldAppointment->getZoomMeeting()) {
221 $appointment->setZoomMeeting($oldAppointment->getZoomMeeting());
222 }
223
224 if (
225 $bookingAS->isBookingApprovedOrPending($appointment->getStatus()->getValue()) &&
226 $bookingAS->isBookingCanceledOrRejectedOrNoShow($oldAppointment->getStatus()->getValue())
227 ) {
228 /** @var AbstractUser $user */
229 $user = $this->container->get('logged.in.user');
230
231 if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user), null, null)) {
232 $result->setResult(CommandResult::RESULT_ERROR);
233 $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']);
234 $result->setData(
235 [
236 'timeSlotUnavailable' => true
237 ]
238 );
239
240 return $result;
241 }
242 }
243
244 $appointment->setGoogleCalendarEventId($oldAppointment->getGoogleCalendarEventId());
245 $appointment->setGoogleMeetUrl($oldAppointment->getGoogleMeetUrl());
246 $appointment->setOutlookCalendarEventId($oldAppointment->getOutlookCalendarEventId());
247 $appointment->setMicrosoftTeamsUrl($oldAppointment->getMicrosoftTeamsUrl());
248 $appointment->setAppleCalendarEventId($oldAppointment->getAppleCalendarEventId());
249
250 $appointmentRepo->beginTransaction();
251
252 /** @var Collection $removedBookings */
253 $removedBookings = new Collection();
254
255 foreach ($removedBookingsData as $removedBookingData) {
256 $removedBookings->addItem(CustomerBookingFactory::create($removedBookingData), $removedBookingData['id']);
257 }
258
259 $paymentData = [];
260
261 $bookingAdded = $bookingAS->isBookingAdded($appointment->getBookings());
262
263 /** @var CustomerBooking $oldBooking */
264 foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) {
265 if (
266 $appointment->getServiceId()->getValue() !== $oldAppointment->getServiceId()->getValue() &&
267 !$appointmentAS->processPackageAppointmentBooking(
268 $oldBooking,
269 $removedBookings,
270 $appointment->getServiceId()->getValue(),
271 $paymentData
272 )
273 ) {
274 $result->setResult(CommandResult::RESULT_ERROR);
275 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
276 $result->setData(
277 [
278 'packageBookingUnavailable' => true
279 ]
280 );
281
282 return $result;
283 }
284 }
285
286 $paymentData = !empty($command->getField('payment')) ? array_merge($command->getField('payment'), ['isBackendBooking' => true]) :
287 ['amount' => 0, 'gateway' => 'onSite', 'isBackendBooking' => true];
288
289 try {
290 $appointmentAS->update(
291 $oldAppointment,
292 $appointment,
293 $removedBookings,
294 $service,
295 $paymentData
296 );
297 } catch (QueryExecutionException $e) {
298 $appointmentRepo->rollback();
299 throw $e;
300 }
301
302 $appointmentRepo->commit();
303
304 do_action(
305 'amelia_after_appointment_updated',
306 $appointment ? $appointment->toArray() : null,
307 $oldAppointment ? $oldAppointment->toArray() : null,
308 $removedBookings ? $removedBookings->toArray() : null,
309 $service ? $service->toArray() : null,
310 $paymentData
311 );
312
313
314 $appointmentStatusChanged = $appointmentAS->isAppointmentStatusChanged($appointment, $oldAppointment);
315
316 $appRescheduled = $appointmentAS->isAppointmentRescheduled($appointment, $oldAppointment);
317
318 if ($appRescheduled) {
319 if (!$appointmentAS->canBeBooked($appointment, false, null, null)) {
320 $result->setResult(CommandResult::RESULT_ERROR);
321 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
322 $result->setData(
323 [
324 'timeSlotUnavailable' => true
325 ]
326 );
327
328 return $result;
329 }
330
331 $appointment->setRescheduled(new BooleanValueObject(true));
332
333 foreach ($appointment->getBookings()->getItems() as $booking) {
334 $bookingStartInUtc = DateTimeService::getCustomDateTimeObjectInUtc(
335 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
336 )->format('Y-m-d H:i:s');
337
338 $paymentAS->updateBookingPaymentDate(
339 $booking,
340 $bookingStartInUtc
341 );
342
343 if ($appointmentAS->isPeriodCustomPricing($service)) {
344 /** @var UserRepository $userRepository */
345 $userRepository = $this->getContainer()->get('domain.users.repository');
346
347 /** @var CustomerBookingRepository $bookingRepository */
348 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
349
350 /** @var Provider $provider */
351 $provider = $userRepository->getById($appointment->getProviderId()->getValue());
352
353 $price = $appointmentAS->getBookingPriceForService(
354 $service,
355 null,
356 $provider,
357 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
358 );
359
360 $booking->setPrice(new Price($price));
361
362 $bookingRepository->updatePrice($booking->getId()->getValue(), $booking);
363 }
364 }
365
366 $bookingAS->bookingRescheduled(
367 $oldAppointment->getId()->getValue(),
368 Entities::APPOINTMENT,
369 null,
370 Entities::CUSTOMER
371 );
372
373 $bookingAS->bookingRescheduled(
374 $oldAppointment->getId()->getValue(),
375 Entities::APPOINTMENT,
376 $oldAppointment->getProviderId()->getValue(),
377 Entities::PROVIDER
378 );
379 }
380
381 if ($appointmentStatusChanged) {
382 $appointmentStatus = $appointment->getStatus()->getValue();
383
384 /** @var CustomerBooking $booking */
385 foreach ($appointment->getBookings()->getItems() as $booking) {
386 if (
387 $booking->getStatus()->getValue() === BookingStatus::APPROVED &&
388 ($appointmentStatus === BookingStatus::PENDING || $appointmentStatus === BookingStatus::APPROVED)
389 ) {
390 $booking->setChangedStatus(new BooleanValueObject(true));
391 }
392 }
393
394 $appointment->setChangedStatus(new BooleanValueObject(true));
395 }
396
397 $appointmentArray = $appointment->toArray();
398
399 $oldAppointmentArray = $oldAppointment->toArray();
400
401 $bookingsWithChangedStatus = $bookingAS->getBookingsWithChangedStatus($appointmentArray, $oldAppointmentArray);
402
403 /** @var CustomerBooking $booking */
404 foreach ($appointment->getBookings()->getItems() as $booking) {
405 $reservationService->updateWooCommerceOrder($booking, $appointment);
406 }
407
408 $result->setResult(CommandResult::RESULT_SUCCESS);
409 $result->setMessage('Successfully updated appointment');
410 $result->setData(
411 [
412 Entities::APPOINTMENT => $appointmentArray,
413 'appointmentStatusChanged' => $appointmentStatusChanged,
414 'oldAppointmentStatus' => $oldAppointment->getStatus()->getValue(),
415 'appointmentRescheduled' => $appRescheduled,
416 'bookingsWithChangedStatus' => $bookingsWithChangedStatus,
417 'appointmentEmployeeChanged' => $userConnectionChanges['appointmentEmployeeChanged'],
418 'appointmentZoomUserChanged' => $userConnectionChanges['appointmentZoomUserChanged'],
419 'bookingAdded' => $bookingAdded,
420 'appointmentZoomUsersLicenced' => $userConnectionChanges['appointmentZoomUsersLicenced']
421 ]
422 );
423
424 $customFieldService->deleteUploadedFilesForDeletedBookings(
425 $appointment->getBookings(),
426 $oldAppointment->getBookings()
427 );
428
429 return $result;
430 }
431 }
432