PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.3
Booking for Appointments and Events Calendar – Amelia v2.3
2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Services / Placeholder / AppointmentPlaceholderService.php
ameliabooking / src / Application / Services / Placeholder Last commit date
AppointmentPlaceholderService.php 2 months ago AppointmentsPlaceholderService.php 5 months ago BasicPackagePlaceholderService.php 6 months ago EventPlaceholderService.php 2 months ago PlaceholderService.php 2 months ago PlaceholderServiceInterface.php 6 months ago
AppointmentPlaceholderService.php
1239 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 if (isset($recurringData['booking']['id'])) {
966 if ($recurringBooking['id'] === $recurringData['booking']['id']) {
967 $recurringBookingKey = $key;
968 }
969 } elseif ($bookingKey !== null && $recurringBooking['customerId'] === $appointment['bookings'][$bookingKey]['customerId']) {
970 $recurringBookingKey = $key;
971 }
972 }
973
974 if ($recurringBookingKey === null) {
975 return [];
976 }
977 } elseif ($bookingKeyForEmployee !== null) {
978 foreach ($recurringData['appointment']['bookings'] as $key => $recurringBooking) {
979 if (isset($recurringData['booking']['id'])) {
980 if ($recurringBooking['id'] === $recurringData['booking']['id']) {
981 $recurringBookingKeyForEmployee = $key;
982 }
983 } else {
984 $recurringBookingKeyForEmployee = $bookingKeyForEmployee;
985 }
986 }
987 }
988
989 $token =
990 $recurringBookingKey !== null &&
991 isset(
992 $recurringData['appointment']['bookings'][$recurringBookingKey],
993 $recurringData['appointment']['bookings'][$recurringBookingKey]['id']
994 ) ? $bookingRepository->getToken($recurringData['appointment']['bookings'][$recurringBookingKey]['id']) : (
995 $recurringBookingKeyForEmployee !== null &&
996 isset(
997 $recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee],
998 $recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee]['id']
999 ) ? $bookingRepository->getToken($recurringData['appointment']['bookings'][$recurringBookingKeyForEmployee]['id']) :
1000 null);
1001
1002 $recurringPlaceholders = [];
1003
1004 $recurringPlaceholders = array_merge(
1005 $recurringPlaceholders,
1006 $this->getEmployeeData($recurringData['appointment'], $recurringBookingKey)
1007 );
1008
1009 $recurringPlaceholders = array_merge(
1010 $recurringPlaceholders,
1011 $this->getAppointmentData($recurringData['appointment'], $recurringBookingKey, $type)
1012 );
1013
1014 $recurringPlaceholders = array_merge(
1015 $recurringPlaceholders,
1016 $this->getServiceData($recurringData['appointment'], $recurringBookingKey, $type)
1017 );
1018
1019 $recurringPlaceholders = array_merge(
1020 $recurringPlaceholders,
1021 $this->getCustomFieldsData($recurringData['appointment'], $type, $recurringBookingKey)
1022 );
1023
1024 $recurringPlaceholders = array_merge(
1025 $recurringPlaceholders,
1026 $this->getBookingData(
1027 $recurringData['appointment'],
1028 $type,
1029 $recurringBookingKey,
1030 isset($token['token']) ? $token['token'] : null,
1031 $recurringPlaceholders['deposit']
1032 )
1033 );
1034
1035 unset($recurringPlaceholders['icsFiles']);
1036
1037 if (!$isForCustomer) {
1038 if (isset($recurringPlaceholders['appointment_cancel_url'])) {
1039 $recurringPlaceholders['appointment_cancel_url'] = '';
1040 }
1041
1042 $recurringPlaceholders['zoom_join_url'] = '';
1043 } else {
1044 $recurringPlaceholders['employee_panel_url'] = '';
1045
1046 $recurringPlaceholders['zoom_host_url'] = '';
1047 }
1048
1049 $placeholderString =
1050 $placeholderType .
1051 'Placeholders' .
1052 ($isForCustomer && $placeholderType === 'package' ? 'Customer' : '') .
1053 ($isForCustomer && $placeholderType === 'recurring' ? 'Customer' : '') .
1054 ($isForCustomer && $placeholderType === 'cart' ? 'Customer' : '') .
1055 ($type === 'email' ? '' : 'Sms');
1056
1057 /** @var HelperService $helperService */
1058 $helperService = $this->container->get('application.helper.service');
1059
1060 $content = $helperService->getBookingTranslation(
1061 $recurringBookingKey !== null ?
1062 $helperService->getLocaleFromBooking($recurringData['appointment']['bookings'][$recurringBookingKey]['info']) :
1063 null,
1064 json_encode($appointmentsSettings['translations']),
1065 $placeholderString
1066 ) ?: $appointmentsSettings[$placeholderString];
1067
1068 if ($type === 'whatsapp') {
1069 $content = str_replace(array("\n","\r"), '; ', $content);
1070 $content = preg_replace('!\s+!', ' ', $content);
1071 }
1072
1073 $recurringAppointmentDetails[] = $placeholderService->applyPlaceholders(
1074 $content,
1075 $recurringPlaceholders
1076 );
1077 }
1078
1079 return [
1080 "{$placeholderType}_appointments_details" => $recurringAppointmentDetails ? implode(
1081 $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL),
1082 $recurringAppointmentDetails
1083 ) : ''
1084 ];
1085 }
1086
1087 /**
1088 * @param array $appointment
1089 * @param int $bookingKey
1090 * @param string $type
1091 *
1092 * @return array
1093 *
1094 * @throws ContainerValueNotFoundException
1095 * @throws NotFoundException
1096 * @throws QueryExecutionException
1097 * @throws ContainerException
1098 * @throws Exception
1099 */
1100 public function getGroupedAppointmentData($appointment, $bookingKey, $type)
1101 {
1102 /** @var PlaceholderService $placeholderService */
1103 $placeholderService = $this->container->get("application.placeholder.appointment.service");
1104
1105 /** @var SettingsService $settingsService */
1106 $settingsService = $this->container->get('domain.settings.service');
1107
1108 $appointmentsSettings = $settingsService->getCategorySettings('appointments');
1109
1110 $groupAppointmentDetails = [];
1111
1112 if ($bookingKey) {
1113 return [
1114 "group_appointment_details" => ''
1115 ];
1116 }
1117
1118 foreach ($appointment['bookings'] as $bookingId => $booking) {
1119 if (
1120 $booking['status'] === BookingStatus::CANCELED ||
1121 $booking['status'] === BookingStatus::REJECTED ||
1122 $booking['status'] === BookingStatus::NO_SHOW
1123 ) {
1124 continue;
1125 }
1126
1127 /** @var CustomerBookingRepository $bookingRepository */
1128 $bookingRepository = $this->container->get('domain.booking.customerBooking.repository');
1129
1130 $token = $bookingRepository->getToken($appointment['bookings'][$bookingId]['id']);
1131
1132 $groupPlaceholders = array_merge(
1133 $this->getAppointmentData($appointment, $bookingId, $type),
1134 $this->getServiceData($appointment, $bookingId, $type),
1135 $this->getCustomFieldsData($appointment, $type, $bookingId),
1136 $this->getCustomersData($appointment, $type, $bookingId),
1137 $this->getBookingData(
1138 $appointment,
1139 $type,
1140 $bookingId,
1141 isset($token['token']) ? $token['token'] : null,
1142 null,
1143 true
1144 )
1145 );
1146
1147 $content = $appointmentsSettings['groupAppointmentPlaceholder' . ($type === null || $type === 'email' ? '' : 'Sms')] ;
1148 if ($type === 'email') {
1149 $content = str_replace(array("\n","\r"), '', $content);
1150 } elseif ($type === 'whatsapp') {
1151 $content = str_replace(array("\n","\r"), '; ', $content);
1152 $content = preg_replace('!\s+!', ' ', $content);
1153 }
1154
1155 $groupAppointmentDetails[] = $placeholderService->applyPlaceholders(
1156 $content,
1157 $groupPlaceholders
1158 );
1159 }
1160
1161 return [
1162 "group_appointment_details" => $groupAppointmentDetails ? implode(
1163 $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL),
1164 $groupAppointmentDetails
1165 ) : ''
1166 ];
1167 }
1168
1169 /**
1170 * @param array $bookingArray
1171 * @param array $entity
1172 *
1173 * @return array
1174 * @throws InvalidArgumentException
1175 * @throws NotFoundException
1176 * @throws QueryExecutionException
1177 */
1178 public function getAmountData(&$bookingArray, $entity, $invoice = false)
1179 {
1180 /** @var ReservationServiceInterface $reservationService */
1181 $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT);
1182
1183 $couponIdToFetch = !empty($bookingArray['couponId'])
1184 ? $bookingArray['couponId']
1185 : (!empty($bookingArray['coupon']['id']) ? $bookingArray['coupon']['id'] : null);
1186
1187 if ($couponIdToFetch) {
1188 $bookingArray['couponId'] = $couponIdToFetch;
1189 }
1190
1191 $couponIsIncomplete = $couponIdToFetch && (
1192 empty($bookingArray['coupon'])
1193 || empty($bookingArray['coupon']['code'])
1194 || !isset($bookingArray['coupon']['discount'])
1195 || !isset($bookingArray['coupon']['deduction'])
1196 );
1197
1198 if ($couponIsIncomplete) {
1199 /** @var CouponRepository $couponRepository */
1200 $couponRepository = $this->container->get('domain.coupon.repository');
1201
1202 /** @var Coupon $coupon */
1203 $coupon = $couponRepository->getById($couponIdToFetch);
1204
1205 $bookingArray['coupon'] = $coupon ? $coupon->toArray() : null;
1206 }
1207
1208 $extras = [];
1209
1210 foreach ($bookingArray['extras'] as $extra) {
1211 $extras[$extra['extraId']] = [
1212 'price' => $extra['price'],
1213 'aggregatedPrice' => !!$extra['aggregatedPrice'],
1214 ];
1215 }
1216
1217 /** @var AbstractBookable $bookable */
1218 $bookable = ServiceFactory::create(
1219 [
1220 'price' => $bookingArray['price'],
1221 'aggregatedPrice' => !empty($bookingArray['aggregatedPrice']),
1222 'extras' => $extras,
1223 ]
1224 );
1225
1226 /** @var CustomerBooking $booking */
1227 $booking = CustomerBookingFactory::create(
1228 [
1229 'persons' => $bookingArray['persons'],
1230 'coupon' => !empty($bookingArray['coupon']) ? $bookingArray['coupon'] : null,
1231 'extras' => $bookingArray['extras'],
1232 'tax' => !empty($bookingArray['tax']) ? $bookingArray['tax'] : null,
1233 ]
1234 );
1235
1236 return $reservationService->getPaymentAmount($booking, $bookable, $invoice);
1237 }
1238 }
1239