PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
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 / GetAppointmentBookingsCommandHandler.php
ameliabooking / src / Application / Commands / Booking / Appointment Last commit date
AddAppointmentCommand.php 1 year ago AddAppointmentCommandHandler.php 2 months ago AddBookingCommand.php 1 year ago AddBookingCommandHandler.php 1 year ago ApproveBookingRemotelyCommand.php 1 year ago ApproveBookingRemotelyCommandHandler.php 2 months ago CancelBookingCommand.php 1 year ago CancelBookingCommandHandler.php 6 months ago CancelBookingRemotelyCommand.php 1 year ago CancelBookingRemotelyCommandHandler.php 1 month ago DeleteAppointmentCommand.php 1 year ago DeleteAppointmentCommandHandler.php 1 year ago DeleteBookingCommand.php 1 year ago DeleteBookingCommandHandler.php 10 months ago DeleteBookingRemotelyCommand.php 10 months ago DeleteBookingRemotelyCommandHandler.php 6 months ago GetAppointmentBookingsCommand.php 6 months ago GetAppointmentBookingsCommandHandler.php 2 months ago GetAppointmentCommand.php 7 years ago GetAppointmentCommandHandler.php 2 weeks ago GetAppointmentsCommand.php 1 year ago GetAppointmentsCommandHandler.php 2 weeks ago GetIcsCommand.php 6 months ago GetIcsCommandHandler.php 4 years ago GetTimeSlotsCommand.php 1 year ago GetTimeSlotsCommandHandler.php 1 month ago ReassignBookingCommand.php 1 year ago ReassignBookingCommandHandler.php 3 months ago RejectBookingRemotelyCommand.php 1 year ago RejectBookingRemotelyCommandHandler.php 4 months ago SuccessfulBookingCommand.php 1 year ago SuccessfulBookingCommandHandler.php 1 year ago UpdateAppointmentCommand.php 1 year ago UpdateAppointmentCommandHandler.php 3 months ago UpdateAppointmentNoteCommand.php 3 months ago UpdateAppointmentNoteCommandHandler.php 3 months ago UpdateAppointmentStatusCommand.php 1 year ago UpdateAppointmentStatusCommandHandler.php 2 months ago UpdateAppointmentTimeCommand.php 1 year ago UpdateAppointmentTimeCommandHandler.php 1 month ago UpdateBookingStatusCommand.php 1 year ago UpdateBookingStatusCommandHandler.php 5 months ago
GetAppointmentBookingsCommandHandler.php
355 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\Booking\AppointmentApplicationService;
9 use AmeliaBooking\Application\Services\Helper\HelperService;
10 use AmeliaBooking\Application\Services\Payment\PaymentApplicationService;
11 use AmeliaBooking\Application\Services\User\ProviderApplicationService;
12 use AmeliaBooking\Domain\Collection\Collection;
13 use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException;
14 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
15 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
16 use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment;
17 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
18 use AmeliaBooking\Domain\Entity\Entities;
19 use AmeliaBooking\Domain\Entity\User\AbstractUser;
20 use AmeliaBooking\Domain\Services\Settings\SettingsService;
21 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
22 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
23 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository;
24 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
25 use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository;
26 use DateTimeZone;
27
28 /**
29 * Class GetAppointmentBookingsCommandHandler
30 *
31 * @package AmeliaBooking\Application\Commands\Booking\Appointment
32 */
33 class GetAppointmentBookingsCommandHandler extends CommandHandler
34 {
35 /**
36 * @param GetAppointmentBookingsCommand $command
37 *
38 * @return CommandResult
39 *
40 * @throws InvalidArgumentException
41 * @throws QueryExecutionException
42 * @throws AccessDeniedException
43 */
44 public function handle(GetAppointmentBookingsCommand $command)
45 {
46 $result = new CommandResult();
47
48 /** @var HelperService $helperService */
49 $helperService = $this->container->get('application.helper.service');
50
51 /** @var AppointmentRepository $appointmentRepository */
52 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
53
54 /** @var ServiceRepository $serviceRepository */
55 $serviceRepository = $this->container->get('domain.bookable.service.repository');
56
57 /** @var SettingsService $settingsDS */
58 $settingsDS = $this->container->get('domain.settings.service');
59
60 /** @var PaymentApplicationService $paymentAS */
61 $paymentAS = $this->container->get('application.payment.service');
62
63 /** @var AppointmentApplicationService $appointmentAS */
64 $appointmentAS = $this->container->get('application.booking.appointment.service');
65
66 /** @var ProviderRepository $providerRepository */
67 $providerRepository = $this->container->get('domain.users.providers.repository');
68
69 /** @var ProviderApplicationService $providerAS */
70 $providerAS = $this->container->get('application.user.provider.service');
71
72
73 $params = $command->getField('params');
74
75 if (isset($params['dates']) && empty($params['dates'][0]) && empty($params['dates'][1])) {
76 unset($params['dates']);
77 }
78
79 try {
80 /** @var AbstractUser $user */
81 $user = $command->getUserApplicationService()->authorization(null, $command->getCabinetType());
82 } catch (AuthorizationException $e) {
83 $result->setResult(CommandResult::RESULT_ERROR);
84 $result->setData(
85 [
86 'reauthorize' => true
87 ]
88 );
89
90 return $result;
91 }
92
93 $readOthers = $this->container->getPermissionsService()->currentUserCanReadOthers(Entities::APPOINTMENTS);
94
95 $providerCountParams = [];
96 if (
97 (!$readOthers) &&
98 $user && $user->getType() === Entities::PROVIDER
99 ) {
100 $providerCountParams['providerId'] = $user->getId()->getValue();
101 $params['providers'] = [$user->getId()->getValue()];
102 }
103
104 $customerCountParams = [];
105 if ($user && $user->getType() === Entities::CUSTOMER) {
106 $customerCountParams['customers'] = [$user->getId()->getValue()];
107 $params['customers'] = [$user->getId()->getValue()];
108 }
109
110 $entitiesIds = !empty($params['search']) ? $appointmentAS->getAppointmentEntitiesIdsBySearchString($params['search']) : [];
111
112 $appointmentsIds = [];
113
114 $helperService->convertDates($params);
115
116 /** @var Collection $periodAppointments */
117 $periodAppointments = $appointmentRepository->getPeriodAppointments(
118 array_merge(
119 $params,
120 ['search' => $entitiesIds, 'searchTerm' => !empty($params['search']) ? $params['search'] : ''],
121 ['skipBookings' => empty($params['customers']) && empty($entitiesIds['customers'])]
122 ),
123 $params['limit']
124 );
125
126 $serviceIds = [];
127
128 /** @var Appointment $appointment */
129 foreach ($periodAppointments->getItems() as $appointment) {
130 $appointmentsIds[] = $appointment->getId()->getValue();
131 $serviceIds[] = $appointment->getServiceId()->getValue();
132 }
133
134 /** @var Collection $appointments */
135 $appointments = new Collection();
136
137 $customersNoShowCountIds = [];
138
139 $noShowTagEnabled = $settingsDS->isFeatureEnabled('noShowTag');
140
141 if ($appointmentsIds) {
142 $appointments = $appointmentRepository->getFiltered(
143 [
144 'ids' => $appointmentsIds,
145 'withLocations' => true,
146 'sort' => !empty($params['sort']) ? $params['sort'] : null,
147 'customers' => $user && $user->getType() === Entities::CUSTOMER
148 ? [$user->getId()->getValue()]
149 : [],
150 ]
151 );
152 }
153
154 /** @var Collection $services */
155 $services = $serviceRepository->getAllArrayIndexedById($serviceIds);
156
157 $providersServices = $providerRepository->getProvidersServices($serviceIds);
158
159 $appointmentsArray = [];
160
161 /** @var Appointment $appointment */
162 foreach ($appointments->getItems() as $appointment) {
163 /** @var Service $service */
164 $service = $services->getItem($appointment->getServiceId()->getValue());
165
166 $providerId = $appointment->getProviderId()->getValue();
167
168 // skip appointments for other providers if user is provider
169 if (
170 (!$readOthers) &&
171 $user->getType() === Entities::PROVIDER &&
172 $user->getId()->getValue() !== $providerId
173 ) {
174 continue;
175 }
176
177 $appointmentAS->calculateAndSetAppointmentEnd($appointment, $service);
178
179 $timeZone = !empty($params['timeZone'])
180 ? $params['timeZone']
181 : ($user && $user->getType() === Entities::PROVIDER ? $providerAS->getTimeZone($user) : null);
182
183 if ($timeZone) {
184 $appointment->getBookingStart()->getValue()->setTimezone(new DateTimeZone($timeZone));
185
186 $appointment->getBookingEnd()->getValue()->setTimezone(new DateTimeZone($timeZone));
187 }
188
189 $bookedSpots = 0;
190 $bookings = [];
191
192 $isPackageAppointment = false;
193 $bookingPrice = 0;
194 $paidPrice = 0;
195 $bookingSource = 'backend';
196 $frontendBookings = 0;
197
198 $wcTax = 0;
199 $wcDiscount = 0;
200
201 /** @var CustomerBooking $booking */
202 foreach ($appointment->getBookings()->getItems() as $booking) {
203 // fix for wrongly saved JSON
204 if (
205 $booking->getCustomFields() &&
206 json_decode($booking->getCustomFields()->getValue(), true) === null
207 ) {
208 $booking->setCustomFields(null);
209 }
210
211 if ($noShowTagEnabled && !in_array($booking->getCustomerId()->getValue(), $customersNoShowCountIds)) {
212 $customersNoShowCountIds[] = $booking->getCustomerId()->getValue();
213 }
214
215 if (in_array($booking->getStatus()->getValue(), ['approved', 'pending'], true)) {
216 $bookedSpots += $booking->getPersons()->getValue();
217 }
218
219 $bookings[] = [
220 'id' => $booking->getId()->getValue(),
221 'status' => $booking->getStatus()->getValue(),
222 'customer' => $booking->getCustomer() ? $booking->getCustomer()->toArray() : null,
223 'payment' => [
224 'paymentMethods' => array_map(
225 function ($payment) {
226 return $payment['gateway'];
227 },
228 $booking->getPayments()->toArray()
229 ),
230 'status' => $paymentAS->getFullStatus($booking->toArray(), 'appointment'),
231 ],
232 'created' => $booking->getCreated() ?
233 $booking->getCreated()->getValue()->format('Y-m-d') : null,
234 ];
235
236 $isPackageAppointment = !empty($booking->getPackageCustomerService());
237
238 $bookingPrice += $paymentAS->calculateAppointmentPrice($booking->toArray(), 'appointment');
239
240 foreach ($booking->getPayments()->toArray() as $payment) {
241 if ($payment['status'] === 'paid' || $payment['status'] === 'partiallyPaid') {
242 $paidPrice += $payment['amount'];
243 }
244
245 $paymentAS->addWcFields($payment);
246
247 $wcTax += !empty($payment['wcItemTaxValue']) ? $payment['wcItemTaxValue'] : 0;
248
249 $wcDiscount += !empty($payment['wcItemCouponValue']) ? $payment['wcItemCouponValue'] : 0;
250 }
251
252 if ($booking->getInfo()) {
253 $bookingSource = 'frontendAndBackend';
254 $frontendBookings++;
255 }
256 }
257
258 if ($frontendBookings === $appointment->getBookings()->length()) {
259 $bookingSource = 'frontend';
260 }
261
262 $bookingStart = $appointment->getBookingStart() ? $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') : null;
263 $bookingEnd = $appointment->getBookingEnd() ? $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s') : null;
264
265 $appointmentsArray[] = [
266 'id' => $appointment->getId()->getValue(),
267 'bookedSpots' => $bookedSpots,
268 'bookingStartDateTime' => $bookingStart,
269 'bookingEndDateTime' => $bookingEnd,
270 'bookingStartDate' => $bookingStart ? explode(' ', $bookingStart)[0] : null,
271 'bookingSource' => $bookingSource,
272 'employee' => $appointment->getProvider() ? [
273 'id' => $appointment->getProvider()->getId()->getValue(),
274 'firstName' => $appointment->getProvider()->getFirstName() ? $appointment->getProvider()->getFirstName()->getValue() : null,
275 'lastName' => $appointment->getProvider()->getLastName() ? $appointment->getProvider()->getLastName()->getValue() : null,
276 'picture' => $appointment->getProvider()->getPicture() ? $appointment->getProvider()->getPicture()->getThumbPath() : null,
277 'badge' => $appointment->getProvider()->getBadgeId() ? $providerAS->getBadge($appointment->getProvider()->getBadgeId()->getValue()) : null,
278 ] : null,
279 'googleMeetLink' => $appointment->getGoogleMeetUrl(),
280 'zoomHostLink' => $appointment->getZoomMeeting() ? $appointment->getZoomMeeting()->getStartUrl()->getValue() : null,
281 'zoomJoinLink' => $appointment->getZoomMeeting() ? $appointment->getZoomMeeting()->getJoinUrl()->getValue() : null,
282 'lessonSpace' => $appointment->getLessonSpace() ? $appointment->getLessonSpace() : null,
283 'microsoftTeamsLink' => $appointment->getMicrosoftTeamsUrl() ? $appointment->getMicrosoftTeamsUrl() : null,
284 'location' => $appointment->getLocation() ? [
285 'id' => $appointment->getLocation()->getId()->getValue(),
286 'name' => $appointment->getLocation()->getName()->getValue(),
287 ] : null,
288 'service' => $appointment->getService() ? [
289 'id' => $appointment->getService()->getId()->getValue(),
290 'name' => $appointment->getService()->getName()->getValue(),
291 'color' => $appointment->getService()->getColor() ? $service->getColor()->getValue() : null,
292 'picture' => $appointment->getService()->getPicture() ? $appointment->getService()->getPicture()->getThumbPath() : null,
293 ] : null,
294 'bookings' => $bookings,
295 'type' => $appointment->getBookings()->length() > 1 ? 'groupBooking' : ($isPackageAppointment ? 'package' : 'standAlone'),
296 'maxCapacity' => !empty($providersServices[$providerId][$service->getId()->getValue()]) ?
297 $providersServices[$providerId][$service->getId()->getValue()]['maxCapacity'] :
298 $service->getMaxCapacity()->getValue(),
299 'status' => $appointment->getStatus() ? $appointment->getStatus()->getValue() : null,
300 'note' => $appointment->getInternalNotes() ? $appointment->getInternalNotes()->getValue() : null,
301 'price' => [
302 'total' => $bookingPrice + $wcTax - $wcDiscount,
303 ],
304 'paidPrice' => $paidPrice,
305 'cancelable' => $appointmentAS->isCancelable($appointment, $service, $user),
306 'reschedulable' => $appointmentAS->isReschedulable($appointment, $service, $user),
307 ];
308 }
309
310 $periodsAppointmentsCount = $appointmentRepository->getPeriodAppointments(
311 array_merge_recursive(
312 $params,
313 ['search' => $entitiesIds, 'searchTerm' => !empty($params['search']) ? $params['search'] : ''],
314 ['skipBookings' => empty($params['customers']) && empty($entitiesIds['customers'])]
315 )
316 );
317
318 $periodsAppointmentsTotalCount = $appointmentRepository->getPeriodAppointments(
319 array_merge($customerCountParams, $providerCountParams, ['skipBookings' => true])
320 );
321
322 if ($noShowTagEnabled && $customersNoShowCountIds) {
323 /** @var CustomerBookingRepository $bookingRepository */
324 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
325
326 $customersNoShowCount = $bookingRepository->countByNoShowStatus($customersNoShowCountIds);
327
328 foreach ($appointmentsArray as &$appointmentArray) {
329 foreach ($appointmentArray['bookings'] as &$booking) {
330 if (!empty($customersNoShowCount[$booking['customer']['id']])) {
331 $booking['customer']['noShowCount'] = $customersNoShowCount[$booking['customer']['id']]['count'];
332 }
333 }
334 }
335 }
336
337 $appointmentsArray = apply_filters('amelia_get_appointments_filter', $appointmentsArray);
338
339 do_action('amelia_get_appointments', $appointmentsArray);
340
341 $result->setResult(CommandResult::RESULT_SUCCESS);
342 $result->setMessage('Successfully retrieved appointments');
343
344 $result->setData(
345 [
346 Entities::APPOINTMENTS => $appointmentsArray,
347 'totalCount' => $periodsAppointmentsTotalCount->length(),
348 'filteredCount' => $periodsAppointmentsCount->length(),
349 ]
350 );
351
352 return $result;
353 }
354 }
355