PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.31
Booking for Appointments and Events Calendar – Amelia v1.2.31
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Services / Bookable / BookableApplicationService.php
ameliabooking / src / Application / Services / Bookable Last commit date
AbstractPackageApplicationService.php 1 year ago BasicPackageApplicationService.php 1 year ago BookableApplicationService.php 1 year ago
BookableApplicationService.php
1180 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Services\Bookable;
4
5 use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService;
6 use AmeliaBooking\Application\Services\Booking\BookingApplicationService;
7 use AmeliaBooking\Application\Services\Gallery\GalleryApplicationService;
8 use AmeliaBooking\Application\Services\Payment\PaymentApplicationService;
9 use AmeliaBooking\Domain\Collection\Collection;
10 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
11 use AmeliaBooking\Domain\Entity\Bookable\Service\Category;
12 use AmeliaBooking\Domain\Entity\Bookable\Service\Extra;
13 use AmeliaBooking\Domain\Entity\Bookable\Service\Package;
14 use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer;
15 use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService;
16 use AmeliaBooking\Domain\Entity\Bookable\Service\PackageService;
17 use AmeliaBooking\Domain\Entity\Bookable\Service\Service;
18 use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment;
19 use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking;
20 use AmeliaBooking\Domain\Entity\Entities;
21 use AmeliaBooking\Domain\Entity\Location\Location;
22 use AmeliaBooking\Domain\Entity\Payment\Payment;
23 use AmeliaBooking\Domain\Entity\Schedule\Period;
24 use AmeliaBooking\Domain\Entity\Schedule\PeriodService;
25 use AmeliaBooking\Domain\Entity\Schedule\SpecialDay;
26 use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriod;
27 use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodService;
28 use AmeliaBooking\Domain\Entity\Schedule\WeekDay;
29 use AmeliaBooking\Domain\Entity\User\Provider;
30 use AmeliaBooking\Domain\Factory\Bookable\Service\PackageServiceFactory;
31 use AmeliaBooking\Domain\Factory\Location\LocationFactory;
32 use AmeliaBooking\Domain\Factory\User\UserFactory;
33 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
34 use AmeliaBooking\Domain\Services\User\ProviderService;
35 use AmeliaBooking\Domain\ValueObjects\BooleanValueObject;
36 use AmeliaBooking\Domain\ValueObjects\Duration;
37 use AmeliaBooking\Domain\ValueObjects\Json;
38 use AmeliaBooking\Domain\ValueObjects\Number\Float\Price;
39 use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id;
40 use AmeliaBooking\Domain\ValueObjects\Number\Integer\PositiveInteger;
41 use AmeliaBooking\Domain\ValueObjects\Number\Integer\WholeNumber;
42 use AmeliaBooking\Infrastructure\Common\Container;
43 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
44 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
45 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository;
46 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ExtraRepository;
47 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository;
48 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository;
49 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageRepository;
50 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceLocationRepository;
51 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceProviderRepository;
52 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceRepository;
53 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ProviderServiceRepository;
54 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceEntitiesRepository;
55 use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository;
56 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository;
57 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository;
58 use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository;
59 use AmeliaBooking\Infrastructure\Repository\Coupon\CouponServiceRepository;
60 use AmeliaBooking\Infrastructure\Repository\Coupon\CouponPackageRepository;
61 use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldServiceRepository;
62 use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository;
63 use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository;
64 use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodServiceRepository;
65 use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodServiceRepository;
66 use AmeliaBooking\Infrastructure\Repository\Tax\TaxEntityRepository;
67 use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository;
68 use Interop\Container\Exception\ContainerException;
69 use Slim\Exception\ContainerValueNotFoundException;
70
71 /**
72 * Class BookableApplicationService
73 *
74 * @package AmeliaBooking\Application\Services\Booking
75 */
76 class BookableApplicationService
77 {
78 private $container;
79
80 /**
81 * BookableApplicationService constructor.
82 *
83 * @param Container $container
84 */
85 public function __construct(Container $container)
86 {
87 $this->container = $container;
88 }
89
90 /**
91 * @param int $serviceId
92 * @param int $providerId
93 *
94 * @return Service
95 *
96 * @throws ContainerValueNotFoundException
97 * @throws QueryExecutionException
98 * @throws InvalidArgumentException
99 * @throws NotFoundException
100 */
101 public function getAppointmentService($serviceId, $providerId)
102 {
103 /** @var ServiceRepository $serviceRepository */
104 $serviceRepository = $this->container->get('domain.bookable.service.repository');
105
106 /** @var Collection $providerServices */
107 $providerServices = $serviceRepository->getProviderServicesWithExtras($serviceId, $providerId);
108
109 return $providerServices->keyExists($serviceId) ?
110 $providerServices->getItem($serviceId) : $serviceRepository->getByIdWithExtras($serviceId);
111 }
112
113 /**
114 * @param Collection $categories
115 * @param Collection $services
116 *
117 * @throws InvalidArgumentException
118 */
119 public function addServicesToCategories($categories, $services)
120 {
121 /** @var Category $category */
122 foreach ($categories->getItems() as $category) {
123 $category->setServiceList(new Collection());
124 }
125
126 /** @var Service $service */
127 foreach ($services->getItems() as $service) {
128 $categoryId = $service->getCategoryId()->getValue();
129
130 $categories
131 ->getItem($categoryId)
132 ->getServiceList()
133 ->addItem($service, $service->getId()->getValue());
134 }
135 }
136
137 /**
138 * @param Service $service
139 * @param Collection $providers
140 *
141 * @throws ContainerValueNotFoundException
142 * @throws QueryExecutionException
143 */
144 public function manageProvidersForServiceAdd($service, $providers)
145 {
146 /** @var ProviderServiceRepository $providerServiceRepo */
147 $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository');
148
149 /** @var Provider $provider */
150 foreach ($providers->getItems() as $provider) {
151 $providerServiceRepo->add($service, $provider->getId()->getValue());
152 }
153 }
154
155 /**
156 * @param Package $package
157 *
158 * @throws ContainerValueNotFoundException
159 * @throws QueryExecutionException
160 */
161 public function manageServicesForPackageAdd($package)
162 {
163 /** @var PackageServiceRepository $packageServiceRepository */
164 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
165 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
166 $packageServiceLocationRepository =
167 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
168 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
169 $packageServiceProviderRepository =
170 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
171
172 /** @var PackageService $bookable */
173 foreach ($package->getBookable()->getItems() as $bookable) {
174 $bookableId = $packageServiceRepository->add($bookable, $package->getId()->getValue());
175
176 $bookable->setId(new Id($bookableId));
177
178 /** @var Location $location */
179 foreach ($bookable->getLocations()->getItems() as $location) {
180 $packageServiceLocationRepository->add($location, $bookable->getId()->getValue());
181 }
182
183 /** @var Provider $provider */
184 foreach ($bookable->getProviders()->getItems() as $provider) {
185 $packageServiceProviderRepository->add($provider, $bookable->getId()->getValue());
186 }
187 }
188 }
189
190 /**
191 * @param Package $package
192 * @param array $bookableServices
193 *
194 * @throws ContainerValueNotFoundException
195 * @throws QueryExecutionException
196 * @throws InvalidArgumentException
197 */
198 public function manageServicesForPackageUpdate($package, $bookableServices)
199 {
200 /** @var PackageRepository $packageRepository */
201 $packageRepository = $this->container->get('domain.bookable.package.repository');
202 /** @var PackageServiceRepository $packageServiceRepository */
203 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
204 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
205 $packageServiceLocationRepository =
206 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
207 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
208 $packageServiceProviderRepository =
209 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
210 /** @var ServiceRepository $serviceRepository */
211 $serviceRepository = $this->container->get('domain.bookable.service.repository');
212
213 /** @var Collection $services */
214 $services = $serviceRepository->getByCriteria(['services' => array_keys($bookableServices)]);
215
216 /** @var Package $oldPackage */
217 $oldPackage = $packageRepository->getById($package->getId()->getValue());
218
219 $oldPackageServicesIds = [];
220
221 /** @var PackageService $oldPackageService */
222 foreach ($oldPackage->getBookable()->getItems() as $oldPackageService) {
223 $serviceId = $oldPackageService->getService()->getId()->getValue();
224
225 $oldPackageServicesIds[$serviceId] = [
226 'providersIds' => [],
227 'locationsIds' => [],
228 ];
229
230 /** @var Location $location */
231 foreach ($oldPackageService->getLocations()->getItems() as $location) {
232 $oldPackageServicesIds[$serviceId]['locationsIds'][] = $location->getId()->getValue();
233 }
234
235 /** @var Provider $provider */
236 foreach ($oldPackageService->getProviders()->getItems() as $provider) {
237 $oldPackageServicesIds[$serviceId]['providersIds'][] = $provider->getId()->getValue();
238 }
239 }
240
241 foreach ($bookableServices as $serviceId => $data) {
242 if (!in_array($serviceId, array_keys($oldPackageServicesIds), false)) {
243 $packageService = PackageServiceFactory::create(
244 [
245 'service' => $services->getItem($serviceId)->toArray(),
246 'quantity' => $data['quantity'],
247 'minimumScheduled' => $data['minimumScheduled'],
248 'maximumScheduled' => $data['maximumScheduled'],
249 'allowProviderSelection' => $data['allowProviderSelection'],
250 'providers' => $data['providers'],
251 'locations' => $data['locations'],
252 'position' => $data['position'],
253 ]
254 );
255
256 $packageServiceId = $packageServiceRepository->add($packageService, $package->getId()->getValue());
257
258 $packageService->setId(new Id($packageServiceId));
259
260 /** @var Location $location */
261 foreach ($packageService->getLocations()->getItems() as $location) {
262 $packageServiceLocationRepository->add($location, $packageService->getId()->getValue());
263 }
264
265 /** @var Provider $provider */
266 foreach ($packageService->getProviders()->getItems() as $provider) {
267 $packageServiceProviderRepository->add($provider, $packageService->getId()->getValue());
268 }
269 }
270 }
271
272 /** @var PackageService $oldPackageService */
273 foreach ($oldPackage->getBookable()->getItems() as $oldPackageService) {
274 $serviceId = $oldPackageService->getService()->getId()->getValue();
275
276 if (in_array($serviceId, array_keys($bookableServices), false)) {
277 $oldPackageService->setQuantity(new PositiveInteger($bookableServices[$serviceId]['quantity']));
278
279 $oldPackageService->setMinimumScheduled(
280 new WholeNumber($bookableServices[$serviceId]['minimumScheduled'])
281 );
282
283 $oldPackageService->setMaximumScheduled(
284 new WholeNumber($bookableServices[$serviceId]['maximumScheduled'])
285 );
286
287 $oldPackageService->setAllowProviderSelection(
288 new BooleanValueObject($bookableServices[$serviceId]['allowProviderSelection'])
289 );
290
291 $oldPackageService->setPosition(
292 new PositiveInteger($bookableServices[$serviceId]['position'])
293 );
294
295 $packageServiceRepository->update($oldPackageService->getId()->getValue(), $oldPackageService);
296
297 foreach ($bookableServices[$serviceId]['locations'] as $data) {
298 if (!in_array($data['id'], $oldPackageServicesIds[$serviceId]['locationsIds'], false)) {
299 $packageServiceLocationRepository->add(
300 LocationFactory::create($data),
301 $oldPackageService->getId()->getValue()
302 );
303 }
304 }
305
306 $packageServiceLocationRepository->deleteAllNotInLocationsServicesArrayForPackage(
307 array_column($bookableServices[$serviceId]['locations'], 'id'),
308 $oldPackageService->getId()->getValue()
309 );
310
311 foreach ($bookableServices[$serviceId]['providers'] as $data) {
312 if (!in_array($data['id'], $oldPackageServicesIds[$serviceId]['providersIds'], false)) {
313 $packageServiceProviderRepository->add(
314 UserFactory::create($data),
315 $oldPackageService->getId()->getValue()
316 );
317 }
318 }
319
320 $packageServiceProviderRepository->deleteAllNotInProvidersServicesArrayForPackage(
321 array_column($bookableServices[$serviceId]['providers'], 'id'),
322 $oldPackageService->getId()->getValue()
323 );
324 } else {
325 $packageServiceLocationRepository->deleteAllNotInLocationsServicesArrayForPackage(
326 $oldPackageServicesIds[$serviceId]['locationsIds'],
327 $oldPackageService->getId()->getValue()
328 );
329
330 $packageServiceProviderRepository->deleteAllNotInProvidersServicesArrayForPackage(
331 $oldPackageServicesIds[$serviceId]['providersIds'],
332 $oldPackageService->getId()->getValue()
333 );
334 }
335 }
336
337 $packageServiceRepository->deleteAllNotInServicesArrayForPackage(
338 array_keys($bookableServices),
339 $package->getId()->getValue()
340 );
341 }
342
343 /**
344 * @param Service $service
345 * @param array $serviceProvidersIds
346 * @param bool $updateCustomPricing
347 *
348 * @throws ContainerValueNotFoundException
349 * @throws QueryExecutionException
350 * @throws InvalidArgumentException
351 */
352 public function manageProvidersForServiceUpdate($service, $serviceProvidersIds, $updateCustomPricing)
353 {
354 /** @var ProviderRepository $providerRepo */
355 $providerRepo = $this->container->get('domain.users.providers.repository');
356 /** @var ProviderServiceRepository $providerServiceRepo */
357 $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository');
358 /** @var PeriodServiceRepository $periodServiceRepo */
359 $periodServiceRepo = $this->container->get('domain.schedule.period.service.repository');
360 /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepo */
361 $specialDayPeriodServiceRepo = $this->container->get('domain.schedule.specialDay.period.service.repository');
362
363 /** @var ServiceRepository $serviceRepository */
364 $serviceRepository = $this->container->get('domain.bookable.service.repository');
365 /** @var ProviderService $providerDomainService */
366 $providerDomainService = $this->container->get('domain.user.provider.service');
367
368 /** @var Collection $services */
369 $services = $serviceRepository->getAllArrayIndexedById();
370
371 /** @var Collection $providers */
372 $providers = $providerRepo->getWithSchedule([]);
373
374 /** @var Collection $serviceProviders */
375 $serviceProviders = new Collection();
376
377 /** @var Provider $provider */
378 foreach ($providers->getItems() as $provider) {
379 /** @var Service $providerService */
380 foreach ($provider->getServiceList()->getItems() as $providerService) {
381 if ($providerService->getId()->getValue() === $service->getId()->getValue()) {
382 $providerDomainService->setProviderServices($provider, $services, true);
383
384 $serviceProviders->addItem($provider, $provider->getId()->getValue());
385
386 break;
387 }
388 }
389 }
390
391 $serviceId = $service->getId()->getValue();
392
393 /** @var Provider $provider */
394 foreach ($serviceProviders->getItems() as $provider) {
395 $isServiceProvider = in_array($provider->getId()->getValue(), $serviceProvidersIds, false);
396
397 if (!$isServiceProvider) {
398 /** @var WeekDay $weekDay */
399 foreach ($provider->getWeekDayList()->getItems() as $weekDay) {
400 /** @var Period $period */
401 foreach ($weekDay->getPeriodList()->getItems() as $period) {
402 /** @var PeriodService $periodService */
403 foreach ($period->getPeriodServiceList()->getItems() as $periodService) {
404 if ($periodService->getServiceId()->getValue() === $serviceId) {
405 $periodServiceRepo->delete($periodService->getId()->getValue());
406 }
407 }
408 }
409 }
410
411 /** @var SpecialDay $specialDay */
412 foreach ($provider->getSpecialDayList()->getItems() as $specialDay) {
413 /** @var SpecialDayPeriod $period */
414 foreach ($specialDay->getPeriodList()->getItems() as $period) {
415 /** @var SpecialDayPeriodService $periodService */
416 foreach ($period->getPeriodServiceList()->getItems() as $periodService) {
417 if ($periodService->getServiceId()->getValue() === $serviceId) {
418 $specialDayPeriodServiceRepo->delete($periodService->getId()->getValue());
419 }
420 }
421 }
422 }
423 }
424
425 if ($updateCustomPricing && $isServiceProvider) {
426 if ($provider->getServiceList()->keyExists($serviceId)) {
427 /** @var Service $providerService */
428 $providerService = $provider->getServiceList()->getItem($serviceId);
429
430 $updateProviderService = false;
431
432 if (
433 (!$providerService->getCustomPricing() && $service->getCustomPricing()) ||
434 ($providerService->getCustomPricing() && !$service->getCustomPricing())
435 ) {
436 $updateProviderService = true;
437
438 $providerService->setCustomPricing($service->getCustomPricing());
439 } elseif ($service->getCustomPricing() && $providerService->getCustomPricing()) {
440 $serviceCustomPricing = json_decode($service->getCustomPricing()->getValue(), true);
441
442 if (empty($serviceCustomPricing['persons'])) {
443 $serviceCustomPricing['persons'] = [];
444 }
445
446 $providerCustomPricing = json_decode($providerService->getCustomPricing()->getValue(), true);
447
448 if (empty($providerCustomPricing['persons'])) {
449 $providerCustomPricing['persons'] = [];
450 }
451
452 foreach ($serviceCustomPricing['durations'] as $duration => $durationData) {
453 if (array_key_exists($duration, $providerCustomPricing['durations'])) {
454 $serviceCustomPricing['durations'][$duration] =
455 $providerCustomPricing['durations'][$duration];
456 } else {
457 $updateProviderService = true;
458 }
459 }
460
461 foreach ($serviceCustomPricing['persons'] as $range => $rangeData) {
462 if (array_key_exists($range, $providerCustomPricing['persons'])) {
463 $serviceCustomPricing['persons'][$range] =
464 $providerCustomPricing['persons'][$range];
465 } else {
466 $updateProviderService = true;
467 }
468 }
469
470 if ($serviceCustomPricing['enabled'] !== $providerCustomPricing['enabled']) {
471 $updateProviderService = true;
472 }
473
474 $providerService->setCustomPricing(new Json(json_encode($serviceCustomPricing)));
475
476 if (!$updateProviderService) {
477 foreach ($providerCustomPricing['durations'] as $duration => $durationData) {
478 if (!array_key_exists($duration, $serviceCustomPricing['durations'])) {
479 $updateProviderService = true;
480 }
481 }
482
483 foreach ($providerCustomPricing['persons'] as $range => $rangeData) {
484 if (!array_key_exists($range, $serviceCustomPricing['persons'])) {
485 $updateProviderService = true;
486 }
487 }
488 }
489 }
490
491 if ($updateProviderService) {
492 $providerServiceRepo->updateServiceForProvider(
493 $providerService,
494 $providerService->getId()->getValue(),
495 $provider->getId()->getValue()
496 );
497 }
498 }
499 }
500 }
501
502 $providerServiceRepo->deleteAllNotInProvidersArrayForService($serviceProvidersIds, $serviceId);
503
504 foreach ($serviceProvidersIds as $providerId) {
505 if (!in_array($providerId, $serviceProviders->keys(), false)) {
506 $providerServiceRepo->add($service, (int)$providerId);
507 }
508 }
509
510 $providerServiceRepo->deleteDuplicated(
511 $service->getId()->getValue(),
512 Entities::SERVICE
513 );
514 }
515
516 /**
517 * @param Service $service
518 *
519 * @throws ContainerValueNotFoundException
520 * @throws QueryExecutionException
521 * @throws InvalidArgumentException
522 */
523 public function managePackagesForServiceUpdate($service)
524 {
525 /** @var PackageRepository $packageRepository */
526 $packageRepository = $this->container->get('domain.bookable.package.repository');
527
528 /** @var Collection $packages */
529 $packages = $packageRepository->getByCriteria([]);
530
531 /** @var Package $package */
532 foreach ($packages->getItems() as $package) {
533 $hasService = false;
534
535 /** @var PackageService $bookable */
536 foreach ($package->getBookable()->getItems() as $bookable) {
537 if ($bookable->getService()->getId()->getValue() === $service->getId()->getValue()) {
538 $hasService = true;
539
540 break;
541 }
542 }
543
544 if ($hasService && $package->getCalculatedPrice()->getValue()) {
545 $price = 0;
546
547 /** @var PackageService $bookable */
548 foreach ($package->getBookable()->getItems() as $bookable) {
549 $price += $bookable->getService()->getPrice()->getValue() * $bookable->getQuantity()->getValue();
550 }
551
552 $package->setPrice(new Price($price));
553
554 $packageRepository->update($package->getId()->getValue(), $package);
555 }
556 }
557 }
558
559 /**
560 * Accept two collection: services and providers
561 * For each service function will add providers that are working on this service
562 *
563 * @param Service $service
564 * @param Collection $providers
565 *
566 * @return Collection
567 *
568 * @throws InvalidArgumentException
569 */
570 public function getServiceProviders($service, $providers)
571 {
572 $serviceProviders = new Collection();
573
574 /** @var Provider $provider */
575 foreach ($providers->getItems() as $provider) {
576 /** @var Service $providerService */
577 foreach ($provider->getServiceList()->getItems() as $providerService) {
578 if ($providerService->getId()->getValue() === $service->getId()->getValue()) {
579 $serviceProviders->addItem($provider, $provider->getId()->getValue());
580 }
581 }
582 }
583
584 return $serviceProviders;
585 }
586
587 /**
588 * Add 0 as duration for service time before or time after if it is null
589 *
590 * @param Service $service
591 *
592 * @throws InvalidArgumentException
593 */
594 public function checkServiceTimes($service)
595 {
596 if (!$service->getTimeBefore()) {
597 $service->setTimeBefore(new Duration(0));
598 }
599
600 if (!$service->getTimeAfter()) {
601 $service->setTimeAfter(new Duration(0));
602 }
603 }
604
605 /**
606 * Return collection of extras that are passed in $extraIds array for provided service
607 *
608 * @param array $extraIds
609 * @param Service $service
610 *
611 * @return Collection
612 * @throws InvalidArgumentException
613 */
614 public function filterServiceExtras($extraIds, $service)
615 {
616 $extras = new Collection();
617
618 foreach ((array)$service->getExtras()->keys() as $extraKey) {
619 /** @var Extra $extra */
620 $extra = $service->getExtras()->getItem($extraKey);
621
622 if (in_array($extra->getId()->getValue(), $extraIds, false)) {
623 if (!$extra->getDuration()) {
624 $extra->setDuration(new Duration(0));
625 }
626
627 $extras->addItem($extra, $extraKey);
628 }
629 }
630
631 return $extras;
632 }
633
634 /**
635 *
636 * @param array $servicesIds
637 *
638 * @return array
639 *
640 * @throws ContainerValueNotFoundException
641 * @throws QueryExecutionException
642 * @throws InvalidArgumentException
643 */
644 public function getAppointmentsCountForServices($servicesIds)
645 {
646 /** @var AppointmentRepository $appointmentRepository */
647 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
648
649 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
650 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
651
652 $futureAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount(
653 [
654 'services' => $servicesIds,
655 'dates' => [
656 0 => DateTimeService::getNowDateTime()
657 ]
658 ]
659 );
660
661 $pastAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount(
662 [
663 'services' => $servicesIds,
664 'dates' => [
665 1 => DateTimeService::getNowDateTime()
666 ]
667 ]
668 );
669
670 if ($futureAppointmentsCount) {
671 return [
672 'futureAppointments' => $futureAppointmentsCount,
673 'pastAppointments' => $pastAppointmentsCount,
674 ];
675 }
676
677 /** @var Collection $appointments */
678 $appointments = $appointmentRepository->getFiltered(['services' => $servicesIds]);
679
680 /** @var Collection $packageCustomerServices */
681 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['services' => $servicesIds]);
682
683 /** @var AbstractPackageApplicationService $packageApplicationService */
684 $packageApplicationService = $this->container->get('application.bookable.package');
685
686 return [
687 'futureAppointments' => $futureAppointmentsCount,
688 'pastAppointments' => $pastAppointmentsCount,
689 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount(
690 $packageCustomerServices,
691 $appointments
692 ),
693 ];
694 }
695
696 /**
697 *
698 * @param array $packagesIds
699 *
700 * @return array
701 *
702 * @throws ContainerValueNotFoundException
703 * @throws QueryExecutionException
704 * @throws InvalidArgumentException
705 */
706 public function getAppointmentsCountForPackages($packagesIds)
707 {
708 /** @var AppointmentRepository $appointmentRepository */
709 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
710
711 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
712 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
713
714 /** @var Collection $packageCustomerServices */
715 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['packages' => $packagesIds]);
716
717 /** @var Collection $appointments */
718 $appointments = $packageCustomerServices->keys() ? $appointmentRepository->getFiltered(
719 ['packageCustomerServices' => $packageCustomerServices->keys()]
720 ) : new Collection();
721
722 $now = DateTimeService::getNowDateTimeObject();
723
724 $futureAppointments = 0;
725
726 $pastAppointments = 0;
727
728 /** @var Appointment $appointment */
729 foreach ($appointments->getItems() as $appointment) {
730 if ($appointment->getBookingStart()->getValue() >= $now) {
731 $futureAppointments++;
732 } else {
733 $pastAppointments++;
734 }
735 }
736
737 /** @var AbstractPackageApplicationService $packageApplicationService */
738 $packageApplicationService = $this->container->get('application.bookable.package');
739
740 return [
741 'futureAppointments' => $futureAppointments,
742 'pastAppointments' => $pastAppointments,
743 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount(
744 $packageCustomerServices,
745 $appointments
746 ),
747 ];
748 }
749
750 /**
751 *
752 * @param Category $category
753 *
754 * @return boolean
755 *
756 * @throws ContainerValueNotFoundException
757 * @throws QueryExecutionException
758 * @throws ContainerException
759 * @throws InvalidArgumentException
760 */
761 public function deleteCategory($category)
762 {
763 /** @var CategoryRepository $categoryRepository */
764 $categoryRepository = $this->container->get('domain.bookable.category.repository');
765
766 /** @var Service $service */
767 foreach ($category->getServiceList()->getItems() as $service) {
768 if (!$this->deleteService($service)) {
769 return false;
770 }
771 }
772
773 return $categoryRepository->delete($category->getId()->getValue());
774 }
775
776 /**
777 *
778 * @param Service $service
779 *
780 * @return boolean
781 *
782 * @throws ContainerValueNotFoundException
783 * @throws QueryExecutionException
784 * @throws ContainerException
785 * @throws InvalidArgumentException
786 */
787 public function deleteService($service)
788 {
789 /** @var GalleryApplicationService $galleryService */
790 $galleryService = $this->container->get('application.gallery.service');
791
792 /** @var AppointmentRepository $appointmentRepository */
793 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
794
795 /** @var ServiceRepository $serviceRepository */
796 $serviceRepository = $this->container->get('domain.bookable.service.repository');
797
798 /** @var TaxEntityRepository $taxEntityRepository */
799 $taxEntityRepository = $this->container->get('domain.tax.entity.repository');
800
801 /** @var CouponServiceRepository $couponServiceRepository */
802 $couponServiceRepository = $this->container->get('domain.coupon.service.repository');
803
804 /** @var ProviderServiceRepository $providerServiceRepository */
805 $providerServiceRepository = $this->container->get('domain.bookable.service.providerService.repository');
806
807 /** @var PeriodServiceRepository $periodServiceRepository */
808 $periodServiceRepository = $this->container->get('domain.schedule.period.service.repository');
809
810 /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepository */
811 $specialDayPeriodServiceRepository =
812 $this->container->get('domain.schedule.specialDay.period.service.repository');
813
814 /** @var CustomFieldServiceRepository $customFieldServiceRepository */
815 $customFieldServiceRepository = $this->container->get('domain.customFieldService.repository');
816
817 /** @var AppointmentApplicationService $appointmentApplicationService */
818 $appointmentApplicationService = $this->container->get('application.booking.appointment.service');
819
820 /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */
821 $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository');
822
823 /** @var PackageServiceRepository $packageServiceRepository */
824 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
825
826 /** @var ResourceEntitiesRepository $resourceEntitiesRepository */
827 $resourceEntitiesRepository = $this->container->get('domain.bookable.resourceEntities.repository');
828
829 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
830 $packageCustomerServiceRepository =
831 $this->container->get('domain.bookable.packageCustomerService.repository');
832
833 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
834 $packageServiceProviderRepository =
835 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
836
837 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
838 $packageServiceLocationRepository =
839 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
840
841 /** @var PackageRepository $packageRepository */
842 $packageRepository = $this->container->get('domain.bookable.package.repository');
843
844 /** @var Collection $packages */
845 $packages = $packageRepository->getByCriteria(['services' => [$service->getId()->getValue()]]);
846
847 /** @var Collection $appointments */
848 $appointments = $appointmentRepository->getFiltered(
849 [
850 'services' => [$service->getId()->getValue()]
851 ]
852 );
853
854 /** @var Appointment $appointment */
855 foreach ($appointments->getItems() as $appointment) {
856 if (!$appointmentApplicationService->delete($appointment)) {
857 return false;
858 }
859 }
860
861 if (!$notificationEntitiesRepo->removeIfOnly($service->getId()->getValue())) {
862 return false;
863 }
864
865 /** @var Extra $extra */
866 foreach ($service->getExtras()->getItems() as $extra) {
867 if (!$this->deleteExtra($extra)) {
868 return false;
869 }
870 }
871
872 /** @var Package $package */
873 foreach ($packages->getItems() as $package) {
874 /** @var PackageService $packageService */
875 foreach ($package->getBookable()->getItems() as $packageService) {
876 if ($packageService->getService()->getId()->getValue() === $service->getId()->getValue()) {
877 if (
878 !$packageServiceProviderRepository->deleteByEntityId(
879 $packageService->getId()->getValue(),
880 'packageServiceId'
881 ) ||
882 !$packageServiceLocationRepository->deleteByEntityId(
883 $packageService->getId()->getValue(),
884 'packageServiceId'
885 )
886 ) {
887 return false;
888 }
889 }
890 }
891 }
892
893 return
894 $galleryService->manageGalleryForEntityDelete($service->getGallery()) &&
895 $customFieldServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
896 $specialDayPeriodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
897 $periodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
898 $providerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
899 $taxEntityRepository->deleteByEntityIdAndEntityType($service->getId()->getValue(), 'service') &&
900 $couponServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
901 $serviceRepository->deleteViewStats($service->getId()->getValue()) &&
902 $packageServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
903 $packageCustomerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
904 $resourceEntitiesRepository->deleteByEntityIdAndEntityType($service->getId()->getValue(), 'service') &&
905 $serviceRepository->delete($service->getId()->getValue());
906 }
907
908 /**
909 *
910 * @param Package $package
911 *
912 * @return boolean
913 *
914 * @throws ContainerValueNotFoundException
915 * @throws QueryExecutionException
916 * @throws ContainerException
917 * @throws InvalidArgumentException
918 */
919 public function deletePackage($package)
920 {
921 /** @var GalleryApplicationService $galleryService */
922 $galleryService = $this->container->get('application.gallery.service');
923
924 /** @var CustomerBookingRepository $customerBookingRepository */
925 $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository');
926
927 /** @var PaymentRepository $paymentRepository */
928 $paymentRepository = $this->container->get('domain.payment.repository');
929
930 /** @var PackageRepository $packageRepository */
931 $packageRepository = $this->container->get('domain.bookable.package.repository');
932
933 /** @var PackageServiceRepository $packageServiceRepository */
934 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
935
936 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
937 $packageServiceLocationRepository =
938 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
939
940 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
941 $packageServiceProviderRepository =
942 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
943
944 /** @var PackageCustomerRepository $packageCustomerRepository */
945 $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository');
946
947 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
948 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
949
950 /** @var PaymentApplicationService $paymentAS */
951 $paymentAS = $this->container->get('application.payment.service');
952
953 /** @var TaxEntityRepository $taxEntityRepository */
954 $taxEntityRepository = $this->container->get('domain.tax.entity.repository');
955
956 /** @var CouponPackageRepository $couponPackageRepository */
957 $couponPackageRepository = $this->container->get('domain.coupon.package.repository');
958
959 /** @var Collection $packageCustomerServices */
960 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(
961 ['packages' => [$package->getId()->getValue()]]
962 );
963
964 /** @var PackageCustomerService $packageCustomerService */
965 foreach ($packageCustomerServices->getItems() as $packageCustomerService) {
966 if (
967 !$customerBookingRepository->updateByEntityId(
968 $packageCustomerService->getId()->getValue(),
969 null,
970 'packageCustomerServiceId'
971 )
972 ) {
973 return false;
974 }
975 }
976
977 /** @var Collection $packageCustomers */
978 $packageCustomers = $packageCustomerRepository->getByEntityId($package->getId()->getValue(), 'packageId');
979
980 /** @var PackageCustomer $packageCustomer */
981 foreach ($packageCustomers->getItems() as $packageCustomer) {
982 /** @var Collection $payments */
983 $payments = $paymentRepository->getByEntityId(
984 $packageCustomer->getId()->getValue(),
985 'packageCustomerId'
986 );
987
988 /** @var Payment $payment */
989 foreach ($payments->getItems() as $payment) {
990 if (!$paymentAS->delete($payment)) {
991 return false;
992 }
993 }
994
995 if (
996 !$packageCustomerServiceRepository->deleteByEntityId(
997 $packageCustomer->getId()->getValue(),
998 'packageCustomerId'
999 ) ||
1000 !$packageCustomerRepository->delete($packageCustomer->getId()->getValue())
1001 ) {
1002 return false;
1003 }
1004 }
1005
1006 /** @var PackageService $packageService */
1007 foreach ($package->getBookable()->getItems() as $packageService) {
1008 $packageServiceId = $packageService->getId()->getValue();
1009
1010 if (
1011 !$packageServiceLocationRepository->deleteByEntityId($packageServiceId, 'packageServiceId') ||
1012 !$packageServiceProviderRepository->deleteByEntityId($packageServiceId, 'packageServiceId')
1013 ) {
1014 return false;
1015 }
1016 }
1017
1018 return
1019 $galleryService->manageGalleryForEntityDelete($package->getGallery()) &&
1020 $packageServiceRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') &&
1021 $taxEntityRepository->deleteByEntityIdAndEntityType($package->getId()->getValue(), 'package') &&
1022 $couponPackageRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') &&
1023 $packageRepository->delete($package->getId()->getValue());
1024 }
1025
1026 /**
1027 *
1028 * @param PackageCustomer $packageCustomer
1029 *
1030 * @return array|bool
1031 *
1032 * @throws ContainerException
1033 * @throws InvalidArgumentException
1034 * @throws NotFoundException
1035 * @throws QueryExecutionException
1036 */
1037 public function deletePackageCustomer($packageCustomer)
1038 {
1039 /** @var AppointmentApplicationService $appointmentApplicationService */
1040 $appointmentApplicationService = $this->container->get('application.booking.appointment.service');
1041
1042 /** @var BookingApplicationService $bookingApplicationService */
1043 $bookingApplicationService = $this->container->get('application.booking.booking.service');
1044
1045 /** @var PaymentRepository $paymentRepository */
1046 $paymentRepository = $this->container->get('domain.payment.repository');
1047
1048 /** @var PackageCustomerRepository $packageCustomerRepository */
1049 $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository');
1050
1051 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
1052 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
1053
1054 /** @var AppointmentRepository $appointmentRepository */
1055 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
1056
1057 /** @var PaymentApplicationService $paymentApplicationService */
1058 $paymentApplicationService = $this->container->get('application.payment.service');
1059
1060
1061 $resultData = [
1062 'updatedAppointments' => [],
1063 'deletedAppointments' => [],
1064 ];
1065
1066 /** @var Collection $packageCustomerServices */
1067 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(
1068 ['packagesCustomers' => [$packageCustomer->getId()->getValue()]]
1069 );
1070
1071 /** @var Collection $packageAppointments */
1072 $packageAppointments = $packageCustomerServices->length() ? $appointmentRepository->getFiltered(
1073 [
1074 'packageCustomerServices' => $packageCustomerServices->keys()
1075 ]
1076 ) : new Collection();
1077
1078 if ($packageAppointments->length()) {
1079 /** @var Collection $appointments */
1080 $appointments = $appointmentRepository->getFiltered(['ids' => $packageAppointments->keys()]);
1081
1082 /** @var Appointment $appointment */
1083 foreach ($appointments->getItems() as $appointment) {
1084 if ($appointment->getBookings()->length() === 1) {
1085 if (!$appointmentApplicationService->delete($appointment)) {
1086 return false;
1087 }
1088
1089 $resultData['deletedAppointments'][] =
1090 $appointmentApplicationService->removeBookingFromNonGroupAppointment(
1091 $appointment,
1092 $appointment->getBookings()->getItem($appointment->getBookings()->keys()[0])
1093 );
1094 } else {
1095 $removedBooking = null;
1096
1097 /** @var CustomerBooking $customerBooking */
1098 foreach ($appointment->getBookings()->getItems() as $customerBooking) {
1099 if (
1100 $customerBooking->getPackageCustomerService() &&
1101 in_array(
1102 $customerBooking->getPackageCustomerService()->getId()->getValue(),
1103 $packageCustomerServices->keys()
1104 )
1105 ) {
1106 if (!$bookingApplicationService->delete($customerBooking)) {
1107 return false;
1108 }
1109
1110 $removedBooking = $customerBooking;
1111 }
1112 }
1113
1114 if ($removedBooking) {
1115 $result = $appointmentApplicationService->removeBookingFromGroupAppointment(
1116 $appointment,
1117 $removedBooking
1118 );
1119
1120 foreach ($result['bookingsWithChangedStatus'] as &$booking) {
1121 if ($booking['id'] === $removedBooking->getId()->getValue()) {
1122 $booking['skipNotification'] = true;
1123 }
1124 }
1125
1126 $resultData['updatedAppointments'][] = $result;
1127 }
1128 }
1129 }
1130 }
1131
1132 /** @var Collection $payments */
1133 $payments = $paymentRepository->getByEntityId(
1134 $packageCustomer->getId()->getValue(),
1135 'packageCustomerId'
1136 );
1137
1138 /** @var Payment $payment */
1139 foreach ($payments->getItems() as $payment) {
1140 if (!$paymentApplicationService->delete($payment)) {
1141 return false;
1142 }
1143 }
1144
1145 if (
1146 !$packageCustomerServiceRepository->deleteByEntityId(
1147 $packageCustomer->getId()->getValue(),
1148 'packageCustomerId'
1149 ) ||
1150 !$packageCustomerRepository->delete($packageCustomer->getId()->getValue())
1151 ) {
1152 return false;
1153 }
1154
1155 return $resultData;
1156 }
1157
1158 /**
1159 *
1160 * @param Extra $extra
1161 *
1162 * @return boolean
1163 *
1164 * @throws ContainerValueNotFoundException
1165 * @throws QueryExecutionException
1166 */
1167 public function deleteExtra($extra)
1168 {
1169 /** @var ExtraRepository $extraRepository */
1170 $extraRepository = $this->container->get('domain.bookable.extra.repository');
1171
1172 /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */
1173 $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository');
1174
1175 return
1176 $customerBookingExtraRepository->deleteByEntityId($extra->getId()->getValue(), 'extraId') &&
1177 $extraRepository->delete($extra->getId()->getValue());
1178 }
1179 }
1180