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