PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.0.1
Booking for Appointments and Events Calendar – Amelia v2.0.1
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 / Infrastructure / Repository / Payment / PaymentRepository.php
ameliabooking / src / Infrastructure / Repository / Payment Last commit date
PaymentRepository.php 8 months ago
PaymentRepository.php
1547 lines
1 <?php
2
3 /**
4 * @copyright © Melograno Ventures. All rights reserved.
5 * @licence See LICENCE.md for license details.
6 */
7
8 namespace AmeliaBooking\Infrastructure\Repository\Payment;
9
10 use AmeliaBooking\Domain\Collection\Collection;
11 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
12 use AmeliaBooking\Domain\Entity\Payment\Payment;
13 use AmeliaBooking\Domain\Factory\Payment\PaymentFactory;
14 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
15 use AmeliaBooking\Infrastructure\Repository\AbstractRepository;
16 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
17 use AmeliaBooking\Infrastructure\Connection;
18 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Bookable\PackagesCustomersServicesTable;
19 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Booking\CustomerBookingsToExtrasTable;
20 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Coupon\CouponsTable;
21 use AmeliaBooking\Infrastructure\WP\InstallActions\DB\Location\LocationsTable;
22
23 /**
24 * Class PaymentRepository
25 *
26 * @package AmeliaBooking\Infrastructure\Repository\Payment
27 */
28 class PaymentRepository extends AbstractRepository
29 {
30 /** @var string */
31 protected $appointmentsTable;
32
33 /** @var string */
34 protected $bookingsTable;
35
36 /** @var string */
37 protected $servicesTable;
38
39 /** @var string */
40 protected $usersTable;
41
42 /** @var string */
43 protected $eventsTable;
44
45 /** @var string */
46 protected $eventsProvidersTable;
47
48 /** @var string */
49 protected $eventsPeriodsTable;
50
51 /** @var string */
52 protected $customerBookingsToEventsPeriodsTable;
53
54 /** @var string */
55 protected $packagesTable;
56
57 /** @var string */
58 protected $packagesCustomersTable;
59
60 /** @var string */
61 protected $packagesCustomersServiceTable;
62
63
64 /**
65 * @param Connection $connection
66 * @param string $table
67 * @param string $appointmentsTable
68 * @param string $bookingsTable
69 * @param string $servicesTable
70 * @param string $usersTable
71 * @param string $eventsTable
72 * @param string $eventsProvidersTable
73 * @param string $eventsPeriodsTable
74 * @param string $customerBookingsToEventsPeriodsTable
75 * @param string $packagesTable
76 * @param string $packagesCustomersTable
77 */
78 public function __construct(
79 Connection $connection,
80 $table,
81 $appointmentsTable,
82 $bookingsTable,
83 $servicesTable,
84 $usersTable,
85 $eventsTable,
86 $eventsProvidersTable,
87 $eventsPeriodsTable,
88 $customerBookingsToEventsPeriodsTable,
89 $packagesTable,
90 $packagesCustomersTable
91 ) {
92 parent::__construct($connection, $table);
93
94 $this->appointmentsTable = $appointmentsTable;
95 $this->bookingsTable = $bookingsTable;
96 $this->servicesTable = $servicesTable;
97 $this->usersTable = $usersTable;
98 $this->eventsTable = $eventsTable;
99 $this->eventsProvidersTable = $eventsProvidersTable;
100 $this->eventsPeriodsTable = $eventsPeriodsTable;
101 $this->customerBookingsToEventsPeriodsTable = $customerBookingsToEventsPeriodsTable;
102 $this->packagesTable = $packagesTable;
103 $this->packagesCustomersTable = $packagesCustomersTable;
104 $this->packagesCustomersServiceTable = PackagesCustomersServicesTable::getTableName();
105 }
106
107 public const FACTORY = PaymentFactory::class;
108
109 /**
110 * @param Payment $entity
111 *
112 * @return int
113 * @throws QueryExecutionException
114 */
115 public function add($entity)
116 {
117 $data = $entity->toArray();
118
119 $params = [
120 ':customerBookingId' => $data['customerBookingId'] ? $data['customerBookingId'] : null,
121 ':packageCustomerId' => $data['packageCustomerId'] ? $data['packageCustomerId'] : null,
122 ':parentId' => $data['parentId'] ? $data['parentId'] : null,
123 ':amount' => $data['amount'],
124 ':dateTime' => DateTimeService::getCustomDateTimeInUtc($data['dateTime']),
125 ':status' => $data['status'],
126 ':gateway' => $data['gateway'],
127 ':gatewayTitle' => $data['gatewayTitle'],
128 ':data' => $data['data'],
129 ':entity' => $data['entity'],
130 ':created' => DateTimeService::getNowDateTimeInUtc(),
131 ':wcOrderId' => !empty($data['wcOrderId']) ? $data['wcOrderId'] : null,
132 ':transactionId' => !empty($data['transactionId']) ? $data['transactionId'] : null,
133 ':wcOrderItemId' => !empty($data['wcOrderItemId']) ? $data['wcOrderItemId'] : null,
134 ];
135
136 if (!empty($data['invoiceNumber'])) {
137 $params[':invoiceNumber'] = $data['invoiceNumber'];
138
139 $invoiceNumberText = ":invoiceNumber";
140 } else {
141 $invoiceNumberText = "(SELECT COALESCE(MAX(invoiceNumber), 0) + 1 FROM {$this->table} p)";
142 }
143
144 if ($data['parentId']) {
145 $params[':actionsCompleted'] = null;
146 } else {
147 $params[':actionsCompleted'] = !empty($data['actionsCompleted']) ? 1 : 0;
148 }
149
150 try {
151 $statement = $this->connection->prepare(
152 "INSERT INTO
153 {$this->table}
154 (
155 `customerBookingId`,
156 `packageCustomerId`,
157 `parentId`,
158 `amount`,
159 `dateTime`,
160 `status`,
161 `gateway`,
162 `gatewayTitle`,
163 `data`, `entity`,
164 `actionsCompleted`,
165 `created`,
166 `wcOrderId`,
167 `wcOrderItemId`,
168 `transactionId`,
169 `invoiceNumber`
170 ) VALUES (
171 :customerBookingId,
172 :packageCustomerId,
173 :parentId,
174 :amount,
175 :dateTime,
176 :status,
177 :gateway,
178 :gatewayTitle,
179 :data,
180 :entity,
181 :actionsCompleted,
182 :created,
183 :wcOrderId,
184 :wcOrderItemId,
185 :transactionId,
186 {$invoiceNumberText}
187 )"
188 );
189
190 $response = $statement->execute($params);
191 } catch (\Exception $e) {
192 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
193 }
194
195 if (!$response) {
196 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
197 }
198
199 return $this->connection->lastInsertId();
200 }
201
202 /**
203 * @param int $id
204 * @param Payment $entity
205 *
206 * @return bool
207 * @throws QueryExecutionException
208 */
209 public function update($id, $entity)
210 {
211 $data = $entity->toArray();
212
213 $params = [
214 ':customerBookingId' => $data['customerBookingId'] ? $data['customerBookingId'] : null,
215 ':packageCustomerId' => $data['packageCustomerId'] ? $data['packageCustomerId'] : null,
216 ':parentId' => $data['parentId'] ? $data['parentId'] : null,
217 ':amount' => $data['amount'],
218 ':dateTime' => DateTimeService::getCustomDateTimeInUtc($data['dateTime']),
219 ':status' => $data['status'],
220 ':gateway' => $data['gateway'],
221 ':gatewayTitle' => $data['gatewayTitle'],
222 ':data' => $data['data'],
223 ':transactionId' => $data['transactionId'],
224 ':id' => $id,
225 ];
226
227 try {
228 $statement = $this->connection->prepare(
229 "UPDATE {$this->table}
230 SET
231 `customerBookingId` = :customerBookingId,
232 `packageCustomerId` = :packageCustomerId,
233 `parentId` = :parentId,
234 `amount` = :amount,
235 `dateTime` = :dateTime,
236 `status` = :status,
237 `gateway` = :gateway,
238 `gatewayTitle` = :gatewayTitle,
239 `data` = :data,
240 `transactionId` = :transactionId
241 WHERE
242 id = :id"
243 );
244
245 $response = $statement->execute($params);
246 } catch (\Exception $e) {
247 throw new QueryExecutionException('Unable to save data in ' . __CLASS__, $e->getCode(), $e);
248 }
249
250 if (!$response) {
251 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
252 }
253
254 return $response;
255 }
256
257 /**
258 * @param array $criteria
259 *
260 * @return Collection
261 * @throws QueryExecutionException
262 */
263 public function getByCriteria($criteria)
264 {
265 $result = new Collection();
266
267 $params = [];
268
269 $where = [];
270
271 if (!empty($criteria['bookingIds'])) {
272 $queryBookings = [];
273
274 foreach ($criteria['bookingIds'] as $index => $value) {
275 $param = ':id' . $index;
276
277 $queryBookings[] = $param;
278
279 $params[$param] = $value;
280 }
281
282 $where[] = 'customerBookingId IN (' . implode(', ', $queryBookings) . ')';
283 }
284
285
286 if (!empty($criteria['packageCustomerId'])) {
287 $params[':packageCustomerId'] = $criteria['packageCustomerId'];
288 $where[] = 'packageCustomerId = :packageCustomerId';
289 }
290
291 if (!empty($criteria['ids'])) {
292 $queryIds = [];
293
294 foreach ($criteria['ids'] as $index => $value) {
295 $param = ':id' . $index;
296
297 $queryIds[] = $param;
298
299 $params[$param] = $value;
300 }
301
302 $where[] = 'id IN (' . implode(', ', $queryIds) . ')';
303 }
304
305 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
306
307 try {
308 $statement = $this->connection->prepare(
309 "SELECT
310 id AS id,
311 customerBookingId AS customerBookingId,
312 packageCustomerId AS packageCustomerId,
313 parentId AS parentId,
314 invoiceNumber AS invoiceNumber,
315 amount AS amount,
316 dateTime AS dateTime,
317 status AS status,
318 gateway AS gateway,
319 gatewayTitle AS gatewayTitle,
320 data AS data
321 FROM {$this->table}
322 {$where}"
323 );
324
325 $statement->execute($params);
326
327 while ($row = $statement->fetch()) {
328 $result->addItem(call_user_func([static::FACTORY, 'create'], $row), $row['id']);
329 }
330 } catch (\Exception $e) {
331 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
332 }
333
334 return $result;
335 }
336
337 /**
338 * @param array $criteria
339 * @param int $itemsPerPage
340 * @param boolean $invoice
341 *
342 * @return array
343 * @throws QueryExecutionException
344 */
345 public function getFilteredIds($criteria, $itemsPerPage = null, $invoice = false)
346 {
347 $params = [];
348 $appointmentParams1 = [];
349 $appointmentParams2 = [];
350 $eventParams = [];
351 $whereAppointment1 = [];
352 $whereAppointment2 = [];
353 $whereEvent = [];
354
355 if ($invoice) {
356 $whereAppointment1[] = 'p.parentId IS NULL';
357 $whereAppointment2[] = 'p.parentId IS NULL';
358 $whereEvent[] = 'p.parentId IS NULL';
359 }
360
361 $basedOnDate = $invoice ? 'created' : 'dateTime';
362
363 if (!empty($criteria['ids'])) {
364 $queryIds1 = [];
365 $queryIds2 = [];
366 $queryIds3 = [];
367
368 foreach ($criteria['ids'] as $index => $value) {
369 $param1 = ':id0' . $index;
370 $param2 = ':id1' . $index;
371 $param3 = ':id2' . $index;
372 $queryIds1[] = $param1;
373 $queryIds2[] = $param2;
374 $queryIds3[] = $param3;
375 $appointmentParams1[$param1] = $value;
376 $appointmentParams2[$param2] = $value;
377 $eventParams[$param3] = $value;
378 }
379
380 $whereAppointment1[] = 'p.id IN (' . implode(', ', $queryIds1) . ')';
381 $whereAppointment2[] = 'p.id IN (' . implode(', ', $queryIds2) . ')';
382 $whereEvent[] = 'p.id IN (' . implode(', ', $queryIds3) . ')';
383 }
384
385 if (!empty($criteria['dates'])) {
386 $whereAppointment1[] = "(p.{$basedOnDate} BETWEEN :paymentAppointmentFrom1 AND :paymentAppointmentTo1)";
387 $whereAppointment2[] = "(p.{$basedOnDate} BETWEEN :paymentAppointmentFrom2 AND :paymentAppointmentTo2)";
388 $appointmentParams1[':paymentAppointmentFrom1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
389 $appointmentParams2[':paymentAppointmentFrom2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
390 $appointmentParams1[':paymentAppointmentTo1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
391 $appointmentParams2[':paymentAppointmentTo2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
392
393 $whereEvent[] = "(p.{$basedOnDate} BETWEEN :paymentEventFrom AND :paymentEventTo)";
394 $eventParams[':paymentEventFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
395 $eventParams[':paymentEventTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
396 }
397
398 if (!empty($criteria['customerId'])) {
399 $criteria['customers'][] = $criteria['customerId'];
400 }
401
402 if (!empty($criteria['customers'])) {
403 $queryCustomers1 = [];
404 $queryCustomers2 = [];
405 $queryCustomers3 = [];
406
407 foreach ((array)$criteria['customers'] as $index => $value) {
408 $param1 = ':customer0' . $index;
409 $param2 = ':customer1' . $index;
410 $param3 = ':customer2' . $index;
411 $queryCustomers1[] = $param1;
412 $queryCustomers2[] = $param2;
413 $queryCustomers3[] = $param3;
414 $appointmentParams1[$param1] = $value;
415 $appointmentParams2[$param2] = $value;
416 $eventParams[$param3] = $value;
417 }
418
419 $whereAppointment1[] = 'cb.customerId IN (' . implode(', ', $queryCustomers1) . ')';
420 $whereAppointment2[] = 'pc.customerId IN (' . implode(', ', $queryCustomers2) . ')';
421 $whereEvent[] = 'cb.customerId IN (' . implode(', ', $queryCustomers3) . ')';
422 }
423
424 $eventsProvidersJoin = '';
425
426 if (!empty($criteria['providerId'])) {
427 $criteria['providers'][] = $criteria['providerId'];
428 }
429
430 if (!empty($criteria['providers'])) {
431 $queryProviders1 = [];
432 $queryProviders2 = [];
433 $queryProviders3 = [];
434
435 foreach ((array)$criteria['providers'] as $index => $value) {
436 $param1 = ':provider0' . $index;
437 $param2 = ':provider1' . $index;
438 $param3 = ':provider2' . $index;
439 $queryProviders1[] = $param1;
440 $queryProviders2[] = $param2;
441 $queryProviders3[] = $param3;
442 $appointmentParams1[$param1] = $value;
443 $appointmentParams2[$param2] = $value;
444 $eventParams[$param3] = $value;
445 }
446
447 $whereAppointment1[] = 'a.providerId IN (' . implode(', ', $queryProviders1) . ')';
448 $whereAppointment2[] = 'a.providerId IN (' . implode(', ', $queryProviders2) . ')';
449 $whereEvent[] = 'epu.userId IN (' . implode(', ', $queryProviders3) . ')';
450
451 $eventsProvidersJoin = "
452 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
453 INNER JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
454 ";
455 }
456
457 if (!empty($criteria['services'])) {
458 $queryServices1 = [];
459 $queryServices2 = [];
460
461 foreach ((array)$criteria['services'] as $index => $value) {
462 $param1 = ':service0' . $index;
463 $param2 = ':service1' . $index;
464 $queryServices1[] = $param1;
465 $queryServices2[] = $param2;
466 $appointmentParams1[$param1] = $value;
467 $appointmentParams2[$param2] = $value;
468 }
469
470 $whereAppointment1[] = 'a.serviceId IN (' . implode(', ', $queryServices1) . ')';
471 $whereAppointment2[] = 'a.serviceId IN (' . implode(', ', $queryServices2) . ')';
472 }
473
474 $appointments2ProvidersServicesJoin = '';
475
476 if (!empty($criteria['providers']) || !empty($criteria['services'])) {
477 $appointments2ProvidersServicesJoin = "
478 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
479 INNER JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
480 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
481 ";
482 }
483
484 if (!empty($criteria['status'])) {
485 $criteria['statuses'][] = $criteria['status'];
486 }
487
488 if (!empty($criteria['statuses'])) {
489 $queryStatuses1 = [];
490 $queryStatuses2 = [];
491 $queryStatuses3 = [];
492
493 foreach ($criteria['statuses'] as $index => $value) {
494 $param1 = ':status0' . $index;
495 $param2 = ':status1' . $index;
496 $param3 = ':status2' . $index;
497 $queryStatuses1[] = $param1;
498 $queryStatuses2[] = $param2;
499 $queryStatuses3[] = $param3;
500 $appointmentParams1[$param1] = $value;
501 $appointmentParams2[$param2] = $value;
502 $eventParams[$param3] = $value;
503 }
504
505 $whereAppointment1[] = 'p.status IN (' . implode(', ', $queryStatuses1) . ')';
506 $whereAppointment2[] = 'p.status IN (' . implode(', ', $queryStatuses2) . ')';
507 $whereEvent[] = 'p.status IN (' . implode(', ', $queryStatuses3) . ')';
508 }
509
510 if (!empty($criteria['packages'])) {
511 $queryPackages = [];
512
513 foreach ((array)$criteria['packages'] as $index => $value) {
514 $param = ':package' . $index;
515 $queryPackages[] = $param;
516 $appointmentParams2[$param] = $value;
517 }
518
519 $whereAppointment2[] = "p.packageCustomerId IN (SELECT pc.id
520 FROM {$this->packagesCustomersTable} pc
521 WHERE pc.packageId IN (" . implode(', ', $queryPackages) . '))';
522 }
523
524 if (!empty($criteria['events'])) {
525 $queryEvents = [];
526
527 foreach ((array)$criteria['events'] as $index => $value) {
528 $param = ':event' . $index;
529 $queryEvents[] = $param;
530 $eventParams[$param] = $value;
531 }
532
533 $whereEvent[] = "p.customerBookingId IN (SELECT cbe.customerBookingId
534 FROM {$this->eventsTable} e
535 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.eventId = e.id
536 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.eventPeriodId = ep.id
537 WHERE e.id IN (" . implode(', ', $queryEvents) . '))';
538 }
539
540 $whereAppointment1 = $whereAppointment1 ? ' AND ' . implode(' AND ', $whereAppointment1) : '';
541 $whereAppointment2 = $whereAppointment2 ? ' AND ' . implode(' AND ', $whereAppointment2) : '';
542 $whereEvent = $whereEvent ? ' AND ' . implode(' AND ', $whereEvent) : '';
543
544 $groupBy = '';
545 $groupByAppointment1Clause = empty($criteria['separateRows']) ? "GROUP BY p.customerBookingId" : "";
546 $groupByAppointment2Clause = empty($criteria['separateRows']) ? "GROUP BY p.packageCustomerId" : "";
547 $groupByEventClause = empty($criteria['separateRows']) ? "GROUP BY p.customerBookingId" : "";
548 if ($invoice) {
549 $groupBy = 'GROUP BY IFNULL(invoiceNumber, id)';
550 $groupByAppointment1Clause = '';
551 $groupByAppointment2Clause = '';
552 $groupByEventClause = '';
553 }
554
555 $appointmentQuery1 = "SELECT
556 p.id AS id,
557 p.dateTime AS dateTime,
558 p.created AS created,
559 p.status AS status,
560 p.invoiceNumber AS invoiceNumber,
561 'appointment' AS type
562 FROM {$this->table} p
563 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
564 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
565 WHERE 1=1 {$whereAppointment1} {$groupByAppointment1Clause} ORDER BY p.id ASC";
566
567 $appointmentQuery2 = "SELECT
568 p.id AS id,
569 p.dateTime AS dateTime,
570 p.created AS created,
571 p.status AS status,
572 p.invoiceNumber AS invoiceNumber,
573 'package' AS type
574 FROM {$this->table} p
575 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
576 {$appointments2ProvidersServicesJoin}
577 WHERE 1=1 {$whereAppointment2} {$groupByAppointment2Clause} ORDER BY p.id ASC";
578
579 $eventQuery = "SELECT
580 p.id AS id,
581 p.dateTime AS dateTime,
582 p.created AS created,
583 p.status AS status,
584 p.invoiceNumber AS invoiceNumber,
585 'event' AS type
586 FROM {$this->table} p
587 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
588 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
589 {$eventsProvidersJoin}
590 WHERE 1=1 {$whereEvent} {$groupByEventClause} ORDER BY p.id ASC";
591
592 $result = [];
593
594 if (isset($criteria['events'], $criteria['services'])) {
595 return $result;
596 } elseif (isset($criteria['services'])) {
597 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2})";
598 $params = array_merge($params, $appointmentParams1, $appointmentParams2);
599 } elseif (isset($criteria['events'])) {
600 $paymentQuery = "({$eventQuery})";
601 $params = array_merge($params, $eventParams);
602 } elseif (isset($criteria['packages'])) {
603 $paymentQuery = "({$appointmentQuery2})";
604 $params = array_merge($params, $appointmentParams2);
605 } else {
606 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2}) UNION ALL ({$eventQuery})";
607 $params = array_merge($params, $appointmentParams1, $appointmentParams2, $eventParams);
608 }
609
610 $limit = $this->getLimit(
611 !empty($criteria['page']) ? (int)$criteria['page'] : 0,
612 $itemsPerPage ?: (!empty($criteria['limit']) ? (int)$criteria['limit'] : 0)
613 );
614
615 $bookingTypeCondition = '';
616 if (!empty($criteria['bookingTypes'])) {
617 $bookingTypeCondition = 'WHERE type IN ("' . implode('", "', $criteria['bookingTypes']) . '")';
618 }
619
620 try {
621 $order = "ORDER BY id, {$basedOnDate}";
622 if (!empty($criteria['sort'])) {
623 $order = "ORDER BY {$criteria['sort']['field']} {$criteria['sort']['order']}";
624 }
625
626 $statement = $this->connection->prepare(
627 "SELECT * FROM ({$paymentQuery}) payments
628 {$bookingTypeCondition}
629 {$groupBy}
630 {$order}
631 {$limit}"
632 );
633
634 $statement->execute($params);
635
636 $rows = $statement->fetchAll();
637 } catch (\Exception $e) {
638 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
639 }
640
641 foreach ($rows as $row) {
642 $result[(int)$row['id']] = $row['type'];
643 }
644
645 return $result;
646 }
647
648 /**
649 * @param array $criteria
650 * @param boolean $invoice
651 *
652 * @return int
653 * @throws QueryExecutionException
654 */
655 public function getFilteredIdsCount($criteria, $invoice = false)
656 {
657 $params = [];
658 $appointmentParams1 = [];
659 $appointmentParams2 = [];
660 $eventParams = [];
661 $whereAppointment1 = [];
662 $whereAppointment2 = [];
663 $whereEvent = [];
664
665 if ($invoice) {
666 $whereAppointment1[] = 'p.parentId IS NULL';
667 $whereAppointment2[] = 'p.parentId IS NULL';
668 $whereEvent[] = 'p.parentId IS NULL';
669 }
670
671 $basedOnDate = $invoice ? 'created' : 'dateTime';
672
673 if (!empty($criteria['ids'])) {
674 $queryIds1 = [];
675 $queryIds2 = [];
676 $queryIds3 = [];
677
678 foreach ($criteria['ids'] as $index => $value) {
679 $param1 = ':id0' . $index;
680 $param2 = ':id1' . $index;
681 $param3 = ':id2' . $index;
682 $queryIds1[] = $param1;
683 $queryIds2[] = $param2;
684 $queryIds3[] = $param3;
685 $appointmentParams1[$param1] = $value;
686 $appointmentParams2[$param2] = $value;
687 $eventParams[$param3] = $value;
688 }
689
690 $whereAppointment1[] = 'p.id IN (' . implode(', ', $queryIds1) . ')';
691 $whereAppointment2[] = 'p.id IN (' . implode(', ', $queryIds2) . ')';
692 $whereEvent[] = 'p.id IN (' . implode(', ', $queryIds3) . ')';
693 }
694
695 if (!empty($criteria['dates'])) {
696 $whereAppointment1[] = "(p.{$basedOnDate} BETWEEN :paymentAppointmentFrom1 AND :paymentAppointmentTo1)";
697 $whereAppointment2[] = "(p.{$basedOnDate} BETWEEN :paymentAppointmentFrom2 AND :paymentAppointmentTo2)";
698 $appointmentParams1[':paymentAppointmentFrom1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
699 $appointmentParams2[':paymentAppointmentFrom2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
700 $appointmentParams1[':paymentAppointmentTo1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
701 $appointmentParams2[':paymentAppointmentTo2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
702
703 $whereEvent[] = "(p.{$basedOnDate} BETWEEN :paymentEventFrom AND :paymentEventTo)";
704 $eventParams[':paymentEventFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
705 $eventParams[':paymentEventTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
706 }
707
708 if (!empty($criteria['customerId'])) {
709 $criteria['customers'][] = $criteria['customerId'];
710 }
711
712 if (!empty($criteria['customers'])) {
713 $queryCustomers1 = [];
714 $queryCustomers2 = [];
715 $queryCustomers3 = [];
716
717 foreach ((array)$criteria['customers'] as $index => $value) {
718 $param1 = ':customer0' . $index;
719 $param2 = ':customer1' . $index;
720 $param3 = ':customer2' . $index;
721 $queryCustomers1[] = $param1;
722 $queryCustomers2[] = $param2;
723 $queryCustomers3[] = $param3;
724 $appointmentParams1[$param1] = $value;
725 $appointmentParams2[$param2] = $value;
726 $eventParams[$param3] = $value;
727 }
728
729 $whereAppointment1[] = 'cb.customerId IN (' . implode(', ', $queryCustomers1) . ')';
730 $whereAppointment2[] = 'pc.customerId IN (' . implode(', ', $queryCustomers2) . ')';
731 $whereEvent[] = 'cb.customerId IN (' . implode(', ', $queryCustomers3) . ')';
732 }
733
734 $eventsProvidersJoin = '';
735
736 if (!empty($criteria['providerId'])) {
737 $criteria['providers'][] = $criteria['providerId'];
738 }
739
740 if (!empty($criteria['providers'])) {
741 $queryProviders1 = [];
742 $queryProviders2 = [];
743 $queryProviders3 = [];
744
745 foreach ((array)$criteria['providers'] as $index => $value) {
746 $param1 = ':provider0' . $index;
747 $param2 = ':provider1' . $index;
748 $param3 = ':provider2' . $index;
749 $queryProviders1[] = $param1;
750 $queryProviders2[] = $param2;
751 $queryProviders3[] = $param3;
752 $appointmentParams1[$param1] = $value;
753 $appointmentParams2[$param2] = $value;
754 $eventParams[$param3] = $value;
755 }
756
757 $whereAppointment1[] = 'a.providerId IN (' . implode(', ', $queryProviders1) . ')';
758 $whereAppointment2[] = 'a.providerId IN (' . implode(', ', $queryProviders2) . ')';
759 $whereEvent[] = 'epu.userId IN (' . implode(', ', $queryProviders3) . ')';
760
761 $eventsProvidersJoin = "
762 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
763 INNER JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
764 ";
765 }
766
767 if (!empty($criteria['services'])) {
768 $queryServices1 = [];
769 $queryServices2 = [];
770
771 foreach ((array)$criteria['services'] as $index => $value) {
772 $param1 = ':service0' . $index;
773 $param2 = ':service1' . $index;
774 $queryServices1[] = $param1;
775 $queryServices2[] = $param2;
776 $appointmentParams1[$param1] = $value;
777 $appointmentParams2[$param2] = $value;
778 }
779
780 $whereAppointment1[] = 'a.serviceId IN (' . implode(', ', $queryServices1) . ')';
781 $whereAppointment2[] = 'a.serviceId IN (' . implode(', ', $queryServices2) . ')';
782 }
783
784 $appointments2ProvidersServicesJoin = '';
785
786 if (!empty($criteria['providers']) || !empty($criteria['services'])) {
787 $appointments2ProvidersServicesJoin = "
788 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
789 INNER JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
790 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
791 ";
792 }
793
794 if (!empty($criteria['status'])) {
795 $criteria['statuses'][] = $criteria['status'];
796 }
797
798 if (!empty($criteria['statuses'])) {
799 $queryStatuses1 = [];
800 $queryStatuses2 = [];
801 $queryStatuses3 = [];
802
803 foreach ($criteria['statuses'] as $index => $value) {
804 $param1 = ':status0' . $index;
805 $param2 = ':status1' . $index;
806 $param3 = ':status2' . $index;
807 $queryStatuses1[] = $param1;
808 $queryStatuses2[] = $param2;
809 $queryStatuses3[] = $param3;
810 $appointmentParams1[$param1] = $value;
811 $appointmentParams2[$param2] = $value;
812 $eventParams[$param3] = $value;
813 }
814
815 $whereAppointment1[] = 'p.status IN (' . implode(', ', $queryStatuses1) . ')';
816 $whereAppointment2[] = 'p.status IN (' . implode(', ', $queryStatuses2) . ')';
817 $whereEvent[] = 'p.status IN (' . implode(', ', $queryStatuses3) . ')';
818 }
819
820 if (!empty($criteria['packages'])) {
821 $queryPackages = [];
822
823 foreach ((array)$criteria['packages'] as $index => $value) {
824 $param = ':package' . $index;
825 $queryPackages[] = $param;
826 $appointmentParams2[$param] = $value;
827 }
828
829 $whereAppointment2[] = "p.packageCustomerId IN (SELECT pc.id
830 FROM {$this->packagesCustomersTable} pc
831 WHERE pc.packageId IN (" . implode(', ', $queryPackages) . '))';
832 }
833
834 if (!empty($criteria['events'])) {
835 $queryEvents = [];
836
837 foreach ((array)$criteria['events'] as $index => $value) {
838 $param = ':event' . $index;
839 $queryEvents[] = $param;
840 $eventParams[$param] = $value;
841 }
842
843 $whereEvent[] = "p.customerBookingId IN (SELECT cbe.customerBookingId
844 FROM {$this->eventsTable} e
845 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.eventId = e.id
846 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.eventPeriodId = ep.id
847 WHERE e.id IN (" . implode(', ', $queryEvents) . '))';
848 }
849
850 $whereAppointment1 = $whereAppointment1 ? ' AND ' . implode(' AND ', $whereAppointment1) : '';
851 $whereAppointment2 = $whereAppointment2 ? ' AND ' . implode(' AND ', $whereAppointment2) : '';
852 $whereEvent = $whereEvent ? ' AND ' . implode(' AND ', $whereEvent) : '';
853
854 $groupByAppointment1Clause = empty($criteria['separateRows']) ? "GROUP BY p.customerBookingId" : "";
855 $groupByAppointment2Clause = empty($criteria['separateRows']) ? "GROUP BY p.packageCustomerId" : "";
856 $groupByEventClause = empty($criteria['separateRows']) ? "GROUP BY p.customerBookingId" : "";
857
858 // Build list-style subqueries mirroring getFilteredIds (no ORDER BY / LIMIT here)
859 $listAppointment1 = "SELECT
860 p.id AS id,
861 p.dateTime AS dateTime,
862 p.created AS created,
863 p.status AS status,
864 p.invoiceNumber AS invoiceNumber,
865 'appointment' AS type
866 FROM {$this->table} p
867 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
868 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
869 WHERE 1=1 {$whereAppointment1} {$groupByAppointment1Clause}";
870
871 $listAppointment2 = "SELECT
872 p.id AS id,
873 p.dateTime AS dateTime,
874 p.created AS created,
875 p.status AS status,
876 p.invoiceNumber AS invoiceNumber,
877 'package' AS type
878 FROM {$this->table} p
879 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
880 {$appointments2ProvidersServicesJoin}
881 WHERE 1=1 {$whereAppointment2} {$groupByAppointment2Clause}";
882
883 $listEvent = "SELECT
884 p.id AS id,
885 p.dateTime AS dateTime,
886 p.created AS created,
887 p.status AS status,
888 p.invoiceNumber AS invoiceNumber,
889 'event' AS type
890 FROM {$this->table} p
891 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
892 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
893 {$eventsProvidersJoin}
894 WHERE 1=1 {$whereEvent} {$groupByEventClause}";
895
896 if (isset($criteria['events'], $criteria['services'])) {
897 return 0;
898 }
899
900 // Assemble a single union of the list-style subqueries matching the list endpoint
901 if (isset($criteria['services'])) {
902 $listPaymentQuery = "({$listAppointment1}) UNION ALL ({$listAppointment2})";
903 $params = array_merge($params, $appointmentParams1, $appointmentParams2);
904 } elseif (isset($criteria['events'])) {
905 $listPaymentQuery = "({$listEvent})";
906 $params = array_merge($params, $eventParams);
907 } elseif (isset($criteria['packages'])) {
908 $listPaymentQuery = "({$listAppointment2})";
909 $params = array_merge($params, $appointmentParams2);
910 } else {
911 $listPaymentQuery = "({$listAppointment1}) UNION ALL ({$listAppointment2}) UNION ALL ({$listEvent})";
912 $params = array_merge($params, $appointmentParams1, $appointmentParams2, $eventParams);
913 }
914
915 $bookingTypeCondition = '';
916 if (!empty($criteria['bookingTypes'])) {
917 $bookingTypeCondition = 'WHERE type IN ("' . implode('", "', $criteria['bookingTypes']) . '")';
918 }
919
920 // Invoice page: count distinct invoices across the union to mirror list grouping
921 if ($invoice) {
922 try {
923 $statement = $this->connection->prepare(
924 "SELECT COUNT(DISTINCT IFNULL(invoiceNumber, id)) AS cnt FROM ({$listPaymentQuery}) payments {$bookingTypeCondition}"
925 );
926 $statement->execute($params);
927 $row = $statement->fetch();
928 return (int)($row['cnt'] ?? 0);
929 } catch (\Exception $e) {
930 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
931 }
932 }
933
934 // Non-invoice: simply count rows of the grouped list union (matches separateRows logic)
935 try {
936 $statement = $this->connection->prepare(
937 "SELECT COUNT(*) AS cnt FROM ({$listPaymentQuery}) payments {$bookingTypeCondition}"
938 );
939 $statement->execute($params);
940 $row = $statement->fetch();
941 return (int)($row['cnt'] ?? 0);
942 } catch (\Exception $e) {
943 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
944 }
945 }
946
947 /**
948 * Returns a collection of customers that have birthday on today's date and where notification is not sent
949 *
950 * @return Collection
951 * @throws InvalidArgumentException
952 * @throws QueryExecutionException
953 * @throws \Exception
954 */
955 public function getUncompletedActionsForPayments()
956 {
957 $params = [];
958
959 $currentDateTime = "STR_TO_DATE('" . DateTimeService::getNowDateTimeInUtc() . "', '%Y-%m-%d %H:%i:%s')";
960
961 $pastDateTime =
962 "STR_TO_DATE('" .
963 DateTimeService::getNowDateTimeObjectInUtc()->modify('-1 day')->format('Y-m-d H:i:s') .
964 "', '%Y-%m-%d %H:%i:%s')";
965
966 try {
967 $statement = $this->connection->prepare(
968 "SELECT * FROM {$this->table}
969 WHERE
970 actionsCompleted = 0 AND
971 {$currentDateTime} > DATE_ADD(created, INTERVAL 300 SECOND) AND
972 {$pastDateTime} < created AND
973 entity IS NOT NULL"
974 );
975
976 $statement->execute($params);
977
978 $rows = $statement->fetchAll();
979 } catch (\Exception $e) {
980 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
981 }
982
983 $items = [];
984
985 foreach ($rows as $row) {
986 $items[] = call_user_func([static::FACTORY, 'create'], $row);
987 }
988
989 return new Collection($items);
990 }
991
992 /**
993 * @param array $data
994 * @param boolean $invoice
995 *
996 * @return array
997 * @throws QueryExecutionException
998 */
999 public function getSecondaryPaymentIds($data, $invoice)
1000 {
1001 $params = [];
1002
1003 $where = [];
1004
1005 $parentIdParam1 = null;
1006 $parentIdParam2 = null;
1007 $paymentIdParam2 = null;
1008
1009 foreach ($data as $index => $item) {
1010 $paymentIdParam1 = ':paymentId1' . $index;
1011 $params[$paymentIdParam1] = $item['paymentId'];
1012
1013 if ($invoice) {
1014 if (!empty($item['parentId'])) {
1015 $parentIdParam1 = ':parentId1' . $index;
1016 $params[$parentIdParam1] = $item['parentId'];
1017 $parentIdParam2 = ':parentId2' . $index;
1018 $params[$parentIdParam2] = $item['parentId'];
1019 }
1020 $paymentIdParam2 = ':paymentId2' . $index;
1021 $params[$paymentIdParam2] = $item['paymentId'];
1022 }
1023
1024 $relationParam = ':' . $item['columnName'] . $index;
1025
1026 $params[$relationParam] = $item['columnId'];
1027
1028 // change in the future to simply retrieve by invoiceNumber when on invoice page since all the related payments will have the same invoiceNumber
1029 // cannot be done immediately since invoiceNumber is NULL for existing payments
1030 if ($invoice) {
1031 $where[] =
1032 "((id <> $paymentIdParam1 AND " .
1033 $item['columnName'] . " = $relationParam) OR parentId = $paymentIdParam2" .
1034 (!empty($item['parentId']) ? " OR id = $parentIdParam1 OR parentId = $parentIdParam2)" : ")");
1035 } else {
1036 $where[] = "(id <> $paymentIdParam1 AND " . $item['columnName'] . " = $relationParam)";
1037 }
1038 }
1039
1040 $where = $where ? 'WHERE ' . implode(' OR ', $where) : '';
1041
1042 try {
1043 $statement = $this->connection->prepare(
1044 "SELECT
1045 p.id AS id,
1046 p.entity AS entity
1047 FROM {$this->table} p
1048 {$where}"
1049 );
1050
1051 $statement->execute($params);
1052
1053 $rows = $statement->fetchAll();
1054 } catch (\Exception $e) {
1055 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
1056 }
1057
1058 $result = [];
1059
1060 foreach ($rows as $row) {
1061 $result[(int)$row['id']] = $row['entity'];
1062 }
1063
1064 return $result;
1065 }
1066
1067 /**
1068 * @param int $paymentId
1069 * @param string $transactionId
1070 *
1071 * @throws QueryExecutionException
1072 */
1073 public function updateTransactionId($paymentId, $transactionId)
1074 {
1075 $params = [
1076 ':transactionId' => $transactionId,
1077 ':paymentId1' => $paymentId,
1078 ':paymentId2' => $paymentId
1079 ];
1080
1081 try {
1082 $statement = $this->connection->prepare(
1083 "UPDATE {$this->table} SET `transactionId` = :transactionId WHERE id = :paymentId1 OR parentId = :paymentId2"
1084 );
1085
1086 $response = $statement->execute($params);
1087 } catch (\Exception $e) {
1088 throw new QueryExecutionException('Unable to update data in ' . __CLASS__, $e->getCode(), $e);
1089 }
1090
1091 if (!$response) {
1092 throw new QueryExecutionException('Unable to update data in ' . __CLASS__);
1093 }
1094
1095 return $response;
1096 }
1097
1098
1099
1100 /**
1101 * @param array $data
1102 *
1103 * @return bool
1104 * @throws QueryExecutionException
1105 */
1106 public function setInvoiceNumber($data)
1107 {
1108 $params = [
1109 ':id1' => $data['id'],
1110 ':id2' => $data['id'],
1111 ":{$data['columnName']}" => $data['columnValue']
1112 ];
1113
1114 $where = "WHERE id = :id1 OR parentId = :id2 OR {$data['columnName']} = :{$data['columnName']}";
1115
1116 if (!empty($data['parentId'])) {
1117 $params[':parentId1'] = $params[':parentId2'] = $data['parentId'];
1118 $where = ' OR id = :parentId1 OR parentId = :parentId2';
1119 }
1120
1121 try {
1122 $statement = $this->connection->prepare(
1123 "UPDATE {$this->table}
1124 SET `invoiceNumber` = (SELECT COALESCE(MAX(invoiceNumber), 0) + 1 FROM (SELECT * FROM {$this->table}) AS p)
1125 {$where}"
1126 );
1127
1128 $response = $statement->execute($params);
1129 } catch (\Exception $e) {
1130 throw new QueryExecutionException('Unable to save invoice number in ' . __CLASS__, $e->getCode(), $e);
1131 }
1132
1133 if (!$response) {
1134 throw new QueryExecutionException('Unable to save invoice number in ' . __CLASS__);
1135 }
1136
1137 return $response;
1138 }
1139
1140 /**
1141 * @param array $rows
1142 *
1143 * @return array
1144 */
1145 private function getEntitiesPaymentsResult($rows)
1146 {
1147 $result = [];
1148
1149 foreach ($rows as &$row) {
1150 $customerInfo = $row['info'] ? json_decode($row['info'], true) : null;
1151
1152 if (empty($result[(int)$row['id']])) {
1153 $result[(int)$row['id']] = [
1154 'id' => (int)$row['id'],
1155 'dateTime' => DateTimeService::getCustomDateTimeFromUtc($row['dateTime']),
1156 'created' => DateTimeService::getCustomDateTimeFromUtc($row['created']),
1157 'bookingStart' => $row['bookingStart'] ?
1158 DateTimeService::getCustomDateTimeFromUtc($row['bookingStart']) : null,
1159 'status' => $row['status'],
1160 'parentId' => $row['parentId'],
1161 'wcOrderId' => $row['wcOrderId'],
1162 'wcOrderItemId' => $row['wcOrderItemId'],
1163 'gateway' => $row['gateway'],
1164 'gatewayTitle' => $row['gatewayTitle'],
1165 'transactionId' => $row['transactionId'],
1166 'type' => $row['type'],
1167 'name' => $row['bookableName'],
1168 'customerBookingId' => (int)$row['customerBookingId'] ?: null,
1169 'packageCustomerId' => (int)$row['packageCustomerId'] ?: null,
1170 'amount' => (float)$row['amount'],
1171 'invoiceNumber' => $row['invoiceNumber'],
1172 'providers' => (int)$row['providerId'] ? [
1173 [
1174 'id' => (int)$row['providerId'],
1175 'fullName' => $row['providerFirstName'] . ' ' . $row['providerLastName'],
1176 'email' => $row['providerEmail'],
1177 'firstName' => $row['providerFirstName'],
1178 'lastName' => $row['providerLastName'],
1179 'picture' => $row['providerPictureThumbPath'],
1180 ]
1181 ] : [],
1182 'location' => (int)$row['locationId'] || $row['location_address'] ?
1183 [
1184 'id' => (int)$row['locationId'],
1185 'location_name' => $row['location_name'],
1186 'location_address' => $row['location_address'],
1187 ]
1188 : null,
1189 'customerId' => (int)$row['customerId'],
1190 'serviceId' => (int)$row['serviceId'] ?: null,
1191 'appointmentId' => (int)$row['appointmentId'] ?: null,
1192 'packageId' => (int)$row['packageId'] ?: null,
1193 'bookedPrice' => (float)$row['bookedPrice'] ?: 0,
1194 'bookedTax' => $row['bookedTax'] ?: null,
1195 'bookingId' => !empty($row['bookingId']) ? (int)$row['bookingId'] : null,
1196 'bookableName' => $row['bookableName'],
1197 'customerFirstName' => $customerInfo ? $customerInfo['firstName'] : $row['customerFirstName'],
1198 'customerLastName' => $customerInfo ? $customerInfo['lastName'] : $row['customerLastName'],
1199 'info' => $row['info'],
1200 'customerEmail' => $row['customerEmail'],
1201 'customerStatus' => $row['customerStatus'],
1202 'coupon' => !empty($row['coupon_id']) ? [
1203 'id' => (int)$row['coupon_id'],
1204 'discount' => (float)$row['coupon_discount'],
1205 'deduction' => (float)$row['coupon_deduction'],
1206 'code' => $row['coupon_code']
1207 ] : null,
1208 'persons' => (int)$row['persons'],
1209 'aggregatedPrice' => (bool)$row['aggregatedPrice'],
1210 'extras' => [],
1211 ];
1212 }
1213
1214 if ($result[(int)$row['id']] && $row['bookingExtra_id']) {
1215 $result[(int)$row['id']]['extras'][] = [
1216 'id' => (int)$row['bookingExtra_id'],
1217 'extraId' => (int)$row['bookingExtra_extraId'],
1218 'quantity' => (int)$row['bookingExtra_quantity'],
1219 'price' => (float)$row['bookingExtra_price'],
1220 'aggregatedPrice' => (bool)$row['bookingExtra_aggregatedPrice'],
1221 'tax' => $row['bookingExtra_tax'] ?: null
1222 ];
1223 }
1224 }
1225
1226 return $result;
1227 }
1228
1229 /**
1230 * @param array $ids
1231 *
1232 * @return array
1233 * @throws QueryExecutionException
1234 * @throws InvalidArgumentException
1235 */
1236 public function getAppointmentsPaymentsByIds($ids)
1237 {
1238 $params = [];
1239
1240 $where = [];
1241
1242 if (!empty($ids)) {
1243 foreach ($ids as $index => $value) {
1244 $param = ':sId' . $index;
1245
1246 $params[$param] = $value;
1247 }
1248
1249 $where[] = 'p.id IN (' . implode(', ', array_keys($params)) . ')';
1250 }
1251
1252 $where = $where ? ' AND ' . implode(' AND ', $where) : '';
1253
1254 $customerBookingsExtrasTable = CustomerBookingsToExtrasTable::getTableName();
1255
1256 $couponsTable = CouponsTable::getTableName();
1257
1258 $locationsTable = LocationsTable::getTableName();
1259
1260 try {
1261 $statement = $this->connection->prepare(
1262 "SELECT
1263 p.id AS id,
1264 p.customerBookingId AS customerBookingId,
1265 NULL AS packageCustomerId,
1266 p.amount AS amount,
1267 p.invoiceNumber AS invoiceNumber,
1268 p.dateTime AS dateTime,
1269 p.created AS created,
1270 p.status AS status,
1271 p.wcOrderId AS wcOrderId,
1272 p.wcOrderItemId AS wcOrderItemId,
1273 p.gateway AS gateway,
1274 p.gatewayTitle AS gatewayTitle,
1275 p.transactionId AS transactionId,
1276 p.parentId AS parentId,
1277 p.entity AS type,
1278
1279 NULL AS packageId,
1280 cb.id AS bookingId,
1281 cb.price AS bookedPrice,
1282 cb.tax AS bookedTax,
1283 a.providerId AS providerId,
1284 cb.customerId AS customerId,
1285 cb.persons AS persons,
1286 cb.aggregatedPrice AS aggregatedPrice,
1287 cb.info AS info,
1288
1289 cbe.id AS bookingExtra_id,
1290 cbe.extraId AS bookingExtra_extraId,
1291 cbe.quantity AS bookingExtra_quantity,
1292 cbe.price AS bookingExtra_price,
1293 cbe.aggregatedPrice AS bookingExtra_aggregatedPrice,
1294 cbe.tax AS bookingExtra_tax,
1295
1296 c.id AS coupon_id,
1297 c.discount AS coupon_discount,
1298 c.deduction AS coupon_deduction,
1299 c.code AS coupon_code,
1300
1301 a.serviceId AS serviceId,
1302 a.id AS appointmentId,
1303 a.bookingStart AS bookingStart,
1304 s.name AS bookableName,
1305 cu.firstName AS customerFirstName,
1306 cu.lastName AS customerLastName,
1307 cu.email AS customerEmail,
1308 cu.status AS customerStatus,
1309 pu.firstName AS providerFirstName,
1310 pu.lastName AS providerLastName,
1311 pu.email AS providerEmail,
1312 pu.pictureThumbPath AS providerPictureThumbPath,
1313 l.id AS locationId,
1314 l.name AS location_name,
1315 l.address AS location_address
1316 FROM {$this->table} p
1317 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
1318 LEFT JOIN {$customerBookingsExtrasTable} cbe ON cbe.customerBookingId = cb.id
1319 LEFT JOIN {$couponsTable} c ON c.id = cb.couponId
1320 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
1321 INNER JOIN {$this->servicesTable} s ON s.id = a.serviceId
1322 INNER JOIN {$this->usersTable} cu ON cu.id = cb.customerId
1323 INNER JOIN {$this->usersTable} pu ON pu.id = a.providerId
1324 LEFT JOIN {$locationsTable} l ON l.id = a.locationId
1325 WHERE 1=1 {$where}"
1326 );
1327
1328 $statement->execute($params);
1329
1330 $rows = $statement->fetchAll();
1331 } catch (\Exception $e) {
1332 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1333 }
1334
1335 return $this->getEntitiesPaymentsResult($rows);
1336 }
1337
1338 /**
1339 * @param array $ids
1340 *
1341 * @return array
1342 * @throws QueryExecutionException
1343 * @throws InvalidArgumentException
1344 */
1345 public function getEventsPaymentsByIds($ids)
1346 {
1347 $params = [];
1348
1349 $where = [];
1350
1351 if (!empty($ids)) {
1352 foreach ($ids as $index => $value) {
1353 $param = ':eId' . $index;
1354
1355 $params[$param] = $value;
1356 }
1357
1358 $where[] = 'p.id IN (' . implode(', ', array_keys($params)) . ')';
1359 }
1360
1361 $where = $where ? ' AND ' . implode(' AND ', $where) : '';
1362
1363 $couponsTable = CouponsTable::getTableName();
1364
1365 $locationsTable = LocationsTable::getTableName();
1366
1367 try {
1368 $statement = $this->connection->prepare(
1369 "SELECT
1370 p.id AS id,
1371 p.customerBookingId AS customerBookingId,
1372 NULL AS packageCustomerId,
1373 p.amount AS amount,
1374 p.invoiceNumber AS invoiceNumber,
1375 p.dateTime AS dateTime,
1376 p.created AS created,
1377 p.status AS status,
1378 p.wcOrderId AS wcOrderId,
1379 p.wcOrderItemId AS wcOrderItemId,
1380 p.gateway AS gateway,
1381 p.gatewayTitle AS gatewayTitle,
1382 p.transactionId AS transactionId,
1383 p.parentId AS parentId,
1384 p.entity AS type,
1385
1386 NULL AS packageId,
1387 cb.id AS bookingId,
1388 cb.price AS bookedPrice,
1389 cb.tax AS bookedTax,
1390 NULL AS providerId,
1391 cb.customerId AS customerId,
1392 cb.persons AS persons,
1393 cb.aggregatedPrice AS aggregatedPrice,
1394 cb.info AS info,
1395
1396 NULL AS bookingExtra_id,
1397 NULL AS bookingExtra_extraId,
1398 NULL AS bookingExtra_quantity,
1399 NULL AS bookingExtra_price,
1400 NULL AS bookingExtra_aggregatedPrice,
1401 NULL AS bookingExtra_tax,
1402
1403 c.id AS coupon_id,
1404 c.discount AS coupon_discount,
1405 c.deduction AS coupon_deduction,
1406 c.code AS coupon_code,
1407
1408 NULL AS serviceId,
1409 NULL AS appointmentId,
1410 NULL AS bookingStart,
1411 NULL AS bookableName,
1412 cu.firstName AS customerFirstName,
1413 cu.lastName AS customerLastName,
1414 cu.email AS customerEmail,
1415 cu.status AS customerStatus,
1416 NULL AS providerFirstName,
1417 NULL AS providerLastName,
1418 NULL AS providerEmail,
1419 l.id AS locationId,
1420 l.name AS location_name,
1421 (CASE WHEN e.customlocation IS NOT NULL THEN e.customlocation ELSE l.address END) AS location_address
1422 FROM {$this->table} p
1423 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
1424 LEFT JOIN {$couponsTable} c ON c.id = cb.couponId
1425 INNER JOIN {$this->usersTable} cu ON cu.id = cb.customerId
1426 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
1427 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
1428 INNER JOIN {$this->eventsTable} e ON e.id = ep.eventId
1429 LEFT JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
1430 LEFT JOIN {$locationsTable} l ON l.id = e.locationId
1431 WHERE 1=1 {$where}"
1432 );
1433
1434 $statement->execute($params);
1435
1436 $rows = $statement->fetchAll();
1437 } catch (\Exception $e) {
1438 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1439 }
1440
1441 return $this->getEntitiesPaymentsResult($rows);
1442 }
1443
1444 /**
1445 * @param array $ids
1446 *
1447 * @return array
1448 * @throws QueryExecutionException
1449 * @throws InvalidArgumentException
1450 */
1451 public function getPackagesPaymentsByIds($ids)
1452 {
1453 $params = [];
1454
1455 $where = [];
1456
1457 if (!empty($ids)) {
1458 foreach ($ids as $index => $value) {
1459 $param = ':pId' . $index;
1460
1461 $params[$param] = $value;
1462 }
1463
1464 $where[] = 'p.id IN (' . implode(', ', array_keys($params)) . ')';
1465 }
1466
1467 $where = $where ? ' AND ' . implode(' AND ', $where) : '';
1468
1469 $couponsTable = CouponsTable::getTableName();
1470
1471 try {
1472 $statement = $this->connection->prepare(
1473 "SELECT
1474 p.id AS id,
1475 NULL AS customerBookingId,
1476 p.packageCustomerId AS packageCustomerId,
1477 p.amount AS amount,
1478 p.invoiceNumber AS invoiceNumber,
1479 p.dateTime AS dateTime,
1480 p.created AS created,
1481 p.status AS status,
1482 p.wcOrderId AS wcOrderId,
1483 p.wcOrderItemId AS wcOrderItemId,
1484 p.gateway AS gateway,
1485 p.gatewayTitle AS gatewayTitle,
1486 p.transactionId AS transactionId,
1487 p.parentId AS parentId,
1488 p.entity AS type,
1489
1490 pc.packageId AS packageId,
1491 pc.id AS bookingId,
1492 pc.price AS bookedPrice,
1493 pc.tax AS bookedTax,
1494 NULL AS providerId,
1495 pc.customerId AS customerId,
1496 NULL AS persons,
1497 NULL AS aggregatedPrice,
1498 cb.info AS info,
1499
1500 NULL AS bookingExtra_id,
1501 NULL AS bookingExtra_extraId,
1502 NULL AS bookingExtra_quantity,
1503 NULL AS bookingExtra_price,
1504 NULL AS bookingExtra_aggregatedPrice,
1505 NULL AS bookingExtra_tax,
1506
1507 c.id AS coupon_id,
1508 c.discount AS coupon_discount,
1509 c.deduction AS coupon_deduction,
1510 c.code AS coupon_code,
1511
1512 NULL AS serviceId,
1513 NULL AS appointmentId,
1514 NULL AS bookingStart,
1515 pa.name AS bookableName,
1516 cu.firstName AS customerFirstName,
1517 cu.lastName AS customerLastName,
1518 cu.email AS customerEmail,
1519 cu.status AS customerStatus,
1520 '' AS providerFirstName,
1521 '' AS providerLastName,
1522 '' AS providerEmail,
1523 '' AS locationId,
1524 '' AS location_name,
1525 '' AS location_address
1526 FROM {$this->table} p
1527 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
1528 INNER JOIN {$this->usersTable} cu ON cu.id = pc.customerId
1529 LEFT JOIN {$couponsTable} c ON c.id = pc.couponId
1530 INNER JOIN {$this->packagesTable} pa ON pa.id = pc.packageId
1531 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
1532 LEFT JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
1533 LEFT JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
1534 WHERE 1=1 {$where} ORDER BY p.id ASC"
1535 );
1536
1537 $statement->execute($params);
1538
1539 $rows = $statement->fetchAll();
1540 } catch (\Exception $e) {
1541 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1542 }
1543
1544 return $this->getEntitiesPaymentsResult($rows);
1545 }
1546 }
1547