PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.11
Booking for Appointments and Events Calendar – Amelia v1.2.11
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 7 years ago AddAppointmentCommandHandler.php 1 year ago AddBookingCommand.php 7 years ago AddBookingCommandHandler.php 1 year ago ApproveBookingRemotelyCommand.php 2 years ago ApproveBookingRemotelyCommandHandler.php 1 year ago CancelBookingCommand.php 7 years ago CancelBookingCommandHandler.php 2 years ago CancelBookingRemotelyCommand.php 7 years ago CancelBookingRemotelyCommandHandler.php 2 years ago DeleteAppointmentCommand.php 7 years ago DeleteAppointmentCommandHandler.php 2 years ago DeleteBookingCommand.php 4 years ago DeleteBookingCommandHandler.php 2 years ago GetAppointmentCommand.php 7 years ago GetAppointmentCommandHandler.php 1 year ago GetAppointmentsCommand.php 7 years ago GetAppointmentsCommandHandler.php 1 year ago GetIcsCommand.php 5 years ago GetIcsCommandHandler.php 4 years ago GetPackageAppointmentsCommand.php 1 year ago GetPackageAppointmentsCommandHandler.php 1 year ago GetTimeSlotsCommand.php 7 years ago GetTimeSlotsCommandHandler.php 1 year ago ReassignBookingCommand.php 5 years ago ReassignBookingCommandHandler.php 1 year ago RejectBookingRemotelyCommand.php 2 years ago RejectBookingRemotelyCommandHandler.php 1 year ago SuccessfulBookingCommand.php 7 years ago SuccessfulBookingCommandHandler.php 1 year ago UpdateAppointmentCommand.php 7 years ago UpdateAppointmentCommandHandler.php 1 year ago UpdateAppointmentStatusCommand.php 7 years ago UpdateAppointmentStatusCommandHandler.php 1 year ago UpdateAppointmentTimeCommand.php 7 years ago UpdateAppointmentTimeCommandHandler.php 1 year ago
UpdateAppointmentCommandHandler.php
428 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 $initialBookingStart = $oldAppointment->getBookingStart()->getValue();
164 $initialBookingEnd = $oldAppointment->getBookingEnd()->getValue();
165
166 /** @var CustomerBooking $newBooking */
167 foreach ($appointment->getBookings()->getItems() as $newBooking) {
168 /** @var CustomerBooking $oldBooking */
169 foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) {
170 if ($newBooking->getId() &&
171 $newBooking->getId()->getValue() === $oldBooking->getId()->getValue()
172 ) {
173 if ($oldBooking->getUtcOffset()) {
174 $newBooking->setUtcOffset($oldBooking->getUtcOffset());
175 }
176
177 if ($oldBooking->getCreated()) {
178 $newBooking->setCreated($oldBooking->getCreated());
179 }
180
181 if ($oldBooking->getInfo()) {
182 $newBooking->setInfo($oldBooking->getInfo());
183 }
184
185 if ($oldBooking->getStatus()->getValue() === $newBooking->getStatus()->getValue()) {
186 $newBooking->setUpdated(
187 new BooleanValueObject(
188 $appointmentAS->appointmentDetailsChanged($appointment, $oldAppointment) || $appointmentAS->bookingDetailsChanged($newBooking, $oldBooking)
189 )
190 );
191 }
192 }
193 }
194 }
195
196 $appointment->setBookingEnd(
197 new DateTimeValue(
198 DateTimeService::getCustomDateTimeObject(
199 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
200 )->modify('+' . $appointmentAS->getAppointmentLengthTime($appointment, $service) . ' second')
201 )
202 );
203
204 $appointmentEmployeeChanged = null;
205
206 $appointmentZoomUserChanged = false;
207
208 $appointmentZoomUsersLicenced = false;
209
210 if ($appointment->getProviderId()->getValue() !== $oldAppointment->getProviderId()->getValue()) {
211 $appointmentEmployeeChanged = $oldAppointment->getProviderId()->getValue();
212
213 $provider = $providerRepository->getById($appointment->getProviderId()->getValue());
214
215 $oldProvider = $providerRepository->getById($oldAppointment->getProviderId()->getValue());
216
217 if ($provider && $oldProvider && $provider->getZoomUserId() && $oldProvider->getZoomUserId() &&
218 $provider->getZoomUserId()->getValue() !== $oldProvider->getZoomUserId()->getValue()) {
219 $appointmentZoomUserChanged = true;
220
221 $zoomUserType = 0;
222
223 $zoomOldUserType = 0;
224
225 $zoomResult = $zoomService->getUsers();
226
227 if (!(isset($zoomResult['code']) && $zoomResult['code'] === 124) &&
228 !($zoomResult['users'] === null && isset($zoomResult['message']))) {
229 $zoomUsers = $zoomResult['users'];
230 foreach ($zoomUsers as $key => $val) {
231 if ($val['id'] === $provider->getZoomUserId()->getValue()) {
232 $zoomUserType = $val['type'];
233 }
234 if ($val['id'] === $oldProvider->getZoomUserId()->getValue()) {
235 $zoomOldUserType = $val['type'];
236 }
237 }
238 }
239 if ($zoomOldUserType > 1 && $zoomUserType > 1) {
240 $appointmentZoomUsersLicenced = true;
241 }
242 }
243 }
244
245 if ($oldAppointment->getZoomMeeting()) {
246 $appointment->setZoomMeeting($oldAppointment->getZoomMeeting());
247 }
248
249 if ($bookingAS->isBookingApprovedOrPending($appointment->getStatus()->getValue()) &&
250 $bookingAS->isBookingCanceledOrRejectedOrNoShow($oldAppointment->getStatus()->getValue())
251 ) {
252 /** @var AbstractUser $user */
253 $user = $this->container->get('logged.in.user');
254
255 if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user), null, null)) {
256 $result->setResult(CommandResult::RESULT_ERROR);
257 $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']);
258 $result->setData(
259 [
260 'timeSlotUnavailable' => true
261 ]
262 );
263
264 return $result;
265 }
266 }
267
268 $appointment->setGoogleCalendarEventId($oldAppointment->getGoogleCalendarEventId());
269 $appointment->setGoogleMeetUrl($oldAppointment->getGoogleMeetUrl());
270 $appointment->setOutlookCalendarEventId($oldAppointment->getOutlookCalendarEventId());
271
272 $appointmentRepo->beginTransaction();
273
274 /** @var Collection $removedBookings */
275 $removedBookings = new Collection();
276
277 foreach ($removedBookingsData as $removedBookingData) {
278 $removedBookings->addItem(CustomerBookingFactory::create($removedBookingData), $removedBookingData['id']);
279 }
280
281 $paymentData = null;
282
283 $bookingAdded = $bookingAS->isBookingAdded($appointment->getBookings());
284
285 /** @var CustomerBooking $booking */
286 foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) {
287 if ($appointment->getServiceId()->getValue() !== $oldAppointment->getServiceId()->getValue() &&
288 !$appointmentAS->processPackageAppointmentBooking(
289 $oldBooking,
290 $removedBookings,
291 $appointment->getServiceId()->getValue(),
292 $paymentData
293 )
294 ) {
295 $result->setResult(CommandResult::RESULT_ERROR);
296 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
297 $result->setData(
298 [
299 'packageBookingUnavailable' => true
300 ]
301 );
302
303 return $result;
304 }
305 }
306
307 $paymentData = !empty($command->getField('payment')) ? array_merge($command->getField('payment'), ['isBackendBooking' => true]) :
308 ['amount' => 0, 'gateway' => 'onSite', 'isBackendBooking' => true];
309
310 try {
311 $appointmentAS->update(
312 $oldAppointment,
313 $appointment,
314 $removedBookings,
315 $service,
316 $paymentData
317 );
318 } catch (QueryExecutionException $e) {
319 $appointmentRepo->rollback();
320 throw $e;
321 }
322
323 $appointmentRepo->commit();
324
325 do_action(
326 'amelia_after_appointment_updated',
327 $appointment ? $appointment->toArray() : null,
328 $oldAppointment ? $oldAppointment->toArray() : null,
329 $removedBookings ? $removedBookings->toArray() : null,
330 $service ? $service->toArray() : null,
331 $paymentData
332 );
333
334
335 $appointmentStatusChanged = $appointmentAS->isAppointmentStatusChanged($appointment, $oldAppointment);
336
337 $appRescheduled = $appointmentAS->isAppointmentRescheduled($appointment, $oldAppointment);
338
339 if ($appRescheduled) {
340 if (!$appointmentAS->canBeBooked($appointment, false, null, null)) {
341 $result->setResult(CommandResult::RESULT_ERROR);
342 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
343 $result->setData(
344 [
345 'timeSlotUnavailable' => true
346 ]
347 );
348
349 return $result;
350 }
351
352 $appointment->setRescheduled(new BooleanValueObject(true));
353
354 foreach ($appointment->getBookings()->getItems() as $booking) {
355 $paymentAS->updateBookingPaymentDate(
356 $booking,
357 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
358 );
359 }
360
361 $bookingAS->bookingRescheduled(
362 $oldAppointment->getId()->getValue(),
363 Entities::APPOINTMENT,
364 null,
365 Entities::CUSTOMER
366 );
367
368 $bookingAS->bookingRescheduled(
369 $oldAppointment->getId()->getValue(),
370 Entities::APPOINTMENT,
371 $oldAppointment->getProviderId()->getValue(),
372 Entities::PROVIDER
373 );
374 }
375
376 if ($appointmentStatusChanged) {
377 $appointmentStatus = $appointment->getStatus()->getValue();
378
379 /** @var CustomerBooking $booking */
380 foreach ($appointment->getBookings()->getItems() as $booking) {
381 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED &&
382 ($appointmentStatus === BookingStatus::PENDING || $appointmentStatus === BookingStatus::APPROVED)
383 ) {
384 $booking->setChangedStatus(new BooleanValueObject(true));
385 }
386 }
387 }
388
389 $appointmentArray = $appointment->toArray();
390
391 $oldAppointmentArray = $oldAppointment->toArray();
392
393 $bookingsWithChangedStatus = $bookingAS->getBookingsWithChangedStatus($appointmentArray, $oldAppointmentArray);
394
395 /** @var CustomerBooking $booking */
396 foreach ($appointment->getBookings()->getItems() as $booking) {
397 $reservationService->updateWooCommerceOrder($booking, $appointment);
398 }
399
400 $result->setResult(CommandResult::RESULT_SUCCESS);
401 $result->setMessage('Successfully updated appointment');
402 $result->setData(
403 [
404 Entities::APPOINTMENT => $appointmentArray,
405 'appointmentStatusChanged' => $appointmentStatusChanged,
406 'appointmentRescheduled' => $appRescheduled,
407 'initialAppointmentDateTime' => [
408 'bookingStart' => $initialBookingStart->format('Y-m-d H:i:s'),
409 'bookingEnd' => $initialBookingEnd->format('Y-m-d H:i:s'),
410 ],
411 'bookingsWithChangedStatus' => $bookingsWithChangedStatus,
412 'appointmentEmployeeChanged' => $appointmentEmployeeChanged,
413 'appointmentZoomUserChanged' => $appointmentZoomUserChanged,
414 'bookingAdded' => $bookingAdded,
415 'appointmentZoomUsersLicenced' => $appointmentZoomUsersLicenced,
416 'createPaymentLinks' => $command->getField('createPaymentLinks')
417 ]
418 );
419
420 $customFieldService->deleteUploadedFilesForDeletedBookings(
421 $appointment->getBookings(),
422 $oldAppointment->getBookings()
423 );
424
425 return $result;
426 }
427 }
428