PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / trunk
Booking for Appointments and Events Calendar – Amelia vtrunk
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 month ago BasicPackageApplicationService.php 1 month ago BookableApplicationService.php 10 months ago
BookableApplicationService.php
1202 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 $updateProviderService = true;
441
442 $serviceCustomPricing = json_decode($service->getCustomPricing()->getValue(), true);
443
444 if (empty($serviceCustomPricing['persons'])) {
445 $serviceCustomPricing['persons'] = [];
446 }
447
448 if (empty($serviceCustomPricing['periods'])) {
449 $serviceCustomPricing['periods'] = ['default' => [], 'custom' => []];
450 }
451
452 $providerCustomPricing = json_decode($providerService->getCustomPricing()->getValue(), true);
453
454 if (empty($providerCustomPricing['persons'])) {
455 $providerCustomPricing['persons'] = [];
456 }
457
458 if (empty($providerCustomPricing['periods'])) {
459 $providerCustomPricing['periods'] = ['default' => [], 'custom' => []];
460 }
461
462 foreach ($serviceCustomPricing['durations'] as $duration => $durationData) {
463 if (array_key_exists($duration, $providerCustomPricing['durations'])) {
464 $serviceCustomPricing['durations'][$duration] =
465 $providerCustomPricing['durations'][$duration];
466 }
467 }
468
469 foreach ($serviceCustomPricing['persons'] as $range => $rangeData) {
470 if (array_key_exists($range, $providerCustomPricing['persons'])) {
471 $serviceCustomPricing['persons'][$range] =
472 $providerCustomPricing['persons'][$range];
473 }
474 }
475
476 foreach ($serviceCustomPricing['periods']['default'] as $indexService => &$dayData) {
477 foreach ($dayData['ranges'] as &$serviceRange) {
478 foreach ($providerCustomPricing['periods']['default'] as $indexProvider => $providerData) {
479 if ($indexService === $indexProvider) {
480 foreach ($providerData['ranges'] as $providerRange) {
481 if ($providerRange['from'] === $serviceRange['from'] &&
482 $providerRange['to'] === $serviceRange['to']
483 ) {
484 $serviceRange['price'] = $providerRange['price'];
485 }
486 }
487 }
488 }
489 }
490 }
491
492 foreach ($serviceCustomPricing['periods']['custom'] as &$dayData) {
493 foreach ($dayData['ranges'] as &$serviceRange) {
494 foreach ($providerCustomPricing['periods']['custom'] as $providerData) {
495 if ($dayData['dates']['start'] === $providerData['dates']['start'] &&
496 $dayData['dates']['end'] === $providerData['dates']['end']
497 ) {
498 foreach ($providerData['ranges'] as $providerRange) {
499 if ($providerRange['from'] === $serviceRange['from'] &&
500 $providerRange['to'] === $serviceRange['to']
501 ) {
502 $serviceRange['price'] = $providerRange['price'];
503 }
504 }
505 }
506 }
507 }
508 }
509
510 $providerService->setCustomPricing(new Json(json_encode($serviceCustomPricing)));
511 }
512
513 if ($updateProviderService) {
514 $providerServiceRepo->updateServiceForProvider(
515 $providerService,
516 $providerService->getId()->getValue(),
517 $provider->getId()->getValue()
518 );
519 }
520 }
521 }
522 }
523
524 $providerServiceRepo->deleteAllNotInProvidersArrayForService($serviceProvidersIds, $serviceId);
525
526 foreach ($serviceProvidersIds as $providerId) {
527 if (!in_array($providerId, $serviceProviders->keys(), false)) {
528 $providerServiceRepo->add($service, (int)$providerId);
529 }
530 }
531
532 $providerServiceRepo->deleteDuplicated(
533 $service->getId()->getValue(),
534 Entities::SERVICE
535 );
536 }
537
538 /**
539 * @param Service $service
540 *
541 * @throws ContainerValueNotFoundException
542 * @throws QueryExecutionException
543 * @throws InvalidArgumentException
544 */
545 public function managePackagesForServiceUpdate($service)
546 {
547 /** @var PackageRepository $packageRepository */
548 $packageRepository = $this->container->get('domain.bookable.package.repository');
549
550 /** @var Collection $packages */
551 $packages = $packageRepository->getByCriteria([]);
552
553 /** @var Package $package */
554 foreach ($packages->getItems() as $package) {
555 $hasService = false;
556
557 /** @var PackageService $bookable */
558 foreach ($package->getBookable()->getItems() as $bookable) {
559 if ($bookable->getService()->getId()->getValue() === $service->getId()->getValue()) {
560 $hasService = true;
561
562 break;
563 }
564 }
565
566 if ($hasService && $package->getCalculatedPrice()->getValue()) {
567 $price = 0;
568
569 /** @var PackageService $bookable */
570 foreach ($package->getBookable()->getItems() as $bookable) {
571 $price += $bookable->getService()->getPrice()->getValue() * $bookable->getQuantity()->getValue();
572 }
573
574 $package->setPrice(new Price($price));
575
576 $packageRepository->update($package->getId()->getValue(), $package);
577 }
578 }
579 }
580
581 /**
582 * Accept two collection: services and providers
583 * For each service function will add providers that are working on this service
584 *
585 * @param Service $service
586 * @param Collection $providers
587 *
588 * @return Collection
589 *
590 * @throws InvalidArgumentException
591 */
592 public function getServiceProviders($service, $providers)
593 {
594 $serviceProviders = new Collection();
595
596 /** @var Provider $provider */
597 foreach ($providers->getItems() as $provider) {
598 /** @var Service $providerService */
599 foreach ($provider->getServiceList()->getItems() as $providerService) {
600 if ($providerService->getId()->getValue() === $service->getId()->getValue()) {
601 $serviceProviders->addItem($provider, $provider->getId()->getValue());
602 }
603 }
604 }
605
606 return $serviceProviders;
607 }
608
609 /**
610 * Add 0 as duration for service time before or time after if it is null
611 *
612 * @param Service $service
613 *
614 * @throws InvalidArgumentException
615 */
616 public function checkServiceTimes($service)
617 {
618 if (!$service->getTimeBefore()) {
619 $service->setTimeBefore(new Duration(0));
620 }
621
622 if (!$service->getTimeAfter()) {
623 $service->setTimeAfter(new Duration(0));
624 }
625 }
626
627 /**
628 * Return collection of extras that are passed in $extraIds array for provided service
629 *
630 * @param array $extraIds
631 * @param Service $service
632 *
633 * @return Collection
634 * @throws InvalidArgumentException
635 */
636 public function filterServiceExtras($extraIds, $service)
637 {
638 $extras = new Collection();
639
640 foreach ((array)$service->getExtras()->keys() as $extraKey) {
641 /** @var Extra $extra */
642 $extra = $service->getExtras()->getItem($extraKey);
643
644 if (in_array($extra->getId()->getValue(), $extraIds, false)) {
645 if (!$extra->getDuration()) {
646 $extra->setDuration(new Duration(0));
647 }
648
649 $extras->addItem($extra, $extraKey);
650 }
651 }
652
653 return $extras;
654 }
655
656 /**
657 *
658 * @param array $servicesIds
659 *
660 * @return array
661 *
662 * @throws ContainerValueNotFoundException
663 * @throws QueryExecutionException
664 * @throws InvalidArgumentException
665 */
666 public function getAppointmentsCountForServices($servicesIds)
667 {
668 /** @var AppointmentRepository $appointmentRepository */
669 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
670
671 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
672 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
673
674 $futureAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount(
675 [
676 'services' => $servicesIds,
677 'dates' => [
678 0 => DateTimeService::getNowDateTime()
679 ]
680 ]
681 );
682
683 $pastAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount(
684 [
685 'services' => $servicesIds,
686 'dates' => [
687 1 => DateTimeService::getNowDateTime()
688 ]
689 ]
690 );
691
692 if ($futureAppointmentsCount) {
693 return [
694 'futureAppointments' => $futureAppointmentsCount,
695 'pastAppointments' => $pastAppointmentsCount,
696 ];
697 }
698
699 /** @var Collection $appointments */
700 $appointments = $appointmentRepository->getFiltered(['services' => $servicesIds]);
701
702 /** @var Collection $packageCustomerServices */
703 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['services' => $servicesIds]);
704
705 /** @var AbstractPackageApplicationService $packageApplicationService */
706 $packageApplicationService = $this->container->get('application.bookable.package');
707
708 return [
709 'futureAppointments' => $futureAppointmentsCount,
710 'pastAppointments' => $pastAppointmentsCount,
711 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount(
712 $packageCustomerServices,
713 $appointments
714 ),
715 ];
716 }
717
718 /**
719 *
720 * @param array $packagesIds
721 *
722 * @return array
723 *
724 * @throws ContainerValueNotFoundException
725 * @throws QueryExecutionException
726 * @throws InvalidArgumentException
727 */
728 public function getAppointmentsCountForPackages($packagesIds)
729 {
730 /** @var AppointmentRepository $appointmentRepository */
731 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
732
733 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
734 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
735
736 /** @var Collection $packageCustomerServices */
737 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['packages' => $packagesIds]);
738
739 /** @var Collection $appointments */
740 $appointments = $packageCustomerServices->keys() ? $appointmentRepository->getFiltered(
741 ['packageCustomerServices' => $packageCustomerServices->keys()]
742 ) : new Collection();
743
744 $now = DateTimeService::getNowDateTimeObject();
745
746 $futureAppointments = 0;
747
748 $pastAppointments = 0;
749
750 /** @var Appointment $appointment */
751 foreach ($appointments->getItems() as $appointment) {
752 if ($appointment->getBookingStart()->getValue() >= $now) {
753 $futureAppointments++;
754 } else {
755 $pastAppointments++;
756 }
757 }
758
759 /** @var AbstractPackageApplicationService $packageApplicationService */
760 $packageApplicationService = $this->container->get('application.bookable.package');
761
762 return [
763 'futureAppointments' => $futureAppointments,
764 'pastAppointments' => $pastAppointments,
765 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount(
766 $packageCustomerServices,
767 $appointments
768 ),
769 ];
770 }
771
772 /**
773 *
774 * @param Category $category
775 *
776 * @return boolean
777 *
778 * @throws ContainerValueNotFoundException
779 * @throws QueryExecutionException
780 * @throws ContainerException
781 * @throws InvalidArgumentException
782 */
783 public function deleteCategory($category)
784 {
785 /** @var CategoryRepository $categoryRepository */
786 $categoryRepository = $this->container->get('domain.bookable.category.repository');
787
788 /** @var Service $service */
789 foreach ($category->getServiceList()->getItems() as $service) {
790 if (!$this->deleteService($service)) {
791 return false;
792 }
793 }
794
795 return $categoryRepository->delete($category->getId()->getValue());
796 }
797
798 /**
799 *
800 * @param Service $service
801 *
802 * @return boolean
803 *
804 * @throws ContainerValueNotFoundException
805 * @throws QueryExecutionException
806 * @throws ContainerException
807 * @throws InvalidArgumentException
808 */
809 public function deleteService($service)
810 {
811 /** @var GalleryApplicationService $galleryService */
812 $galleryService = $this->container->get('application.gallery.service');
813
814 /** @var AppointmentRepository $appointmentRepository */
815 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
816
817 /** @var ServiceRepository $serviceRepository */
818 $serviceRepository = $this->container->get('domain.bookable.service.repository');
819
820 /** @var TaxEntityRepository $taxEntityRepository */
821 $taxEntityRepository = $this->container->get('domain.tax.entity.repository');
822
823 /** @var CouponServiceRepository $couponServiceRepository */
824 $couponServiceRepository = $this->container->get('domain.coupon.service.repository');
825
826 /** @var ProviderServiceRepository $providerServiceRepository */
827 $providerServiceRepository = $this->container->get('domain.bookable.service.providerService.repository');
828
829 /** @var PeriodServiceRepository $periodServiceRepository */
830 $periodServiceRepository = $this->container->get('domain.schedule.period.service.repository');
831
832 /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepository */
833 $specialDayPeriodServiceRepository =
834 $this->container->get('domain.schedule.specialDay.period.service.repository');
835
836 /** @var CustomFieldServiceRepository $customFieldServiceRepository */
837 $customFieldServiceRepository = $this->container->get('domain.customFieldService.repository');
838
839 /** @var AppointmentApplicationService $appointmentApplicationService */
840 $appointmentApplicationService = $this->container->get('application.booking.appointment.service');
841
842 /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */
843 $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository');
844
845 /** @var PackageServiceRepository $packageServiceRepository */
846 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
847
848 /** @var ResourceEntitiesRepository $resourceEntitiesRepository */
849 $resourceEntitiesRepository = $this->container->get('domain.bookable.resourceEntities.repository');
850
851 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
852 $packageCustomerServiceRepository =
853 $this->container->get('domain.bookable.packageCustomerService.repository');
854
855 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
856 $packageServiceProviderRepository =
857 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
858
859 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
860 $packageServiceLocationRepository =
861 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
862
863 /** @var PackageRepository $packageRepository */
864 $packageRepository = $this->container->get('domain.bookable.package.repository');
865
866 /** @var Collection $packages */
867 $packages = $packageRepository->getByCriteria(['services' => [$service->getId()->getValue()]]);
868
869 /** @var Collection $appointments */
870 $appointments = $appointmentRepository->getFiltered(
871 [
872 'services' => [$service->getId()->getValue()]
873 ]
874 );
875
876 /** @var Appointment $appointment */
877 foreach ($appointments->getItems() as $appointment) {
878 if (!$appointmentApplicationService->delete($appointment)) {
879 return false;
880 }
881 }
882
883 if (!$notificationEntitiesRepo->removeIfOnly($service->getId()->getValue())) {
884 return false;
885 }
886
887 /** @var Extra $extra */
888 foreach ($service->getExtras()->getItems() as $extra) {
889 if (!$this->deleteExtra($extra)) {
890 return false;
891 }
892 }
893
894 /** @var Package $package */
895 foreach ($packages->getItems() as $package) {
896 /** @var PackageService $packageService */
897 foreach ($package->getBookable()->getItems() as $packageService) {
898 if ($packageService->getService()->getId()->getValue() === $service->getId()->getValue()) {
899 if (
900 !$packageServiceProviderRepository->deleteByEntityId(
901 $packageService->getId()->getValue(),
902 'packageServiceId'
903 ) ||
904 !$packageServiceLocationRepository->deleteByEntityId(
905 $packageService->getId()->getValue(),
906 'packageServiceId'
907 )
908 ) {
909 return false;
910 }
911 }
912 }
913 }
914
915 return
916 $galleryService->manageGalleryForEntityDelete($service->getGallery()) &&
917 $customFieldServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
918 $specialDayPeriodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
919 $periodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
920 $providerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
921 $taxEntityRepository->deleteByEntityIdAndEntityType($service->getId()->getValue(), 'service') &&
922 $couponServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
923 $serviceRepository->deleteViewStats($service->getId()->getValue()) &&
924 $packageServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
925 $packageCustomerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') &&
926 $resourceEntitiesRepository->deleteByEntityIdAndEntityType($service->getId()->getValue(), 'service') &&
927 $serviceRepository->delete($service->getId()->getValue());
928 }
929
930 /**
931 *
932 * @param Package $package
933 *
934 * @return boolean
935 *
936 * @throws ContainerValueNotFoundException
937 * @throws QueryExecutionException
938 * @throws ContainerException
939 * @throws InvalidArgumentException
940 */
941 public function deletePackage($package)
942 {
943 /** @var GalleryApplicationService $galleryService */
944 $galleryService = $this->container->get('application.gallery.service');
945
946 /** @var CustomerBookingRepository $customerBookingRepository */
947 $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository');
948
949 /** @var PaymentRepository $paymentRepository */
950 $paymentRepository = $this->container->get('domain.payment.repository');
951
952 /** @var PackageRepository $packageRepository */
953 $packageRepository = $this->container->get('domain.bookable.package.repository');
954
955 /** @var PackageServiceRepository $packageServiceRepository */
956 $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository');
957
958 /** @var PackageServiceLocationRepository $packageServiceLocationRepository */
959 $packageServiceLocationRepository =
960 $this->container->get('domain.bookable.package.packageServiceLocation.repository');
961
962 /** @var PackageServiceProviderRepository $packageServiceProviderRepository */
963 $packageServiceProviderRepository =
964 $this->container->get('domain.bookable.package.packageServiceProvider.repository');
965
966 /** @var PackageCustomerRepository $packageCustomerRepository */
967 $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository');
968
969 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
970 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
971
972 /** @var PaymentApplicationService $paymentAS */
973 $paymentAS = $this->container->get('application.payment.service');
974
975 /** @var TaxEntityRepository $taxEntityRepository */
976 $taxEntityRepository = $this->container->get('domain.tax.entity.repository');
977
978 /** @var CouponPackageRepository $couponPackageRepository */
979 $couponPackageRepository = $this->container->get('domain.coupon.package.repository');
980
981 /** @var Collection $packageCustomerServices */
982 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(
983 ['packages' => [$package->getId()->getValue()]]
984 );
985
986 /** @var PackageCustomerService $packageCustomerService */
987 foreach ($packageCustomerServices->getItems() as $packageCustomerService) {
988 if (
989 !$customerBookingRepository->updateByEntityId(
990 $packageCustomerService->getId()->getValue(),
991 null,
992 'packageCustomerServiceId'
993 )
994 ) {
995 return false;
996 }
997 }
998
999 /** @var Collection $packageCustomers */
1000 $packageCustomers = $packageCustomerRepository->getByEntityId($package->getId()->getValue(), 'packageId');
1001
1002 /** @var PackageCustomer $packageCustomer */
1003 foreach ($packageCustomers->getItems() as $packageCustomer) {
1004 /** @var Collection $payments */
1005 $payments = $paymentRepository->getByEntityId(
1006 $packageCustomer->getId()->getValue(),
1007 'packageCustomerId'
1008 );
1009
1010 /** @var Payment $payment */
1011 foreach ($payments->getItems() as $payment) {
1012 if (!$paymentAS->delete($payment)) {
1013 return false;
1014 }
1015 }
1016
1017 if (
1018 !$packageCustomerServiceRepository->deleteByEntityId(
1019 $packageCustomer->getId()->getValue(),
1020 'packageCustomerId'
1021 ) ||
1022 !$packageCustomerRepository->delete($packageCustomer->getId()->getValue())
1023 ) {
1024 return false;
1025 }
1026 }
1027
1028 /** @var PackageService $packageService */
1029 foreach ($package->getBookable()->getItems() as $packageService) {
1030 $packageServiceId = $packageService->getId()->getValue();
1031
1032 if (
1033 !$packageServiceLocationRepository->deleteByEntityId($packageServiceId, 'packageServiceId') ||
1034 !$packageServiceProviderRepository->deleteByEntityId($packageServiceId, 'packageServiceId')
1035 ) {
1036 return false;
1037 }
1038 }
1039
1040 return
1041 $galleryService->manageGalleryForEntityDelete($package->getGallery()) &&
1042 $packageServiceRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') &&
1043 $taxEntityRepository->deleteByEntityIdAndEntityType($package->getId()->getValue(), 'package') &&
1044 $couponPackageRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') &&
1045 $packageRepository->delete($package->getId()->getValue());
1046 }
1047
1048 /**
1049 *
1050 * @param PackageCustomer $packageCustomer
1051 *
1052 * @return array|bool
1053 *
1054 * @throws ContainerException
1055 * @throws InvalidArgumentException
1056 * @throws NotFoundException
1057 * @throws QueryExecutionException
1058 */
1059 public function deletePackageCustomer($packageCustomer)
1060 {
1061 /** @var AppointmentApplicationService $appointmentApplicationService */
1062 $appointmentApplicationService = $this->container->get('application.booking.appointment.service');
1063
1064 /** @var BookingApplicationService $bookingApplicationService */
1065 $bookingApplicationService = $this->container->get('application.booking.booking.service');
1066
1067 /** @var PaymentRepository $paymentRepository */
1068 $paymentRepository = $this->container->get('domain.payment.repository');
1069
1070 /** @var PackageCustomerRepository $packageCustomerRepository */
1071 $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository');
1072
1073 /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */
1074 $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository');
1075
1076 /** @var AppointmentRepository $appointmentRepository */
1077 $appointmentRepository = $this->container->get('domain.booking.appointment.repository');
1078
1079 /** @var PaymentApplicationService $paymentApplicationService */
1080 $paymentApplicationService = $this->container->get('application.payment.service');
1081
1082
1083 $resultData = [
1084 'updatedAppointments' => [],
1085 'deletedAppointments' => [],
1086 ];
1087
1088 /** @var Collection $packageCustomerServices */
1089 $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(
1090 ['packagesCustomers' => [$packageCustomer->getId()->getValue()]]
1091 );
1092
1093 /** @var Collection $packageAppointments */
1094 $packageAppointments = $packageCustomerServices->length() ? $appointmentRepository->getFiltered(
1095 [
1096 'packageCustomerServices' => $packageCustomerServices->keys()
1097 ]
1098 ) : new Collection();
1099
1100 if ($packageAppointments->length()) {
1101 /** @var Collection $appointments */
1102 $appointments = $appointmentRepository->getFiltered(['ids' => $packageAppointments->keys()]);
1103
1104 /** @var Appointment $appointment */
1105 foreach ($appointments->getItems() as $appointment) {
1106 if ($appointment->getBookings()->length() === 1) {
1107 if (!$appointmentApplicationService->delete($appointment)) {
1108 return false;
1109 }
1110
1111 $resultData['deletedAppointments'][] =
1112 $appointmentApplicationService->removeBookingFromNonGroupAppointment(
1113 $appointment,
1114 $appointment->getBookings()->getItem($appointment->getBookings()->keys()[0])
1115 );
1116 } else {
1117 $removedBooking = null;
1118
1119 /** @var CustomerBooking $customerBooking */
1120 foreach ($appointment->getBookings()->getItems() as $customerBooking) {
1121 if (
1122 $customerBooking->getPackageCustomerService() &&
1123 in_array(
1124 $customerBooking->getPackageCustomerService()->getId()->getValue(),
1125 $packageCustomerServices->keys()
1126 )
1127 ) {
1128 if (!$bookingApplicationService->delete($customerBooking)) {
1129 return false;
1130 }
1131
1132 $removedBooking = $customerBooking;
1133 }
1134 }
1135
1136 if ($removedBooking) {
1137 $result = $appointmentApplicationService->removeBookingFromGroupAppointment(
1138 $appointment,
1139 $removedBooking
1140 );
1141
1142 foreach ($result['bookingsWithChangedStatus'] as &$booking) {
1143 if ($booking['id'] === $removedBooking->getId()->getValue()) {
1144 $booking['skipNotification'] = true;
1145 }
1146 }
1147
1148 $resultData['updatedAppointments'][] = $result;
1149 }
1150 }
1151 }
1152 }
1153
1154 /** @var Collection $payments */
1155 $payments = $paymentRepository->getByEntityId(
1156 $packageCustomer->getId()->getValue(),
1157 'packageCustomerId'
1158 );
1159
1160 /** @var Payment $payment */
1161 foreach ($payments->getItems() as $payment) {
1162 if (!$paymentApplicationService->delete($payment)) {
1163 return false;
1164 }
1165 }
1166
1167 if (
1168 !$packageCustomerServiceRepository->deleteByEntityId(
1169 $packageCustomer->getId()->getValue(),
1170 'packageCustomerId'
1171 ) ||
1172 !$packageCustomerRepository->delete($packageCustomer->getId()->getValue())
1173 ) {
1174 return false;
1175 }
1176
1177 return $resultData;
1178 }
1179
1180 /**
1181 *
1182 * @param Extra $extra
1183 *
1184 * @return boolean
1185 *
1186 * @throws ContainerValueNotFoundException
1187 * @throws QueryExecutionException
1188 */
1189 public function deleteExtra($extra)
1190 {
1191 /** @var ExtraRepository $extraRepository */
1192 $extraRepository = $this->container->get('domain.bookable.extra.repository');
1193
1194 /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */
1195 $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository');
1196
1197 return
1198 $customerBookingExtraRepository->deleteByEntityId($extra->getId()->getValue(), 'extraId') &&
1199 $extraRepository->delete($extra->getId()->getValue());
1200 }
1201 }
1202