PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.32
Booking for Appointments and Events Calendar – Amelia v1.2.32
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 / Infrastructure / Repository / Coupon / CouponRepository.php
ameliabooking / src / Infrastructure / Repository / Coupon Last commit date
CouponEventRepository.php 1 year ago CouponPackageRepository.php 1 year ago CouponRepository.php 1 year ago CouponServiceRepository.php 1 year ago
CouponRepository.php
740 lines
1 <?php
2
3 /**
4 * @copyright © TMS-Plugins. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace AmeliaBooking\Infrastructure\Repository\Coupon;
9
10 use AmeliaBooking\Domain\Collection\Collection;
11 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
12 use AmeliaBooking\Domain\Entity\Coupon\Coupon;
13 use AmeliaBooking\Domain\Entity\Entities;
14 use AmeliaBooking\Domain\Factory\Coupon\CouponFactory;
15 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
16 use AmeliaBooking\Domain\ValueObjects\Number\Integer\WholeNumber;
17 use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException;
18 use AmeliaBooking\Infrastructure\Connection;
19 use AmeliaBooking\Infrastructure\Repository\AbstractRepository;
20 use AmeliaBooking\Domain\Repository\Coupon\CouponRepositoryInterface;
21 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
22
23 /**
24 * Class CouponRepository
25 *
26 * @package AmeliaBooking\Infrastructure\Repository\Coupon
27 */
28 class CouponRepository extends AbstractRepository implements CouponRepositoryInterface
29 {
30 public const FACTORY = CouponFactory::class;
31
32 /** @var string */
33 protected $servicesTable;
34
35 /** @var string */
36 protected $couponToServicesTable;
37
38 /** @var string */
39 protected $eventsTable;
40
41 /** @var string */
42 protected $couponToEventsTable;
43
44 /** @var string */
45 protected $packagesTable;
46
47 /** @var string */
48 protected $couponToPackagesTable;
49
50 /** @var string */
51 protected $bookingsTable;
52
53 /**
54 * @param Connection $connection
55 * @param string $table
56 * @param string $servicesTable
57 * @param string $couponToServicesTable
58 * @param string $eventsTable
59 * @param string $couponToEventsTable
60 * @param string $packagesTable
61 * @param string $couponToPackagesTable
62 * @param string $bookingsTable
63 */
64 public function __construct(
65 Connection $connection,
66 $table,
67 $servicesTable,
68 $couponToServicesTable,
69 $eventsTable,
70 $couponToEventsTable,
71 $packagesTable,
72 $couponToPackagesTable,
73 $bookingsTable
74 ) {
75 parent::__construct($connection, $table);
76
77 $this->servicesTable = $servicesTable;
78 $this->couponToServicesTable = $couponToServicesTable;
79 $this->eventsTable = $eventsTable;
80 $this->couponToEventsTable = $couponToEventsTable;
81 $this->packagesTable = $packagesTable;
82 $this->couponToPackagesTable = $couponToPackagesTable;
83 $this->bookingsTable = $bookingsTable;
84 }
85
86 /**
87 * @param Coupon $entity
88 *
89 * @return bool
90 * @throws QueryExecutionException
91 */
92 public function add($entity)
93 {
94 $data = $entity->toArray();
95
96 $params = [
97 ':code' => $data['code'],
98 ':discount' => $data['discount'],
99 ':deduction' => $data['deduction'],
100 ':limit' => (int)$data['limit'],
101 ':customerLimit' => (int)$data['customerLimit'],
102 ':status' => $data['status'],
103 ':notificationInterval' => $data['notificationInterval'],
104 ':notificationRecurring' => $data['notificationRecurring'] ? 1 : 0,
105 ':expirationDate' => $data['expirationDate'],
106 ':allServices' => $data['allServices'],
107 ':allEvents' => $data['allEvents'],
108 ':allPackages' => $data['allPackages']
109 ];
110
111 try {
112 $statement = $this->connection->prepare(
113 "INSERT INTO
114 {$this->table}
115 (
116 `code`,
117 `discount`,
118 `deduction`,
119 `limit`,
120 `customerLimit`,
121 `status`,
122 `notificationInterval`,
123 `notificationRecurring`,
124 `expirationDate`,
125 `allServices`,
126 `allEvents`,
127 `allPackages`
128 ) VALUES (
129 :code,
130 :discount,
131 :deduction,
132 :limit,
133 :customerLimit,
134 :status,
135 :notificationInterval,
136 :notificationRecurring,
137 :expirationDate,
138 :allServices,
139 :allEvents,
140 :allPackages
141 )"
142 );
143
144
145 $response = $statement->execute($params);
146 } catch (\Exception $e) {
147 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
148 }
149
150 if (!$response) {
151 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
152 }
153
154 return $this->connection->lastInsertId();
155 }
156
157 /**
158 * @param int $id
159 * @param Coupon $entity
160 *
161 * @return bool
162 * @throws QueryExecutionException
163 */
164 public function update($id, $entity)
165 {
166 $data = $entity->toArray();
167
168 $params = [
169 ':code' => $data['code'],
170 ':discount' => $data['discount'],
171 ':deduction' => $data['deduction'],
172 ':limit' => (int)$data['limit'],
173 ':customerLimit' => (int)$data['customerLimit'],
174 ':status' => $data['status'],
175 ':notificationInterval' => $data['notificationInterval'],
176 ':notificationRecurring' => $data['notificationRecurring'] ? 1 : 0,
177 ':id' => $id,
178 ':expirationDate' => $data['expirationDate'],
179 ':allServices' => $data['allServices'],
180 ':allEvents' => $data['allEvents'],
181 ':allPackages' => $data['allPackages']
182 ];
183
184 try {
185 $statement = $this->connection->prepare(
186 "UPDATE {$this->table}
187 SET
188 `code` = :code,
189 `discount` = :discount,
190 `deduction` = :deduction,
191 `limit` = :limit,
192 `customerLimit` = :customerLimit,
193 `status` = :status,
194 `notificationInterval` = :notificationInterval,
195 `notificationRecurring` = :notificationRecurring,
196 `expirationDate` = :expirationDate,
197 `allServices` = :allServices,
198 `allEvents` = :allEvents,
199 `allPackages` = :allPackages
200 WHERE
201 id = :id"
202 );
203
204 $response = $statement->execute($params);
205 } catch (\Exception $e) {
206 throw new QueryExecutionException('Unable to save data in ' . __CLASS__ . $e->getMessage());
207 }
208
209 if (!$response) {
210 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
211 }
212
213 return $response;
214 }
215
216 /**
217 * @param int $id
218 *
219 * @return Coupon
220 * @throws QueryExecutionException
221 * @throws NotFoundException
222 */
223 public function getById($id)
224 {
225 try {
226 $statement = $this->connection->prepare(
227 "SELECT
228 c.id AS coupon_id,
229 c.code AS coupon_code,
230 c.discount AS coupon_discount,
231 c.deduction AS coupon_deduction,
232 c.limit AS coupon_limit,
233 c.customerLimit AS coupon_customerLimit,
234 c.notificationInterval AS coupon_notificationInterval,
235 c.notificationRecurring AS coupon_notificationRecurring,
236 c.status AS coupon_status,
237 c.expirationDate AS coupon_expirationDate,
238 c.allServices AS coupon_allServices,
239 c.allEvents AS coupon_allEvents,
240 c.allPackages AS coupon_allPackages,
241 s.id AS service_id,
242 s.price AS service_price,
243 s.minCapacity AS service_minCapacity,
244 s.maxCapacity AS service_maxCapacity,
245 s.name AS service_name,
246 s.description AS service_description,
247 s.color AS service_color,
248 s.status AS service_status,
249 s.categoryId AS service_categoryId,
250 s.duration AS service_duration,
251 e.id AS event_id,
252 e.price AS event_price,
253 e.name AS event_name,
254 p.id AS package_id,
255 p.price AS package_price,
256 p.name AS package_name
257 FROM {$this->table} c
258 LEFT JOIN {$this->couponToServicesTable} cs ON cs.couponId = c.id
259 LEFT JOIN {$this->couponToEventsTable} ce ON ce.couponId = c.id
260 LEFT JOIN {$this->couponToPackagesTable} cp ON cp.couponId = c.id
261 LEFT JOIN {$this->servicesTable} s ON cs.serviceId = s.id
262 LEFT JOIN {$this->eventsTable} e ON ce.eventId = e.id
263 LEFT JOIN {$this->packagesTable} p ON cp.packageId = p.id
264 WHERE c.id = :couponId"
265 );
266
267 $statement->bindParam(':couponId', $id);
268
269 $statement->execute();
270
271 $rows = $statement->fetchAll();
272 } catch (\Exception $e) {
273 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
274 }
275
276 if (!$rows) {
277 throw new NotFoundException('Data not found in ' . __CLASS__);
278 }
279
280 return call_user_func([static::FACTORY, 'createCollection'], $rows)->getItem($id);
281 }
282
283 /**
284 * @param array $criteria
285 * @param int $itemsPerPage
286 *
287 * @return Collection
288 * @throws QueryExecutionException
289 */
290 public function getFiltered($criteria, $itemsPerPage)
291 {
292 try {
293 $params = [];
294
295 $where = [];
296
297 if (!empty($criteria['search'])) {
298 $params[':search'] = "%{$criteria['search']}%";
299
300 $where[] = 'UPPER(c.code) LIKE UPPER(:search)';
301 }
302
303 if (!empty($criteria['ids'])) {
304 $queryIds = [];
305
306 foreach ((array)$criteria['ids'] as $index => $value) {
307 $param = ':id' . $index;
308 $queryIds[] = $param;
309 $params[$param] = $value;
310 }
311
312 $where[] = "c.id IN (" . implode(', ', $queryIds) . ')';
313 }
314
315 if (!empty($criteria['services'])) {
316 $queryServices = [];
317
318 foreach ((array)$criteria['services'] as $index => $value) {
319 $param = ':service' . $index;
320 $queryServices[] = $param;
321 $params[$param] = $value;
322 }
323
324 $where[] = "c.id IN (
325 SELECT couponId FROM {$this->couponToServicesTable}
326 WHERE serviceId IN (" . implode(', ', $queryServices) . ')
327 )';
328 }
329
330 if (!empty($criteria['events'])) {
331 $queryEvents = [];
332
333 foreach ((array)$criteria['events'] as $index => $value) {
334 $param = ':event' . $index;
335 $queryEvents[] = $param;
336 $params[$param] = $value;
337 }
338
339 $where[] = "c.id IN (
340 SELECT couponId FROM {$this->couponToEventsTable}
341 WHERE eventId IN (" . implode(', ', $queryEvents) . ')
342 )';
343 }
344
345 if (!empty($criteria['packages'])) {
346 $queryPackages = [];
347
348 foreach ((array)$criteria['packages'] as $index => $value) {
349 $param = ':package' . $index;
350 $queryPackages[] = $param;
351 $params[$param] = $value;
352 }
353
354 $where[] = "c.id IN (
355 SELECT couponId FROM {$this->couponToPackagesTable}
356 WHERE packageId IN (" . implode(', ', $queryPackages) . ')
357 )';
358 }
359
360
361 $where = $where ? ' WHERE ' . implode(' AND ', $where) : '';
362
363 $limit = $this->getLimit(
364 !empty($criteria['page']) ? (int)$criteria['page'] : 0,
365 (int)$itemsPerPage
366 );
367
368 $statement = $this->connection->prepare(
369 "SELECT
370 c.id AS coupon_id,
371 c.code AS coupon_code,
372 c.discount AS coupon_discount,
373 c.deduction AS coupon_deduction,
374 c.limit AS coupon_limit,
375 c.customerLimit AS coupon_customerLimit,
376 c.notificationInterval AS coupon_notificationInterval,
377 c.notificationRecurring AS coupon_notificationRecurring,
378 c.status AS coupon_status,
379 c.expirationDate AS coupon_expirationDate,
380 c.allServices AS coupon_allServices,
381 c.allEvents AS coupon_allEvents,
382 c.allPackages AS coupon_allPackages
383 FROM {$this->table} c
384 {$where}
385 {$limit}"
386 );
387
388 $statement->execute($params);
389
390 $rows = $statement->fetchAll();
391 } catch (\Exception $e) {
392 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
393 }
394
395 return call_user_func([static::FACTORY, 'createCollection'], $rows);
396 }
397
398 /**
399 * @param array $criteria
400 *
401 * @return mixed
402 * @throws QueryExecutionException
403 */
404 public function getCount($criteria)
405 {
406 try {
407 $params = [];
408
409 $where = [];
410
411 if (!empty($criteria['search'])) {
412 $params[':search'] = "%{$criteria['search']}%";
413
414 $where[] = 'c.code LIKE :search';
415 }
416
417 if (!empty($criteria['services'])) {
418 $queryServices = [];
419
420 foreach ((array)$criteria['services'] as $index => $value) {
421 $param = ':service' . $index;
422 $queryServices[] = $param;
423 $params[$param] = $value;
424 }
425
426 $where[] = "c.id IN (SELECT couponId FROM {$this->couponToServicesTable}
427 WHERE serviceId IN (" . implode(', ', $queryServices) . '))';
428 }
429
430 $where = $where ? ' WHERE ' . implode(' AND ', $where) : '';
431
432 $statement = $this->connection->prepare(
433 "SELECT COUNT(*) AS count
434 FROM {$this->table} c
435 $where"
436 );
437
438 $statement->execute($params);
439
440 $row = $statement->fetch()['count'];
441 } catch (\Exception $e) {
442 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
443 }
444
445 return $row;
446 }
447
448 /**
449 * @param int $id
450 * @param string $status
451 *
452 * @return mixed
453 * @throws QueryExecutionException
454 */
455 public function updateStatusById($id, $status)
456 {
457 $params = [
458 ':id' => $id,
459 ':status' => $status
460 ];
461
462 try {
463 $statement = $this->connection->prepare(
464 "UPDATE {$this->table}
465 SET
466 `status` = :status
467 WHERE id = :id"
468 );
469
470 $res = $statement->execute($params);
471
472 if (!$res) {
473 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
474 }
475
476 return $res;
477 } catch (\Exception $e) {
478 throw new QueryExecutionException('Unable to save data in ' . __CLASS__, $e->getCode(), $e);
479 }
480 }
481
482 /**
483 * @param array $criteria
484 *
485 * @return Collection
486 * @throws QueryExecutionException
487 * @throws InvalidArgumentException
488 * @throws InvalidArgumentException
489 */
490 public function getAllByCriteria($criteria)
491 {
492 try {
493 $params = [];
494
495 $where = [];
496
497 if (isset($criteria['code'])) {
498 $where[] = $criteria['couponsCaseInsensitive'] ? 'LOWER(c.code) = LOWER(:code)' : 'c.code = :code';
499
500 $params[':code'] = $criteria['code'];
501 }
502
503 if (!empty($criteria['notificationInterval'])) {
504 $where[] = 'c.notificationInterval != 0';
505 }
506
507 if (!empty($criteria['notExpired'])) {
508 $currentDateTime = "STR_TO_DATE('" . DateTimeService::getNowDateTimeInUtc() . "', '%Y-%m-%d %H:%i:%s')";
509
510 $where[] = "(c.expirationDate IS NULL OR c.expirationDate >= {$currentDateTime})";
511 }
512
513 if (!empty($criteria['couponIds'])) {
514 $couponIdsParams = [];
515
516 foreach ((array)$criteria['couponIds'] as $key => $id) {
517 $couponIdsParams[":id$key"] = $id;
518 }
519
520 if ($couponIdsParams) {
521 $where[] = '(c.id IN ( ' . implode(', ', array_keys($couponIdsParams)) . '))';
522
523 $params = array_merge($params, $couponIdsParams);
524 }
525 }
526
527 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
528
529 $statement = $this->connection->prepare(
530 "SELECT
531 c.id AS coupon_id,
532 c.code AS coupon_code,
533 c.discount AS coupon_discount,
534 c.deduction AS coupon_deduction,
535 c.limit AS coupon_limit,
536 c.customerLimit AS coupon_customerLimit,
537 c.notificationInterval AS coupon_notificationInterval,
538 c.notificationRecurring AS coupon_notificationRecurring,
539 c.status AS coupon_status,
540 c.expirationDate AS coupon_expirationDate,
541 c.allServices AS coupon_allServices,
542 c.allEvents AS coupon_allEvents,
543 c.allPackages AS coupon_allPackages
544 FROM {$this->table} c
545 {$where}"
546 );
547
548 $statement->execute($params);
549
550 $rows = $statement->fetchAll();
551 } catch (\Exception $e) {
552 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
553 }
554
555 /** @var Collection $coupons */
556 $coupons = call_user_func([static::FACTORY, 'createCollection'], $rows);
557
558 if (!$coupons->length()) {
559 return $coupons;
560 }
561
562 $params = [];
563
564 foreach ($coupons->keys() as $key => $id) {
565 $params[":id$key"] = $id;
566 }
567
568 $where = 'WHERE cb.couponId IN ( ' . implode(', ', array_keys($params)) . ')';
569
570 try {
571 $statement = $this->connection->prepare(
572 "SELECT
573 DISTINCT(cb.couponId) AS couponId,
574 COUNT(*) AS used
575 FROM {$this->bookingsTable} cb
576 {$where}
577 GROUP BY cb.couponId"
578 );
579
580 $statement->execute($params);
581
582 $rows = $statement->fetchAll();
583 } catch (\Exception $e) {
584 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
585 }
586
587 foreach ($rows as $row) {
588 if ($coupons->keyExists($row['couponId'])) {
589 /** @var Coupon $coupon */
590 $coupon = $coupons->getItem($row['couponId']);
591
592 $coupon->setUsed(new WholeNumber($row['used']));
593 }
594 }
595
596 return $coupons;
597 }
598
599 /**
600 * @param array $couponIds
601 * @param array $serviceIds
602 *
603 * @return array
604 *
605 * @throws QueryExecutionException
606 */
607 public function getCouponsServicesIds($couponIds, $serviceIds = [])
608 {
609 $couponsParams = [];
610
611 $servicesParams = [];
612
613 $where = [];
614
615 if ($couponIds) {
616 foreach ($couponIds as $key => $couponId) {
617 $couponsParams[":id$key"] = $couponId;
618 }
619
620 $where[] = '(couponId IN (' . implode(', ', array_keys($couponsParams)) . '))';
621 }
622
623 if ($serviceIds) {
624 foreach ($serviceIds as $key => $serviceId) {
625 $servicesParams[":serviceId$key"] = $serviceId;
626 }
627
628 $where[] = '(serviceId IN (' . implode(', ', array_keys($servicesParams)) . '))';
629 }
630
631 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
632
633 try {
634 $statement = $this->connection->prepare(
635 "SELECT serviceId, couponId FROM {$this->couponToServicesTable} {$where} GROUP BY serviceId, couponId"
636 );
637
638 $statement->execute(array_merge($couponsParams, $servicesParams));
639
640 return $statement->fetchAll();
641 } catch (\Exception $e) {
642 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
643 }
644 }
645
646 /**
647 * @param array $couponIds
648 * @param array $eventIds
649 *
650 * @return array
651 *
652 * @throws QueryExecutionException
653 */
654 public function getCouponsEventsIds($couponIds, $eventIds = [])
655 {
656 $couponsParams = [];
657
658 $eventsParams = [];
659
660 $where = [];
661
662 if ($couponIds) {
663 foreach ($couponIds as $key => $couponId) {
664 $couponsParams[":id$key"] = $couponId;
665 }
666
667 $where[] = '(couponId IN (' . implode(', ', array_keys($couponsParams)) . '))';
668 }
669
670 if ($eventIds) {
671 foreach ($eventIds as $key => $eventId) {
672 $eventsParams[":eventId$key"] = $eventId;
673 }
674
675 $where[] = '(eventId IN (' . implode(', ', array_keys($eventsParams)) . '))';
676 }
677
678 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
679
680 try {
681 $statement = $this->connection->prepare(
682 "SELECT eventId, couponId FROM {$this->couponToEventsTable} {$where} GROUP BY eventId, couponId"
683 );
684
685 $statement->execute(array_merge($couponsParams, $eventsParams));
686
687 return $statement->fetchAll();
688 } catch (\Exception $e) {
689 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
690 }
691 }
692
693 /**
694 * @param array $couponIds
695 * @param array $packageIds
696 *
697 * @return array
698 *
699 * @throws QueryExecutionException
700 */
701 public function getCouponsPackagesIds($couponIds, $packageIds = [])
702 {
703 $couponsParams = [];
704
705 $packagesParams = [];
706
707 $where = [];
708
709 if ($couponIds) {
710 foreach ($couponIds as $key => $couponId) {
711 $couponsParams[":id$key"] = $couponId;
712 }
713
714 $where[] = '(couponId IN (' . implode(', ', array_keys($couponsParams)) . '))';
715 }
716
717 if ($packageIds) {
718 foreach ($packageIds as $key => $packageId) {
719 $packagesParams[":packageId$key"] = $packageId;
720 }
721
722 $where[] = '(packageId IN (' . implode(', ', array_keys($packagesParams)) . '))';
723 }
724
725 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
726
727 try {
728 $statement = $this->connection->prepare(
729 "SELECT packageId, couponId FROM {$this->couponToPackagesTable} {$where} GROUP BY packageId, couponId"
730 );
731
732 $statement->execute(array_merge($couponsParams, $packagesParams));
733
734 return $statement->fetchAll();
735 } catch (\Exception $e) {
736 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
737 }
738 }
739 }
740