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