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