PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
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 / Services / Notification / AppointmentNotificationService.php
ameliabooking / src / Application / Services / Notification Last commit date
AbstractNotificationService.php 2 months ago AbstractWhatsAppNotificationService.php 3 months ago ApplicationNotificationService.php 2 months ago AppointmentNotificationService.php 2 weeks ago BasicWhatsAppNotificationService.php 6 months ago EmailNotificationService.php 1 month ago NotificationHelperService.php 6 months ago SMSAPIService.php 2 months ago SMSNotificationService.php 1 month ago
AppointmentNotificationService.php
514 lines
1 <?php
2
3 /**
4 * @copyright © Melograno Ventures. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace AmeliaBooking\Application\Services\Notification;
9
10 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
11 use AmeliaBooking\Application\Services\Invoice\AbstractInvoiceApplicationService;
12 use AmeliaBooking\Application\Services\Payment\PaymentApplicationService;
13 use AmeliaBooking\Domain\Collection\Collection;
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\Booking\Event\Event;
19 use AmeliaBooking\Domain\Entity\Entities;
20 use AmeliaBooking\Domain\Entity\Notification\Notification;
21 use AmeliaBooking\Domain\Entity\Payment\Payment;
22 use AmeliaBooking\Domain\Entity\User\Customer;
23 use AmeliaBooking\Domain\Services\Settings\SettingsService;
24 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
25 use AmeliaBooking\Domain\ValueObjects\String\NotificationStatus;
26 use AmeliaBooking\Infrastructure\Common\Container;
27 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
28 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
29 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
30 use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository;
31
32 /**
33 * Class AppointmentNotificationService
34 *
35 * @package AmeliaBooking\Application\Services\Notification
36 */
37 class AppointmentNotificationService
38 {
39 protected $container;
40
41 /**
42 * AppointmentNotificationService constructor.
43 *
44 * @param Container $container
45 */
46 public function __construct(Container $container)
47 {
48 $this->container = $container;
49 }
50
51 /**
52 * @param AbstractNotificationService $notificationService
53 * @param Appointment $appointment
54 * @param bool $logNotification
55 *
56 * @throws InvalidArgumentException
57 * @throws QueryExecutionException
58 */
59 public function sendProviderStatusNotifications(
60 $notificationService,
61 $appointment,
62 $logNotification = true
63 ) {
64 $appointmentArray = $appointment->toArray();
65 $appointmentArray['sendCF'] = true;
66
67 /** @var Collection $providerNotifications */
68 $providerNotifications = $notificationService->getByNameAndType(
69 "provider_appointment_{$appointment->getStatus()->getValue()}",
70 $notificationService->getType()
71 );
72
73 $sendDefault = $notificationService->sendDefault($providerNotifications, $appointmentArray);
74
75 /** @var Notification $providerNotification */
76 foreach ($providerNotifications->getItems() as $providerNotification) {
77 if (
78 $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
79 $notificationService->checkCustom($providerNotification, $appointmentArray, $sendDefault)
80 ) {
81 $notificationService->sendNotification(
82 $appointmentArray,
83 $providerNotification,
84 $logNotification
85 );
86 }
87 }
88 }
89
90 /**
91 * @param AbstractNotificationService $notificationService
92 * @param Appointment $appointment
93 * @param Collection $bookings
94 * @param bool $logNotification
95 * @param bool $isBackend
96 * @param bool $sendInvoice
97 *
98 * @throws InvalidArgumentException
99 * @throws QueryExecutionException
100 * @throws NotFoundException
101 * @throws AccessDeniedException
102 */
103 public function sendCustomersStatusNotifications(
104 $notificationService,
105 $appointment,
106 $bookings,
107 $logNotification = true,
108 $isBackend = true,
109 $sendInvoice = false,
110 $notifyCustomers = true
111 ) {
112 /** @var AbstractInvoiceApplicationService $invoiceService */
113 $invoiceService = $this->container->get('application.invoice.service');
114
115 /** @var Collection $statusNotifications */
116 $statusNotifications = new Collection();
117
118 /** @var CustomerBooking $booking */
119 foreach ($bookings->getItems() as $bookingKey => $booking) {
120 if ($booking->isChangedStatus() && $booking->isChangedStatus()->getValue()) {
121 $notificationStatus = $appointment->getStatus()->getValue() === BookingStatus::PENDING &&
122 (
123 $booking->getStatus()->getValue() === BookingStatus::APPROVED ||
124 $booking->getStatus()->getValue() === BookingStatus::PENDING
125 )
126 ? BookingStatus::PENDING
127 : $booking->getStatus()->getValue();
128
129 if (!$statusNotifications->keyExists($notificationStatus)) {
130 $statusNotifications->addItem(
131 $notificationService->getByNameAndType(
132 "customer_appointment_{$notificationStatus}",
133 $notificationService->getType()
134 ),
135 $notificationStatus
136 );
137 }
138
139 /** @var Collection $customerNotifications */
140 $customerNotifications = $statusNotifications->getItem($notificationStatus);
141
142 $sendDefault = $notificationService->sendDefault($customerNotifications, $appointment->toArray());
143
144 /** @var Notification $customerNotification */
145 foreach ($customerNotifications->getItems() as $customerNotification) {
146 if (
147 $customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
148 $notificationService->checkCustom(
149 $customerNotification,
150 $appointment->toArray(),
151 $sendDefault
152 ) && $notifyCustomers
153 ) {
154 if (
155 $customerNotification->getContent() &&
156 $customerNotification->getContent()->getValue() &&
157 strpos($customerNotification->getContent()->getValue(), '%payment_link_') !== false
158 ) {
159 $this->setPaymentLink($appointment, $bookingKey);
160 }
161
162 $notificationService->sendNotification(
163 array_merge(
164 $appointment->toArray(),
165 [
166 'bookings' => $bookings->toArray(),
167 'isBackend' => $isBackend,
168 ]
169 ),
170 $customerNotification,
171 $logNotification,
172 $bookingKey,
173 null,
174 (
175 $sendInvoice &&
176 $booking->getPayments()->length() &&
177 $booking->getPayments()->keyExists(0) &&
178 $booking->getStatus()->getValue() !== BookingStatus::WAITING
179 )
180 ? $invoiceService->generateInvoice(
181 $booking->getPayments()->getItem(0)->getId()->getValue()
182 )
183 : null
184 );
185 }
186 }
187 }
188 }
189 }
190
191 /**
192 * @param AbstractNotificationService $notificationService
193 * @param Appointment $appointment
194 * @param bool $notifyProvider
195 * @param bool $notifyCustomers
196 *
197 * @throws QueryExecutionException
198 * @throws InvalidArgumentException
199 * @throws NotFoundException
200 */
201 public function sendRescheduledNotifications(
202 $notificationService,
203 $appointment,
204 $notifyProvider = true,
205 $notifyCustomers = true
206 ) {
207 if ($notifyProvider) {
208 /** @var Collection $providerNotifications */
209 $providerNotifications = $notificationService->getByNameAndType(
210 "provider_appointment_rescheduled",
211 $notificationService->getType()
212 );
213
214 $sendDefault = $notificationService->sendDefault($providerNotifications, $appointment->toArray());
215
216 /** @var Notification $providerNotification */
217 foreach ($providerNotifications->getItems() as $providerNotification) {
218 if (
219 $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
220 $notificationService->checkCustom($providerNotification, $appointment->toArray(), $sendDefault)
221 ) {
222 $notificationService->sendNotification(
223 $appointment->toArray(),
224 $providerNotification,
225 true
226 );
227 }
228 }
229 }
230
231 if ($notifyCustomers && $appointment->isNotifyParticipants()) {
232 /** @var Collection $customerNotifications */
233 $customerNotifications = $notificationService->getByNameAndType(
234 "customer_appointment_rescheduled",
235 $notificationService->getType()
236 );
237
238 $sendDefault = $notificationService->sendDefault($customerNotifications, $appointment->toArray());
239
240 /** @var Notification $customerNotification */
241 foreach ($customerNotifications->getItems() as $customerNotification) {
242 if (
243 $customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
244 $notificationService->checkCustom($customerNotification, $appointment->toArray(), $sendDefault)
245 ) {
246 /** @var CustomerBooking $booking */
247 foreach ($appointment->getBookings()->getItems() as $bookingKey => $booking) {
248 if (
249 (!$booking->isNew() || !$booking->isNew()->getValue()) &&
250 (
251 $booking->getStatus()->getValue() === BookingStatus::APPROVED ||
252 $booking->getStatus()->getValue() === BookingStatus::PENDING
253 )
254 ) {
255 if (
256 $customerNotification->getContent() &&
257 $customerNotification->getContent()->getValue() &&
258 strpos($customerNotification->getContent()->getValue(), '%payment_link_') !== false
259 ) {
260 $this->setPaymentLink($appointment, $bookingKey);
261 }
262
263 $notificationService->sendNotification(
264 $appointment->toArray(),
265 $customerNotification,
266 true,
267 $bookingKey
268 );
269 }
270 }
271 }
272 }
273 }
274 }
275
276 /**
277 * Send waiting list available spot notifications.
278 * Triggered when a booking for an approved appointment is canceled and there are waiting bookings.
279 * Sends one notification to provider and one to each waiting customer.
280 *
281 * @param AbstractNotificationService $notificationService
282 * @param Appointment $appointment
283 * @param Collection $waitingBookings Collection of CustomerBooking objects with status 'waiting'
284 *
285 * @throws InvalidArgumentException
286 * @throws QueryExecutionException
287 */
288 public function sendWaitingListAvailableSpotNotification(
289 $notificationService,
290 $appointment,
291 $waitingBookings
292 ) {
293 if (!$waitingBookings->length()) {
294 return;
295 }
296
297 // Provider notification (single)
298 /** @var Collection $providerNotifications */
299 $providerNotifications = $notificationService->getByNameAndType(
300 'provider_appointment_waiting_available_spot',
301 $notificationService->getType()
302 );
303 $sendDefaultProvider = $notificationService->sendDefault($providerNotifications, $appointment->toArray());
304 foreach ($providerNotifications->getItems() as $providerNotification) {
305 if (
306 $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
307 $notificationService->checkCustom($providerNotification, $appointment->toArray(), $sendDefaultProvider)
308 ) {
309 $notificationService->sendNotification(
310 $appointment->toArray(),
311 $providerNotification,
312 true
313 );
314 }
315 }
316
317 // Customer notifications (each waiting booking)
318 /** @var Collection $customerNotifications */
319 $customerNotifications = $notificationService->getByNameAndType(
320 'customer_appointment_waiting_available_spot',
321 $notificationService->getType()
322 );
323 $sendDefaultCustomer = $notificationService->sendDefault($customerNotifications, $appointment->toArray());
324 foreach ($customerNotifications->getItems() as $customerNotification) {
325 if (
326 $customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
327 $notificationService->checkCustom($customerNotification, $appointment->toArray(), $sendDefaultCustomer)
328 ) {
329 foreach ($waitingBookings->getItems() as $waitingBooking) {
330 $bookingKey = null;
331 foreach ($appointment->getBookings()->getItems() as $appBookingKey => $appBooking) {
332 if ($appBooking->getId()->getValue() === $waitingBooking->getId()->getValue()) {
333 $bookingKey = $appBookingKey;
334 break;
335 }
336 }
337 if ($bookingKey !== null) {
338 $notificationService->sendNotification(
339 array_merge($appointment->toArray(), [
340 'bookings' => $appointment->getBookings()->toArray(),
341 ]),
342 $customerNotification,
343 true,
344 $bookingKey
345 );
346 }
347 }
348 }
349 }
350 }
351
352 /**
353 * @param AbstractNotificationService $notificationService
354 * @param Appointment $appointment
355 * @param bool $notifyProvider
356 * @param bool $notifyCustomers
357 *
358 * @throws QueryExecutionException
359 * @throws InvalidArgumentException
360 */
361 public function sendUpdatedNotifications(
362 $notificationService,
363 $appointment,
364 $notifyProvider,
365 $notifyCustomers
366 ) {
367 if ($notifyProvider) {
368 /** @var Collection $providerNotifications */
369 $providerNotifications = $notificationService->getByNameAndType(
370 "provider_appointment_updated",
371 $notificationService->getType()
372 );
373
374 $sendDefault = $notificationService->sendDefault($providerNotifications, $appointment->toArray());
375
376 /** @var Notification $providerNotification */
377 foreach ($providerNotifications->getItems() as $providerNotification) {
378 if (
379 $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
380 $notificationService->checkCustom($providerNotification, $appointment->toArray(), $sendDefault)
381 ) {
382 $appointmentArray = $appointment->toArray();
383 $appointmentArray['sendForAllBookings'] = true;
384
385 $notificationService->sendNotification(
386 $appointmentArray,
387 $providerNotification,
388 true
389 );
390 }
391 }
392 }
393
394 if ($notifyCustomers && $appointment->isNotifyParticipants()) {
395 /** @var Collection $customerNotifications */
396 $customerNotifications = $notificationService->getByNameAndType(
397 "customer_appointment_updated",
398 $notificationService->getType()
399 );
400
401 $sendDefault = $notificationService->sendDefault($customerNotifications, $appointment->toArray());
402
403 /** @var Notification $customerNotification */
404 foreach ($customerNotifications->getItems() as $customerNotification) {
405 if (
406 $customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED &&
407 $notificationService->checkCustom($customerNotification, $appointment->toArray(), $sendDefault)
408 ) {
409 /** @var CustomerBooking $booking */
410 foreach ($appointment->getBookings()->getItems() as $bookingKey => $booking) {
411 if (
412 $booking->getStatus()->getValue() === BookingStatus::APPROVED &&
413 (!$booking->isNew() || !$booking->isNew()->getValue()) &&
414 $booking->isUpdated() &&
415 $booking->isUpdated()->getValue()
416 ) {
417 $notificationService->sendNotification(
418 $appointment->toArray(),
419 $customerNotification,
420 true,
421 $bookingKey
422 );
423 }
424 }
425 }
426 }
427 }
428 }
429
430 /**
431 * @param AbstractNotificationService $notificationService
432 * @param Event $event
433 * @param bool $logNotification
434 * @param int $bookingKey
435 *
436 *
437 * @throws InvalidArgumentException
438 * @throws QueryExecutionException
439 */
440 public function sendQrNotifications(
441 $notificationService,
442 $event,
443 $bookingKey,
444 $logNotification = true
445 ) {
446 $notifications = $notificationService->getByNameAndType(
447 "customer_event_qr_code",
448 $notificationService->getType()
449 );
450
451 $qrNotification = $notifications->getItem($notifications->keys()[0]);
452
453 if ($qrNotification->getStatus()->getValue() === NotificationStatus::ENABLED) {
454 $notificationService->sendNotification(
455 $event->toArray(),
456 $qrNotification,
457 $logNotification,
458 $bookingKey
459 );
460 }
461 }
462
463 /**
464 * @param Appointment $appointment
465 * @param int $bookingKey
466 *
467 *
468 * @throws InvalidArgumentException
469 * @throws QueryExecutionException
470 * @throws NotFoundException
471 */
472 private function setPaymentLink($appointment, $bookingKey)
473 {
474 /** @var CustomerBooking $booking */
475 $booking = $appointment->getBookings()->getItem($bookingKey);
476
477 /** @var Payment $payment */
478 $payment = $booking->getPayments() && $booking->getPayments()->keyExists(0)
479 ? $booking->getPayments()->getItem(0)
480 : null;
481
482 if ($payment && $payment->getId() && !$payment->getPaymentLinks()) {
483 /** @var PaymentApplicationService $paymentAS */
484 $paymentAS = $this->container->get('application.payment.service');
485
486 /** @var ServiceRepository $serviceRepository */
487 $serviceRepository = $this->container->get('domain.bookable.service.repository');
488
489 /** @var CustomerRepository $customerRepository */
490 $customerRepository = $this->container->get('domain.users.customers.repository');
491
492 /** @var Service $service */
493 $service = $appointment->getService() ?: $serviceRepository->getById($appointment->getServiceId()->getValue());
494
495 /** @var Customer $customer */
496 $customer = $booking->getCustomer() ?: $customerRepository->getById($booking->getCustomerId()->getValue());
497
498 $payment->setPaymentLinks(
499 $paymentAS->createPaymentLink(
500 [
501 'type' => Entities::APPOINTMENT,
502 'booking' => $booking->toArray(),
503 'appointment' => $appointment->toArray(),
504 'paymentId' => $payment->getId()->getValue(),
505 'bookable' => $service->toArray(),
506 'customer' => $customer->toArray(),
507 ],
508 $bookingKey
509 )
510 );
511 }
512 }
513 }
514