Completed
Push — docs-installation-setup ( 464016 )
by Kamil
05:18
created

OrderRepository::countPaidForChannelInPeriod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Bundle\CoreBundle\Doctrine\ORM;
15
16
use Doctrine\ORM\EntityManager;
17
use Doctrine\ORM\Mapping;
18
use Doctrine\ORM\QueryBuilder;
19
use Sylius\Bundle\OrderBundle\Doctrine\ORM\OrderRepository as BaseOrderRepository;
20
use Sylius\Component\Core\Model\ChannelInterface;
21
use Sylius\Component\Core\Model\CustomerInterface;
22
use Sylius\Component\Core\Model\OrderInterface;
23
use Sylius\Component\Core\Model\PromotionCouponInterface;
24
use Sylius\Component\Core\OrderCheckoutStates;
25
use Sylius\Component\Core\OrderPaymentStates;
26
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
27
use SyliusLabs\AssociationHydrator\AssociationHydrator;
28
29
class OrderRepository extends BaseOrderRepository implements OrderRepositoryInterface
30
{
31
    /** @var AssociationHydrator */
32
    protected $associationHydrator;
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function __construct(EntityManager $entityManager, Mapping\ClassMetadata $class)
38
    {
39
        parent::__construct($entityManager, $class);
40
41
        $this->associationHydrator = new AssociationHydrator($entityManager, $class);
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function createListQueryBuilder(): QueryBuilder
48
    {
49
        return $this->createQueryBuilder('o')
50
            ->addSelect('channel')
51
            ->addSelect('customer')
52
            ->innerJoin('o.channel', 'channel')
53
            ->leftJoin('o.customer', 'customer')
54
            ->andWhere('o.state != :state')
55
            ->setParameter('state', OrderInterface::STATE_CART)
56
        ;
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function createByCustomerIdQueryBuilder($customerId): QueryBuilder
63
    {
64
        return $this->createListQueryBuilder()
65
            ->andWhere('o.customer = :customerId')
66
            ->setParameter('customerId', $customerId)
67
        ;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73
    public function createByCustomerAndChannelIdQueryBuilder($customerId, $channelId): QueryBuilder
74
    {
75
        return $this->createQueryBuilder('o')
76
            ->andWhere('o.customer = :customerId')
77
            ->andWhere('o.channel = :channelId')
78
            ->andWhere('o.state != :state')
79
            ->setParameter('customerId', $customerId)
80
            ->setParameter('channelId', $channelId)
81
            ->setParameter('state', OrderInterface::STATE_CART)
82
        ;
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function findByCustomer(CustomerInterface $customer): array
89
    {
90
        return $this->createByCustomerIdQueryBuilder($customer->getId())
91
            ->getQuery()
92
            ->getResult()
93
        ;
94
    }
95
96
    /**
97
     * {@inheritdoc}
98
     */
99
    public function findForCustomerStatistics(CustomerInterface $customer): array
100
    {
101
        return $this->createQueryBuilder('o')
102
            ->andWhere('o.customer = :customerId')
103
            ->andWhere('o.state = :state')
104
            ->setParameter('customerId', $customer->getId())
105
            ->setParameter('state', OrderInterface::STATE_FULFILLED)
106
            ->getQuery()
107
            ->getResult()
108
        ;
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function findOneForPayment($id): ?OrderInterface
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
115
    {
116
        return $this->createQueryBuilder('o')
117
            ->addSelect('payments')
118
            ->addSelect('paymentMethods')
119
            ->leftJoin('o.payments', 'payments')
120
            ->leftJoin('payments.method', 'paymentMethods')
121
            ->andWhere('o.id = :id')
122
            ->setParameter('id', $id)
123
            ->getQuery()
124
            ->getOneOrNullResult()
125
        ;
126
    }
127
128
    public function countByCustomerAndCoupon(
129
        CustomerInterface $customer,
130
        PromotionCouponInterface $coupon,
131
        bool $includeCancelled = false
132
    ): int {
133
        $states = [OrderInterface::STATE_CART];
134
        if ($coupon->isReusableFromCancelledOrders()) {
135
            $states[] = OrderInterface::STATE_CANCELLED;
136
        }
137
138
        return (int) $this->createQueryBuilder('o')
139
            ->select('COUNT(o.id)')
140
            ->andWhere('o.customer = :customer')
141
            ->andWhere('o.promotionCoupon = :coupon')
142
            ->andWhere('o.state NOT IN (:states)')
143
            ->setParameter('customer', $customer)
144
            ->setParameter('coupon', $coupon)
145
            ->setParameter('states', $states)
146
            ->getQuery()
147
            ->getSingleScalarResult()
148
        ;
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public function countByCustomer(CustomerInterface $customer): int
155
    {
156
        return (int) $this->createQueryBuilder('o')
157
            ->select('COUNT(o.id)')
158
            ->andWhere('o.customer = :customer')
159
            ->andWhere('o.state NOT IN (:states)')
160
            ->setParameter('customer', $customer)
161
            ->setParameter('states', [OrderInterface::STATE_CART, OrderInterface::STATE_CANCELLED])
162
            ->getQuery()
163
            ->getSingleScalarResult()
164
        ;
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170
    public function findOneByNumberAndCustomer(string $number, CustomerInterface $customer): ?OrderInterface
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
171
    {
172
        return $this->createQueryBuilder('o')
173
            ->andWhere('o.customer = :customer')
174
            ->andWhere('o.number = :number')
175
            ->setParameter('customer', $customer)
176
            ->setParameter('number', $number)
177
            ->getQuery()
178
            ->getOneOrNullResult()
179
        ;
180
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185
    public function findCartByChannel($id, ChannelInterface $channel): ?OrderInterface
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
186
    {
187
        return $this->createQueryBuilder('o')
188
            ->andWhere('o.id = :id')
189
            ->andWhere('o.state = :state')
190
            ->andWhere('o.channel = :channel')
191
            ->setParameter('id', $id)
192
            ->setParameter('state', OrderInterface::STATE_CART)
193
            ->setParameter('channel', $channel)
194
            ->getQuery()
195
            ->getOneOrNullResult()
196
        ;
197
    }
198
199
    /**
200
     * {@inheritdoc}
201
     */
202
    public function findLatestCartByChannelAndCustomer(ChannelInterface $channel, CustomerInterface $customer): ?OrderInterface
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
203
    {
204
        return $this->createQueryBuilder('o')
205
            ->andWhere('o.state = :state')
206
            ->andWhere('o.channel = :channel')
207
            ->andWhere('o.customer = :customer')
208
            ->setParameter('state', OrderInterface::STATE_CART)
209
            ->setParameter('channel', $channel)
210
            ->setParameter('customer', $customer)
211
            ->addOrderBy('o.createdAt', 'DESC')
212
            ->setMaxResults(1)
213
            ->getQuery()
214
            ->getOneOrNullResult()
215
        ;
216
    }
217
218
    /**
219
     * {@inheritdoc}
220
     */
221
    public function getTotalSalesForChannel(ChannelInterface $channel): int
222
    {
223
        return (int) $this->createQueryBuilder('o')
224
            ->select('SUM(o.total)')
225
            ->andWhere('o.channel = :channel')
226
            ->andWhere('o.state = :state')
227
            ->setParameter('channel', $channel)
228
            ->setParameter('state', OrderInterface::STATE_FULFILLED)
229
            ->getQuery()
230
            ->getSingleScalarResult()
231
        ;
232
    }
233
234
    public function getTotalPaidSalesForChannel(ChannelInterface $channel): int
235
    {
236
        return (int) $this->createQueryBuilder('o')
237
            ->select('SUM(o.total)')
238
            ->andWhere('o.channel = :channel')
239
            ->andWhere('o.paymentState = :state')
240
            ->setParameter('channel', $channel)
241
            ->setParameter('state', OrderPaymentStates::STATE_PAID)
242
            ->getQuery()
243
            ->getSingleScalarResult()
244
        ;
245
    }
246
247
    public function getTotalPaidSalesForChannelInPeriod(
248
        ChannelInterface $channel,
249
        \DateTimeInterface $startDate,
250
        \DateTimeInterface $endDate
251
    ): int {
252
        return (int) $this->createQueryBuilder('o')
253
            ->select('SUM(o.total)')
254
            ->andWhere('o.channel = :channel')
255
            ->andWhere('o.paymentState = :state')
256
            ->andWhere('o.checkoutCompletedAt >= :startDate')
257
            ->andWhere('o.checkoutCompletedAt <= :endDate')
258
            ->setParameter('channel', $channel)
259
            ->setParameter('state', OrderPaymentStates::STATE_PAID)
260
            ->setParameter('startDate', $startDate)
261
            ->setParameter('endDate', $endDate)
262
            ->getQuery()
263
            ->getSingleScalarResult()
264
        ;
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270
    public function countFulfilledByChannel(ChannelInterface $channel): int
271
    {
272
        return (int) $this->createQueryBuilder('o')
273
            ->select('COUNT(o.id)')
274
            ->andWhere('o.channel = :channel')
275
            ->andWhere('o.state = :state')
276
            ->setParameter('channel', $channel)
277
            ->setParameter('state', OrderInterface::STATE_FULFILLED)
278
            ->getQuery()
279
            ->getSingleScalarResult()
280
        ;
281
    }
282
283
    public function countPaidByChannel(ChannelInterface $channel): int
284
    {
285
        return (int) $this->createQueryBuilder('o')
286
            ->select('COUNT(o.id)')
287
            ->andWhere('o.channel = :channel')
288
            ->andWhere('o.paymentState = :state')
289
            ->setParameter('channel', $channel)
290
            ->setParameter('state', OrderPaymentStates::STATE_PAID)
291
            ->getQuery()
292
            ->getSingleScalarResult()
293
        ;
294
    }
295
296
    public function countPaidForChannelInPeriod(
297
        ChannelInterface $channel,
298
        \DateTimeInterface $startDate,
299
        \DateTimeInterface $endDate
300
    ): int {
301
        return (int) $this->createQueryBuilder('o')
302
            ->select('COUNT(o.id)')
303
            ->andWhere('o.channel = :channel')
304
            ->andWhere('o.paymentState = :state')
305
            ->andWhere('o.checkoutCompletedAt >= :startDate')
306
            ->andWhere('o.checkoutCompletedAt <= :endDate')
307
            ->setParameter('channel', $channel)
308
            ->setParameter('state', OrderPaymentStates::STATE_PAID)
309
            ->setParameter('startDate', $startDate)
310
            ->setParameter('endDate', $endDate)
311
            ->getQuery()
312
            ->getSingleScalarResult()
313
        ;
314
    }
315
316
    /**
317
     * {@inheritdoc}
318
     */
319
    public function findLatestInChannel(int $count, ChannelInterface $channel): array
320
    {
321
        return $this->createQueryBuilder('o')
322
            ->andWhere('o.channel = :channel')
323
            ->andWhere('o.state != :state')
324
            ->addOrderBy('o.checkoutCompletedAt', 'DESC')
325
            ->setParameter('channel', $channel)
326
            ->setParameter('state', OrderInterface::STATE_CART)
327
            ->setMaxResults($count)
328
            ->getQuery()
329
            ->getResult()
330
        ;
331
    }
332
333
    /**
334
     * {@inheritdoc}
335
     */
336
    public function findOrdersUnpaidSince(\DateTimeInterface $terminalDate): array
337
    {
338
        return $this->createQueryBuilder('o')
339
            ->where('o.checkoutState = :checkoutState')
340
            ->andWhere('o.paymentState != :paymentState')
341
            ->andWhere('o.state = :orderState')
342
            ->andWhere('o.checkoutCompletedAt < :terminalDate')
343
            ->setParameter('checkoutState', OrderCheckoutStates::STATE_COMPLETED)
344
            ->setParameter('paymentState', OrderPaymentStates::STATE_PAID)
345
            ->setParameter('orderState', OrderInterface::STATE_NEW)
346
            ->setParameter('terminalDate', $terminalDate)
347
            ->getQuery()
348
            ->getResult()
349
        ;
350
    }
351
352
    /**
353
     * {@inheritdoc}
354
     */
355
    public function findCartForSummary($id): ?OrderInterface
356
    {
357
        /** @var OrderInterface $order */
358
        $order = $this->createQueryBuilder('o')
359
            ->andWhere('o.id = :id')
360
            ->andWhere('o.state = :state')
361
            ->setParameter('id', $id)
362
            ->setParameter('state', OrderInterface::STATE_CART)
363
            ->getQuery()
364
            ->getOneOrNullResult()
365
        ;
366
367
        $this->associationHydrator->hydrateAssociations($order, [
368
            'adjustments',
369
            'items',
370
            'items.adjustments',
371
            'items.units',
372
            'items.units.adjustments',
373
            'items.variant',
374
            'items.variant.optionValues',
375
            'items.variant.optionValues.translations',
376
            'items.variant.product',
377
            'items.variant.product.translations',
378
            'items.variant.product.images',
379
            'items.variant.product.options',
380
            'items.variant.product.options.translations',
381
        ]);
382
383
        return $order;
384
    }
385
386
    /**
387
     * {@inheritdoc}
388
     */
389
    public function findCartForAddressing($id): ?OrderInterface
390
    {
391
        /** @var OrderInterface $order */
392
        $order = $this->createQueryBuilder('o')
393
            ->andWhere('o.id = :id')
394
            ->andWhere('o.state = :state')
395
            ->setParameter('id', $id)
396
            ->setParameter('state', OrderInterface::STATE_CART)
397
            ->getQuery()
398
            ->getOneOrNullResult()
399
        ;
400
401
        $this->associationHydrator->hydrateAssociations($order, [
402
            'items',
403
            'items.variant',
404
            'items.variant.product',
405
            'items.variant.product.translations',
406
        ]);
407
408
        return $order;
409
    }
410
411
    /**
412
     * {@inheritdoc}
413
     */
414
    public function findCartForSelectingShipping($id): ?OrderInterface
415
    {
416
        /** @var OrderInterface $order */
417
        $order = $this->createQueryBuilder('o')
418
            ->andWhere('o.id = :id')
419
            ->andWhere('o.state = :state')
420
            ->setParameter('id', $id)
421
            ->setParameter('state', OrderInterface::STATE_CART)
422
            ->getQuery()
423
            ->getOneOrNullResult()
424
        ;
425
426
        $this->associationHydrator->hydrateAssociations($order, [
427
            'items',
428
            'items.variant',
429
            'items.variant.product',
430
            'items.variant.product.translations',
431
        ]);
432
433
        return $order;
434
    }
435
436
    /**
437
     * {@inheritdoc}
438
     */
439
    public function findCartForSelectingPayment($id): ?OrderInterface
440
    {
441
        /** @var OrderInterface $order */
442
        $order = $this->createQueryBuilder('o')
443
            ->andWhere('o.id = :id')
444
            ->andWhere('o.state = :state')
445
            ->setParameter('id', $id)
446
            ->setParameter('state', OrderInterface::STATE_CART)
447
            ->getQuery()
448
            ->getOneOrNullResult()
449
        ;
450
451
        $this->associationHydrator->hydrateAssociations($order, [
452
            'items',
453
            'items.variant',
454
            'items.variant.product',
455
            'items.variant.product.translations',
456
        ]);
457
458
        return $order;
459
    }
460
}
461