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 / AddAppointmentCommandHandler.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
AddAppointmentCommandHandler.php
378 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\Entity\EntityApplicationService;
11 use AmeliaBooking\Application\Services\User\UserApplicationService;
12 use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException;
13 use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException;
14 use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException;
15 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
16 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
17 use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment;
18 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
19 use AmeliaBooking\Domain\Entity\Entities;
20 use AmeliaBooking\Domain\Entity\User\AbstractUser;
21 use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface;
22 use AmeliaBooking\Domain\Services\Settings\SettingsService;
23 use AmeliaBooking\Domain\ValueObjects\PositiveDuration;
24 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
25 use AmeliaBooking\Domain\ValueObjects\String\Description;
26 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
27 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
28 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository;
29 use Exception;
30 use Interop\Container\Exception\ContainerException;
31 use Slim\Exception\ContainerValueNotFoundException;
32
33 /**
34 * Class AddAppointmentCommandHandler
35 *
36 * @package AmeliaBooking\Application\Commands\Booking\Appointment
37 */
38 class AddAppointmentCommandHandler extends CommandHandler
39 {
40 /**
41 * @var array
42 */
43 public $mandatoryFields = [
44 'bookings',
45 'bookingStart',
46 'notifyParticipants',
47 'serviceId',
48 'providerId'
49 ];
50
51 /**
52 * @param AddAppointmentCommand $command
53 *
54 * @return CommandResult
55 * @throws NotFoundException
56 * @throws ContainerValueNotFoundException
57 * @throws InvalidArgumentException
58 * @throws QueryExecutionException
59 * @throws ContainerException
60 * @throws Exception
61 */
62 public function handle(AddAppointmentCommand $command)
63 {
64 $result = new CommandResult();
65
66 $this->checkMandatoryFields($command);
67
68 /** @var AppointmentRepository $appointmentRepo */
69 $appointmentRepo = $this->container->get('domain.booking.appointment.repository');
70 /** @var AppointmentApplicationService $appointmentAS */
71 $appointmentAS = $this->container->get('application.booking.appointment.service');
72 /** @var BookableApplicationService $bookableAS */
73 $bookableAS = $this->container->get('application.bookable.service');
74 /** @var UserApplicationService $userAS */
75 $userAS = $this->getContainer()->get('application.user.service');
76 /** @var SettingsService $settingsDS */
77 $settingsDS = $this->container->get('domain.settings.service');
78 /** @var EntityApplicationService $entityService */
79 $entityService = $this->container->get('application.entity.service');
80 /** @var ReservationServiceInterface $reservationService */
81 $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT);
82
83 if ($missingEntity = $entityService->getMissingEntityForAppointment($command->getFields())) {
84 return $entityService->getMissingEntityResponse($missingEntity);
85 }
86
87 try {
88 /** @var AbstractUser $user */
89 $user = $command->getUserApplicationService()->authorization(
90 $command->getPage() === 'cabinet' ? $command->getToken() : null,
91 $command->getCabinetType()
92 );
93 } catch (AuthorizationException $e) {
94 $result->setResult(CommandResult::RESULT_ERROR);
95 $result->setData(
96 [
97 'reauthorize' => true
98 ]
99 );
100
101 return $result;
102 }
103
104 if ($userAS->isCustomer($user)) {
105 throw new AccessDeniedException('You are not allowed to update appointment');
106 }
107
108 if ($userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteAppointments')) {
109 throw new AccessDeniedException('You are not allowed to add an appointment');
110 }
111
112 $appointmentData = $command->getFields();
113
114 $paymentData = !empty($command->getField('payment')) ? array_merge($command->getField('payment'), ['isBackendBooking' => true]) :
115 ['amount' => 0, 'gateway' => 'onSite', 'isBackendBooking' => true];
116
117 /** @var Service $service */
118 $service = $bookableAS->getAppointmentService($appointmentData['serviceId'], $appointmentData['providerId']);
119
120 $appointmentData = apply_filters('amelia_before_appointment_added_filter', $appointmentData, $service ? $service->toArray() : null, $paymentData);
121
122 do_action('amelia_before_appointment_added', $appointmentData, $service ? $service->toArray() : null, $paymentData);
123
124 $maxDuration = 0;
125
126 foreach ($appointmentData['bookings'] as $booking) {
127 if ($booking['duration'] > $maxDuration && ($booking['status'] === BookingStatus::APPROVED || BookingStatus::PENDING)) {
128 $maxDuration = $booking['duration'];
129 }
130 }
131
132 if ($maxDuration) {
133 $service->setDuration(new PositiveDuration($maxDuration));
134 }
135
136 $appointmentAS->convertTime($appointmentData);
137
138 $reservationService->manageTaxes($appointmentData);
139
140 $appointmentRepo->beginTransaction();
141
142 $ignoredData = [];
143
144 /** @var Appointment $existingAppointment */
145 $existingAppointment = $appointmentAS->getAlreadyBookedAppointment($appointmentData, []);
146
147 /** @var Appointment $appointment */
148 $appointment = $appointmentAS->build(
149 $existingAppointment ? $existingAppointment->toArray() : $appointmentData,
150 $service
151 );
152
153 if ($existingAppointment && !empty($appointmentData['internalNotes'])) {
154 if ($existingAppointment->getInternalNotes() &&
155 $existingAppointment->getInternalNotes()->getValue()
156 ) {
157 $appointment->setInternalNotes(
158 new Description(
159 $existingAppointment->getInternalNotes()->getValue() .
160 PHP_EOL .
161 PHP_EOL .
162 $appointmentData['internalNotes']
163 )
164 );
165 } else {
166 $appointment->setInternalNotes(
167 new Description(
168 $appointmentData['internalNotes']
169 )
170 );
171 }
172 }
173
174 try {
175 $appointmentAS->addOrEditAppointment(
176 $appointment,
177 $existingAppointment,
178 $service,
179 $appointmentData['bookings'],
180 $paymentData
181 );
182 } catch (CustomerBookedException $e) {
183 $appointmentRepo->rollback();
184
185 $result->setResult(CommandResult::RESULT_ERROR);
186 $result->setMessage($e->getMessage());
187 $result->setData(
188 [
189 'customerAlreadyBooked' => true
190 ]
191 );
192
193 return $result;
194 } catch (BookingUnavailableException $e) {
195 $appointmentRepo->rollback();
196
197 $result->setResult(CommandResult::RESULT_ERROR);
198 $result->setMessage($e->getMessage());
199 $result->setData(
200 [
201 'timeSlotUnavailable' => true
202 ]
203 );
204
205 return $result;
206 }
207
208 if ($existingAppointment !== null) {
209 $existingAppointmentId = $existingAppointment->getId()->getValue();
210
211 $ignoredData[$existingAppointmentId] = [
212 'status' => $existingAppointment->getStatus()->getValue(),
213 'bookingsIds' => [],
214 ];
215
216 /** @var CustomerBooking $booking */
217 foreach ($existingAppointment->getBookings()->getItems() as $booking) {
218 $ignoredData[$existingAppointmentId]['bookingsIds'][$booking->getId()->getValue()] = true;
219 }
220 }
221
222 $error = false;
223
224 $recurringAppointments = [];
225
226 foreach ($command->getField('recurring') as $recurringData) {
227 $recurringAppointmentData = array_merge(
228 $appointmentData,
229 [
230 'bookingStart' => $recurringData['bookingStart'],
231 'locationId' => $recurringData['locationId'],
232 'parentId' => $appointment->getId()->getValue()
233 ]
234 );
235
236 if ($appointment->getBookings() &&
237 $appointment->getBookings()->keyExists(0) &&
238 $appointment->getBookings()->getItem(0)->getPayments() &&
239 $appointment->getBookings()->getItem(0)->getPayments()->keyExists(0)
240 ) {
241 $paymentData['parentId'] =
242 $appointment->getBookings()->getItem(0)->getPayments()->getItem(0)->getId()->getValue();
243 }
244
245 $appointmentAS->convertTime($recurringAppointmentData);
246
247 /** @var Appointment $existingRecurringAppointment */
248 $existingRecurringAppointment = $appointmentAS->getAlreadyBookedAppointment($recurringAppointmentData, []);
249
250 /** @var Appointment $recurringAppointment */
251 $recurringAppointment = $appointmentAS->build(
252 $existingRecurringAppointment ? $existingRecurringAppointment->toArray() : $recurringAppointmentData,
253 $service
254 );
255
256 if ($existingRecurringAppointment && $recurringAppointmentData['internalNotes']) {
257 if ($existingRecurringAppointment->getInternalNotes() &&
258 $existingRecurringAppointment->getInternalNotes()->getValue()
259 ) {
260 $recurringAppointment->setInternalNotes(
261 new Description(
262 $existingRecurringAppointment->getInternalNotes()->getValue() .
263 PHP_EOL .
264 PHP_EOL .
265 $recurringAppointmentData['internalNotes']
266 )
267 );
268 } else {
269 $recurringAppointment->setInternalNotes(
270 new Description(
271 $recurringAppointmentData['internalNotes']
272 )
273 );
274 }
275 }
276
277 try {
278 $appointmentAS->addOrEditAppointment(
279 $recurringAppointment,
280 $existingRecurringAppointment,
281 $service,
282 $recurringAppointmentData['bookings'],
283 $paymentData
284 );
285 } catch (CustomerBookedException $e) {
286 $appointmentRepo->rollback();
287
288 $result->setResult(CommandResult::RESULT_ERROR);
289 $result->setMessage($e->getMessage());
290 $result->setData(
291 [
292 'customerAlreadyBooked' => true
293 ]
294 );
295
296 $error = true;
297 } catch (BookingUnavailableException $e) {
298 $appointmentRepo->rollback();
299
300 $result->setResult(CommandResult::RESULT_ERROR);
301 $result->setMessage($e->getMessage());
302 $result->setData(
303 [
304 'timeSlotUnavailable' => true
305 ]
306 );
307
308 $error = true;
309 }
310
311 if ($error) {
312 $appointmentAS->delete($appointment, $ignoredData);
313
314 if ($appointment->getId() &&
315 $appointment->getId()->getValue() &&
316 !empty($ignoredData[$appointment->getId()->getValue()])
317 ) {
318 $appointmentRepo->updateFieldById(
319 $appointment->getId()->getValue(),
320 $ignoredData[$appointment->getId()->getValue()]['status'],
321 'status'
322 );
323 }
324
325 foreach ($recurringAppointments as $savedRecurringAppointment) {
326 $appointmentAS->delete(
327 $appointmentAS->build($savedRecurringAppointment[Entities::APPOINTMENT], $service),
328 $ignoredData
329 );
330
331 if (!empty($ignoredData[$savedRecurringAppointment[Entities::APPOINTMENT]['id']])) {
332 $appointmentRepo->updateFieldById(
333 $savedRecurringAppointment[Entities::APPOINTMENT]['id'],
334 $ignoredData[$savedRecurringAppointment[Entities::APPOINTMENT]['id']]['status'],
335 'status'
336 );
337 }
338 }
339
340 return $result;
341 }
342
343 if ($existingRecurringAppointment !== null) {
344 $existingAppointmentId = $existingRecurringAppointment->getId()->getValue();
345
346 $ignoredData[$existingAppointmentId] = [
347 'status' => $existingRecurringAppointment->getStatus()->getValue(),
348 'bookingsIds' => [],
349 ];
350
351 /** @var CustomerBooking $booking */
352 foreach ($existingRecurringAppointment->getBookings()->getItems() as $booking) {
353 $ignoredData[$existingAppointmentId]['bookingsIds'][$booking->getId()->getValue()] = true;
354 }
355 }
356
357 $recurringAppointments[] = [
358 Entities::APPOINTMENT => $recurringAppointment->toArray()
359 ];
360 }
361
362 $result->setResult(CommandResult::RESULT_SUCCESS);
363 $result->setMessage('Successfully added new appointment');
364 $result->setData(
365 [
366 Entities::APPOINTMENT => $appointment->toArray(),
367 'recurring' => $recurringAppointments
368 ]
369 );
370
371 $appointmentRepo->commit();
372
373 do_action('amelia_after_appointment_added', $appointment ? $appointment->toArray() : null, $service ? $service->toArray() : null, $paymentData);
374
375 return $result;
376 }
377 }
378