PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.32
Booking for Appointments and Events Calendar – Amelia v1.2.32
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 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 / Services / Notification / SMSNotificationService.php
ameliabooking / src / Application / Services / Notification Last commit date
AbstractNotificationService.php 1 year ago AbstractWhatsAppNotificationService.php 1 year ago ApplicationNotificationService.php 1 year ago AppointmentNotificationService.php 1 year ago BasicWhatsAppNotificationService.php 1 year ago EmailNotificationService.php 1 year ago NotificationHelperService.php 1 year ago SMSAPIService.php 1 year ago SMSNotificationService.php 1 year ago
SMSNotificationService.php
504 lines
1 <?php
2
3 /**
4 * @copyright © TMS-Plugins. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace AmeliaBooking\Application\Services\Notification;
9
10 use AmeliaBooking\Application\Services\Helper\HelperService;
11 use AmeliaBooking\Application\Services\Placeholder\PlaceholderService;
12 use AmeliaBooking\Domain\Collection\Collection;
13 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
14 use AmeliaBooking\Domain\Entity\Entities;
15 use AmeliaBooking\Domain\Entity\Notification\Notification;
16 use AmeliaBooking\Domain\Entity\Notification\NotificationLog;
17 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
18 use AmeliaBooking\Domain\Services\Settings\SettingsService;
19 use AmeliaBooking\Domain\ValueObjects\String\NotificationStatus;
20 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
21 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
22 use AmeliaBooking\Infrastructure\Repository\Notification\NotificationLogRepository;
23 use AmeliaBooking\Infrastructure\Repository\Notification\NotificationSMSHistoryRepository;
24 use Exception;
25 use Interop\Container\Exception\ContainerException;
26 use Slim\Exception\ContainerValueNotFoundException;
27
28 /**
29 * Class SMSNotificationService
30 *
31 * @package AmeliaBooking\Application\Services\Notification
32 */
33 class SMSNotificationService extends AbstractNotificationService
34 {
35 /** @var bool */
36 private $sentSmsLowEmail = false;
37
38 /** @noinspection MoreThanThreeArgumentsInspection */
39 /**
40 * @param array $appointmentArray
41 * @param Notification $notification
42 * @param bool $logNotification
43 * @param int|null $bookingKey
44 *
45 * @throws NotFoundException
46 * @throws QueryExecutionException
47 * @throws ContainerException
48 * @throws Exception
49 */
50 public function sendNotification(
51 $appointmentArray,
52 $notification,
53 $logNotification,
54 $bookingKey = null,
55 $allBookings = null,
56 $invoice = []
57 ) {
58 /** @var \AmeliaBooking\Application\Services\Settings\SettingsService $settingsAS */
59 $settingsAS = $this->container->get('application.settings.service');
60 /** @var PlaceholderService $placeholderService */
61 $placeholderService = $this->container->get("application.placeholder.{$appointmentArray['type']}.service");
62 /** @var HelperService $helperService */
63 $helperService = $this->container->get('application.helper.service');
64
65 $data = $placeholderService->getPlaceholdersData(
66 $appointmentArray,
67 $bookingKey,
68 'sms',
69 null,
70 $allBookings,
71 false,
72 $notification->getName()->getValue()
73 );
74
75 $isCustomerPackage = isset($appointmentArray['isForCustomer']) && $appointmentArray['isForCustomer'];
76
77 if ($appointmentArray['type'] === Entities::PACKAGE) {
78 if (!empty($appointmentArray['recurring'][0]['booking']['info']) && $isCustomerPackage) {
79 $info = $appointmentArray['recurring'][0]['booking']['info'];
80
81 $infoArray = json_decode($info, true);
82
83 if (!empty($infoArray['phone'])) {
84 $appointmentArray['customer']['phone'] = $infoArray['phone'];
85 }
86 } else {
87 $info = $isCustomerPackage ? json_encode($appointmentArray['customer']) : null;
88 }
89 } else {
90 $info = $bookingKey !== null ? $appointmentArray['bookings'][$bookingKey]['info'] : null;
91 }
92
93 $notificationContent = $helperService->getBookingTranslation(
94 $helperService->getLocaleFromBooking($info),
95 $notification->getTranslations() ? $notification->getTranslations()->getValue() : null,
96 'content'
97 ) ?: $notification->getContent()->getValue();
98
99 $text = $placeholderService->applyPlaceholders($notificationContent, $data);
100
101 $users = $this->getUsersInfo(
102 $notification->getSendTo()->getValue(),
103 $appointmentArray,
104 $bookingKey,
105 $data
106 );
107
108 foreach ($users as $user) {
109 if ($user['phone']) {
110 if (!$isCustomerPackage && !empty($data['providersAppointments'][$user['id']])) {
111 $text = $placeholderService->applyPlaceholders(
112 $notificationContent,
113 array_merge(
114 $data,
115 ['cart_appointments_details' => $data['providersAppointments'][$user['id']]]
116 )
117 );
118 }
119
120 $reParsedData = !$isCustomerPackage ?
121 $placeholderService->reParseContentForProvider(
122 $appointmentArray,
123 '',
124 $text,
125 $user['id']
126 ) : [
127 'body' => $text,
128 ];
129
130 try {
131 $this->saveAndSend(
132 $notification,
133 $user,
134 $appointmentArray,
135 $reParsedData,
136 $logNotification,
137 $user['phone']
138 );
139
140 $additionalPhoneNumbers = $settingsAS->getBccSms();
141
142 foreach ($additionalPhoneNumbers as $phoneNumber) {
143 $this->saveAndSend(
144 $notification,
145 null,
146 $appointmentArray,
147 $reParsedData,
148 $logNotification,
149 $phoneNumber
150 );
151 }
152 } catch (QueryExecutionException $e) {
153 } catch (ContainerException $e) {
154 }
155 }
156 }
157 }
158
159
160 private function sendSmsBalanceLowEmail()
161 {
162 /** @var SettingsService $settingsService */
163 $settingsService = $this->container->get('domain.settings.service');
164 /** @var SMSAPIService $smsApiService */
165 $smsApiService = $this->container->get('application.smsApi.service');
166
167 $smsLowEmail = $settingsService->getSetting('notifications', 'smsBalanceEmail');
168 if ($smsLowEmail && $smsLowEmail['enabled']) {
169 try {
170 $userResponse = $smsApiService->getUserInfo();
171 if (
172 !empty($userResponse) &&
173 $userResponse->status === 'OK' &&
174 !empty($userResponse->user) &&
175 $userResponse->user->balance <= $smsLowEmail['minimum']
176 ) {
177 /** @var EmailNotificationService $notificationService */
178 $notificationService = $this->container->get('application.emailNotification.service');
179 $notificationService->sendSmsBalanceLowEmail($smsLowEmail['email']);
180
181 $this->sentSmsLowEmail = true;
182 }
183 } catch (\Exception $e) {
184 }
185 }
186 }
187
188 /**
189 * @throws ContainerValueNotFoundException
190 * @throws QueryExecutionException
191 * @throws InvalidArgumentException
192 */
193 public function sendUndeliveredNotifications()
194 {
195 /** @var NotificationLogRepository $notificationLogRepository */
196 $notificationLogRepository = $this->container->get('domain.notificationLog.repository');
197
198 /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */
199 $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository');
200
201 /** @var Collection $undeliveredNotifications */
202 $undeliveredNotifications = $notificationLogRepository->getUndeliveredNotifications('sms');
203
204 /** @var SMSAPIService $smsApiService */
205 $smsApiService = $this->container->get('application.smsApi.service');
206
207 /** @var NotificationLog $undeliveredNotification */
208 foreach ($undeliveredNotifications->getItems() as $undeliveredNotification) {
209 try {
210 $data = json_decode($undeliveredNotification->getData()->getValue(), true);
211
212 if ($history = $notificationsSMSHistoryRepo->getById($data['historyId'])) {
213 $apiResponse = $smsApiService->send(
214 $history['phone'],
215 $data['body'],
216 AMELIA_ACTION_URL . '/notifications/sms/history/' . $data['historyId']
217 );
218
219 if ($apiResponse->status === 'OK') {
220 $this->updateSmsHistory($data['historyId'], $apiResponse);
221
222 $notificationLogRepository->updateFieldById(
223 $undeliveredNotification->getId()->getValue(),
224 1,
225 'sent'
226 );
227 }
228 }
229 } catch (Exception $e) {
230 }
231 }
232 }
233
234 /**
235 * @throws QueryExecutionException
236 * @throws InvalidArgumentException
237 * @throws Exception
238 */
239 public function sendBirthdayGreetingNotifications()
240 {
241 /** @var Collection $notifications */
242 $notifications = $this->getByNameAndType('customer_birthday_greeting', $this->type);
243
244 /** @var Notification $notification */
245 $notification = $notifications->getItem($notifications->keys()[0]);
246
247 // Check if notification is enabled and it is time to send notification
248 if (
249 $notification->getStatus()->getValue() === NotificationStatus::ENABLED &&
250 $notification->getTime() &&
251 DateTimeService::getNowDateTimeObject() >=
252 DateTimeService::getCustomDateTimeObject($notification->getTime()->getValue())
253 ) {
254 /** @var NotificationLogRepository $notificationLogRepo */
255 $notificationLogRepo = $this->container->get('domain.notificationLog.repository');
256 /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */
257 $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository');
258 /** @var SMSAPIService $smsApiService */
259 $smsApiService = $this->container->get('application.smsApi.service');
260 /** @var PlaceholderService $placeholderService */
261 $placeholderService = $this->container->get('application.placeholder.appointment.service');
262 /** @var SettingsService $settingsService */
263 $settingsService = $this->container->get('domain.settings.service');
264
265 $customers = $notificationLogRepo->getBirthdayCustomers($this->type);
266
267 $companyData = $placeholderService->getCompanyData();
268
269 $customersArray = $customers->toArray();
270
271 foreach ($customersArray as $bookingKey => $customerArray) {
272 $data = [
273 'customer_email' => $customerArray['email'],
274 'customer_first_name' => $customerArray['firstName'],
275 'customer_last_name' => $customerArray['lastName'],
276 'customer_full_name' => $customerArray['firstName'] . ' ' . $customerArray['lastName'],
277 'customer_phone' => $customerArray['phone'],
278 'customer_id' => $customerArray['id'],
279 ];
280
281 /** @noinspection AdditionOperationOnArraysInspection */
282 $data += $companyData;
283
284 $text = $placeholderService->applyPlaceholders(
285 $notification->getContent()->getValue(),
286 $data
287 );
288
289 if ($data['customer_phone']) {
290 try {
291 $historyId = $notificationsSMSHistoryRepo->add(
292 [
293 'notificationId' => $notification->getId()->getValue(),
294 'userId' => $data['customer_id'],
295 'text' => $text,
296 'phone' => $data['customer_phone'],
297 'alphaSenderId' => $settingsService->getSetting('notifications', 'smsAlphaSenderId'),
298 ]
299 );
300
301 $smsData = apply_filters(
302 'amelia_manipulate_sms_data',
303 [
304 'text' => $text,
305 'to' => $data['customer_phone']
306 ]
307 );
308
309 $apiResponse = null;
310
311 if (empty($smsData['skipSending'])) {
312 $apiResponse = $smsApiService->send(
313 $smsData['customer_phone'],
314 $smsData['text'],
315 AMELIA_ACTION_URL . '/notifications/sms/history/' . $historyId
316 );
317 }
318
319 if ($apiResponse && $apiResponse->status === 'OK') {
320 $this->updateSmsHistory($historyId, $apiResponse);
321
322 $logNotificationId = $notificationLogRepo->add(
323 $notification,
324 $data['customer_id']
325 );
326
327 if ($logNotificationId) {
328 $notificationLogRepo->updateFieldById($logNotificationId, 1, 'sent');
329 }
330 }
331 } catch (QueryExecutionException $e) {
332 }
333 }
334 }
335 }
336 }
337
338 /** @noinspection MoreThanThreeArgumentsInspection */
339 /**
340 * @param Notification $notification
341 * @param array $user
342 * @param array $appointmentArray
343 * @param array $reParsedData
344 * @param bool $logNotification
345 * @param string $sendTo
346 *
347 * @return void
348 *
349 * @throws QueryExecutionException
350 * @throws InvalidArgumentException
351 */
352 private function saveAndSend($notification, $user, $appointmentArray, $reParsedData, $logNotification, $sendTo)
353 {
354
355 /** @var NotificationLogRepository $notificationsLogRepository */
356 $notificationsLogRepository = $this->container->get('domain.notificationLog.repository');
357 /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */
358 $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository');
359 /** @var SettingsService $settingsService */
360 $settingsService = $this->container->get('domain.settings.service');
361 /** @var SMSAPIService $smsApiService */
362 $smsApiService = $this->container->get('application.smsApi.service');
363
364 if ($user && !empty($appointmentArray['isRetry'])) {
365 /** @var Collection $sentNotifications */
366 $sentNotifications = $notificationsLogRepository->getSentNotificationsByUserAndEntity(
367 $user['id'],
368 'sms',
369 $appointmentArray['type'],
370 $appointmentArray['type'] === Entities::PACKAGE ?
371 $appointmentArray['packageCustomerId'] : $appointmentArray['id']
372 );
373
374 if ($sentNotifications->length()) {
375 return;
376 }
377 }
378
379 $historyId = $notificationsSMSHistoryRepo->add(
380 [
381 'notificationId' => $notification->getId()->getValue(),
382 'userId' => $user ? $user['id'] : null,
383 'appointmentId' =>
384 $appointmentArray['type'] === Entities::APPOINTMENT ? $appointmentArray['id'] : null,
385 'eventId' =>
386 $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : null,
387 'packageCustomerId' => $appointmentArray['type'] === Entities::PACKAGE ?
388 $appointmentArray['packageCustomerId'] : null,
389 'text' => $reParsedData['body'],
390 'phone' => $user ? $user['phone'] : $sendTo,
391 'alphaSenderId' => $settingsService->getSetting('notifications', 'smsAlphaSenderId')
392 ]
393 );
394
395 $logNotificationId = null;
396
397 if ($logNotification) {
398 $logNotificationId = $notificationsLogRepository->add(
399 $notification,
400 $user ? $user['id'] : null,
401 $appointmentArray['type'] === Entities::APPOINTMENT ? $appointmentArray['id'] : null,
402 $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : null,
403 $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : null,
404 json_encode(
405 [
406 'subject' => '',
407 'body' => $reParsedData['body'],
408 'icsFiles' => [],
409 'historyId' => $historyId,
410 ]
411 )
412 );
413 }
414
415
416
417 $data = [
418 'sendTo' => $sendTo,
419 'body' => $reParsedData['body'],
420 'historyId' => $historyId,
421 'logNotificationId' => $logNotificationId,
422 ];
423
424 if ($this->getSend()) {
425 $this->sendSms($data);
426 } else {
427 $this->addPreparedNotificationData($data);
428
429 if ($data['logNotificationId']) {
430 $notificationsLogRepository->updateFieldById((int)$data['logNotificationId'], 1, 'sent');
431 }
432 }
433 }
434
435 /**
436 * @param int $historyId
437 * @param mixed $apiResponse
438 * @throws QueryExecutionException
439 */
440 public function updateSmsHistory($historyId, $apiResponse)
441 {
442 /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */
443 $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository');
444
445 $notificationsSMSHistoryRepo->update(
446 $historyId,
447 [
448 'logId' => $apiResponse->message->logId,
449 'status' => $apiResponse->message->status,
450 'price' => $apiResponse->message->price,
451 'dateTime' => DateTimeService::getNowDateTimeInUtc(),
452 'segments' => $apiResponse->message->segments
453 ]
454 );
455 }
456
457 /**
458 * @param $data array
459 *
460 * @return void
461 * @throws QueryExecutionException
462 */
463 protected function sendSms($data)
464 {
465 /** @var NotificationLogRepository $notificationsLogRepository */
466 $notificationsLogRepository = $this->container->get('domain.notificationLog.repository');
467 /** @var SMSAPIService $smsApiService */
468 $smsApiService = $this->container->get('application.smsApi.service');
469
470 $apiResponse = $smsApiService->send(
471 $data['sendTo'],
472 $data['body'],
473 AMELIA_ACTION_URL . '/notifications/sms/history/' . $data['historyId']
474 );
475
476 if ($apiResponse->status === 'OK') {
477 $this->updateSmsHistory($data['historyId'], $apiResponse);
478
479 if ($data['logNotificationId']) {
480 $notificationsLogRepository->updateFieldById((int)$data['logNotificationId'], 1, 'sent');
481 }
482
483 if (!$this->sentSmsLowEmail) {
484 $this->sendSmsBalanceLowEmail();
485 }
486 } else {
487 if ($data['logNotificationId']) {
488 $notificationsLogRepository->updateFieldById((int)$data['logNotificationId'], 0, 'sent');
489 }
490 }
491 }
492
493 /**
494 * @return void
495 * @throws QueryExecutionException
496 */
497 public function sendPreparedNotifications()
498 {
499 foreach ($this->getPreparedNotificationData() as $item) {
500 $this->sendSms($item);
501 }
502 }
503 }
504