PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.20
Booking for Appointments and Events Calendar – Amelia v1.2.20
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 UpdateBookingStatusCommand.php 1 year ago UpdateBookingStatusCommandHandler.php 1 year ago
UpdateAppointmentCommandHandler.php
403 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 ($newBooking->getId() &&
177 $newBooking->getId()->getValue() === $oldBooking->getId()->getValue()
178 ) {
179 if ($oldBooking->getUtcOffset()) {
180 $newBooking->setUtcOffset($oldBooking->getUtcOffset());
181 }
182
183 if ($oldBooking->getCreated()) {
184 $newBooking->setCreated($oldBooking->getCreated());
185 }
186
187 if ($oldBooking->getInfo()) {
188 $newBooking->setInfo($oldBooking->getInfo());
189 }
190
191 if ($oldBooking->getStatus()->getValue() === $newBooking->getStatus()->getValue()) {
192 $newBooking->setUpdated(
193 new BooleanValueObject(
194 $appointmentAS->appointmentDetailsChanged($appointment, $oldAppointment) || $appointmentAS->bookingDetailsChanged($newBooking, $oldBooking)
195 )
196 );
197 }
198 }
199 }
200 }
201
202 $appointment->setBookingEnd(
203 new DateTimeValue(
204 DateTimeService::getCustomDateTimeObject(
205 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
206 )->modify('+' . $appointmentAS->getAppointmentLengthTime($appointment, $service) . ' second')
207 )
208 );
209
210 $userConnectionChanges = $appointmentAS->getUserConnectionChanges(
211 $appointment->getProviderId()->getValue(),
212 $oldAppointment->getProviderId()->getValue()
213 );
214
215 if ($oldAppointment->getZoomMeeting()) {
216 $appointment->setZoomMeeting($oldAppointment->getZoomMeeting());
217 }
218
219 if ($bookingAS->isBookingApprovedOrPending($appointment->getStatus()->getValue()) &&
220 $bookingAS->isBookingCanceledOrRejectedOrNoShow($oldAppointment->getStatus()->getValue())
221 ) {
222 /** @var AbstractUser $user */
223 $user = $this->container->get('logged.in.user');
224
225 if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user), null, null)) {
226 $result->setResult(CommandResult::RESULT_ERROR);
227 $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']);
228 $result->setData(
229 [
230 'timeSlotUnavailable' => true
231 ]
232 );
233
234 return $result;
235 }
236 }
237
238 $appointment->setGoogleCalendarEventId($oldAppointment->getGoogleCalendarEventId());
239 $appointment->setGoogleMeetUrl($oldAppointment->getGoogleMeetUrl());
240 $appointment->setOutlookCalendarEventId($oldAppointment->getOutlookCalendarEventId());
241 $appointment->setMicrosoftTeamsUrl($oldAppointment->getMicrosoftTeamsUrl());
242 $appointment->setAppleCalendarEventId($oldAppointment->getAppleCalendarEventId());
243
244 $appointmentRepo->beginTransaction();
245
246 /** @var Collection $removedBookings */
247 $removedBookings = new Collection();
248
249 foreach ($removedBookingsData as $removedBookingData) {
250 $removedBookings->addItem(CustomerBookingFactory::create($removedBookingData), $removedBookingData['id']);
251 }
252
253 $paymentData = null;
254
255 $bookingAdded = $bookingAS->isBookingAdded($appointment->getBookings());
256
257 /** @var CustomerBooking $booking */
258 foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) {
259 if ($appointment->getServiceId()->getValue() !== $oldAppointment->getServiceId()->getValue() &&
260 !$appointmentAS->processPackageAppointmentBooking(
261 $oldBooking,
262 $removedBookings,
263 $appointment->getServiceId()->getValue(),
264 $paymentData
265 )
266 ) {
267 $result->setResult(CommandResult::RESULT_ERROR);
268 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
269 $result->setData(
270 [
271 'packageBookingUnavailable' => true
272 ]
273 );
274
275 return $result;
276 }
277 }
278
279 $paymentData = !empty($command->getField('payment')) ? array_merge($command->getField('payment'), ['isBackendBooking' => true]) :
280 ['amount' => 0, 'gateway' => 'onSite', 'isBackendBooking' => true];
281
282 try {
283 $appointmentAS->update(
284 $oldAppointment,
285 $appointment,
286 $removedBookings,
287 $service,
288 $paymentData
289 );
290 } catch (QueryExecutionException $e) {
291 $appointmentRepo->rollback();
292 throw $e;
293 }
294
295 $appointmentRepo->commit();
296
297 do_action(
298 'amelia_after_appointment_updated',
299 $appointment ? $appointment->toArray() : null,
300 $oldAppointment ? $oldAppointment->toArray() : null,
301 $removedBookings ? $removedBookings->toArray() : null,
302 $service ? $service->toArray() : null,
303 $paymentData
304 );
305
306
307 $appointmentStatusChanged = $appointmentAS->isAppointmentStatusChanged($appointment, $oldAppointment);
308
309 $appRescheduled = $appointmentAS->isAppointmentRescheduled($appointment, $oldAppointment);
310
311 if ($appRescheduled) {
312 if (!$appointmentAS->canBeBooked($appointment, false, null, null)) {
313 $result->setResult(CommandResult::RESULT_ERROR);
314 $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']);
315 $result->setData(
316 [
317 'timeSlotUnavailable' => true
318 ]
319 );
320
321 return $result;
322 }
323
324 $appointment->setRescheduled(new BooleanValueObject(true));
325
326 foreach ($appointment->getBookings()->getItems() as $booking) {
327 $bookingStartInUtc = DateTimeService::getCustomDateTimeObjectInUtc(
328 $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s')
329 )->format('Y-m-d H:i:s');
330
331 $paymentAS->updateBookingPaymentDate(
332 $booking,
333 $bookingStartInUtc
334 );
335 }
336
337 $bookingAS->bookingRescheduled(
338 $oldAppointment->getId()->getValue(),
339 Entities::APPOINTMENT,
340 null,
341 Entities::CUSTOMER
342 );
343
344 $bookingAS->bookingRescheduled(
345 $oldAppointment->getId()->getValue(),
346 Entities::APPOINTMENT,
347 $oldAppointment->getProviderId()->getValue(),
348 Entities::PROVIDER
349 );
350 }
351
352 if ($appointmentStatusChanged) {
353 $appointmentStatus = $appointment->getStatus()->getValue();
354
355 /** @var CustomerBooking $booking */
356 foreach ($appointment->getBookings()->getItems() as $booking) {
357 if ($booking->getStatus()->getValue() === BookingStatus::APPROVED &&
358 ($appointmentStatus === BookingStatus::PENDING || $appointmentStatus === BookingStatus::APPROVED)
359 ) {
360 $booking->setChangedStatus(new BooleanValueObject(true));
361 }
362 }
363
364 $appointment->setChangedStatus(new BooleanValueObject(true));
365 }
366
367 $appointmentArray = $appointment->toArray();
368
369 $oldAppointmentArray = $oldAppointment->toArray();
370
371 $bookingsWithChangedStatus = $bookingAS->getBookingsWithChangedStatus($appointmentArray, $oldAppointmentArray);
372
373 /** @var CustomerBooking $booking */
374 foreach ($appointment->getBookings()->getItems() as $booking) {
375 $reservationService->updateWooCommerceOrder($booking, $appointment);
376 }
377
378 $result->setResult(CommandResult::RESULT_SUCCESS);
379 $result->setMessage('Successfully updated appointment');
380 $result->setData(
381 [
382 Entities::APPOINTMENT => $appointmentArray,
383 'appointmentStatusChanged' => $appointmentStatusChanged,
384 'oldAppointmentStatus' => $oldAppointment->getStatus()->getValue(),
385 'appointmentRescheduled' => $appRescheduled,
386 'bookingsWithChangedStatus' => $bookingsWithChangedStatus,
387 'appointmentEmployeeChanged' => $userConnectionChanges['appointmentEmployeeChanged'],
388 'appointmentZoomUserChanged' => $userConnectionChanges['appointmentZoomUserChanged'],
389 'bookingAdded' => $bookingAdded,
390 'appointmentZoomUsersLicenced' => $userConnectionChanges['appointmentZoomUsersLicenced'],
391 'createPaymentLinks' => $command->getField('createPaymentLinks')
392 ]
393 );
394
395 $customFieldService->deleteUploadedFilesForDeletedBookings(
396 $appointment->getBookings(),
397 $oldAppointment->getBookings()
398 );
399
400 return $result;
401 }
402 }
403