PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.2
Booking for Appointments and Events Calendar – Amelia v2.2
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 / Placeholder / AppointmentPlaceholderService.php
ameliabooking / src / Application / Services / Placeholder Last commit date
AppointmentPlaceholderService.php 4 months ago AppointmentsPlaceholderService.php 6 months ago BasicPackagePlaceholderService.php 8 months ago EventPlaceholderService.php 4 months ago PlaceholderService.php 4 months ago PlaceholderServiceInterface.php 8 months ago
AppointmentPlaceholderService.php
1212 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\Placeholder;
9
10 use AmeliaBooking\Application\Services\Bookable\BookableApplicationService;
11 use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService;
12 use AmeliaBooking\Application\Services\Helper\HelperService;
13 use AmeliaBooking\Domain\Collection\Collection;
14 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
15 use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable;
16 use AmeliaBooking\Domain\Entity\Bookable\Service\Category;
17 use AmeliaBooking\Domain\Entity\Bookable\Service\Extra;
18 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
19 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
20 use AmeliaBooking\Domain\Entity\Coupon\Coupon;
21 use AmeliaBooking\Domain\Entity\Entities;
22 use AmeliaBooking\Domain\Entity\Location\Location;
23 use AmeliaBooking\Domain\Entity\User\AbstractUser;
24 use AmeliaBooking\Domain\Entity\User\Provider;
25 use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory;
26 use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory;
27 use AmeliaBooking\Domain\Factory\User\UserFactory;
28 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
29 use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface;
30 use AmeliaBooking\Domain\Services\Settings\SettingsService;
31 use AmeliaBooking\Domain\ValueObjects\String\BookingStatus;
32 use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus;
33 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
34 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
35 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository;
36 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ExtraRepository;
37 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
38 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
39 use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository;
40 use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository;
41 use AmeliaBooking\Infrastructure\Repository\User\UserRepository;
42 use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings;
43 use DateTime;
44 use Exception;
45 use Interop\Container\Exception\ContainerException;
46 use Slim\Exception\ContainerValueNotFoundException;
47
48 /**
49 * Class AppointmentPlaceholderService
50 *
51 * @package AmeliaBooking\Application\Services\Placeholder
52 */
53 class AppointmentPlaceholderService extends PlaceholderService
54 {
55 /**
56 *
57 * @return array
58 *
59 * @throws ContainerException
60 */
61 public function getEntityPlaceholdersDummyData($type)
62 {
63 /** @var SettingsService $settingsService */
64 $settingsService = $this->container->get('domain.settings.service');
65
66 /** @var HelperService $helperService */
67 $helperService = $this->container->get('application.helper.service');
68
69 $companySettings = $settingsService->getCategorySettings('company');
70
71 $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat');
72 $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat');
73
74 $timeZone = get_option('timezone_string');
75
76 if (empty($timeZone)) {
77 $gmtOffset = get_option('gmt_offset');
78 $timeZone = sprintf('Etc/GMT%+d', -$gmtOffset);
79 }
80
81 $dateTime = new DateTime("now", new \DateTimeZone($timeZone));
82
83 $appointment_date = $dateTime->format($dateFormat);
84 $appointment_date_time = $dateTime->format($dateFormat . ' ' . $timeFormat);
85 $appointment_start_time = $dateTime->format($timeFormat);
86 $appointment_end_time = (new DateTime("now +1 hour", new \DateTimeZone($timeZone)))->format($timeFormat);
87
88 return [
89 'appointment_id' => '1',
90 'appointment_date' => $appointment_date,
91 'appointment_date_time' => $appointment_date_time,
92 'appointment_start_time' => $appointment_start_time,
93 'appointment_end_time' => $appointment_end_time,
94 'appointment_notes' => 'Appointment note',
95 'appointment_price' => $helperService->getFormattedPrice(100),
96 'payment_due_amount' => $helperService->getFormattedPrice(80),
97 'appointment_cancel_url' => 'http://cancel_url.com',
98 'appointment_approve_url' => 'http://approve_url.com',
99 'appointment_reject_url' => 'http://reject_url.com',
100 'zoom_join_url' => $type === 'email' ?
101 '<a href="#">' . BackendStrings::get('zoom_click_to_join') . '</a>' : 'https://join_zoom_link.com',
102 'zoom_host_url' => $type === 'email' ?
103 '<a href="#">' . BackendStrings::get('zoom_click_to_start') . '</a>' : 'https://start_zoom_link.com',
104 'google_meet_url' => 'https://join_google_meet_link.com',
105 'lesson_space_url' => 'https://lessonspace.com/room-id',
106 'microsoft_teams_url' => 'https://join_microsoft_teams_link.com',
107 'appointment_duration' => $helperService->secondsToNiceDuration(1800),
108 'appointment_deposit_payment' => $helperService->getFormattedPrice(20),
109 'appointment_status' => BackendStrings::get('approved'),
110 'category_name' => 'Category Name',
111 'service_description' => 'Service Description',
112 'reservation_description' => 'Service Description',
113 'service_duration' => $helperService->secondsToNiceDuration(5400),
114 'service_name' => 'Service Name',
115 'service_id' => '123',
116 'reservation_name' => 'Service Name',
117 'service_price' => $helperService->getFormattedPrice(100),
118 'service_extras' => 'Extra1, Extra2, Extra3',
119 'service_extras_details' => '<p>Extra1: ($1.00 x 1) x 3</p><p>Extra2: ($2.00 x 2)</p><p>Extra3: ($3.00 x 3)</p>' .
120 '<p>-------------------------</p>' . '<p>' . BackendStrings::get('extras_total_price') . ' $16.00</p>'
121
122 ];
123 }
124
125 /**
126 * @param array $appointment
127 * @param int $bookingKey
128 * @param string $type
129 * @param string $token
130 * @param bool $invoice
131 * @param string $notificationType
132 *
133 * @return array
134 *
135 * @throws InvalidArgumentException
136 * @throws ContainerValueNotFoundException
137 * @throws NotFoundException
138 * @throws QueryExecutionException
139 * @throws ContainerException
140 * @throws Exception
141 */
142 public function getAppointmentPlaceholderData(
143 $appointment,
144 $bookingKey = null,
145 $type = null,
146 $token = null,
147 $invoice = false,
148 $notificationType = null
149 ) {
150 $data = [];
151
152 $this->setData($appointment, $bookingKey);
153
154 $data = array_merge($data, $this->getAppointmentData($appointment, $bookingKey, $type));
155 $data = array_merge($data, $this->getServiceData($appointment, $bookingKey, $type));
156 $data = array_merge($data, $this->getEmployeeData($appointment, $bookingKey));
157 $data = array_merge($data, $this->getBookingData($appointment, $type, $bookingKey, $token, $data['deposit'], null, $invoice));
158 $data = array_merge($data, $this->getCustomFieldsData($appointment, $type, $bookingKey));
159
160 if ($notificationType === 'customer_appointment_approved') {
161 $data = array_merge($data, $this->getCouponsData($appointment, $type, $bookingKey));
162 }
163
164 return $data;
165 }
166
167 /**
168 * @param array $appointment
169 * @param int $bookingKey
170 * @param string $type
171 * @param AbstractUser $customer
172 * @param array $allBookings
173 * @param bool $invoice
174 * @param string $notificationType
175 *
176 * @return array
177 *
178 * @throws InvalidArgumentException
179 * @throws ContainerValueNotFoundException
180 * @throws NotFoundException
181 * @throws QueryExecutionException
182 * @throws ContainerException
183 * @throws Exception
184 */
185 public function getPlaceholdersData(
186 $appointment,
187 $bookingKey = null,
188 $type = null,
189 $customer = null,
190 $allBookings = null,
191 $invoice = false,
192 $notificationType = null
193 ) {
194 /** @var CustomerBookingRepository $bookingRepository */
195 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
196
197 $bookingKeyForEmployee = null;
198
199 if ($bookingKey === null) {
200 $bookingKeyForEmployee = $this->getBookingKeyForEmployee($appointment);
201 }
202
203 $token = isset($appointment['bookings'][$bookingKey]) ?
204 $bookingRepository->getToken($appointment['bookings'][$bookingKey]['id']) :
205 ($bookingKeyForEmployee ? $bookingRepository->getToken($bookingKeyForEmployee) : null);
206
207 $token = isset($token['token']) ? $token['token'] : null;
208
209 $data = [];
210
211 $this->setData($appointment, $bookingKey);
212
213 $locale = $this->getLocale($appointment, $bookingKey);
214
215 $data = array_merge($data, $this->getAppointmentPlaceholderData($appointment, $bookingKey, $type, $token, false, $notificationType));
216 $data = array_merge($data, $this->getRecurringAppointmentsData($appointment, $bookingKey, $type, 'recurring', $bookingKeyForEmployee));
217 if (empty($customer)) {
218 $data = array_merge($data, $this->getGroupedAppointmentData($appointment, $bookingKey, $type));
219 }
220 $data = array_merge($data, $this->getCompanyData($bookingKey !== null ? $locale : null));
221 $data = array_merge($data, $this->getCustomersData($appointment, $type, $bookingKey, $customer));
222
223 return $data;
224 }
225
226
227 /**
228 * @param array $reservationData
229 *
230 * @return array
231 *
232 * @throws InvalidArgumentException
233 * @throws ContainerValueNotFoundException
234 * @throws NotFoundException
235 * @throws QueryExecutionException
236 * @throws ContainerException
237 * @throws Exception
238 */
239 public function getInvoicePlaceholdersData($reservationData)
240 {
241 $type = 'email';
242
243 $data = ['customer_custom_fields' => []];
244
245 $appointment = $reservationData['appointment'];
246 $bookingKey = array_search($reservationData['booking']['id'], array_column($appointment['bookings'], 'id'));
247
248 $this->setData($appointment, $bookingKey);
249
250 $locale = $this->getLocale($appointment, $bookingKey);
251
252 $appointments = array_merge([['appointment' => $appointment, 'booking' => $reservationData['booking']]], $reservationData['recurring']);
253
254 foreach ($appointments as $recurringAppointment) {
255 $appointment = $recurringAppointment['appointment'];
256 $bookingKey = array_search($recurringAppointment['booking']['id'], array_column($appointment['bookings'], 'id'));
257
258 $placeholders = $this->getAppointmentPlaceholderData($appointment, $bookingKey, $type, null, true);
259 $invoiceItem = $placeholders['invoice_items_booking'][0];
260
261 if (empty($data['invoice_number'])) {
262 $data['invoice_number'] = $placeholders['payment_invoice_number'];
263 }
264 $data['invoice_method'] = !empty($placeholders['payment_gateway_title']) ? $placeholders['payment_gateway_title'] : $placeholders['payment_type'];
265 $data['invoice_issued'] = $placeholders['payment_created'];
266
267 $index = "service_{$appointment['serviceId']}_{$recurringAppointment['booking']['price']}";
268 if (!empty($data['items'][$index])) {
269 $data['items'][$index]['invoice_qty'] += $invoiceItem['invoice_qty'];
270 $data['items'][$index]['invoice_subtotal'] += $invoiceItem['invoice_subtotal'];
271 $data['items'][$index]['invoice_discount'] += $invoiceItem['invoice_discount'];
272 $data['items'][$index]['service_discount'] += $invoiceItem['service_discount'];
273 $data['items'][$index]['invoice_tax'] += $invoiceItem['invoice_tax'];
274 $data['items'][$index]['invoice_paid_amount'] += $invoiceItem['invoice_paid_amount'];
275 $data['items'][$index]['total_tax'] += $invoiceItem['total_tax'];
276 } else {
277 $data['items'][$index] = $invoiceItem;
278 $data['items'][$index]['item_name'] = $placeholders['service_name'];
279 }
280
281 $extraItems = $placeholders['invoice_items_extras'];
282 $extraItemsTaxes = $invoiceItem['invoice_extras_items'];
283 foreach ($extraItems as $extraItem) {
284 $index = $extraItem['item_index'];
285 if (!empty($data['items'][$index])) {
286 $data['items'][$index]['invoice_qty'] += $extraItem['invoice_qty'];
287 $data['items'][$index]['invoice_subtotal'] += $extraItem['invoice_subtotal'];
288 $data['items'][$index]['invoice_tax'] += !empty($extraItemsTaxes[$extraItem['item_id']]['tax']['amount']) ?
289 $extraItemsTaxes[$extraItem['item_id']]['tax']['amount'] : 0;
290 $data['items'][$index]['invoice_discount'] += !empty($extraItemsTaxes[$extraItem['item_id']]['full_discount']) ?
291 $extraItemsTaxes[$extraItem['item_id']]['full_discount'] : 0;
292 } else {
293 $data['items'][$index] = array_merge(
294 $extraItem,
295 !empty($extraItemsTaxes[$extraItem['item_id']]) ?
296 [
297 'invoice_tax' =>
298 $extraItemsTaxes[$extraItem['item_id']]['tax']['amount'],
299 'invoice_tax_rate' => $extraItemsTaxes[$extraItem['item_id']]['tax']['rate'],
300 'invoice_tax_excluded' => $extraItemsTaxes[$extraItem['item_id']]['tax']['excluded'],
301 'invoice_tax_type' => $extraItemsTaxes[$extraItem['item_id']]['tax']['type'],
302 'invoice_discount' => !empty($extraItemsTaxes[$extraItem['item_id']]['full_discount']) ?
303 $extraItemsTaxes[$extraItem['item_id']]['full_discount'] : 0,
304 ] :
305 []
306 );
307 }
308 }
309
310 $data['customer_custom_fields'] = array_merge(
311 $data['customer_custom_fields'],
312 array_filter($placeholders, function ($key) {
313 return strpos($key, 'invoice_custom_field_') === 0;
314 }, ARRAY_FILTER_USE_KEY)
315 );
316 }
317
318 $data['items'] = array_values($data['items']);
319 $data['invoice_tax'] = array_sum(array_column($data['items'], 'total_tax'));
320
321 $data = array_merge($data, $this->getCompanyData($bookingKey !== null ? $locale : null));
322 $data = array_merge($data, $this->getCustomersData($appointment, $type, $bookingKey));
323
324 return $data;
325 }
326
327 /**
328 * @param $appointment
329 * @param null $bookingKey
330 * @param string $type
331 *
332 * @return array
333 *
334 * @throws Exception
335 */
336 protected function getAppointmentData($appointment, $bookingKey = null, $type = null)
337 {
338 /** @var UserRepository $userRepository */
339 $userRepository = $this->container->get('domain.users.repository');
340
341 /** @var SettingsService $settingsService */
342 $settingsService = $this->container->get('domain.settings.service');
343
344 $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat');
345 $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat');
346
347 if ($appointment['providerId'] && empty($appointment['provider'])) {
348 /** @var Provider $user */
349 $user = $userRepository->getById($appointment['providerId']);
350
351 $appointment['provider'] = $user->toArray();
352 }
353
354 if (
355 $bookingKey !== null && $appointment['bookings'][$bookingKey]['utcOffset'] !== null
356 && $settingsService->getSetting('general', 'showClientTimeZone')
357 ) {
358 $info = !empty($appointment['bookings'][$bookingKey]['info'])
359 ? json_decode($appointment['bookings'][$bookingKey]['info'], true)
360 : null;
361
362 $timeZone = !empty($info['timeZone']) ? $info['timeZone'] : '';
363
364 $bookingStart = DateTimeService::getClientUtcCustomDateTimeObject(
365 DateTimeService::getCustomDateTimeInUtc($appointment['bookingStart']),
366 $appointment['bookings'][$bookingKey]['utcOffset']
367 );
368
369 $bookingEnd = DateTimeService::getClientUtcCustomDateTimeObject(
370 DateTimeService::getCustomDateTimeInUtc($appointment['bookingEnd']),
371 $appointment['bookings'][$bookingKey]['utcOffset']
372 );
373
374 $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getClientUtcCustomDateTimeObject(
375 DateTimeService::getCustomDateTimeInUtc($appointment['initialAppointmentDateTime']['bookingStart']),
376 $appointment['bookings'][$bookingKey]['utcOffset']
377 ) : '';
378
379 $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getClientUtcCustomDateTimeObject(
380 DateTimeService::getCustomDateTimeInUtc($appointment['initialAppointmentDateTime']['bookingEnd']),
381 $appointment['bookings'][$bookingKey]['utcOffset']
382 ) : '';
383
384 if (!empty($appointment['initialAppointmentDateTime']) && $timeZone) {
385 $bookingStart = DateTimeService::getDateTimeObjectInTimeZone(
386 DateTimeService::getCustomDateTimeObject(
387 $appointment['bookingStart']
388 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
389 'UTC'
390 );
391
392 $bookingEnd = DateTimeService::getDateTimeObjectInTimeZone(
393 DateTimeService::getCustomDateTimeObject(
394 $appointment['bookingEnd']
395 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
396 'UTC'
397 );
398
399 $oldBookingStart = DateTimeService::getDateTimeObjectInTimeZone(
400 DateTimeService::getCustomDateTimeObject(
401 $appointment['initialAppointmentDateTime']['bookingStart']
402 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
403 'UTC'
404 );
405
406 $oldBookingEnd = DateTimeService::getDateTimeObjectInTimeZone(
407 DateTimeService::getCustomDateTimeObject(
408 $appointment['initialAppointmentDateTime']['bookingEnd']
409 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
410 'UTC'
411 );
412 }
413 } elseif ($bookingKey === null && !empty($appointment['provider']['timeZone'])) {
414 $timeZone = $appointment['provider']['timeZone'];
415
416 $bookingStart = DateTimeService::getDateTimeObjectInTimeZone(
417 DateTimeService::getCustomDateTimeObject(
418 $appointment['bookingStart']
419 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
420 'UTC'
421 );
422
423 $bookingEnd = DateTimeService::getDateTimeObjectInTimeZone(
424 DateTimeService::getCustomDateTimeObject(
425 $appointment['bookingEnd']
426 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
427 'UTC'
428 );
429
430 $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ?
431 DateTimeService::getDateTimeObjectInTimeZone(
432 DateTimeService::getCustomDateTimeObject(
433 $appointment['initialAppointmentDateTime']['bookingStart']
434 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
435 'UTC'
436 ) : '';
437
438 $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ?
439 DateTimeService::getDateTimeObjectInTimeZone(
440 DateTimeService::getCustomDateTimeObject(
441 $appointment['initialAppointmentDateTime']['bookingEnd']
442 )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'),
443 'UTC'
444 ) : '';
445 } else {
446 $timeZone = get_option('timezone_string');
447
448 $bookingStart = DateTime::createFromFormat('Y-m-d H:i:s', $appointment['bookingStart']);
449
450 $bookingEnd = DateTime::createFromFormat('Y-m-d H:i:s', $appointment['bookingEnd']);
451
452 $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ?
453 DateTime::createFromFormat('Y-m-d H:i:s', $appointment['initialAppointmentDateTime']['bookingStart']) : '';
454
455 $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ?
456 DateTime::createFromFormat('Y-m-d H:i:s', $appointment['initialAppointmentDateTime']['bookingEnd']) : '';
457 }
458
459 $zoomStartUrl = '';
460 $zoomJoinUrl = '';
461
462 $lessonSpaceLink = '';
463 if (array_key_exists('lessonSpace', $appointment) && $appointment['lessonSpace']) {
464 $lessonSpaceLink = $appointment['lessonSpace'];
465 }
466
467 if (isset($appointment['zoomMeeting']['joinUrl'], $appointment['zoomMeeting']['startUrl'])) {
468 $zoomStartUrl = $appointment['zoomMeeting']['startUrl'];
469 $zoomJoinUrl = $appointment['zoomMeeting']['joinUrl'];
470 }
471
472 $googleMeetUrl = '';
473 if (array_key_exists('googleMeetUrl', $appointment) && $appointment['googleMeetUrl']) {
474 $googleMeetUrl = $appointment['googleMeetUrl'];
475 }
476
477 $microsoftTeamsUrl = '';
478 if (array_key_exists('microsoftTeamsUrl', $appointment) && $appointment['microsoftTeamsUrl']) {
479 $microsoftTeamsUrl = $appointment['microsoftTeamsUrl'];
480 }
481
482 return [
483 'appointment_id' => !empty($appointment['id']) ? $appointment['id'] : '',
484 'appointment_status' => BackendStrings::get($appointment['status']),
485 'appointment_notes' => !empty($appointment['internalNotes']) ? $appointment['internalNotes'] : '',
486 'appointment_date' => date_i18n($dateFormat, $bookingStart->getTimestamp()),
487 'appointment_date_time' => date_i18n($dateFormat . ' ' . $timeFormat, $bookingStart->getTimestamp()),
488 'appointment_start_time' => date_i18n($timeFormat, $bookingStart->getTimestamp()),
489 'appointment_end_time' => date_i18n($timeFormat, $bookingEnd->getTimestamp()),
490 'initial_appointment_date' => !empty($oldBookingStart) ? date_i18n($dateFormat, $oldBookingStart->getTimestamp()) : '',
491 'initial_appointment_date_time' => !empty($oldBookingStart) ? date_i18n($dateFormat . ' ' . $timeFormat, $oldBookingStart->getTimestamp()) : '',
492 'initial_appointment_start_time' => !empty($oldBookingStart) ? date_i18n($timeFormat, $oldBookingStart->getTimestamp()) : '',
493 'initial_appointment_end_time' => !empty($oldBookingEnd) ? date_i18n($timeFormat, $oldBookingEnd->getTimestamp()) : '',
494 'lesson_space_url' => $lessonSpaceLink,
495 'zoom_host_url' => $zoomStartUrl && $type === 'email' ?
496 '<a href="' . $zoomStartUrl . '">' . BackendStrings::get('zoom_click_to_start') . '</a>'
497 : $zoomStartUrl,
498 'zoom_join_url' => $zoomJoinUrl && $type === 'email' ?
499 '<a href="' . $zoomJoinUrl . '">' . BackendStrings::get('zoom_click_to_join') . '</a>'
500 : $zoomJoinUrl,
501 'google_meet_url' => $googleMeetUrl,
502 'microsoft_teams_url' => $microsoftTeamsUrl,
503 'time_zone' => $timeZone,
504 ];
505 }
506
507 /**
508 * @param $appointmentArray
509 * @param $bookingKey
510 *
511 * @return array
512 * @throws ContainerValueNotFoundException
513 * @throws NotFoundException
514 * @throws QueryExecutionException
515 * @throws ContainerException
516 * @throws InvalidArgumentException
517 */
518 private function getServiceData($appointmentArray, $bookingKey, $type)
519 {
520 /** @var CategoryRepository $categoryRepository */
521 $categoryRepository = $this->container->get('domain.bookable.category.repository');
522 /** @var ServiceRepository $serviceRepository */
523 $serviceRepository = $this->container->get('domain.bookable.service.repository');
524 /** @var UserRepository $userRepository */
525 $userRepository = $this->container->get('domain.users.repository');
526
527 /** @var HelperService $helperService */
528 $helperService = $this->container->get('application.helper.service');
529 /** @var AppointmentApplicationService $appointmentAS */
530 $appointmentAS = $this->container->get('application.booking.appointment.service');
531 /** @var BookableApplicationService $bookableAS */
532 $bookableAS = $this->container->get('application.bookable.service');
533
534 /** @var Service $service */
535 $service = $appointmentArray['providerId']
536 ? $bookableAS->getAppointmentService($appointmentArray['serviceId'], $appointmentArray['providerId'])
537 : $serviceRepository->getByIdWithExtras($appointmentArray['serviceId']);
538
539 /** @var Category $category */
540 $category = $categoryRepository->getById($service->getCategoryId()->getValue());
541
542 /** @var Provider $provider */
543 $provider = $appointmentAS->isPeriodCustomPricing($service)
544 ? $userRepository->getById($appointmentArray['providerId'])
545 : null;
546
547 $locale = $this->getLocale($appointmentArray, $bookingKey);
548
549 $categoryName = $helperService->getBookingTranslation(
550 $bookingKey !== null ? $locale : null,
551 $category->getTranslations() ? $category->getTranslations()->getValue() : null,
552 'name'
553 ) ?: $category->getName()->getValue();
554
555 $serviceName = $helperService->getBookingTranslation(
556 $bookingKey !== null ? $locale : null,
557 $service->getTranslations() ? $service->getTranslations()->getValue() : null,
558 'name'
559 ) ?: $service->getName()->getValue();
560
561 $serviceDescription = $helperService->getBookingTranslation(
562 $bookingKey !== null ? $locale : null,
563 $service->getTranslations() ? $service->getTranslations()->getValue() : null,
564 'description'
565 ) ?: ($service->getDescription() ? $service->getDescription()->getValue() : '');
566
567 $servicePrices = [];
568
569 $serviceDurations = [];
570
571 if ($bookingKey === null) {
572 foreach ($appointmentArray['bookings'] as $booking) {
573 if ($booking['status'] === BookingStatus::CANCELED || $booking['status'] === BookingStatus::REJECTED) {
574 continue;
575 }
576
577 $duration = $booking['duration'] ?: $service->getDuration()->getValue();
578
579 $price = $appointmentAS->getBookingPriceForService(
580 $service,
581 CustomerBookingFactory::create(
582 [
583 'duration' => $duration,
584 'persons' => $booking['persons'],
585 ]
586 ),
587 $provider,
588 $appointmentArray['bookingStart']
589 );
590
591 $servicePrices[] = $helperService->getFormattedPrice($price);
592
593 $serviceDurations[$duration] = $helperService->secondsToNiceDuration($duration);
594 }
595 } else {
596 $duration = !empty($appointmentArray['bookings'][$bookingKey]['duration'])
597 ? $appointmentArray['bookings'][$bookingKey]['duration'] : $service->getDuration()->getValue();
598
599 $price = $appointmentAS->getBookingPriceForService(
600 $service,
601 CustomerBookingFactory::create(
602 [
603 'duration' => $duration,
604 'persons' => $appointmentArray['bookings'][$bookingKey]['persons'],
605 ]
606 ),
607 $provider,
608 $appointmentArray['bookingStart']
609 );
610
611 $servicePrices[] = $helperService->getFormattedPrice(
612 $price
613 );
614
615 $serviceDurations[$duration] = $helperService->secondsToNiceDuration(
616 $duration
617 );
618 }
619
620 $data = [
621 'category_name' => $categoryName,
622 'category_id' => $category->getId()->getValue(),
623 'service_description' => $serviceDescription,
624 'reservation_description' => $serviceDescription,
625 'service_duration' => implode(', ', $serviceDurations),
626 'service_name' => $serviceName,
627 'service_id' => $service->getId()->getValue(),
628 'reservation_name' => $serviceName,
629 'service_price' => implode(', ', array_unique($servicePrices)),
630 ];
631
632 $bookingExtras = [];
633
634 $persons = 1;
635
636 foreach ((array)$appointmentArray['bookings'] as $key => $booking) {
637 if (
638 ($bookingKey === null && ($booking['isChangedStatus'] || $booking['status'] === BookingStatus::APPROVED
639 || $booking['status'] === BookingStatus::PENDING)) || $bookingKey === $key
640 ) {
641 foreach ((array)$booking['extras'] as $bookingExtra) {
642 $bookingExtras[$bookingExtra['extraId']] = [
643 'quantity' => $bookingExtra['quantity'],
644 'price' => $bookingExtra['price']
645 ];
646 }
647
648 $persons = $booking['persons'];
649 }
650 }
651
652 /** @var ExtraRepository $extraRepository */
653 $extraRepository = $this->container->get('domain.bookable.extra.repository');
654
655 /** @var Collection $extras */
656 $extras = $extraRepository->getAllIndexedById();
657
658 $duration = $service->getDuration()->getValue();
659
660 if ($bookingKey !== null) {
661 $duration = !empty($appointmentArray['bookings'][$bookingKey]['duration']) ?
662 $appointmentArray['bookings'][$bookingKey]['duration'] : $duration;
663
664 foreach ($appointmentArray['bookings'][$bookingKey]['extras'] as $bookingExtra) {
665 /** @var Extra $extra */
666 $extra = $extras->getItem($bookingExtra['extraId']);
667
668 $duration += $extra->getDuration() ? $extra->getDuration()->getValue() * $bookingExtra['quantity'] : 0;
669 }
670 } else {
671 $maxBookingDuration = 0;
672
673 foreach ($appointmentArray['bookings'] as $booking) {
674 $bookingDuration = $booking['duration'] ? $booking['duration'] : $duration;
675
676 foreach ($booking['extras'] as $bookingExtra) {
677 /** @var Extra $extra */
678 $extra = $extras->getItem($bookingExtra['extraId']);
679
680 $bookingDuration += $extra->getDuration() ?
681 $extra->getDuration()->getValue() * $bookingExtra['quantity'] : 0;
682 }
683
684 if (
685 $bookingDuration > $maxBookingDuration &&
686 ($booking['status'] === BookingStatus::APPROVED || $booking['status'] === BookingStatus::PENDING)
687 ) {
688 $maxBookingDuration = $bookingDuration;
689 }
690 }
691
692 $duration = $maxBookingDuration;
693 }
694
695 $data['appointment_duration'] = $helperService->secondsToNiceDuration($duration);
696
697 /** @var string $break */
698 $break = $type === 'whatsapp' ? '; ' : PHP_EOL;
699
700 $lastBookingExtraIds = [];
701 if ($bookingKey === null) {
702 $lastBookingId = $this->getBookingKeyForEmployee($appointmentArray);
703
704 $lastBooking = array_filter(
705 $appointmentArray['bookings'],
706 function ($b) use ($lastBookingId) {
707 return $b['id'] === $lastBookingId;
708 }
709 );
710
711 foreach ($lastBooking ? array_shift($lastBooking)['extras'] : [] as $ex) {
712 $lastBookingExtraIds[$ex['extraId']] = $ex;
713 }
714 }
715
716 $allExtraNames = "";
717 $allExtraDetails = "";
718 $allExtraSum = 0;
719
720 $invoiceItems = [];
721
722 /** @var Extra $extra */
723 foreach ($extras->getItems() as $extra) {
724 $extraId = $extra->getId()->getValue();
725
726 $data["service_extra_{$extraId}_name"] =
727 array_key_exists($extraId, $bookingExtras) ? $extra->getName()->getValue() : '';
728
729 $data["service_extra_{$extraId}_name"] = $helperService->getBookingTranslation(
730 $bookingKey !== null ? $locale : null,
731 $data["service_extra_{$extraId}_name"] && $extra->getTranslations() ?
732 $extra->getTranslations()->getValue() : null,
733 'name'
734 ) ?: $data["service_extra_{$extraId}_name"];
735
736 $data["service_extra_{$extraId}_quantity"] =
737 array_key_exists($extraId, $bookingExtras) ? $bookingExtras[$extraId]['quantity'] : '';
738
739 $data["service_extra_{$extraId}_price"] = array_key_exists($extraId, $bookingExtras) ?
740 $helperService->getFormattedPrice($extra->getPrice()->getValue()) : '';
741
742 $multiplyByNumberOfPeople = ($extra->getAggregatedPrice() === null ? $service->getAggregatedPrice()->getValue()
743 : $extra->getAggregatedPrice()->getValue()) && $persons !== 1;
744
745 if (!empty($data["service_extra_{$extraId}_name"])) {
746 $allExtraNames .= $data["service_extra_{$extraId}_name"] . ', ';
747 }
748
749 if (array_key_exists($extraId, $bookingExtras) && $bookingExtras[$extraId]['quantity'] !== 0) {
750 if ($bookingKey === null) {
751 if (
752 empty($appointmentArray['sendForAllBookings']) &&
753 !array_key_exists($extraId, $lastBookingExtraIds)
754 ) {
755 continue;
756 }
757 }
758 $allExtraDetails .= ($type === 'email' ? '<p>' : '') . $extra->getName()->getValue() . ': (' .
759 $helperService->getFormattedPrice($extra->getPrice()->getValue()) . ' x ' .
760 $bookingExtras[$extraId]['quantity'] . ') ' .
761 ($multiplyByNumberOfPeople ? ('x ' . $persons) : '') .
762 ($type === 'email' ? '</p>' : $break);
763
764 $allExtraSum += $extra->getPrice()->getValue() * $bookingExtras[$extraId]['quantity'] *
765 ($multiplyByNumberOfPeople ? $persons : 1);
766
767 $invoiceItems[] = [
768 'item_id' => $extraId,
769 'item_index' => "extra_{$extraId}_{$bookingExtras[$extraId]['price']}",
770 'item_name' => $extra->getName()->getValue(),
771 'invoice_qty' => $bookingExtras[$extraId]['quantity'] * ($multiplyByNumberOfPeople ? $persons : 1),
772 'invoice_unit_price' => $bookingExtras[$extraId]['price'],
773 'invoice_subtotal' => 0,
774 'invoice_tax' => 0
775 ];
776 }
777 }
778
779 $data["service_extras"] = substr($allExtraNames, 0, -2);
780
781 $data['deposit'] = $service->getDeposit() && $service->getDeposit()->getValue();
782
783 $data['invoice_items_extras'] = $invoiceItems;
784
785 $data["service_extras_details"] = $allExtraDetails ? ($allExtraDetails . ($type !== 'whatsapp' ?
786 ($type === 'email' ? '<p>' : $break) . "-------------------------" . ($type === 'email' ? '</p>' : $break) : '') .
787 ($type === 'email' ? '<p>' : '') . BackendStrings::get('extras_total_price') .
788 " {$helperService->getFormattedPrice($allExtraSum)}" . ($type === 'email' ? '</p>' : '')) : "";
789
790 return $data;
791 }
792
793 /**
794 * @param $appointment
795 * @param $bookingKey
796 *
797 * @return array
798 *
799 * @throws ContainerValueNotFoundException
800 * @throws NotFoundException
801 * @throws QueryExecutionException
802 */
803 public function getEmployeeData($appointment, $bookingKey = null)
804 {
805 /** @var HelperService $helperService */
806 $helperService = $this->container->get('application.helper.service');
807
808 /** @var UserRepository $userRepository */
809 $userRepository = $this->container->get('domain.users.repository');
810
811 /** @var LocationRepository $locationRepository */
812 $locationRepository = $this->container->get('domain.locations.repository');
813
814 /** @var SettingsService $settingsService */
815 $settingsService = $this->container->get('domain.settings.service');
816
817 /** @var Provider $user */
818 $user = $userRepository->getById($appointment['providerId']);
819
820 $locale = $this->getLocale($appointment, $bookingKey);
821
822 if (!empty($appointment['locationId'])) {
823 $locationId = $appointment['locationId'];
824 } else {
825 $locationId = $user->getLocationId() ? $user->getLocationId()->getValue() : null;
826 }
827
828 /** @var Location $location */
829 $location = $locationId ? $locationRepository->getById($locationId) : null;
830
831 $locationName = $settingsService->getSetting('company', 'address');
832
833 $locationDescription = '';
834
835 if ($location) {
836 $locationName = $helperService->getBookingTranslation(
837 $bookingKey !== null ? $locale : null,
838 $location->getTranslations() ? $location->getTranslations()->getValue() : null,
839 'name'
840 ) ?: $location->getName()->getValue();
841
842 $locationDescription = $helperService->getBookingTranslation(
843 $bookingKey !== null ? $locale : null,
844 $location->getTranslations() ? $location->getTranslations()->getValue() : null,
845 'description'
846 ) ?: ($location->getDescription() ? $location->getDescription()->getValue() : '');
847 }
848
849 $firstName = $helperService->getBookingTranslation(
850 $bookingKey !== null ? $locale : null,
851 $user->getTranslations() ? $user->getTranslations()->getValue() : null,
852 'firstName'
853 ) ?: $user->getFirstName()->getValue();
854
855 $lastName = $helperService->getBookingTranslation(
856 $bookingKey !== null ? $locale : null,
857 $user->getTranslations() ? $user->getTranslations()->getValue() : null,
858 'lastName'
859 ) ?: $user->getLastName()->getValue();
860
861 $userDescription = $helperService->getBookingTranslation(
862 $bookingKey !== null ? $locale : null,
863 $user->getTranslations() ? $user->getTranslations()->getValue() : null,
864 'description'
865 ) ?: ($user->getDescription() ? $user->getDescription()->getValue() : '');
866
867 return [
868 'employee_id' => $user->getId()->getValue(),
869 'employee_email' => $user->getEmail()->getValue(),
870 'employee_first_name' => $firstName,
871 'employee_last_name' => $lastName,
872 'employee_full_name' => $firstName . ' ' . $lastName,
873 'employee_phone' => $user->getPhone()->getValue(),
874 'employee_phone_country' => $user->getCountryPhoneIso() ? $user->getCountryPhoneIso()->getValue() : null,
875 'employee_note' => $user->getNote() ? $user->getNote()->getValue() : '',
876 'employee_description' => $userDescription,
877 'employee_panel_url' => trim(
878 $this->container->get('domain.settings.service')
879 ->getSetting('roles', 'providerCabinet')['pageUrl']
880 ),
881 'location_address' => !$location ?
882 $settingsService->getSetting('company', 'address') : $location->getAddress()->getValue(),
883 'location_phone' => !$location ?
884 $settingsService->getSetting('company', 'phone') : $location->getPhone()->getValue(),
885 'location_id' => $locationId,
886 'location_name' => $locationName,
887 'location_description' => $locationDescription,
888 'location_latitude' => $location && $location->getCoordinates() ? $location->getCoordinates()->getLatitude() : null,
889 'location_longitude' => $location && $location->getCoordinates() ? $location->getCoordinates()->getLongitude() : null,
890 ];
891 }
892
893 /**
894 * @param array $appointment
895 * @param int $bookingKey
896 * @param string $type
897 * @param string $placeholderType
898 *
899 * @return array
900 *
901 * @throws ContainerValueNotFoundException
902 * @throws NotFoundException
903 * @throws QueryExecutionException
904 * @throws ContainerException
905 * @throws Exception
906 */
907 public function getRecurringAppointmentsData($appointment, $bookingKey, $type, $placeholderType, $bookingKeyForEmployee = null)
908 {
909 if (!array_key_exists('recurring', $appointment)) {
910 return [
911 "{$placeholderType}_appointments_details" => ''
912 ];
913 }
914
915 /** @var CustomerBookingRepository $bookingRepository */
916 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
917
918 /** @var PlaceholderService $placeholderService */
919 $placeholderService = $this->container->get("application.placeholder.appointment.service");
920
921 /** @var SettingsService $settingsService */
922 $settingsService = $this->container->get('domain.settings.service');
923
924 $appointmentsSettings = $settingsService->getCategorySettings('appointments');
925
926 $recurringAppointmentDetails = [];
927
928 foreach ($appointment['recurring'] as $recurringData) {
929 $recurringBookingKey = null;
930 $recurringBookingKeyForEmployee = null;
931
932 $isForCustomer =
933 $bookingKey !== null ||
934 (isset($appointment['isForCustomer']) && $appointment['isForCustomer']);
935
936 if ($isForCustomer) {
937 foreach ($recurringData['appointment']['bookings'] as $key => $recurringBooking) {
938 if (isset($recurringData['booking']['id'])) {
939 if ($recurringBooking['id'] === $recurringData['booking']['id']) {
940 $recurringBookingKey = $key;
941 }
942 } elseif ($bookingKey !== null && $recurringBooking['customerId'] === $appointment['bookings'][$bookingKey]['customerId']) {
943 $recurringBookingKey = $key;
944 }
945 }
946
947 if ($recurringBookingKey === null) {
948 return [];
949 }
950 } elseif ($bookingKeyForEmployee !== null) {
951 foreach ($recurringData['appointment']['bookings'] as $key => $recurringBooking) {
952 if (isset($recurringData['booking']['id'])) {
953 if ($recurringBooking['id'] === $recurringData['booking']['id']) {
954 $recurringBookingKeyForEmployee = $key;
955 }
956 } else {
957 $recurringBookingKeyForEmployee = $bookingKeyForEmployee;
958 }
959 }
960 }
961
962 $token =
963 $recurringBookingKey !== null &&
964 isset(
965 $recurringData['appointment']['bookings'][$recurringBookingKey],
966 $recurringData['appointment']['bookings'][$recurringBookingKey]['id']
967 ) ? $bookingRepository->getToken($recurringData['appointment']['bookings'][$recurringBookingKey]['id']) : (
968 $recurringBookingKeyForEmployee !== null &&
969 isset(
970 $recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee],
971 $recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee]['id']
972 ) ? $bookingRepository->getToken($recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee]['id']) :
973 null);
974
975 $recurringPlaceholders = [];
976
977 $recurringPlaceholders = array_merge(
978 $recurringPlaceholders,
979 $this->getEmployeeData($recurringData['appointment'], $recurringBookingKey)
980 );
981
982 $recurringPlaceholders = array_merge(
983 $recurringPlaceholders,
984 $this->getAppointmentData($recurringData['appointment'], $recurringBookingKey, $type)
985 );
986
987 $recurringPlaceholders = array_merge(
988 $recurringPlaceholders,
989 $this->getServiceData($recurringData['appointment'], $recurringBookingKey, $type)
990 );
991
992 $recurringPlaceholders = array_merge(
993 $recurringPlaceholders,
994 $this->getCustomFieldsData($recurringData['appointment'], $type, $recurringBookingKey)
995 );
996
997 $recurringPlaceholders = array_merge(
998 $recurringPlaceholders,
999 $this->getBookingData(
1000 $recurringData['appointment'],
1001 $type,
1002 $recurringBookingKey,
1003 isset($token['token']) ? $token['token'] : null,
1004 $recurringPlaceholders['deposit']
1005 )
1006 );
1007
1008 unset($recurringPlaceholders['icsFiles']);
1009
1010 if (!$isForCustomer) {
1011 if (isset($recurringPlaceholders['appointment_cancel_url'])) {
1012 $recurringPlaceholders['appointment_cancel_url'] = '';
1013 }
1014
1015 $recurringPlaceholders['zoom_join_url'] = '';
1016 } else {
1017 $recurringPlaceholders['employee_panel_url'] = '';
1018
1019 $recurringPlaceholders['zoom_host_url'] = '';
1020 }
1021
1022 $placeholderString =
1023 $placeholderType .
1024 'Placeholders' .
1025 ($isForCustomer && $placeholderType === 'package' ? 'Customer' : '') .
1026 ($isForCustomer && $placeholderType === 'recurring' ? 'Customer' : '') .
1027 ($isForCustomer && $placeholderType === 'cart' ? 'Customer' : '') .
1028 ($type === 'email' ? '' : 'Sms');
1029
1030 /** @var HelperService $helperService */
1031 $helperService = $this->container->get('application.helper.service');
1032
1033 $content = $helperService->getBookingTranslation(
1034 $recurringBookingKey !== null ?
1035 $helperService->getLocaleFromBooking($recurringData['appointment']['bookings'][$recurringBookingKey]['info']) :
1036 null,
1037 json_encode($appointmentsSettings['translations']),
1038 $placeholderString
1039 ) ?: $appointmentsSettings[$placeholderString];
1040
1041 if ($type === 'whatsapp') {
1042 $content = str_replace(array("\n","\r"), '; ', $content);
1043 $content = preg_replace('!\s+!', ' ', $content);
1044 }
1045
1046 $recurringAppointmentDetails[] = $placeholderService->applyPlaceholders(
1047 $content,
1048 $recurringPlaceholders
1049 );
1050 }
1051
1052 return [
1053 "{$placeholderType}_appointments_details" => $recurringAppointmentDetails ? implode(
1054 $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL),
1055 $recurringAppointmentDetails
1056 ) : ''
1057 ];
1058 }
1059
1060 /**
1061 * @param array $appointment
1062 * @param int $bookingKey
1063 * @param string $type
1064 *
1065 * @return array
1066 *
1067 * @throws ContainerValueNotFoundException
1068 * @throws NotFoundException
1069 * @throws QueryExecutionException
1070 * @throws ContainerException
1071 * @throws Exception
1072 */
1073 public function getGroupedAppointmentData($appointment, $bookingKey, $type)
1074 {
1075 /** @var PlaceholderService $placeholderService */
1076 $placeholderService = $this->container->get("application.placeholder.appointment.service");
1077
1078 /** @var SettingsService $settingsService */
1079 $settingsService = $this->container->get('domain.settings.service');
1080
1081 $appointmentsSettings = $settingsService->getCategorySettings('appointments');
1082
1083 $groupAppointmentDetails = [];
1084
1085 if ($bookingKey) {
1086 return [
1087 "group_appointment_details" => ''
1088 ];
1089 }
1090
1091 foreach ($appointment['bookings'] as $bookingId => $booking) {
1092 if (
1093 $booking['status'] === BookingStatus::CANCELED ||
1094 $booking['status'] === BookingStatus::REJECTED ||
1095 $booking['status'] === BookingStatus::NO_SHOW
1096 ) {
1097 continue;
1098 }
1099
1100 /** @var CustomerBookingRepository $bookingRepository */
1101 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
1102
1103 $token = $bookingRepository->getToken($appointment['bookings'][$bookingId]['id']);
1104
1105 $groupPlaceholders = array_merge(
1106 $this->getAppointmentData($appointment, $bookingId, $type),
1107 $this->getServiceData($appointment, $bookingId, $type),
1108 $this->getCustomFieldsData($appointment, $type, $bookingId),
1109 $this->getCustomersData($appointment, $type, $bookingId),
1110 $this->getBookingData(
1111 $appointment,
1112 $type,
1113 $bookingId,
1114 isset($token['token']) ? $token['token'] : null,
1115 null,
1116 true
1117 )
1118 );
1119
1120 $content = $appointmentsSettings['groupAppointmentPlaceholder' . ($type === null || $type === 'email' ? '' : 'Sms')] ;
1121 if ($type === 'email') {
1122 $content = str_replace(array("\n","\r"), '', $content);
1123 } elseif ($type === 'whatsapp') {
1124 $content = str_replace(array("\n","\r"), '; ', $content);
1125 $content = preg_replace('!\s+!', ' ', $content);
1126 }
1127
1128 $groupAppointmentDetails[] = $placeholderService->applyPlaceholders(
1129 $content,
1130 $groupPlaceholders
1131 );
1132 }
1133
1134 return [
1135 "group_appointment_details" => $groupAppointmentDetails ? implode(
1136 $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL),
1137 $groupAppointmentDetails
1138 ) : ''
1139 ];
1140 }
1141
1142 /**
1143 * @param array $bookingArray
1144 * @param array $entity
1145 *
1146 * @return array
1147 * @throws InvalidArgumentException
1148 * @throws NotFoundException
1149 * @throws QueryExecutionException
1150 */
1151 public function getAmountData(&$bookingArray, $entity, $invoice = false)
1152 {
1153 /** @var ReservationServiceInterface $reservationService */
1154 $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT);
1155
1156 $couponIdToFetch = !empty($bookingArray['couponId'])
1157 ? $bookingArray['couponId']
1158 : (!empty($bookingArray['coupon']['id']) ? $bookingArray['coupon']['id'] : null);
1159
1160 if ($couponIdToFetch) {
1161 $bookingArray['couponId'] = $couponIdToFetch;
1162 }
1163
1164 $couponIsIncomplete = $couponIdToFetch && (
1165 empty($bookingArray['coupon'])
1166 || empty($bookingArray['coupon']['code'])
1167 || !isset($bookingArray['coupon']['discount'])
1168 || !isset($bookingArray['coupon']['deduction'])
1169 );
1170
1171 if ($couponIsIncomplete) {
1172 /** @var CouponRepository $couponRepository */
1173 $couponRepository = $this->container->get('domain.coupon.repository');
1174
1175 /** @var Coupon $coupon */
1176 $coupon = $couponRepository->getById($couponIdToFetch);
1177
1178 $bookingArray['coupon'] = $coupon ? $coupon->toArray() : null;
1179 }
1180
1181 $extras = [];
1182
1183 foreach ($bookingArray['extras'] as $extra) {
1184 $extras[$extra['extraId']] = [
1185 'price' => $extra['price'],
1186 'aggregatedPrice' => !!$extra['aggregatedPrice'],
1187 ];
1188 }
1189
1190 /** @var AbstractBookable $bookable */
1191 $bookable = ServiceFactory::create(
1192 [
1193 'price' => $bookingArray['price'],
1194 'aggregatedPrice' => !empty($bookingArray['aggregatedPrice']),
1195 'extras' => $extras,
1196 ]
1197 );
1198
1199 /** @var CustomerBooking $booking */
1200 $booking = CustomerBookingFactory::create(
1201 [
1202 'persons' => $bookingArray['persons'],
1203 'coupon' => !empty($bookingArray['coupon']) ? $bookingArray['coupon'] : null,
1204 'extras' => $bookingArray['extras'],
1205 'tax' => !empty($bookingArray['tax']) ? $bookingArray['tax'] : null,
1206 ]
1207 );
1208
1209 return $reservationService->getPaymentAmount($booking, $bookable, $invoice);
1210 }
1211 }
1212