PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.11
Booking for Appointments and Events Calendar – Amelia v1.2.11
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 1 year ago
PaymentRepository.php
1307 lines
1 <?php
2 /**
3 * @copyright © TMS-Plugins. All rights reserved.
4 * @licence See LICENCE.md for license details.
5 */
6
7 namespace AmeliaBooking\Infrastructure\Repository\Payment;
8
9 use AmeliaBooking\Domain\Collection\Collection;
10 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
11 use AmeliaBooking\Domain\Entity\Payment\Payment;
12 use AmeliaBooking\Domain\Factory\Payment\PaymentFactory;
13 use AmeliaBooking\Domain\Services\DateTime\DateTimeService;
14 use AmeliaBooking\Infrastructure\Repository\AbstractRepository;
15 use AmeliaBooking\Domain\Repository\Payment\PaymentRepositoryInterface;
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 implements PaymentRepositoryInterface
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 const FACTORY = PaymentFactory::class;
108
109 /**
110 * @param Payment $entity
111 *
112 * @return bool
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 MAX(CASE WHEN invoiceNumber IS NULL THEN 0 ELSE invoiceNumber END)+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`, `packageCustomerId`, `parentId`, `amount`, `dateTime`, `status`, `gateway`, `gatewayTitle`, `data`, `entity`, `actionsCompleted`, `created`, `wcOrderId`, `wcOrderItemId`, `transactionId`, `invoiceNumber`
156 ) VALUES (
157 :customerBookingId, :packageCustomerId, :parentId, :amount, :dateTime, :status, :gateway, :gatewayTitle, :data, :entity, :actionsCompleted, :created, :wcOrderId, :wcOrderItemId, :transactionId, {$invoiceNumberText}
158 )"
159 );
160
161 $response = $statement->execute($params);
162 } catch (\Exception $e) {
163 throw new QueryExecutionException('Unable to add data in ' . __CLASS__, $e->getCode(), $e);
164 }
165
166 if (!$response) {
167 throw new QueryExecutionException('Unable to add data in ' . __CLASS__);
168 }
169
170 return $this->connection->lastInsertId();
171 }
172
173 /**
174 * @param int $id
175 * @param Payment $entity
176 *
177 * @return bool
178 * @throws QueryExecutionException
179 */
180 public function update($id, $entity)
181 {
182 $data = $entity->toArray();
183
184 $params = [
185 ':customerBookingId' => $data['customerBookingId'] ? $data['customerBookingId'] : null,
186 ':packageCustomerId' => $data['packageCustomerId'] ? $data['packageCustomerId'] : null,
187 ':parentId' => $data['parentId'] ? $data['parentId'] : null,
188 ':amount' => $data['amount'],
189 ':dateTime' => DateTimeService::getCustomDateTimeInUtc($data['dateTime']),
190 ':status' => $data['status'],
191 ':gateway' => $data['gateway'],
192 ':gatewayTitle' => $data['gatewayTitle'],
193 ':data' => $data['data'],
194 ':transactionId' => $data['transactionId'],
195 ':id' => $id,
196 ];
197
198 try {
199 $statement = $this->connection->prepare(
200 "UPDATE {$this->table}
201 SET
202 `customerBookingId` = :customerBookingId,
203 `packageCustomerId` = :packageCustomerId,
204 `parentId` = :parentId,
205 `amount` = :amount,
206 `dateTime` = :dateTime,
207 `status` = :status,
208 `gateway` = :gateway,
209 `gatewayTitle` = :gatewayTitle,
210 `data` = :data,
211 `transactionId` = :transactionId
212 WHERE
213 id = :id"
214 );
215
216 $response = $statement->execute($params);
217 } catch (\Exception $e) {
218 throw new QueryExecutionException('Unable to save data in ' . __CLASS__, $e->getCode(), $e);
219 }
220
221 if (!$response) {
222 throw new QueryExecutionException('Unable to save data in ' . __CLASS__);
223 }
224
225 return $response;
226 }
227
228 /**
229 * @param array $criteria
230 *
231 * @return Collection
232 * @throws QueryExecutionException
233 */
234 public function getByCriteria($criteria)
235 {
236 $result = new Collection();
237
238 $params = [];
239
240 $where = [];
241
242 if (!empty($criteria['bookingIds'])) {
243 $queryBookings = [];
244
245 foreach ($criteria['bookingIds'] as $index => $value) {
246 $param = ':id' . $index;
247
248 $queryBookings[] = $param;
249
250 $params[$param] = $value;
251 }
252
253 $where[] = 'customerBookingId IN (' . implode(', ', $queryBookings) . ')';
254 }
255
256
257 if (!empty($criteria['packageCustomerId'])) {
258 $params[':packageCustomerId'] = $criteria['packageCustomerId'];
259 $where[] = 'packageCustomerId = :packageCustomerId';
260 }
261
262 if (!empty($criteria['ids'])) {
263 $queryIds = [];
264
265 foreach ($criteria['ids'] as $index => $value) {
266 $param = ':id' . $index;
267
268 $queryIds[] = $param;
269
270 $params[$param] = $value;
271 }
272
273 $where[] = 'id IN (' . implode(', ', $queryIds) . ')';
274 }
275
276 $where = $where ? 'WHERE ' . implode(' AND ', $where) : '';
277
278 try {
279 $statement = $this->connection->prepare(
280 "SELECT
281 id AS id,
282 customerBookingId AS customerBookingId,
283 packageCustomerId AS packageCustomerId,
284 parentId AS parentId,
285 invoiceNumber AS invoiceNumber,
286 amount AS amount,
287 dateTime AS dateTime,
288 status AS status,
289 gateway AS gateway,
290 gatewayTitle AS gatewayTitle,
291 data AS data
292 FROM {$this->table}
293 {$where}"
294 );
295
296 $statement->execute($params);
297
298 while ($row = $statement->fetch()) {
299 $result->addItem(call_user_func([static::FACTORY, 'create'], $row), $row['id']);
300 }
301 } catch (\Exception $e) {
302 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
303 }
304
305 return $result;
306 }
307
308 /**
309 * @param array $ids
310 * @param boolean $invoice
311 *
312 * @return array
313 * @throws QueryExecutionException
314 * @throws InvalidArgumentException
315 */
316 public function getFiltered($ids, $invoice = false)
317 {
318 $params = [];
319 $appointmentParams1 = [];
320 $appointmentParams2 = [];
321 $eventParams = [];
322 $whereAppointment1 = [];
323 $whereAppointment2 = [];
324 $whereEvent = [];
325
326 $basedOnDate = $invoice ? 'created' : 'dateTime';
327
328 if (!empty($ids['appointment'])) {
329 $appointment1PaymentsIds = [];
330
331 foreach ($ids['appointment'] as $index => $value) {
332 $param = ':sId' . $index;
333
334 $appointment1PaymentsIds[] = $param;
335
336 $params[$param] = $value;
337 }
338
339 $whereAppointment1[] = 'p.id IN (' . implode(', ', $appointment1PaymentsIds) . ')';
340 }
341
342 if (!empty($ids['package'])) {
343 $appointment2PaymentsIds = [];
344
345 foreach ($ids['package'] as $index => $value) {
346 $param = ':pId' . $index;
347
348 $appointment2PaymentsIds[] = $param;
349
350 $params[$param] = $value;
351 }
352
353 $whereAppointment2[] = 'p.id IN (' . implode(', ', $appointment2PaymentsIds) . ')';
354 }
355
356 if (!empty($ids['event'])) {
357 $eventsIds = [];
358
359 foreach ($ids['event'] as $index => $value) {
360 $param = ':eId' . $index;
361
362 $eventsIds[] = $param;
363
364 $params[$param] = $value;
365 }
366
367 $whereEvent[] = 'p.id IN (' . implode(', ', $eventsIds) . ')';
368 }
369
370 $whereAppointment1 = $whereAppointment1 ? ' AND ' . implode(' AND ', $whereAppointment1) : '';
371 $whereAppointment2 = $whereAppointment2 ? ' AND ' . implode(' AND ', $whereAppointment2) : '';
372 $whereEvent = $whereEvent ? ' AND ' . implode(' AND ', $whereEvent) : '';
373
374 $customerBookingsExtrasTable = CustomerBookingsToExtrasTable::getTableName();
375 $couponsTable = CouponsTable::getTableName();
376 $locationsTable = LocationsTable::getTableName();
377
378 $appointmentQuery1 = "SELECT
379 p.id AS id,
380 p.customerBookingId AS customerBookingId,
381 NULL AS packageCustomerId,
382 p.amount AS amount,
383 p.invoiceNumber AS invoiceNumber,
384 p.dateTime AS dateTime,
385 p.created AS created,
386 p.status AS status,
387 p.wcOrderId AS wcOrderId,
388 p.wcOrderItemId AS wcOrderItemId,
389 p.gateway AS gateway,
390 p.gatewayTitle AS gatewayTitle,
391 p.transactionId AS transactionId,
392 p.parentId AS parentId,
393 p.entity AS type,
394
395 NULL AS packageId,
396 cb.id AS bookingId,
397 cb.price AS bookedPrice,
398 cb.tax AS bookedTax,
399 a.providerId AS providerId,
400 cb.customerId AS customerId,
401 cb.persons AS persons,
402 cb.aggregatedPrice AS aggregatedPrice,
403 cb.info AS info,
404
405 cbe.id AS bookingExtra_id,
406 cbe.quantity AS bookingExtra_quantity,
407 cbe.price AS bookingExtra_price,
408 cbe.aggregatedPrice AS bookingExtra_aggregatedPrice,
409 cbe.tax AS bookingExtra_tax,
410
411 c.id AS coupon_id,
412 c.discount AS coupon_discount,
413 c.deduction AS coupon_deduction,
414 c.code AS coupon_code,
415
416 a.serviceId AS serviceId,
417 a.id AS appointmentId,
418 a.bookingStart AS bookingStart,
419 s.name AS bookableName,
420 cu.firstName AS customerFirstName,
421 cu.lastName AS customerLastName,
422 cu.email AS customerEmail,
423 pu.firstName AS providerFirstName,
424 pu.lastName AS providerLastName,
425 pu.email AS providerEmail,
426 l.id AS locationId,
427 l.name AS location_name,
428 l.address AS location_address
429 FROM {$this->table} p
430 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
431 LEFT JOIN {$customerBookingsExtrasTable} cbe ON cbe.customerBookingId = cb.id
432 LEFT JOIN {$couponsTable} c ON c.id = cb.couponId
433 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
434 INNER JOIN {$this->servicesTable} s ON s.id = a.serviceId
435 INNER JOIN {$this->usersTable} cu ON cu.id = cb.customerId
436 INNER JOIN {$this->usersTable} pu ON pu.id = a.providerId
437 LEFT JOIN {$locationsTable} l ON l.id = a.locationId
438 WHERE 1=1 {$whereAppointment1} GROUP BY p.customerBookingId ORDER BY p.id ASC";
439
440 $appointmentQuery2 = "SELECT
441 p.id AS id,
442 NULL AS customerBookingId,
443 p.packageCustomerId AS packageCustomerId,
444 p.amount AS amount,
445 p.invoiceNumber AS invoiceNumber,
446 p.dateTime AS dateTime,
447 p.created AS created,
448 p.status AS status,
449 p.wcOrderId AS wcOrderId,
450 p.wcOrderItemId AS wcOrderItemId,
451 p.gateway AS gateway,
452 p.gatewayTitle AS gatewayTitle,
453 p.transactionId AS transactionId,
454 p.parentId AS parentId,
455 p.entity AS type,
456
457 pc.packageId AS packageId,
458 pc.id AS bookingId,
459 pc.price AS bookedPrice,
460 pc.tax AS bookedTax,
461 NULL AS providerId,
462 pc.customerId AS customerId,
463 NULL AS persons,
464 NULL AS aggregatedPrice,
465 cb.info AS info,
466
467 NULL AS bookingExtra_id,
468 NULL AS bookingExtra_quantity,
469 NULL AS bookingExtra_price,
470 NULL AS bookingExtra_aggregatedPrice,
471 NULL AS bookingExtra_tax,
472
473 c.id AS coupon_id,
474 c.discount AS coupon_discount,
475 c.deduction AS coupon_deduction,
476 c.code AS coupon_code,
477
478 NULL AS serviceId,
479 NULL AS appointmentId,
480 NULL AS bookingStart,
481 pa.name AS bookableName,
482 cu.firstName AS customerFirstName,
483 cu.lastName AS customerLastName,
484 cu.email AS customerEmail,
485 '' AS providerFirstName,
486 '' AS providerLastName,
487 '' AS providerEmail,
488 '' AS locationId,
489 '' AS location_name,
490 '' AS location_address
491 FROM {$this->table} p
492 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
493 INNER JOIN {$this->usersTable} cu ON cu.id = pc.customerId
494 LEFT JOIN {$couponsTable} c ON c.id = pc.couponId
495 INNER JOIN {$this->packagesTable} pa ON pa.id = pc.packageId
496 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
497 LEFT JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
498 LEFT JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
499 WHERE 1=1 {$whereAppointment2} ORDER BY p.id ASC";
500
501 $eventQuery = "SELECT
502 p.id AS id,
503 p.customerBookingId AS customerBookingId,
504 NULL AS packageCustomerId,
505 p.amount AS amount,
506 p.invoiceNumber AS invoiceNumber,
507 p.dateTime AS dateTime,
508 p.created AS created,
509 p.status AS status,
510 p.wcOrderId AS wcOrderId,
511 p.wcOrderItemId AS wcOrderItemId,
512 p.gateway AS gateway,
513 p.gatewayTitle AS gatewayTitle,
514 p.transactionId AS transactionId,
515 p.parentId AS parentId,
516 p.entity AS type,
517
518 NULL AS packageId,
519 cb.id AS bookingId,
520 cb.price AS bookedPrice,
521 cb.tax AS bookedTax,
522 NULL AS providerId,
523 cb.customerId AS customerId,
524 cb.persons AS persons,
525 cb.aggregatedPrice AS aggregatedPrice,
526 cb.info AS info,
527
528 NULL AS bookingExtra_id,
529 NULL AS bookingExtra_quantity,
530 NULL AS bookingExtra_price,
531 NULL AS bookingExtra_aggregatedPrice,
532 NULL AS bookingExtra_tax,
533
534 c.id AS coupon_id,
535 c.discount AS coupon_discount,
536 c.deduction AS coupon_deduction,
537 c.code AS coupon_code,
538
539 NULL AS serviceId,
540 NULL AS appointmentId,
541 NULL AS bookingStart,
542 NULL AS bookableName,
543 cu.firstName AS customerFirstName,
544 cu.lastName AS customerLastName,
545 cu.email AS customerEmail,
546 NULL AS providerFirstName,
547 NULL AS providerLastName,
548 NULL AS providerEmail,
549 l.id AS locationId,
550 l.name AS location_name,
551 (CASE WHEN e.customlocation IS NOT NULL THEN e.customlocation ELSE l.address END) AS location_address
552 FROM {$this->table} p
553 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
554 LEFT JOIN {$couponsTable} c ON c.id = cb.couponId
555 INNER JOIN {$this->usersTable} cu ON cu.id = cb.customerId
556 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
557 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
558 INNER JOIN {$this->eventsTable} e ON e.id = ep.eventId
559 LEFT JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
560 LEFT JOIN {$locationsTable} l ON l.id = e.locationId
561 WHERE 1=1 {$whereEvent} ORDER BY p.id ASC";
562
563 $paymentQuery = '';
564
565 if (!empty($ids['appointment'])) {
566 $paymentQuery = "({$appointmentQuery1})";
567
568 $params = array_merge($params, $appointmentParams1);
569 }
570
571 if (!empty($ids['package'])) {
572 $paymentQuery = $paymentQuery ? $paymentQuery . " UNION ALL ({$appointmentQuery2})" : "({$appointmentQuery2})";
573
574 $params = array_merge($params, $appointmentParams2);
575 }
576
577 if (!empty($ids['event'])) {
578 $paymentQuery = $paymentQuery ? $paymentQuery . " UNION ALL ({$eventQuery})" : "({$eventQuery})";
579
580 $params = array_merge($params, $eventParams);
581 }
582
583 try {
584 $statement = $this->connection->prepare(
585 "{$paymentQuery}
586 ORDER BY {$basedOnDate}, id"
587 );
588
589 $statement->execute($params);
590
591 $rows = $statement->fetchAll();
592 } catch (\Exception $e) {
593 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
594 }
595
596 $result = [];
597
598 foreach ($rows as &$row) {
599 $customerInfo = $row['info'] ? json_decode($row['info'], true) : null;
600
601 $result[(int)$row['id']] = [
602 'id' => (int)$row['id'],
603 'dateTime' => DateTimeService::getCustomDateTimeFromUtc($row['dateTime']),
604 'created' => DateTimeService::getCustomDateTimeFromUtc($row['created']),
605 'bookingStart' => $row['bookingStart'] ?
606 DateTimeService::getCustomDateTimeFromUtc($row['bookingStart']) : null,
607 'status' => $row['status'],
608 'parentId' => $row['parentId'],
609 'wcOrderId' => $row['wcOrderId'],
610 'wcOrderItemId' => $row['wcOrderItemId'],
611 'gateway' => $row['gateway'],
612 'gatewayTitle' => $row['gatewayTitle'],
613 'transactionId' => $row['transactionId'],
614 'type' => $row['type'],
615 'name' => $row['bookableName'],
616 'customerBookingId' => (int)$row['customerBookingId'] ? (int)$row['customerBookingId'] : null,
617 'packageCustomerId' => (int)$row['packageCustomerId'] ? (int)$row['packageCustomerId'] : null,
618 'amount' => (float)$row['amount'],
619 'invoiceNumber' => $row['invoiceNumber'],
620 'providers' => (int)$row['providerId'] ? [
621 [
622 'id' => (int)$row['providerId'],
623 'fullName' => $row['providerFirstName'] . ' ' . $row['providerLastName'],
624 'email' => $row['providerEmail'],
625 ]
626 ] : [],
627 'location' => (int)$row['locationId'] || $row['location_address'] ?
628 [
629 'id' => (int)$row['locationId'],
630 'location_name' => $row['location_name'],
631 'location_address' => $row['location_address'],
632 ]
633 : null,
634 'customerId' => (int)$row['customerId'],
635 'serviceId' => (int)$row['serviceId'] ? (int)$row['serviceId'] : null,
636 'appointmentId' => (int)$row['appointmentId'] ? (int)$row['appointmentId'] : null,
637 'packageId' => (int)$row['packageId'] ? (int)$row['packageId'] : null,
638 'bookedPrice' => $row['bookedPrice'] ? $row['bookedPrice'] : null,
639 'bookedTax' => $row['bookedTax'] ? $row['bookedTax'] : null,
640 'bookingId' => !empty($row['bookingId']) ? (int)$row['bookingId'] : null,
641 'bookableName' => $row['bookableName'],
642 'customerFirstName' => $customerInfo ? $customerInfo['firstName'] : $row['customerFirstName'],
643 'customerLastName' => $customerInfo ? $customerInfo['lastName'] : $row['customerLastName'],
644 'info' => $row['info'],
645 'customerEmail' => $row['customerEmail'],
646 'coupon' => !empty($row['coupon_id']) ? [
647 'id' => $row['coupon_id'],
648 'discount' => $row['coupon_discount'],
649 'deduction' => $row['coupon_deduction'],
650 'code' => $row['coupon_code']
651 ] : null,
652 'persons' => $row['persons'],
653 'aggregatedPrice' => $row['aggregatedPrice'],
654 'extras' => (int)$row['bookingExtra_id'] ? [
655 [
656 'id' => (int)$row['bookingExtra_id'],
657 'quantity' => $row['bookingExtra_quantity'],
658 'price' =>$row['bookingExtra_price'],
659 'aggregatedPrice' => $row['bookingExtra_aggregatedPrice'],
660 'tax' => $row['bookingExtra_tax'] ?: null
661 ]
662 ] : [],
663 ];
664 }
665
666 return $result;
667 }
668
669 /**
670 * @param array $criteria
671 * @param int $itemsPerPage
672 * @param boolean $invoice
673 *
674 * @return array
675 * @throws QueryExecutionException
676 */
677 public function getFilteredIds($criteria, $itemsPerPage = null, $invoice = false)
678 {
679 $params = [];
680 $appointmentParams1 = [];
681 $appointmentParams2 = [];
682 $eventParams = [];
683 $whereAppointment1 = [];
684 $whereAppointment2 = [];
685 $whereEvent = [];
686
687 $basedOnDate = $invoice ? 'created' : 'dateTime';
688
689 if (!empty($criteria['dates'])) {
690 $whereAppointment1[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentAppointmentFrom1 AND :paymentAppointmentTo1)";
691 $whereAppointment2[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentAppointmentFrom2 AND :paymentAppointmentTo2)";
692 $appointmentParams1[':paymentAppointmentFrom1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
693 $appointmentParams2[':paymentAppointmentFrom2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
694 $appointmentParams1[':paymentAppointmentTo1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
695 $appointmentParams2[':paymentAppointmentTo2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
696
697 $whereEvent[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentEventFrom AND :paymentEventTo)";
698 $eventParams[':paymentEventFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
699 $eventParams[':paymentEventTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
700 }
701
702 if (!empty($criteria['customerId'])) {
703 $appointmentParams1[':customerAppointmentId1'] = $criteria['customerId'];
704 $appointmentParams2[':customerAppointmentId2'] = $criteria['customerId'];
705 $whereAppointment1[] = 'cb.customerId = :customerAppointmentId1';
706 $whereAppointment2[] = 'pc.customerId = :customerAppointmentId2';
707
708 $eventParams[':customerEventId'] = $criteria['customerId'];
709 $whereEvent[] = 'cb.customerId = :customerEventId';
710 }
711
712 $eventsProvidersJoin = '';
713
714 if (!empty($criteria['providerId'])) {
715 $appointmentParams1[':providerAppointmentId1'] = $criteria['providerId'];
716 $appointmentParams1[':providerAppointmentId2'] = $criteria['providerId'];
717 $whereAppointment1[] = 'a.providerId = :providerAppointmentId1';
718 $whereAppointment2[] = 'a.providerId = :providerAppointmentId2';
719
720 $eventParams[':providerEventId'] = $criteria['providerId'];
721 $whereEvent[] = 'epu.userId = :providerEventId';
722
723 $eventsProvidersJoin = "
724 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
725 INNER JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
726 ";
727 }
728
729 if (!empty($criteria['services'])) {
730 $queryServices1 = [];
731 $queryServices2 = [];
732
733 foreach ((array)$criteria['services'] as $index => $value) {
734 $param1 = ':service0' . $index;
735 $param2 = ':service1' . $index;
736 $queryServices1[] = $param1;
737 $queryServices2[] = $param2;
738 $appointmentParams1[$param1] = $value;
739 $appointmentParams2[$param2] = $value;
740 }
741
742 $whereAppointment1[] = 'a.serviceId IN (' . implode(', ', $queryServices1) . ')';
743 $whereAppointment2[] = 'a.serviceId IN (' . implode(', ', $queryServices2) . ')';
744 }
745
746 $appointments2ProvidersServicesJoin = '';
747
748 if (!empty($criteria['providerId']) || !empty($criteria['services'])) {
749 $appointments2ProvidersServicesJoin = "
750 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
751 INNER JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
752 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
753 ";
754 }
755
756 if (!empty($criteria['status'])) {
757 $appointmentParams1[':statusAppointment1'] = $criteria['status'];
758 $appointmentParams2[':statusAppointment2'] = $criteria['status'];
759 $whereAppointment1[] = 'p.status = :statusAppointment1';
760 $whereAppointment2[] = 'p.status = :statusAppointment2';
761
762 $eventParams[':statusEvent'] = $criteria['status'];
763 $whereEvent[] = 'p.status = :statusEvent';
764 }
765
766 if (!empty($criteria['packages'])) {
767 $queryPackages = [];
768
769 foreach ((array)$criteria['packages'] as $index => $value) {
770 $param = ':package' . $index;
771 $queryPackages[] = $param;
772 $appointmentParams2[$param] = $value;
773 }
774
775 $whereAppointment2[] = "p.packageCustomerId IN (SELECT pc.id
776 FROM {$this->packagesCustomersTable} pc
777 WHERE pc.packageId IN (" . implode(', ', $queryPackages) . '))';
778 }
779
780 if (!empty($criteria['events'])) {
781 $queryEvents = [];
782
783 foreach ((array)$criteria['events'] as $index => $value) {
784 $param = ':event' . $index;
785 $queryEvents[] = $param;
786 $eventParams[$param] = $value;
787 }
788
789 $whereEvent[] = "p.customerBookingId IN (SELECT cbe.customerBookingId
790 FROM {$this->eventsTable} e
791 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.eventId = e.id
792 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.eventPeriodId = ep.id
793 WHERE e.id IN (" . implode(', ', $queryEvents) . '))';
794 }
795
796 $whereAppointment1 = $whereAppointment1 ? ' AND ' . implode(' AND ', $whereAppointment1) : '';
797 $whereAppointment2 = $whereAppointment2 ? ' AND ' . implode(' AND ', $whereAppointment2) : '';
798 $whereEvent = $whereEvent ? ' AND ' . implode(' AND ', $whereEvent) : '';
799
800 $groupBy = '';
801 if ($invoice) {
802 $groupBy = 'GROUP BY IFNULL(invoiceNumber, id)';
803 }
804
805 $appointmentQuery1 = "SELECT
806 p.id AS id,
807 p.dateTime AS dateTime,
808 p.created AS created,
809 p.invoiceNumber AS invoiceNumber,
810 'appointment' AS type
811 FROM {$this->table} p
812 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
813 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
814 WHERE 1=1 {$whereAppointment1} GROUP BY p.customerBookingId ORDER BY p.id ASC";
815
816 $appointmentQuery2 = "SELECT
817 p.id AS id,
818 p.dateTime AS dateTime,
819 p.created AS created,
820 p.invoiceNumber AS invoiceNumber,
821 'package' AS type
822 FROM {$this->table} p
823 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
824 {$appointments2ProvidersServicesJoin}
825 WHERE 1=1 {$whereAppointment2} GROUP BY p.packageCustomerId ORDER BY p.id ASC";
826
827 $eventQuery = "SELECT
828 p.id AS id,
829 p.dateTime AS dateTime,
830 p.created AS created,
831 p.invoiceNumber AS invoiceNumber,
832 'event' AS type
833 FROM {$this->table} p
834 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
835 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
836 {$eventsProvidersJoin}
837 WHERE 1=1 {$whereEvent} GROUP BY p.customerBookingId ORDER BY p.id ASC";
838
839 $result = [
840 'appointment' => [],
841 'event' => [],
842 'package' => [],
843 ];
844
845 if (isset($criteria['events'], $criteria['services'])) {
846 return $result;
847 } elseif (isset($criteria['services'])) {
848 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2})";
849 $params = array_merge($params, $appointmentParams1, $appointmentParams2);
850 } elseif (isset($criteria['events'])) {
851 $paymentQuery = "({$eventQuery})";
852 $params = array_merge($params, $eventParams);
853 } elseif (isset($criteria['packages'])) {
854 $paymentQuery = "({$appointmentQuery2})";
855 $params = array_merge($params, $appointmentParams2);
856 } else {
857 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2}) UNION ALL ({$eventQuery})";
858 $params = array_merge($params, $appointmentParams1, $appointmentParams2, $eventParams);
859 }
860
861 $limit = $this->getLimit(
862 !empty($criteria['page']) ? (int)$criteria['page'] : 0,
863 (int)$itemsPerPage
864 );
865
866 try {
867 $statement = $this->connection->prepare(
868 "SELECT * FROM ({$paymentQuery}) payments
869 {$groupBy}
870 ORDER BY {$basedOnDate}, id
871 {$limit}"
872 );
873
874 $statement->execute($params);
875
876 $rows = $statement->fetchAll();
877 } catch (\Exception $e) {
878 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
879 }
880
881 foreach ($rows as $row) {
882 $result[$row['type']][] = (int)$row['id'];
883 }
884
885 return $result;
886 }
887
888 /**
889 * @param array $criteria
890 * @param boolean $invoice
891 *
892 * @return array
893 * @throws QueryExecutionException
894 */
895 public function getFilteredIdsCount($criteria, $invoice = false)
896 {
897 $params = [];
898 $appointmentParams1 = [];
899 $appointmentParams2 = [];
900 $eventParams = [];
901 $whereAppointment1 = [];
902 $whereAppointment2 = [];
903 $whereEvent = [];
904
905 $basedOnDate = $invoice ? 'created' : 'dateTime';
906
907 if (!empty($criteria['dates'])) {
908 $whereAppointment1[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentAppointmentFrom1 AND :paymentAppointmentTo1)";
909 $whereAppointment2[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentAppointmentFrom2 AND :paymentAppointmentTo2)";
910 $appointmentParams1[':paymentAppointmentFrom1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
911 $appointmentParams2[':paymentAppointmentFrom2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
912 $appointmentParams1[':paymentAppointmentTo1'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
913 $appointmentParams2[':paymentAppointmentTo2'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
914
915 $whereEvent[] = "(DATE_FORMAT(p.{$basedOnDate}, '%Y-%m-%d %H:%i:%s') BETWEEN :paymentEventFrom AND :paymentEventTo)";
916 $eventParams[':paymentEventFrom'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][0]);
917 $eventParams[':paymentEventTo'] = DateTimeService::getCustomDateTimeInUtc($criteria['dates'][1]);
918 }
919
920 if (!empty($criteria['customerId'])) {
921 $appointmentParams1[':customerAppointmentId1'] = $criteria['customerId'];
922 $appointmentParams2[':customerAppointmentId2'] = $criteria['customerId'];
923 $whereAppointment1[] = 'cb.customerId = :customerAppointmentId1';
924 $whereAppointment2[] = 'pc.customerId = :customerAppointmentId2';
925
926 $eventParams[':customerEventId'] = $criteria['customerId'];
927 $whereEvent[] = 'cb.customerId = :customerEventId';
928 }
929
930 $eventsProvidersJoin = '';
931
932 if (!empty($criteria['providerId'])) {
933 $appointmentParams1[':providerAppointmentId1'] = $criteria['providerId'];
934 $appointmentParams1[':providerAppointmentId2'] = $criteria['providerId'];
935 $whereAppointment1[] = 'a.providerId = :providerAppointmentId1';
936 $whereAppointment2[] = 'a.providerId = :providerAppointmentId2';
937
938 $eventParams[':providerEventId'] = $criteria['providerId'];
939 $whereEvent[] = 'epu.userId = :providerEventId';
940
941 $eventsProvidersJoin = "
942 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.id = cbe.eventPeriodId
943 INNER JOIN {$this->eventsProvidersTable} epu ON epu.eventId = ep.eventId
944 ";
945 }
946
947 if (!empty($criteria['services'])) {
948 $queryServices1 = [];
949 $queryServices2 = [];
950
951 foreach ((array)$criteria['services'] as $index => $value) {
952 $param1 = ':service0' . $index;
953 $param2 = ':service1' . $index;
954 $queryServices1[] = $param1;
955 $queryServices2[] = $param2;
956 $appointmentParams1[$param1] = $value;
957 $appointmentParams2[$param2] = $value;
958 }
959
960 $whereAppointment1[] = 'a.serviceId IN (' . implode(', ', $queryServices1) . ')';
961 $whereAppointment2[] = 'a.serviceId IN (' . implode(', ', $queryServices2) . ')';
962 }
963
964 $appointments2ProvidersServicesJoin = '';
965
966 if (!empty($criteria['providerId']) || !empty($criteria['services'])) {
967 $appointments2ProvidersServicesJoin = "
968 INNER JOIN {$this->packagesCustomersServiceTable} pcs ON pc.id = pcs.packageCustomerId
969 INNER JOIN {$this->bookingsTable} cb ON cb.packageCustomerServiceId = pcs.id
970 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
971 ";
972 }
973
974 if (!empty($criteria['status'])) {
975 $appointmentParams1[':statusAppointment1'] = $criteria['status'];
976 $appointmentParams2[':statusAppointment2'] = $criteria['status'];
977 $whereAppointment1[] = 'p.status = :statusAppointment1';
978 $whereAppointment2[] = 'p.status = :statusAppointment2';
979
980 $eventParams[':statusEvent'] = $criteria['status'];
981 $whereEvent[] = 'p.status = :statusEvent';
982 }
983
984 if (!empty($criteria['events'])) {
985 $queryEvents = [];
986
987 foreach ((array)$criteria['events'] as $index => $value) {
988 $param = ':event' . $index;
989 $queryEvents[] = $param;
990 $eventParams[$param] = $value;
991 }
992
993 $whereEvent[] = "p.customerBookingId IN (SELECT cbe.customerBookingId
994 FROM {$this->eventsTable} e
995 INNER JOIN {$this->eventsPeriodsTable} ep ON ep.eventId = e.id
996 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.eventPeriodId = ep.id
997 WHERE e.id IN (" . implode(', ', $queryEvents) . '))';
998 }
999
1000 if (!empty($criteria['packages'])) {
1001 $queryPackages = [];
1002
1003 foreach ((array)$criteria['packages'] as $index => $value) {
1004 $param = ':package' . $index;
1005 $queryPackages[] = $param;
1006 $appointmentParams2[$param] = $value;
1007 }
1008
1009 $whereAppointment2[] = "p.packageCustomerId IN (SELECT pc.id
1010 FROM {$this->packagesCustomersTable} pc
1011 WHERE pc.packageId IN (" . implode(', ', $queryPackages) . '))';
1012 }
1013
1014 $whereAppointment1 = $whereAppointment1 ? ' AND ' . implode(' AND ', $whereAppointment1) : '';
1015 $whereAppointment2 = $whereAppointment2 ? ' AND ' . implode(' AND ', $whereAppointment2) : '';
1016 $whereEvent = $whereEvent ? ' AND ' . implode(' AND ', $whereEvent) : '';
1017
1018 $groupBy = '';
1019 if ($invoice) {
1020 $groupBy = 'GROUP BY IFNULL(invoiceNumber, id)';
1021 }
1022
1023
1024 $appointmentQuery1 = "SELECT
1025 COUNT(DISTINCT(p.customerBookingId)) AS appointmentsCount1,
1026 0 AS appointmentsCount2,
1027 0 AS eventsCount,
1028 p.id AS id,
1029 p.invoiceNumber AS invoiceNumber,
1030 p.created AS created,
1031 p.dateTime AS dateTime
1032 FROM {$this->table} p
1033 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
1034 INNER JOIN {$this->appointmentsTable} a ON a.id = cb.appointmentId
1035 WHERE 1=1 {$whereAppointment1} GROUP BY p.customerBookingId ORDER BY p.id ASC";
1036
1037 $appointmentQuery2 = "SELECT
1038 0 AS appointmentsCount1,
1039 COUNT(DISTINCT(p.packageCustomerId)) AS appointmentsCount2,
1040 0 AS eventsCount,
1041 p.id AS id,
1042 p.invoiceNumber AS invoiceNumber,
1043 p.created AS created,
1044 p.dateTime AS dateTime
1045 FROM {$this->table} p
1046 INNER JOIN {$this->packagesCustomersTable} pc ON p.packageCustomerId = pc.id
1047 {$appointments2ProvidersServicesJoin}
1048 WHERE 1=1 {$whereAppointment2} GROUP BY p.packageCustomerId ORDER BY p.id ASC";
1049
1050 $eventQuery = "SELECT
1051 0 AS appointmentsCount1,
1052 0 AS appointmentsCount2,
1053 COUNT(DISTINCT(p.customerBookingId)) AS eventsCount,
1054 p.id AS id,
1055 p.invoiceNumber AS invoiceNumber,
1056 p.created AS created,
1057 p.dateTime AS dateTime
1058 FROM {$this->table} p
1059 INNER JOIN {$this->bookingsTable} cb ON cb.id = p.customerBookingId
1060 INNER JOIN {$this->customerBookingsToEventsPeriodsTable} cbe ON cbe.customerBookingId = cb.id
1061 {$eventsProvidersJoin}
1062 WHERE 1=1 {$whereEvent} GROUP BY p.customerBookingId ORDER BY p.id ASC";
1063
1064 if (isset($criteria['events'], $criteria['services'])) {
1065 return [];
1066 } elseif (isset($criteria['services'])) {
1067 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2})";
1068 $params = array_merge($params, $appointmentParams1, $appointmentParams2);
1069 } elseif (isset($criteria['events'])) {
1070 $paymentQuery = "({$eventQuery})";
1071 $params = array_merge($params, $eventParams);
1072 } elseif (isset($criteria['packages'])) {
1073 $paymentQuery = "({$appointmentQuery2})";
1074 $params = array_merge($params, $appointmentParams2);
1075 } else {
1076 $paymentQuery = "({$appointmentQuery1}) UNION ALL ({$appointmentQuery2}) UNION ALL ({$eventQuery})";
1077 $params = array_merge($params, $appointmentParams1, $appointmentParams2, $eventParams);
1078 }
1079
1080 try {
1081 $statement = $this->connection->prepare(
1082 "SELECT * FROM ({$paymentQuery}) payments
1083 {$groupBy}
1084 ORDER BY {$basedOnDate}, id"
1085 );
1086
1087 $statement->execute($params);
1088
1089 $statements = $statement->fetchAll();
1090
1091 $appointmentsCount1 = 0;
1092 $appointmentsCount2 = 0;
1093 $eventsCount = 0;
1094
1095 foreach ($statements as $st) {
1096 $appointmentsCount1 += !empty($st['appointmentsCount1']) ? $st['appointmentsCount1'] : 0;
1097 $appointmentsCount2 += !empty($st['appointmentsCount2']) ? $st['appointmentsCount2'] : 0;
1098 $eventsCount += !empty($st['eventsCount']) ? $st['eventsCount'] : 0;
1099 }
1100 } catch (\Exception $e) {
1101 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1102 }
1103
1104 return $appointmentsCount1 + $appointmentsCount2 + $eventsCount;
1105 }
1106
1107 /**
1108 * Returns a collection of customers that have birthday on today's date and where notification is not sent
1109 *
1110 * @return Collection
1111 * @throws InvalidArgumentException
1112 * @throws QueryExecutionException
1113 * @throws \Exception
1114 */
1115 public function getUncompletedActionsForPayments()
1116 {
1117 $params = [];
1118
1119 $currentDateTime = "STR_TO_DATE('" . DateTimeService::getNowDateTimeInUtc() . "', '%Y-%m-%d %H:%i:%s')";
1120
1121 $pastDateTime =
1122 "STR_TO_DATE('" .
1123 DateTimeService::getNowDateTimeObjectInUtc()->modify('-1 day')->format('Y-m-d H:i:s') .
1124 "', '%Y-%m-%d %H:%i:%s')";
1125
1126 try {
1127 $statement = $this->connection->prepare(
1128 "SELECT * FROM {$this->table}
1129 WHERE
1130 actionsCompleted = 0 AND
1131 {$currentDateTime} > DATE_ADD(created, INTERVAL 300 SECOND) AND
1132 {$pastDateTime} < created AND
1133 entity IS NOT NULL"
1134 );
1135
1136 $statement->execute($params);
1137
1138 $rows = $statement->fetchAll();
1139 } catch (\Exception $e) {
1140 throw new QueryExecutionException('Unable to get data from ' . __CLASS__, $e->getCode(), $e);
1141 }
1142
1143 $items = [];
1144
1145 foreach ($rows as $row) {
1146 $items[] = call_user_func([static::FACTORY, 'create'], $row);
1147 }
1148
1149 return new Collection($items);
1150 }
1151
1152 /**
1153 * @param int $status
1154 */
1155 public function findByStatus($status)
1156 {
1157 // TODO: Implement findByStatus() method.
1158 }
1159
1160 /**
1161 * @param array $data
1162 * @param boolean $invoice
1163 *
1164 * @return array
1165 * @throws QueryExecutionException
1166 */
1167 public function getSecondaryPaymentIds($data, $invoice)
1168 {
1169 $rows = [];
1170
1171 $params = [];
1172
1173 $where = [];
1174
1175 foreach ($data as $index => $item) {
1176 $paymentIdParam1 = ':paymentId1' . $index;
1177 $params[$paymentIdParam1] = $item['paymentId'];
1178
1179 if ($invoice) {
1180 if (!empty($item['parentId'])) {
1181 $parentIdParam1 = ':parentId1' . $index;
1182 $params[$parentIdParam1] = $item['parentId'];
1183 $parentIdParam2 = ':parentId2' . $index;
1184 $params[$parentIdParam2] = $item['parentId'];
1185 }
1186 $paymentIdParam2 = ':paymentId2' . $index;
1187 $params[$paymentIdParam2] = $item['paymentId'];
1188 }
1189
1190 $relationParam = ':' . $item['columnName'] . $index;
1191
1192 $params[$relationParam] = $item['columnId'];
1193
1194 // change in the future to simply retrieve by invoiceNumber when on invoice page since all the related payments will have the same invoiceNumber
1195 // cannot be done immediately since invoiceNumber is NULL for existing payments
1196 if ($invoice) {
1197 $where[] = "((id <> $paymentIdParam1 AND " . $item['columnName'] . " = $relationParam) OR parentId = $paymentIdParam2" . (!empty($item['parentId']) ? " OR id = $parentIdParam1 OR parentId = $parentIdParam2)" : ")");
1198 } else {
1199 $where[] = "(id <> $paymentIdParam1 AND " . $item['columnName'] . " = $relationParam)";
1200 }
1201 }
1202
1203 $where = $where ? 'WHERE ' . implode(' OR ', $where) : '';
1204
1205 try {
1206 $statement = $this->connection->prepare(
1207 "SELECT
1208 p.id AS id,
1209 p.entity AS entity
1210 FROM {$this->table} p
1211 {$where}"
1212 );
1213
1214 $statement->execute($params);
1215
1216 $rows = $statement->fetchAll();
1217 } catch (\Exception $e) {
1218 throw new QueryExecutionException('Unable to find by id in ' . __CLASS__, $e->getCode(), $e);
1219 }
1220
1221 $result = [
1222 'appointment' => [],
1223 'event' => [],
1224 'package' => []
1225 ];
1226
1227 foreach ($rows as $row) {
1228 $result[$row['entity']][] = (int)$row['id'];
1229 }
1230
1231 return $result;
1232 }
1233
1234 /**
1235 * @param int $paymentId
1236 * @param string $transactionId
1237 *
1238 * @throws QueryExecutionException
1239 */
1240 public function updateTransactionId($paymentId, $transactionId)
1241 {
1242 $params = [
1243 ':transactionId' => $transactionId,
1244 ':paymentId1' => $paymentId,
1245 ':paymentId2' => $paymentId
1246 ];
1247
1248 try {
1249 $statement = $this->connection->prepare(
1250 "UPDATE {$this->table} SET `transactionId` = :transactionId WHERE id = :paymentId1 OR parentId = :paymentId2"
1251 );
1252
1253 $response = $statement->execute($params);
1254 } catch (\Exception $e) {
1255 throw new QueryExecutionException('Unable to update data in ' . __CLASS__, $e->getCode(), $e);
1256 }
1257
1258 if (!$response) {
1259 throw new QueryExecutionException('Unable to update data in ' . __CLASS__);
1260 }
1261
1262 return $response;
1263 }
1264
1265
1266
1267 /**
1268 * @param array $data
1269 *
1270 * @return bool
1271 * @throws QueryExecutionException
1272 */
1273 public function setInvoiceNumber($data)
1274 {
1275 $params = [
1276 ':id1' => $data['id'],
1277 ':id2' => $data['id'],
1278 ":{$data['columnName']}" => $data['columnValue']
1279 ];
1280
1281 $where = "WHERE id = :id1 OR parentId = :id2 OR {$data['columnName']} = :{$data['columnName']}";
1282
1283 if (!empty($data['parentId'])) {
1284 $params[':parentId1'] = $params[':parentId2'] = $data['parentId'];
1285 $where = ' OR id = :parentId1 OR parentId = :parentId2';
1286 }
1287
1288 try {
1289 $statement = $this->connection->prepare(
1290 "UPDATE {$this->table}
1291 SET `invoiceNumber` = (SELECT MAX(CASE WHEN invoiceNumber IS NULL THEN 0 ELSE invoiceNumber END)+1 FROM (SELECT * FROM {$this->table}) AS p)
1292 {$where}"
1293 );
1294
1295 $response = $statement->execute($params);
1296 } catch (\Exception $e) {
1297 throw new QueryExecutionException('Unable to save invoice number in ' . __CLASS__, $e->getCode(), $e);
1298 }
1299
1300 if (!$response) {
1301 throw new QueryExecutionException('Unable to save invoice number in ' . __CLASS__);
1302 }
1303
1304 return $response;
1305 }
1306 }
1307